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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [dec-thread.c] - Blame information for rev 231

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

Line No. Rev Author Line
1 227 jeremybenn
/* Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
2
 
3
   This file is part of GDB.
4
 
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3 of the License, or
8
   (at your option) any later version.
9
 
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
 
15
   You should have received a copy of the GNU General Public License
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
 
18
#include "defs.h"
19
#include "command.h"
20
#include "gdbcmd.h"
21
#include "target.h"
22
#include "observer.h"
23
#include <sys/procfs.h>
24
#include "gregset.h"
25
#include "regcache.h"
26
#include "inferior.h"
27
#include "gdbthread.h"
28
 
29
#include <pthread_debug.h>
30
 
31
/* Print debugging traces if set to non-zero.  */
32
static int debug_dec_thread = 0;
33
 
34
/* Non-zero if the dec-thread layer is active.  */
35
static int dec_thread_active = 0;
36
 
37
/* The pthread_debug context.  */
38
pthreadDebugContext_t debug_context;
39
 
40
/* The dec-thread target_ops structure.  */
41
static struct target_ops dec_thread_ops;
42
 
43
/* Print a debug trace if DEBUG_DEC_THREAD is set (its value is adjusted
44
   by the user using "set debug dec-thread ...").  */
45
 
46
static void
47
debug (char *format, ...)
48
{
49
  if (debug_dec_thread)
50
    {
51
      va_list args;
52
 
53
      va_start (args, format);
54
      printf_unfiltered ("DEC Threads: ");
55
      vprintf_unfiltered (format, args);
56
      printf_unfiltered ("\n");
57
      va_end (args);
58
    }
59
}
60
 
61
/* pthread debug callbacks.  */
62
 
63
static int
64
suspend_clbk (void *caller_context)
65
{
66
  return ESUCCESS;
67
}
68
 
69
static int
70
resume_clbk (void *caller_context)
71
{
72
  return ESUCCESS;
73
}
74
 
75
static int
76
hold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
77
{
78
  return ESUCCESS;
79
}
80
 
81
static int
82
unhold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
83
{
84
  return ESUCCESS;
85
}
86
 
87
static int
88
read_clbk (void *caller_context, void *address, void *buffer,
89
           unsigned long size)
90
{
91
  int status = target_read_memory ((CORE_ADDR) address, buffer, size);
92
 
93
  if (status != 0)
94
    return EINVAL;
95
 
96
  return ESUCCESS;
97
}
98
 
99
static int
100
write_clbk (void *caller_context, void *address, void *buffer,
101
            unsigned long size)
102
{
103
  int status = target_write_memory ((CORE_ADDR) address, buffer, size);
104
 
105
  if (status != 0)
106
    return EINVAL;
107
 
108
  return ESUCCESS;
109
}
110
 
111
/* Get integer regs */
112
 
113
static int
114
get_reg_clbk(void *caller_context, pthreadDebugGetRegRtn_t regs,
115
             pthreadDebugKId_t kernel_tid)
116
{
117
  debug ("get_reg_clbk");
118
 
119
  /* Not sure that we actually need to do anything in this callback.  */
120
  return ESUCCESS;
121
}
122
 
123
/* Set integer regs */
124
 
125
static int
126
set_reg_clbk(void *caller_context, const pthreadDebugRegs_t *regs,
127
             pthreadDebugKId_t kernel_tid)
128
{
129
  debug ("set_reg_clbk");
130
 
131
  /* Not sure that we actually need to do anything in this callback.  */
132
  return ESUCCESS;
133
}
134
 
135
static int
136
output_clbk (void *caller_context, char *line)
137
{
138
  printf_filtered ("%s\n", line);
139
  return ESUCCESS;
140
}
141
 
142
static int
143
error_clbk (void *caller_context, char *line)
144
{
145
  fprintf_filtered (gdb_stderr, "%s\n", line);
146
  return ESUCCESS;
147
}
148
 
149
/* Get floating-point regs.  */
150
 
151
static int
152
get_fpreg_clbk (void *caller_context, pthreadDebugFregs_p fregs,
153
                pthreadDebugKId_t kernel_tid)
154
{
155
  debug ("get_fpreg_clbk");
156
 
157
  /* Not sure that we actually need to do anything in this callback.  */
158
  return ESUCCESS;
159
}
160
 
161
/* Set floating-point regs.  */
162
 
163
static int
164
set_fpreg_clbk (void *caller_context, const pthreadDebugFregs_t *fregs,
165
                pthreadDebugKId_t kernel_tid)
166
{
167
  debug ("set_fpreg_clbk");
168
 
169
  /* Not sure that we actually need to do anything in this callback.  */
170
  return ESUCCESS;
171
}
172
 
173
static void *
174
malloc_clbk (void *caller_context, size_t size)
175
{
176
  return xmalloc (size);
177
}
178
 
179
static void
180
free_clbk (void *caller_context, void *address)
181
{
182
  xfree (address);
183
}
184
 
185
static int
186
kthdinfo_clbk (pthreadDebugClient_t caller_context,
187
               pthreadDebugKId_t kernel_tid,
188
               pthreadDebugKThreadInfo_p thread_info)
189
{
190
  return ENOTSUP;
191
}
192
 
193
static int
194
speckthd_clbk (pthreadDebugClient_t caller_context,
195
               pthreadDebugSpecialType_t type,
196
               pthreadDebugKId_t *kernel_tid)
197
{
198
  return ENOTSUP;
199
}
200
 
201
static pthreadDebugCallbacks_t debug_callbacks =
202
{
203
  PTHREAD_DEBUG_VERSION,
204
  (pthreadDebugGetMemRtn_t) read_clbk,
205
  (pthreadDebugSetMemRtn_t) write_clbk,
206
  suspend_clbk,
207
  resume_clbk,
208
  kthdinfo_clbk,
209
  hold_clbk,
210
  unhold_clbk,
211
  (pthreadDebugGetFregRtn_t) get_fpreg_clbk,
212
  (pthreadDebugSetFregRtn_t) set_fpreg_clbk,
213
  (pthreadDebugGetRegRtn_t) get_reg_clbk,
214
  (pthreadDebugSetRegRtn_t) set_reg_clbk,
215
  (pthreadDebugOutputRtn_t) output_clbk,
216
  (pthreadDebugOutputRtn_t) error_clbk,
217
  malloc_clbk,
218
  free_clbk,
219
  speckthd_clbk
220
};
221
 
222
/* Activate thread support if appropriate.  Do nothing if thread
223
   support is already active.  */
224
 
225
static void
226
enable_dec_thread (void)
227
{
228
  struct minimal_symbol *msym;
229
  void* caller_context;
230
  int status;
231
 
232
  /* If already active, nothing more to do.  */
233
  if (dec_thread_active)
234
    return;
235
 
236
  msym = lookup_minimal_symbol ("__pthread_dbg_symtable", NULL, NULL);
237
  if (msym == NULL)
238
    {
239
      debug ("enable_dec_thread: No __pthread_dbg_symtable");
240
      return;
241
    }
242
 
243
  status = pthreadDebugContextInit (&caller_context, &debug_callbacks,
244
                                    (void *) SYMBOL_VALUE_ADDRESS (msym),
245
                                    &debug_context);
246
  if (status != ESUCCESS)
247
    {
248
      debug ("enable_dec_thread: pthreadDebugContextInit -> %d",
249
             status);
250
      return;
251
    }
252
 
253
  push_target (&dec_thread_ops);
254
  dec_thread_active = 1;
255
 
256
  debug ("enable_dec_thread: Thread support enabled.");
257
}
258
 
259
/* Deactivate thread support.  Do nothing is thread support is
260
   already inactive.  */
261
 
262
static void
263
disable_dec_thread (void)
264
{
265
  if (!dec_thread_active)
266
    return;
267
 
268
  pthreadDebugContextDestroy (debug_context);
269
  unpush_target (&dec_thread_ops);
270
  dec_thread_active = 0;
271
}
272
 
273
/* A structure that contains a thread ID and is associated
274
   pthreadDebugThreadInfo_t data.  */
275
 
276
struct dec_thread_info
277
{
278
  pthreadDebugId_t thread;
279
  pthreadDebugThreadInfo_t info;
280
};
281
typedef struct dec_thread_info dec_thread_info_s;
282
 
283
/* The list of user threads.  */
284
 
285
DEF_VEC_O (dec_thread_info_s);
286
VEC(dec_thread_info_s) *dec_thread_list;
287
 
288
/* Release the memory used by the given VECP thread list pointer.
289
   Then set *VECP to NULL.  */
290
 
291
static void
292
free_dec_thread_info_vec (VEC(dec_thread_info_s) **vecp)
293
{
294
  int i;
295
  struct dec_thread_info *item;
296
  VEC(dec_thread_info_s) *vec = *vecp;
297
 
298
  for (i = 0; VEC_iterate (dec_thread_info_s, vec, i, item); i++)
299
     xfree (item);
300
  VEC_free (dec_thread_info_s, vec);
301
  *vecp = NULL;
302
}
303
 
304
/* Return a thread's ptid given its associated INFO.  */
305
 
306
static ptid_t
307
ptid_build_from_info (struct dec_thread_info info)
308
{
309
  int pid = ptid_get_pid (inferior_ptid);
310
 
311
  return ptid_build (pid, 0, (long) info.thread);
312
}
313
 
314
/* Return non-zero if PTID is still alive.
315
 
316
   Assumes that DEC_THREAD_LIST is up to date.  */
317
static int
318
dec_thread_ptid_is_alive (ptid_t ptid)
319
{
320
  pthreadDebugId_t tid = ptid_get_tid (ptid);
321
  int i;
322
  struct dec_thread_info *info;
323
 
324
  if (tid == 0)
325
    /* This is the thread corresponding to the process.  This ptid
326
       is always alive until the program exits.  */
327
    return 1;
328
 
329
  /* Search whether an entry with the same tid exists in the dec-thread
330
     list of threads.  If it does, then the thread is still alive.
331
     No match found means that the thread must be dead, now.  */
332
  for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
333
    if (info->thread == tid)
334
      return 1;
335
  return 0;
336
}
337
 
338
/* Recompute the list of user threads and store the result in
339
   DEC_THREAD_LIST.  */
340
 
341
static void
342
update_dec_thread_list (void)
343
{
344
  pthreadDebugId_t thread;
345
  pthreadDebugThreadInfo_t info;
346
  int res;
347
 
348
  free_dec_thread_info_vec (&dec_thread_list);
349
  res = pthreadDebugThdSeqInit (debug_context, &thread);
350
  while (res == ESUCCESS)
351
    {
352
 
353
      res = pthreadDebugThdGetInfo (debug_context, thread, &info);
354
      if (res != ESUCCESS)
355
        warning (_("unable to get thread info, ignoring thread %ld"),
356
                   thread);
357
      else if (info.kind == PTHREAD_DEBUG_THD_KIND_INITIAL
358
               || info.kind == PTHREAD_DEBUG_THD_KIND_NORMAL)
359
        {
360
          struct dec_thread_info *item =
361
            xmalloc (sizeof (struct dec_thread_info));
362
 
363
          item->thread = thread;
364
          item->info = info;
365
          VEC_safe_push (dec_thread_info_s, dec_thread_list, item);
366
        }
367
      res = pthreadDebugThdSeqNext (debug_context, &thread);
368
    }
369
  pthreadDebugThdSeqDestroy (debug_context);
370
}
371
 
372
/* A callback to count the number of threads known to GDB.  */
373
 
374
static int
375
dec_thread_count_gdb_threads (struct thread_info *ignored, void *context)
376
{
377
  int *count = (int *) context;
378
 
379
  *count = *count + 1;
380
  return 0;
381
}
382
 
383
/* A callback that saves the given thread INFO at the end of an
384
   array.  The end of the array is given in the CONTEXT and is
385
   incremented once the info has been added.  */
386
 
387
static int
388
dec_thread_add_gdb_thread (struct thread_info *info, void *context)
389
{
390
  struct thread_info ***listp = (struct thread_info ***) context;
391
 
392
  **listp = info;
393
  *listp = *listp + 1;
394
  return 0;
395
}
396
 
397
/* Resynchronize the list of threads known by GDB with the actual
398
   list of threads reported by libpthread_debug.  */
399
 
400
static void
401
resync_thread_list (void)
402
{
403
  int i;
404
  struct dec_thread_info *info;
405
  int num_gdb_threads = 0;
406
  struct thread_info **gdb_thread_list;
407
  struct thread_info **next_thread_info;
408
 
409
  update_dec_thread_list ();
410
 
411
  /* Add new threads.  */
412
 
413
  for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
414
    {
415
      ptid_t ptid = ptid_build_from_info (*info);
416
 
417
      if (!in_thread_list (ptid))
418
        add_thread (ptid);
419
    }
420
 
421
  /* Remove threads that no longer exist.  To help with the search,
422
     we build an array of GDB threads, and then iterate over this
423
     array.  */
424
 
425
  iterate_over_threads (dec_thread_count_gdb_threads,
426
                        (void *) &num_gdb_threads);
427
  gdb_thread_list = alloca (num_gdb_threads * sizeof (struct thread_info *));
428
  next_thread_info = gdb_thread_list;
429
  iterate_over_threads (dec_thread_add_gdb_thread, (void *) &next_thread_info);
430
 
431
  for (i = 0; i < num_gdb_threads; i++)
432
    if (!dec_thread_ptid_is_alive (gdb_thread_list[i]->ptid))
433
      delete_thread (gdb_thread_list[i]->ptid);
434
}
435
 
436
/* The "to_detach" method of the dec_thread_ops.  */
437
 
438
static void
439
dec_thread_detach (struct target_ops *ops, char *args, int from_tty)
440
{
441
  struct target_ops *beneath = find_target_beneath (ops);
442
 
443
  debug ("dec_thread_detach");
444
 
445
  disable_dec_thread ();
446
  beneath->to_detach (beneath, args, from_tty);
447
}
448
 
449
/* Return the ptid of the thread that is currently active.  */
450
 
451
static ptid_t
452
get_active_ptid (void)
453
{
454
  int i;
455
  struct dec_thread_info *info;
456
 
457
  for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
458
       i++)
459
    if (info->info.state == PTHREAD_DEBUG_STATE_RUNNING)
460
      return ptid_build_from_info (*info);
461
 
462
  /* No active thread found.  This can happen when the program
463
     has just exited.  */
464
  return null_ptid;
465
}
466
 
467
/* The "to_wait" method of the dec_thread_ops.  */
468
 
469
static ptid_t
470
dec_thread_wait (struct target_ops *ops,
471
                 ptid_t ptid, struct target_waitstatus *status, int options)
472
{
473
  ptid_t active_ptid;
474
  struct target_ops *beneath = find_target_beneath (ops);
475
 
476
  debug ("dec_thread_wait");
477
 
478
  ptid = beneath->to_wait (beneath, ptid, status, options);
479
 
480
  /* The ptid returned by the target beneath us is the ptid of the process.
481
     We need to find which thread is currently active and return its ptid.  */
482
  resync_thread_list ();
483
  active_ptid = get_active_ptid ();
484
  if (ptid_equal (active_ptid, null_ptid))
485
    return ptid;
486
  return active_ptid;
487
}
488
 
489
/* Fetch the general purpose and floating point registers for the given
490
   thread TID, and store the result in GREGSET and FPREGSET.  Return
491
   zero if successful.  */
492
 
493
static int
494
dec_thread_get_regsets (pthreadDebugId_t tid, gdb_gregset_t *gregset,
495
                        gdb_fpregset_t *fpregset)
496
{
497
  int res;
498
  pthreadDebugRegs_t regs;
499
  pthreadDebugFregs_t fregs;
500
 
501
  res = pthreadDebugThdGetReg (debug_context, tid, &regs);
502
  if (res != ESUCCESS)
503
    {
504
      debug ("dec_thread_get_regsets: pthreadDebugThdGetReg -> %d", res);
505
      return -1;
506
    }
507
  memcpy (gregset->regs, &regs, sizeof (regs));
508
 
509
  res = pthreadDebugThdGetFreg (debug_context, tid, &fregs);
510
  if (res != ESUCCESS)
511
    {
512
      debug ("dec_thread_get_regsets: pthreadDebugThdGetFreg -> %d", res);
513
      return -1;
514
    }
515
  memcpy (fpregset->regs, &fregs, sizeof (fregs));
516
 
517
  return 0;
518
}
519
 
520
/* The "to_fetch_registers" method of the dec_thread_ops.
521
 
522
   Because the dec-thread debug API doesn't allow us to fetch
523
   only one register, we simply ignore regno and fetch+supply all
524
   registers.  */
525
 
526
static void
527
dec_thread_fetch_registers (struct target_ops *ops,
528
                            struct regcache *regcache, int regno)
529
{
530
  pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
531
  gregset_t gregset;
532
  fpregset_t fpregset;
533
  int res;
534
 
535
  debug ("dec_thread_fetch_registers (tid=%ld, regno=%d)", tid, regno);
536
 
537
 
538
  if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
539
    {
540
      struct target_ops *beneath = find_target_beneath (ops);
541
 
542
      beneath->to_fetch_registers (beneath, regcache, regno);
543
      return;
544
    }
545
 
546
  res = dec_thread_get_regsets (tid, &gregset, &fpregset);
547
  if (res != 0)
548
    return;
549
 
550
  supply_gregset (regcache, &gregset);
551
  supply_fpregset (regcache, &fpregset);
552
}
553
 
554
/* Store the registers given in GREGSET and FPREGSET into the associated
555
   general purpose and floating point registers of thread TID.  Return
556
   zero if successful.  */
557
 
558
static int
559
dec_thread_set_regsets (pthreadDebugId_t tid, gdb_gregset_t gregset,
560
                        gdb_fpregset_t fpregset)
561
{
562
  int res;
563
  pthreadDebugRegs_t regs;
564
  pthreadDebugFregs_t fregs;
565
 
566
  memcpy (&regs, gregset.regs, sizeof (regs));
567
  res = pthreadDebugThdSetReg (debug_context, tid, &regs);
568
  if (res != ESUCCESS)
569
    {
570
      debug ("dec_thread_set_regsets: pthreadDebugThdSetReg -> %d", res);
571
      return -1;
572
    }
573
 
574
  memcpy (&fregs, fpregset.regs, sizeof (fregs));
575
  res = pthreadDebugThdSetFreg (debug_context, tid, &fregs);
576
  if (res != ESUCCESS)
577
    {
578
      debug ("dec_thread_set_regsets: pthreadDebugThdSetFreg -> %d", res);
579
      return -1;
580
    }
581
 
582
  return 0;
583
}
584
 
585
/* The "to_store_registers" method of the dec_thread_ops.
586
 
587
   Because the dec-thread debug API doesn't allow us to store
588
   just one register, we store all the registers.  */
589
 
590
static void
591
dec_thread_store_registers (struct target_ops *ops,
592
                            struct regcache *regcache, int regno)
593
{
594
  pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
595
  gregset_t gregset;
596
  fpregset_t fpregset;
597
  int res;
598
 
599
  debug ("dec_thread_store_registers (tid=%ld, regno=%d)", tid, regno);
600
 
601
  if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
602
    {
603
      struct target_ops *beneath = find_target_beneath (ops);
604
 
605
      beneath->to_store_registers (beneath, regcache, regno);
606
      return;
607
    }
608
 
609
  /* FIXME: brobecker/2008-05-28: I wonder if we could simply check
610
     in which register set the register is and then only store the
611
     registers for that register set, instead of storing both register
612
     sets.  */
613
  fill_gregset (regcache, &gregset, -1);
614
  fill_fpregset (regcache, &fpregset, -1);
615
 
616
  res = dec_thread_set_regsets (tid, gregset, fpregset);
617
  if (res != 0)
618
    warning (_("failed to store registers."));
619
}
620
 
621
/* The "to_mourn_inferior" method of the dec_thread_ops.  */
622
 
623
static void
624
dec_thread_mourn_inferior (struct target_ops *ops)
625
{
626
  struct target_ops *beneath = find_target_beneath (ops);
627
 
628
  debug ("dec_thread_mourn_inferior");
629
 
630
  disable_dec_thread ();
631
  beneath->to_mourn_inferior (beneath);
632
}
633
 
634
/* The "to_thread_alive" method of the dec_thread_ops.  */
635
static int
636
dec_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
637
{
638
  debug ("dec_thread_thread_alive (tid=%ld)", ptid_get_tid (ptid));
639
 
640
  /* The thread list maintained by GDB is up to date, since we update
641
     it everytime we stop.   So check this list.  */
642
  return in_thread_list (ptid);
643
}
644
 
645
/* The "to_pid_to_str" method of the dec_thread_ops.  */
646
 
647
static char *
648
dec_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
649
{
650
  static char *ret = NULL;
651
 
652
  if (ptid_get_tid (ptid) == 0)
653
    {
654
      struct target_ops *beneath = find_target_beneath (ops);
655
 
656
      return beneath->to_pid_to_str (beneath, ptid);
657
    }
658
 
659
  /* Free previous return value; a new one will be allocated by
660
     xstrprintf().  */
661
  xfree (ret);
662
 
663
  ret = xstrprintf (_("Thread %ld"), ptid_get_tid (ptid));
664
  return ret;
665
}
666
 
667
/* A "new-objfile" observer.  Used to activate/deactivate dec-thread
668
   support.  */
669
 
670
static void
671
dec_thread_new_objfile_observer (struct objfile *objfile)
672
{
673
  if (objfile != NULL)
674
     enable_dec_thread ();
675
  else
676
     disable_dec_thread ();
677
}
678
 
679
/* The "to_get_ada_task_ptid" method of the dec_thread_ops.  */
680
 
681
static ptid_t
682
dec_thread_get_ada_task_ptid (long lwp, long thread)
683
{
684
  int i;
685
  struct dec_thread_info *info;
686
 
687
  debug ("dec_thread_get_ada_task_ptid (lwp=0x%lx, thread=0x%lx)",
688
         lwp, thread);
689
 
690
  for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
691
       i++)
692
    if (info->info.teb == (pthread_t) thread)
693
      return ptid_build_from_info (*info);
694
 
695
  warning (_("Could not find thread id from THREAD = 0x%lx\n"), thread);
696
  return inferior_ptid;
697
}
698
 
699
static void
700
init_dec_thread_ops (void)
701
{
702
  dec_thread_ops.to_shortname          = "dec-threads";
703
  dec_thread_ops.to_longname           = _("DEC threads support");
704
  dec_thread_ops.to_doc                = _("DEC threads support");
705
  dec_thread_ops.to_detach             = dec_thread_detach;
706
  dec_thread_ops.to_wait               = dec_thread_wait;
707
  dec_thread_ops.to_fetch_registers    = dec_thread_fetch_registers;
708
  dec_thread_ops.to_store_registers    = dec_thread_store_registers;
709
  dec_thread_ops.to_mourn_inferior     = dec_thread_mourn_inferior;
710
  dec_thread_ops.to_thread_alive       = dec_thread_thread_alive;
711
  dec_thread_ops.to_pid_to_str         = dec_thread_pid_to_str;
712
  dec_thread_ops.to_stratum            = thread_stratum;
713
  dec_thread_ops.to_get_ada_task_ptid  = dec_thread_get_ada_task_ptid;
714
  dec_thread_ops.to_magic              = OPS_MAGIC;
715
}
716
 
717
void
718
_initialize_dec_thread (void)
719
{
720
  init_dec_thread_ops ();
721
  add_target (&dec_thread_ops);
722
 
723
  observer_attach_new_objfile (dec_thread_new_objfile_observer);
724
 
725
  add_setshow_boolean_cmd ("dec-thread", class_maintenance, &debug_dec_thread,
726
                            _("Set debugging of DEC threads module."),
727
                            _("Show debugging of DEC threads module."),
728
                            _("Enables debugging output (used to debug GDB)."),
729
                            NULL, NULL,
730
                            &setdebuglist, &showdebuglist);
731
}

powered by: WebSVN 2.1.0

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