OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [gdbserver/] [inferiors.c] - Blame information for rev 855

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Inferior process information for the remote server for GDB.
2
   Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   Contributed by MontaVista Software.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
#include <stdlib.h>
23
 
24
#include "server.h"
25
 
26
struct thread_info
27
{
28
  struct inferior_list_entry entry;
29
  void *target_data;
30
  void *regcache_data;
31
  unsigned int gdb_id;
32
};
33
 
34
struct inferior_list all_processes;
35
struct inferior_list all_threads;
36
struct inferior_list all_dlls;
37
int dlls_changed;
38
 
39
struct thread_info *current_inferior;
40
 
41
 
42
/* Oft used ptids */
43
ptid_t null_ptid;
44
ptid_t minus_one_ptid;
45
 
46
/* Create a ptid given the necessary PID, LWP, and TID components.  */
47
 
48
ptid_t
49
ptid_build (int pid, long lwp, long tid)
50
{
51
  ptid_t ptid;
52
 
53
  ptid.pid = pid;
54
  ptid.lwp = lwp;
55
  ptid.tid = tid;
56
  return ptid;
57
}
58
 
59
/* Create a ptid from just a pid.  */
60
 
61
ptid_t
62
pid_to_ptid (int pid)
63
{
64
  return ptid_build (pid, 0, 0);
65
}
66
 
67
/* Fetch the pid (process id) component from a ptid.  */
68
 
69
int
70
ptid_get_pid (ptid_t ptid)
71
{
72
  return ptid.pid;
73
}
74
 
75
/* Fetch the lwp (lightweight process) component from a ptid.  */
76
 
77
long
78
ptid_get_lwp (ptid_t ptid)
79
{
80
  return ptid.lwp;
81
}
82
 
83
/* Fetch the tid (thread id) component from a ptid.  */
84
 
85
long
86
ptid_get_tid (ptid_t ptid)
87
{
88
  return ptid.tid;
89
}
90
 
91
/* ptid_equal() is used to test equality of two ptids.  */
92
 
93
int
94
ptid_equal (ptid_t ptid1, ptid_t ptid2)
95
{
96
  return (ptid1.pid == ptid2.pid
97
          && ptid1.lwp == ptid2.lwp
98
          && ptid1.tid == ptid2.tid);
99
}
100
 
101
/* Return true if this ptid represents a process.  */
102
 
103
int
104
ptid_is_pid (ptid_t ptid)
105
{
106
  if (ptid_equal (minus_one_ptid, ptid))
107
    return 0;
108
  if (ptid_equal (null_ptid, ptid))
109
    return 0;
110
 
111
  return (ptid_get_pid (ptid) != 0
112
          && ptid_get_lwp (ptid) == 0
113
          && ptid_get_tid (ptid) == 0);
114
}
115
 
116
#define get_thread(inf) ((struct thread_info *)(inf))
117
#define get_dll(inf) ((struct dll_info *)(inf))
118
 
119
void
120
add_inferior_to_list (struct inferior_list *list,
121
                      struct inferior_list_entry *new_inferior)
122
{
123
  new_inferior->next = NULL;
124
  if (list->tail != NULL)
125
    list->tail->next = new_inferior;
126
  else
127
    list->head = new_inferior;
128
  list->tail = new_inferior;
129
}
130
 
131
/* Invoke ACTION for each inferior in LIST.  */
132
 
133
void
134
for_each_inferior (struct inferior_list *list,
135
                   void (*action) (struct inferior_list_entry *))
136
{
137
  struct inferior_list_entry *cur = list->head, *next;
138
 
139
  while (cur != NULL)
140
    {
141
      next = cur->next;
142
      (*action) (cur);
143
      cur = next;
144
    }
145
}
146
 
147
void
148
remove_inferior (struct inferior_list *list,
149
                 struct inferior_list_entry *entry)
150
{
151
  struct inferior_list_entry **cur;
152
 
153
  if (list->head == entry)
154
    {
155
      list->head = entry->next;
156
      if (list->tail == entry)
157
        list->tail = list->head;
158
      return;
159
    }
160
 
161
  cur = &list->head;
162
  while (*cur && (*cur)->next != entry)
163
    cur = &(*cur)->next;
164
 
165
  if (*cur == NULL)
166
    return;
167
 
168
  (*cur)->next = entry->next;
169
 
170
  if (list->tail == entry)
171
    list->tail = *cur;
172
}
173
 
174
void
175
add_thread (ptid_t thread_id, void *target_data)
176
{
177
  struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
178
 
179
  memset (new_thread, 0, sizeof (*new_thread));
180
 
181
  new_thread->entry.id = thread_id;
182
 
183
  add_inferior_to_list (&all_threads, & new_thread->entry);
184
 
185
  if (current_inferior == NULL)
186
    current_inferior = new_thread;
187
 
188
  new_thread->target_data = target_data;
189
  set_inferior_regcache_data (new_thread, new_register_cache ());
190
}
191
 
192
ptid_t
193
thread_id_to_gdb_id (ptid_t thread_id)
194
{
195
  struct inferior_list_entry *inf = all_threads.head;
196
 
197
  while (inf != NULL)
198
    {
199
      if (ptid_equal (inf->id, thread_id))
200
        return thread_id;
201
      inf = inf->next;
202
    }
203
 
204
  return null_ptid;
205
}
206
 
207
ptid_t
208
thread_to_gdb_id (struct thread_info *thread)
209
{
210
  return thread->entry.id;
211
}
212
 
213
struct thread_info *
214
find_thread_ptid (ptid_t ptid)
215
{
216
  struct inferior_list_entry *inf = all_threads.head;
217
 
218
  while (inf != NULL)
219
    {
220
      struct thread_info *thread = get_thread (inf);
221
      if (ptid_equal (thread->entry.id, ptid))
222
        return thread;
223
      inf = inf->next;
224
    }
225
 
226
  return NULL;
227
}
228
 
229
ptid_t
230
gdb_id_to_thread_id (ptid_t gdb_id)
231
{
232
  struct thread_info *thread = find_thread_ptid (gdb_id);
233
 
234
  return thread ? thread->entry.id : null_ptid;
235
}
236
 
237
static void
238
free_one_thread (struct inferior_list_entry *inf)
239
{
240
  struct thread_info *thread = get_thread (inf);
241
  free_register_cache (inferior_regcache_data (thread));
242
  free (thread);
243
}
244
 
245
void
246
remove_thread (struct thread_info *thread)
247
{
248
  remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
249
  free_one_thread (&thread->entry);
250
}
251
 
252
/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
253
   returns non-zero.  If no entry is found then return NULL.  */
254
 
255
struct inferior_list_entry *
256
find_inferior (struct inferior_list *list,
257
               int (*func) (struct inferior_list_entry *, void *), void *arg)
258
{
259
  struct inferior_list_entry *inf = list->head;
260
 
261
  while (inf != NULL)
262
    {
263
      struct inferior_list_entry *next;
264
 
265
      next = inf->next;
266
      if ((*func) (inf, arg))
267
        return inf;
268
      inf = next;
269
    }
270
 
271
  return NULL;
272
}
273
 
274
struct inferior_list_entry *
275
find_inferior_id (struct inferior_list *list, ptid_t id)
276
{
277
  struct inferior_list_entry *inf = list->head;
278
 
279
  while (inf != NULL)
280
    {
281
      if (ptid_equal (inf->id, id))
282
        return inf;
283
      inf = inf->next;
284
    }
285
 
286
  return NULL;
287
}
288
 
289
void *
290
inferior_target_data (struct thread_info *inferior)
291
{
292
  return inferior->target_data;
293
}
294
 
295
void
296
set_inferior_target_data (struct thread_info *inferior, void *data)
297
{
298
  inferior->target_data = data;
299
}
300
 
301
void *
302
inferior_regcache_data (struct thread_info *inferior)
303
{
304
  return inferior->regcache_data;
305
}
306
 
307
void
308
set_inferior_regcache_data (struct thread_info *inferior, void *data)
309
{
310
  inferior->regcache_data = data;
311
}
312
 
313
static void
314
free_one_dll (struct inferior_list_entry *inf)
315
{
316
  struct dll_info *dll = get_dll (inf);
317
  if (dll->name != NULL)
318
    free (dll->name);
319
  free (dll);
320
}
321
 
322
/* Find a DLL with the same name and/or base address.  A NULL name in
323
   the key is ignored; so is an all-ones base address.  */
324
 
325
static int
326
match_dll (struct inferior_list_entry *inf, void *arg)
327
{
328
  struct dll_info *iter = (void *) inf;
329
  struct dll_info *key = arg;
330
 
331
  if (key->base_addr != ~(CORE_ADDR) 0
332
      && iter->base_addr == key->base_addr)
333
    return 1;
334
  else if (key->name != NULL
335
           && iter->name != NULL
336
           && strcmp (key->name, iter->name) == 0)
337
    return 1;
338
 
339
  return 0;
340
}
341
 
342
/* Record a newly loaded DLL at BASE_ADDR.  */
343
 
344
void
345
loaded_dll (const char *name, CORE_ADDR base_addr)
346
{
347
  struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
348
  memset (new_dll, 0, sizeof (*new_dll));
349
 
350
  new_dll->entry.id = minus_one_ptid;
351
 
352
  new_dll->name = xstrdup (name);
353
  new_dll->base_addr = base_addr;
354
 
355
  add_inferior_to_list (&all_dlls, &new_dll->entry);
356
  dlls_changed = 1;
357
}
358
 
359
/* Record that the DLL with NAME and BASE_ADDR has been unloaded.  */
360
 
361
void
362
unloaded_dll (const char *name, CORE_ADDR base_addr)
363
{
364
  struct dll_info *dll;
365
  struct dll_info key_dll;
366
 
367
  /* Be careful not to put the key DLL in any list.  */
368
  key_dll.name = (char *) name;
369
  key_dll.base_addr = base_addr;
370
 
371
  dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
372
 
373
  if (dll == NULL)
374
    /* For some inferiors we might get unloaded_dll events without having
375
       a corresponding loaded_dll.  In that case, the dll cannot be found
376
       in ALL_DLL, and there is nothing further for us to do.
377
 
378
       This has been observed when running 32bit executables on Windows64
379
       (i.e. through WOW64, the interface between the 32bits and 64bits
380
       worlds).  In that case, the inferior always does some strange
381
       unloading of unnamed dll.  */
382
    return;
383
  else
384
    {
385
      /* DLL has been found so remove the entry and free associated
386
         resources.  */
387
      remove_inferior (&all_dlls, &dll->entry);
388
      free_one_dll (&dll->entry);
389
      dlls_changed = 1;
390
    }
391
}
392
 
393
#define clear_list(LIST) \
394
  do { (LIST)->head = (LIST)->tail = NULL; } while (0)
395
 
396
void
397
clear_inferiors (void)
398
{
399
  for_each_inferior (&all_threads, free_one_thread);
400
  for_each_inferior (&all_dlls, free_one_dll);
401
 
402
  clear_list (&all_threads);
403
  clear_list (&all_dlls);
404
 
405
  current_inferior = NULL;
406
}
407
 
408
/* Two utility functions for a truly degenerate inferior_list: a simple
409
   PID listing.  */
410
 
411
void
412
add_pid_to_list (struct inferior_list *list, unsigned long pid)
413
{
414
  struct inferior_list_entry *new_entry;
415
 
416
  new_entry = xmalloc (sizeof (struct inferior_list_entry));
417
  new_entry->id = pid_to_ptid (pid);
418
  add_inferior_to_list (list, new_entry);
419
}
420
 
421
int
422
pull_pid_from_list (struct inferior_list *list, unsigned long pid)
423
{
424
  struct inferior_list_entry *new_entry;
425
 
426
  new_entry = find_inferior_id (list, pid_to_ptid (pid));
427
  if (new_entry == NULL)
428
    return 0;
429
  else
430
    {
431
      remove_inferior (list, new_entry);
432
      free (new_entry);
433
      return 1;
434
    }
435
}
436
 
437
struct process_info *
438
add_process (int pid, int attached)
439
{
440
  struct process_info *process;
441
 
442
  process = xcalloc (1, sizeof (*process));
443
 
444
  process->head.id = pid_to_ptid (pid);
445
  process->attached = attached;
446
 
447
  add_inferior_to_list (&all_processes, &process->head);
448
 
449
  return process;
450
}
451
 
452
/* Remove a process from the common process list and free the memory
453
   allocated for it.
454
   The caller is responsible for freeing private data first.  */
455
 
456
void
457
remove_process (struct process_info *process)
458
{
459
  clear_symbol_cache (&process->symbol_cache);
460
  free_all_breakpoints (process);
461
  remove_inferior (&all_processes, &process->head);
462
  free (process);
463
}
464
 
465
struct process_info *
466
find_process_pid (int pid)
467
{
468
  return (struct process_info *)
469
    find_inferior_id (&all_processes, pid_to_ptid (pid));
470
}
471
 
472
/* Return non-zero if INF, a struct process_info, was started by us,
473
   i.e. not attached to.  */
474
 
475
static int
476
started_inferior_callback (struct inferior_list_entry *entry, void *args)
477
{
478
  struct process_info *process = (struct process_info *) entry;
479
 
480
  return ! process->attached;
481
}
482
 
483
/* Return non-zero if there are any inferiors that we have created
484
   (as opposed to attached-to).  */
485
 
486
int
487
have_started_inferiors_p (void)
488
{
489
  return (find_inferior (&all_processes, started_inferior_callback, NULL)
490
          != NULL);
491
}
492
 
493
/* Return non-zero if INF, a struct process_info, was attached to.  */
494
 
495
static int
496
attached_inferior_callback (struct inferior_list_entry *entry, void *args)
497
{
498
  struct process_info *process = (struct process_info *) entry;
499
 
500
  return process->attached;
501
}
502
 
503
/* Return non-zero if there are any inferiors that we have attached to.  */
504
 
505
int
506
have_attached_inferiors_p (void)
507
{
508
  return (find_inferior (&all_processes, attached_inferior_callback, NULL)
509
          != NULL);
510
}
511
 
512
struct process_info *
513
get_thread_process (struct thread_info *thread)
514
{
515
  int pid = ptid_get_pid (thread->entry.id);
516
  return find_process_pid (pid);
517
}
518
 
519
struct process_info *
520
current_process (void)
521
{
522
  if (current_inferior == NULL)
523
    fatal ("Current inferior requested, but current_inferior is NULL\n");
524
 
525
  return get_thread_process (current_inferior);
526
}
527
 
528
void
529
initialize_inferiors (void)
530
{
531
  null_ptid = ptid_build (0, 0, 0);
532
  minus_one_ptid = ptid_build (-1, 0, 0);
533
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.