Home | History | Annotate | Download | only in m_gdbserver
      1 /* Inferior process information for the remote server for GDB.
      2    Copyright (C) 2002, 2005, 2011
      3    Free Software Foundation, Inc.
      4 
      5    Contributed by MontaVista Software.
      6 
      7    This file is part of GDB.
      8    It has been modified to integrate it in valgrind
      9 
     10    This program is free software; you can redistribute it and/or modify
     11    it under the terms of the GNU General Public License as published by
     12    the Free Software Foundation; either version 2 of the License, or
     13    (at your option) any later version.
     14 
     15    This program is distributed in the hope that it will be useful,
     16    but WITHOUT ANY WARRANTY; without even the implied warranty of
     17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18    GNU General Public License for more details.
     19 
     20    You should have received a copy of the GNU General Public License
     21    along with this program; if not, write to the Free Software
     22    Foundation, Inc., 51 Franklin Street, Fifth Floor,
     23    Boston, MA 02110-1301, USA.  */
     24 
     25 #include "server.h"
     26 
     27 struct thread_info
     28 {
     29    struct inferior_list_entry entry;
     30    void *target_data;
     31    void *regcache_data;
     32    unsigned int gdb_id;
     33 };
     34 
     35 struct inferior_list all_threads;
     36 
     37 struct thread_info *current_inferior;
     38 
     39 #define get_thread(inf) ((struct thread_info *)(inf))
     40 
     41 void add_inferior_to_list (struct inferior_list *list,
     42 		      struct inferior_list_entry *new_inferior)
     43 {
     44    new_inferior->next = NULL;
     45    if (list->tail != NULL)
     46       list->tail->next = new_inferior;
     47    else
     48       list->head = new_inferior;
     49    list->tail = new_inferior;
     50 }
     51 
     52 void for_each_inferior (struct inferior_list *list,
     53 		   void (*action) (struct inferior_list_entry *))
     54 {
     55    struct inferior_list_entry *cur = list->head, *next;
     56 
     57    while (cur != NULL) {
     58       next = cur->next;
     59       (*action) (cur);
     60       cur = next;
     61    }
     62 }
     63 
     64 void change_inferior_id (struct inferior_list *list,
     65 		    unsigned long new_id)
     66 {
     67    if (list->head != list->tail)
     68       error ("tried to change thread ID after multiple threads are created\n");
     69 
     70    list->head->id = new_id;
     71 }
     72 
     73 void remove_inferior (struct inferior_list *list,
     74 		 struct inferior_list_entry *entry)
     75 {
     76    struct inferior_list_entry **cur;
     77 
     78    if (list->head == entry) {
     79       list->head = entry->next;
     80       if (list->tail == entry)
     81          list->tail = list->head;
     82       return;
     83    }
     84 
     85    cur = &list->head;
     86    while (*cur && (*cur)->next != entry)
     87       cur = &(*cur)->next;
     88 
     89    if (*cur == NULL)
     90       return;
     91 
     92    (*cur)->next = entry->next;
     93 
     94    if (list->tail == entry)
     95       list->tail = *cur;
     96 }
     97 
     98 void add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
     99 {
    100    struct thread_info *new_thread
    101       = (struct thread_info *) malloc (sizeof (*new_thread));
    102 
    103    VG_(memset) (new_thread, 0, sizeof (*new_thread));
    104 
    105    new_thread->entry.id = thread_id;
    106 
    107    add_inferior_to_list (&all_threads, & new_thread->entry);
    108 
    109    if (current_inferior == NULL)
    110       current_inferior = new_thread;
    111 
    112    new_thread->target_data = target_data;
    113    set_inferior_regcache_data (new_thread, new_register_cache ());
    114    new_thread->gdb_id = gdb_id;
    115 }
    116 
    117 unsigned int thread_id_to_gdb_id (unsigned long thread_id)
    118 {
    119    struct inferior_list_entry *inf = all_threads.head;
    120 
    121    while (inf != NULL) {
    122       struct thread_info *thread = get_thread (inf);
    123       if (inf->id == thread_id)
    124          return thread->gdb_id;
    125       inf = inf->next;
    126    }
    127 
    128    return 0;
    129 }
    130 
    131 unsigned int thread_to_gdb_id (struct thread_info *thread)
    132 {
    133    return thread->gdb_id;
    134 }
    135 
    136 struct thread_info * gdb_id_to_thread (unsigned int gdb_id)
    137 {
    138    struct inferior_list_entry *inf = all_threads.head;
    139 
    140    while (inf != NULL) {
    141       struct thread_info *thread = get_thread (inf);
    142       if (thread->gdb_id == gdb_id)
    143          return thread;
    144       inf = inf->next;
    145    }
    146 
    147    return NULL;
    148 }
    149 
    150 unsigned long gdb_id_to_thread_id (unsigned int gdb_id)
    151 {
    152    struct thread_info *thread = gdb_id_to_thread (gdb_id);
    153 
    154    return thread ? thread->entry.id : 0;
    155 }
    156 
    157 static
    158 void free_one_thread (struct inferior_list_entry *inf)
    159 {
    160    struct thread_info *thread = get_thread (inf);
    161    free_register_cache (inferior_regcache_data (thread));
    162    free (thread);
    163 }
    164 
    165 void remove_thread (struct thread_info *thread)
    166 {
    167    remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
    168    free_one_thread (&thread->entry);
    169 }
    170 
    171 void clear_inferiors (void)
    172 {
    173    for_each_inferior (&all_threads, free_one_thread);
    174 
    175    all_threads.head = all_threads.tail = NULL;
    176 }
    177 
    178 struct inferior_list_entry * find_inferior (struct inferior_list *list,
    179                                             int (*func)
    180                                               (struct inferior_list_entry *,
    181                                                void *),
    182                                             void *arg)
    183 {
    184    struct inferior_list_entry *inf = list->head;
    185 
    186    while (inf != NULL) {
    187       if ((*func) (inf, arg))
    188          return inf;
    189       inf = inf->next;
    190    }
    191 
    192    return NULL;
    193 }
    194 
    195 struct inferior_list_entry * find_inferior_id (struct inferior_list *list,
    196                                                unsigned long id)
    197 {
    198    struct inferior_list_entry *inf = list->head;
    199 
    200    while (inf != NULL) {
    201       if (inf->id == id)
    202          return inf;
    203       inf = inf->next;
    204    }
    205 
    206    return NULL;
    207 }
    208 
    209 void * inferior_target_data (struct thread_info *inferior)
    210 {
    211    return inferior->target_data;
    212 }
    213 
    214 void set_inferior_target_data (struct thread_info *inferior, void *data)
    215 {
    216    inferior->target_data = data;
    217 }
    218 
    219 void * inferior_regcache_data (struct thread_info *inferior)
    220 {
    221    return inferior->regcache_data;
    222 }
    223 
    224 void set_inferior_regcache_data (struct thread_info *inferior, void *data)
    225 {
    226    inferior->regcache_data = data;
    227 }
    228