OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [solib-frv.c] - Blame information for rev 607

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

Line No. Rev Author Line
1 24 jeremybenn
/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
2
   Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
 
19
 
20
#include "defs.h"
21
#include "gdb_string.h"
22
#include "inferior.h"
23
#include "gdbcore.h"
24
#include "solib.h"
25
#include "solist.h"
26
#include "frv-tdep.h"
27
#include "objfiles.h"
28
#include "symtab.h"
29
#include "language.h"
30
#include "command.h"
31
#include "gdbcmd.h"
32
#include "elf/frv.h"
33
 
34
/* Flag which indicates whether internal debug messages should be printed.  */
35
static int solib_frv_debug;
36
 
37
/* FR-V pointers are four bytes wide.  */
38
enum { FRV_PTR_SIZE = 4 };
39
 
40
/* Representation of loadmap and related structs for the FR-V FDPIC ABI.  */
41
 
42
/* External versions; the size and alignment of the fields should be
43
   the same as those on the target.  When loaded, the placement of
44
   the bits in each field will be the same as on the target.  */
45
typedef gdb_byte ext_Elf32_Half[2];
46
typedef gdb_byte ext_Elf32_Addr[4];
47
typedef gdb_byte ext_Elf32_Word[4];
48
 
49
struct ext_elf32_fdpic_loadseg
50
{
51
  /* Core address to which the segment is mapped.  */
52
  ext_Elf32_Addr addr;
53
  /* VMA recorded in the program header.  */
54
  ext_Elf32_Addr p_vaddr;
55
  /* Size of this segment in memory.  */
56
  ext_Elf32_Word p_memsz;
57
};
58
 
59
struct ext_elf32_fdpic_loadmap {
60
  /* Protocol version number, must be zero.  */
61
  ext_Elf32_Half version;
62
  /* Number of segments in this map.  */
63
  ext_Elf32_Half nsegs;
64
  /* The actual memory map.  */
65
  struct ext_elf32_fdpic_loadseg segs[1 /* nsegs, actually */];
66
};
67
 
68
/* Internal versions; the types are GDB types and the data in each
69
   of the fields is (or will be) decoded from the external struct
70
   for ease of consumption.  */
71
struct int_elf32_fdpic_loadseg
72
{
73
  /* Core address to which the segment is mapped.  */
74
  CORE_ADDR addr;
75
  /* VMA recorded in the program header.  */
76
  CORE_ADDR p_vaddr;
77
  /* Size of this segment in memory.  */
78
  long p_memsz;
79
};
80
 
81
struct int_elf32_fdpic_loadmap {
82
  /* Protocol version number, must be zero.  */
83
  int version;
84
  /* Number of segments in this map.  */
85
  int nsegs;
86
  /* The actual memory map.  */
87
  struct int_elf32_fdpic_loadseg segs[1 /* nsegs, actually */];
88
};
89
 
90
/* Given address LDMADDR, fetch and decode the loadmap at that address.
91
   Return NULL if there is a problem reading the target memory or if
92
   there doesn't appear to be a loadmap at the given address.  The
93
   allocated space (representing the loadmap) returned by this
94
   function may be freed via a single call to xfree().  */
95
 
96
static struct int_elf32_fdpic_loadmap *
97
fetch_loadmap (CORE_ADDR ldmaddr)
98
{
99
  struct ext_elf32_fdpic_loadmap ext_ldmbuf_partial;
100
  struct ext_elf32_fdpic_loadmap *ext_ldmbuf;
101
  struct int_elf32_fdpic_loadmap *int_ldmbuf;
102
  int ext_ldmbuf_size, int_ldmbuf_size;
103
  int version, seg, nsegs;
104
 
105
  /* Fetch initial portion of the loadmap.  */
106
  if (target_read_memory (ldmaddr, (gdb_byte *) &ext_ldmbuf_partial,
107
                          sizeof ext_ldmbuf_partial))
108
    {
109
      /* Problem reading the target's memory.  */
110
      return NULL;
111
    }
112
 
113
  /* Extract the version.  */
114
  version = extract_unsigned_integer (ext_ldmbuf_partial.version,
115
                                      sizeof ext_ldmbuf_partial.version);
116
  if (version != 0)
117
    {
118
      /* We only handle version 0.  */
119
      return NULL;
120
    }
121
 
122
  /* Extract the number of segments.  */
123
  nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs,
124
                                    sizeof ext_ldmbuf_partial.nsegs);
125
 
126
  /* Allocate space for the complete (external) loadmap.  */
127
  ext_ldmbuf_size = sizeof (struct ext_elf32_fdpic_loadmap)
128
               + (nsegs - 1) * sizeof (struct ext_elf32_fdpic_loadseg);
129
  ext_ldmbuf = xmalloc (ext_ldmbuf_size);
130
 
131
  /* Copy over the portion of the loadmap that's already been read.  */
132
  memcpy (ext_ldmbuf, &ext_ldmbuf_partial, sizeof ext_ldmbuf_partial);
133
 
134
  /* Read the rest of the loadmap from the target.  */
135
  if (target_read_memory (ldmaddr + sizeof ext_ldmbuf_partial,
136
                          (gdb_byte *) ext_ldmbuf + sizeof ext_ldmbuf_partial,
137
                          ext_ldmbuf_size - sizeof ext_ldmbuf_partial))
138
    {
139
      /* Couldn't read rest of the loadmap.  */
140
      xfree (ext_ldmbuf);
141
      return NULL;
142
    }
143
 
144
  /* Allocate space into which to put information extract from the
145
     external loadsegs.  I.e, allocate the internal loadsegs.  */
146
  int_ldmbuf_size = sizeof (struct int_elf32_fdpic_loadmap)
147
               + (nsegs - 1) * sizeof (struct int_elf32_fdpic_loadseg);
148
  int_ldmbuf = xmalloc (int_ldmbuf_size);
149
 
150
  /* Place extracted information in internal structs.  */
151
  int_ldmbuf->version = version;
152
  int_ldmbuf->nsegs = nsegs;
153
  for (seg = 0; seg < nsegs; seg++)
154
    {
155
      int_ldmbuf->segs[seg].addr
156
        = extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
157
                                    sizeof (ext_ldmbuf->segs[seg].addr));
158
      int_ldmbuf->segs[seg].p_vaddr
159
        = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
160
                                    sizeof (ext_ldmbuf->segs[seg].p_vaddr));
161
      int_ldmbuf->segs[seg].p_memsz
162
        = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
163
                                    sizeof (ext_ldmbuf->segs[seg].p_memsz));
164
    }
165
 
166
  xfree (ext_ldmbuf);
167
  return int_ldmbuf;
168
}
169
 
170
/* External link_map and elf32_fdpic_loadaddr struct definitions.  */
171
 
172
typedef gdb_byte ext_ptr[4];
173
 
174
struct ext_elf32_fdpic_loadaddr
175
{
176
  ext_ptr map;                  /* struct elf32_fdpic_loadmap *map; */
177
  ext_ptr got_value;            /* void *got_value; */
178
};
179
 
180
struct ext_link_map
181
{
182
  struct ext_elf32_fdpic_loadaddr l_addr;
183
 
184
  /* Absolute file name object was found in.  */
185
  ext_ptr l_name;               /* char *l_name; */
186
 
187
  /* Dynamic section of the shared object.  */
188
  ext_ptr l_ld;                 /* ElfW(Dyn) *l_ld; */
189
 
190
  /* Chain of loaded objects.  */
191
  ext_ptr l_next, l_prev;       /* struct link_map *l_next, *l_prev; */
192
};
193
 
194
/* Link map info to include in an allocated so_list entry */
195
 
196
struct lm_info
197
  {
198
    /* The loadmap, digested into an easier to use form.  */
199
    struct int_elf32_fdpic_loadmap *map;
200
    /* The GOT address for this link map entry.  */
201
    CORE_ADDR got_value;
202
    /* The link map address, needed for frv_fetch_objfile_link_map().  */
203
    CORE_ADDR lm_addr;
204
 
205
    /* Cached dynamic symbol table and dynamic relocs initialized and
206
       used only by find_canonical_descriptor_in_load_object().
207
 
208
       Note: kevinb/2004-02-26: It appears that calls to
209
       bfd_canonicalize_dynamic_reloc() will use the same symbols as
210
       those supplied to the first call to this function.  Therefore,
211
       it's important to NOT free the asymbol ** data structure
212
       supplied to the first call.  Thus the caching of the dynamic
213
       symbols (dyn_syms) is critical for correct operation.  The
214
       caching of the dynamic relocations could be dispensed with.  */
215
    asymbol **dyn_syms;
216
    arelent **dyn_relocs;
217
    int dyn_reloc_count;        /* number of dynamic relocs.  */
218
 
219
  };
220
 
221
/* The load map, got value, etc. are not available from the chain
222
   of loaded shared objects.  ``main_executable_lm_info'' provides
223
   a way to get at this information so that it doesn't need to be
224
   frequently recomputed.  Initialized by frv_relocate_main_executable().  */
225
static struct lm_info *main_executable_lm_info;
226
 
227
static void frv_relocate_main_executable (void);
228
static CORE_ADDR main_got (void);
229
static int enable_break2 (void);
230
 
231
/*
232
 
233
   LOCAL FUNCTION
234
 
235
   bfd_lookup_symbol -- lookup the value for a specific symbol
236
 
237
   SYNOPSIS
238
 
239
   CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
240
 
241
   DESCRIPTION
242
 
243
   An expensive way to lookup the value of a single symbol for
244
   bfd's that are only temporary anyway.  This is used by the
245
   shared library support to find the address of the debugger
246
   interface structures in the shared library.
247
 
248
   Note that 0 is specifically allowed as an error return (no
249
   such symbol).
250
 */
251
 
252
static CORE_ADDR
253
bfd_lookup_symbol (bfd *abfd, char *symname)
254
{
255
  long storage_needed;
256
  asymbol *sym;
257
  asymbol **symbol_table;
258
  unsigned int number_of_symbols;
259
  unsigned int i;
260
  struct cleanup *back_to;
261
  CORE_ADDR symaddr = 0;
262
 
263
  storage_needed = bfd_get_symtab_upper_bound (abfd);
264
 
265
  if (storage_needed > 0)
266
    {
267
      symbol_table = (asymbol **) xmalloc (storage_needed);
268
      back_to = make_cleanup (xfree, symbol_table);
269
      number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
270
 
271
      for (i = 0; i < number_of_symbols; i++)
272
        {
273
          sym = *symbol_table++;
274
          if (strcmp (sym->name, symname) == 0)
275
            {
276
              /* Bfd symbols are section relative. */
277
              symaddr = sym->value + sym->section->vma;
278
              break;
279
            }
280
        }
281
      do_cleanups (back_to);
282
    }
283
 
284
  if (symaddr)
285
    return symaddr;
286
 
287
  /* Look for the symbol in the dynamic string table too.  */
288
 
289
  storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
290
 
291
  if (storage_needed > 0)
292
    {
293
      symbol_table = (asymbol **) xmalloc (storage_needed);
294
      back_to = make_cleanup (xfree, symbol_table);
295
      number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table);
296
 
297
      for (i = 0; i < number_of_symbols; i++)
298
        {
299
          sym = *symbol_table++;
300
          if (strcmp (sym->name, symname) == 0)
301
            {
302
              /* Bfd symbols are section relative. */
303
              symaddr = sym->value + sym->section->vma;
304
              break;
305
            }
306
        }
307
      do_cleanups (back_to);
308
    }
309
 
310
  return symaddr;
311
}
312
 
313
 
314
/*
315
 
316
  LOCAL FUNCTION
317
 
318
  open_symbol_file_object
319
 
320
  SYNOPSIS
321
 
322
  void open_symbol_file_object (void *from_tty)
323
 
324
  DESCRIPTION
325
 
326
  If no open symbol file, attempt to locate and open the main symbol
327
  file.
328
 
329
  If FROM_TTYP dereferences to a non-zero integer, allow messages to
330
  be printed.  This parameter is a pointer rather than an int because
331
  open_symbol_file_object() is called via catch_errors() and
332
  catch_errors() requires a pointer argument. */
333
 
334
static int
335
open_symbol_file_object (void *from_ttyp)
336
{
337
  /* Unimplemented.  */
338
  return 0;
339
}
340
 
341
/* Cached value for lm_base(), below.  */
342
static CORE_ADDR lm_base_cache = 0;
343
 
344
/* Link map address for main module.  */
345
static CORE_ADDR main_lm_addr = 0;
346
 
347
/* Return the address from which the link map chain may be found.  On
348
   the FR-V, this may be found in a number of ways.  Assuming that the
349
   main executable has already been relocated, the easiest way to find
350
   this value is to look up the address of _GLOBAL_OFFSET_TABLE_.  A
351
   pointer to the start of the link map will be located at the word found
352
   at _GLOBAL_OFFSET_TABLE_ + 8.  (This is part of the dynamic linker
353
   reserve area mandated by the ABI.)  */
354
 
355
static CORE_ADDR
356
lm_base (void)
357
{
358
  struct minimal_symbol *got_sym;
359
  CORE_ADDR addr;
360
  gdb_byte buf[FRV_PTR_SIZE];
361
 
362
  /* One of our assumptions is that the main executable has been relocated.
363
     Bail out if this has not happened.  (Note that post_create_inferior()
364
     in infcmd.c will call solib_add prior to solib_create_inferior_hook().
365
     If we allow this to happen, lm_base_cache will be initialized with
366
     a bogus value.  */
367
  if (main_executable_lm_info == 0)
368
    return 0;
369
 
370
  /* If we already have a cached value, return it.  */
371
  if (lm_base_cache)
372
    return lm_base_cache;
373
 
374
  got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
375
                                   symfile_objfile);
376
  if (got_sym == 0)
377
    {
378
      if (solib_frv_debug)
379
        fprintf_unfiltered (gdb_stdlog,
380
                            "lm_base: _GLOBAL_OFFSET_TABLE_ not found.\n");
381
      return 0;
382
    }
383
 
384
  addr = SYMBOL_VALUE_ADDRESS (got_sym) + 8;
385
 
386
  if (solib_frv_debug)
387
    fprintf_unfiltered (gdb_stdlog,
388
                        "lm_base: _GLOBAL_OFFSET_TABLE_ + 8 = %s\n",
389
                        hex_string_custom (addr, 8));
390
 
391
  if (target_read_memory (addr, buf, sizeof buf) != 0)
392
    return 0;
393
  lm_base_cache = extract_unsigned_integer (buf, sizeof buf);
394
 
395
  if (solib_frv_debug)
396
    fprintf_unfiltered (gdb_stdlog,
397
                        "lm_base: lm_base_cache = %s\n",
398
                        hex_string_custom (lm_base_cache, 8));
399
 
400
  return lm_base_cache;
401
}
402
 
403
 
404
/* LOCAL FUNCTION
405
 
406
   frv_current_sos -- build a list of currently loaded shared objects
407
 
408
   SYNOPSIS
409
 
410
   struct so_list *frv_current_sos ()
411
 
412
   DESCRIPTION
413
 
414
   Build a list of `struct so_list' objects describing the shared
415
   objects currently loaded in the inferior.  This list does not
416
   include an entry for the main executable file.
417
 
418
   Note that we only gather information directly available from the
419
   inferior --- we don't examine any of the shared library files
420
   themselves.  The declaration of `struct so_list' says which fields
421
   we provide values for.  */
422
 
423
static struct so_list *
424
frv_current_sos (void)
425
{
426
  CORE_ADDR lm_addr, mgot;
427
  struct so_list *sos_head = NULL;
428
  struct so_list **sos_next_ptr = &sos_head;
429
 
430
  /* Make sure that the main executable has been relocated.  This is
431
     required in order to find the address of the global offset table,
432
     which in turn is used to find the link map info.  (See lm_base()
433
     for details.)
434
 
435
     Note that the relocation of the main executable is also performed
436
     by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core
437
     files, this hook is called too late in order to be of benefit to
438
     SOLIB_ADD.  SOLIB_ADD eventually calls this this function,
439
     frv_current_sos, and also precedes the call to
440
     SOLIB_CREATE_INFERIOR_HOOK().   (See post_create_inferior() in
441
     infcmd.c.)  */
442
  if (main_executable_lm_info == 0 && core_bfd != NULL)
443
    frv_relocate_main_executable ();
444
 
445
  /* Fetch the GOT corresponding to the main executable.  */
446
  mgot = main_got ();
447
 
448
  /* Locate the address of the first link map struct.  */
449
  lm_addr = lm_base ();
450
 
451
  /* We have at least one link map entry.  Fetch the the lot of them,
452
     building the solist chain.  */
453
  while (lm_addr)
454
    {
455
      struct ext_link_map lm_buf;
456
      CORE_ADDR got_addr;
457
 
458
      if (solib_frv_debug)
459
        fprintf_unfiltered (gdb_stdlog,
460
                            "current_sos: reading link_map entry at %s\n",
461
                            hex_string_custom (lm_addr, 8));
462
 
463
      if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf, sizeof (lm_buf)) != 0)
464
        {
465
          warning (_("frv_current_sos: Unable to read link map entry.  Shared object chain may be incomplete."));
466
          break;
467
        }
468
 
469
      got_addr
470
        = extract_unsigned_integer (lm_buf.l_addr.got_value,
471
                                    sizeof (lm_buf.l_addr.got_value));
472
      /* If the got_addr is the same as mgotr, then we're looking at the
473
         entry for the main executable.  By convention, we don't include
474
         this in the list of shared objects.  */
475
      if (got_addr != mgot)
476
        {
477
          int errcode;
478
          char *name_buf;
479
          struct int_elf32_fdpic_loadmap *loadmap;
480
          struct so_list *sop;
481
          CORE_ADDR addr;
482
 
483
          /* Fetch the load map address.  */
484
          addr = extract_unsigned_integer (lm_buf.l_addr.map,
485
                                           sizeof lm_buf.l_addr.map);
486
          loadmap = fetch_loadmap (addr);
487
          if (loadmap == NULL)
488
            {
489
              warning (_("frv_current_sos: Unable to fetch load map.  Shared object chain may be incomplete."));
490
              break;
491
            }
492
 
493
          sop = xcalloc (1, sizeof (struct so_list));
494
          sop->lm_info = xcalloc (1, sizeof (struct lm_info));
495
          sop->lm_info->map = loadmap;
496
          sop->lm_info->got_value = got_addr;
497
          sop->lm_info->lm_addr = lm_addr;
498
          /* Fetch the name.  */
499
          addr = extract_unsigned_integer (lm_buf.l_name,
500
                                           sizeof (lm_buf.l_name));
501
          target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
502
                              &errcode);
503
 
504
          if (solib_frv_debug)
505
            fprintf_unfiltered (gdb_stdlog, "current_sos: name = %s\n",
506
                                name_buf);
507
 
508
          if (errcode != 0)
509
            warning (_("Can't read pathname for link map entry: %s."),
510
                     safe_strerror (errcode));
511
          else
512
            {
513
              strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1);
514
              sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
515
              xfree (name_buf);
516
              strcpy (sop->so_original_name, sop->so_name);
517
            }
518
 
519
          *sos_next_ptr = sop;
520
          sos_next_ptr = &sop->next;
521
        }
522
      else
523
        {
524
          main_lm_addr = lm_addr;
525
        }
526
 
527
      lm_addr = extract_unsigned_integer (lm_buf.l_next, sizeof (lm_buf.l_next));
528
    }
529
 
530
  enable_break2 ();
531
 
532
  return sos_head;
533
}
534
 
535
 
536
/* Return 1 if PC lies in the dynamic symbol resolution code of the
537
   run time loader.  */
538
 
539
static CORE_ADDR interp_text_sect_low;
540
static CORE_ADDR interp_text_sect_high;
541
static CORE_ADDR interp_plt_sect_low;
542
static CORE_ADDR interp_plt_sect_high;
543
 
544
static int
545
frv_in_dynsym_resolve_code (CORE_ADDR pc)
546
{
547
  return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
548
          || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
549
          || in_plt_section (pc, NULL));
550
}
551
 
552
/* Given a loadmap and an address, return the displacement needed
553
   to relocate the address.  */
554
 
555
CORE_ADDR
556
displacement_from_map (struct int_elf32_fdpic_loadmap *map,
557
                       CORE_ADDR addr)
558
{
559
  int seg;
560
 
561
  for (seg = 0; seg < map->nsegs; seg++)
562
    {
563
      if (map->segs[seg].p_vaddr <= addr
564
          && addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
565
        {
566
          return map->segs[seg].addr - map->segs[seg].p_vaddr;
567
        }
568
    }
569
 
570
  return 0;
571
}
572
 
573
/* Print a warning about being unable to set the dynamic linker
574
   breakpoint.  */
575
 
576
static void
577
enable_break_failure_warning (void)
578
{
579
  warning (_("Unable to find dynamic linker breakpoint function.\n"
580
           "GDB will be unable to debug shared library initializers\n"
581
           "and track explicitly loaded dynamic code."));
582
}
583
 
584
/*
585
 
586
   LOCAL FUNCTION
587
 
588
   enable_break -- arrange for dynamic linker to hit breakpoint
589
 
590
   SYNOPSIS
591
 
592
   int enable_break (void)
593
 
594
   DESCRIPTION
595
 
596
   The dynamic linkers has, as part of its debugger interface, support
597
   for arranging for the inferior to hit a breakpoint after mapping in
598
   the shared libraries.  This function enables that breakpoint.
599
 
600
   On the FR-V, using the shared library (FDPIC) ABI, the symbol
601
   _dl_debug_addr points to the r_debug struct which contains
602
   a field called r_brk.  r_brk is the address of the function
603
   descriptor upon which a breakpoint must be placed.  Being a
604
   function descriptor, we must extract the entry point in order
605
   to set the breakpoint.
606
 
607
   Our strategy will be to get the .interp section from the
608
   executable.  This section will provide us with the name of the
609
   interpreter.  We'll open the interpreter and then look up
610
   the address of _dl_debug_addr.  We then relocate this address
611
   using the interpreter's loadmap.  Once the relocated address
612
   is known, we fetch the value (address) corresponding to r_brk
613
   and then use that value to fetch the entry point of the function
614
   we're interested in.
615
 
616
 */
617
 
618
static int enable_break1_done = 0;
619
static int enable_break2_done = 0;
620
 
621
static int
622
enable_break2 (void)
623
{
624
  int success = 0;
625
  char **bkpt_namep;
626
  asection *interp_sect;
627
 
628
  if (!enable_break1_done || enable_break2_done)
629
    return 1;
630
 
631
  enable_break2_done = 1;
632
 
633
  /* First, remove all the solib event breakpoints.  Their addresses
634
     may have changed since the last time we ran the program.  */
635
  remove_solib_event_breakpoints ();
636
 
637
  interp_text_sect_low = interp_text_sect_high = 0;
638
  interp_plt_sect_low = interp_plt_sect_high = 0;
639
 
640
  /* Find the .interp section; if not found, warn the user and drop
641
     into the old breakpoint at symbol code.  */
642
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
643
  if (interp_sect)
644
    {
645
      unsigned int interp_sect_size;
646
      gdb_byte *buf;
647
      bfd *tmp_bfd = NULL;
648
      int tmp_fd = -1;
649
      char *tmp_pathname = NULL;
650
      int status;
651
      CORE_ADDR addr, interp_loadmap_addr;
652
      gdb_byte addr_buf[FRV_PTR_SIZE];
653
      struct int_elf32_fdpic_loadmap *ldm;
654
 
655
      /* Read the contents of the .interp section into a local buffer;
656
         the contents specify the dynamic linker this program uses.  */
657
      interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
658
      buf = alloca (interp_sect_size);
659
      bfd_get_section_contents (exec_bfd, interp_sect,
660
                                buf, 0, interp_sect_size);
661
 
662
      /* Now we need to figure out where the dynamic linker was
663
         loaded so that we can load its symbols and place a breakpoint
664
         in the dynamic linker itself.
665
 
666
         This address is stored on the stack.  However, I've been unable
667
         to find any magic formula to find it for Solaris (appears to
668
         be trivial on GNU/Linux).  Therefore, we have to try an alternate
669
         mechanism to find the dynamic linker's base address.  */
670
 
671
      tmp_fd  = solib_open (buf, &tmp_pathname);
672
      if (tmp_fd >= 0)
673
        tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd);
674
 
675
      if (tmp_bfd == NULL)
676
        {
677
          enable_break_failure_warning ();
678
          return 0;
679
        }
680
 
681
      /* Make sure the dynamic linker is really a useful object.  */
682
      if (!bfd_check_format (tmp_bfd, bfd_object))
683
        {
684
          warning (_("Unable to grok dynamic linker %s as an object file"), buf);
685
          enable_break_failure_warning ();
686
          bfd_close (tmp_bfd);
687
          return 0;
688
        }
689
 
690
      status = frv_fdpic_loadmap_addresses (current_gdbarch,
691
                                            &interp_loadmap_addr, 0);
692
      if (status < 0)
693
        {
694
          warning (_("Unable to determine dynamic linker loadmap address."));
695
          enable_break_failure_warning ();
696
          bfd_close (tmp_bfd);
697
          return 0;
698
        }
699
 
700
      if (solib_frv_debug)
701
        fprintf_unfiltered (gdb_stdlog,
702
                            "enable_break: interp_loadmap_addr = %s\n",
703
                            hex_string_custom (interp_loadmap_addr, 8));
704
 
705
      ldm = fetch_loadmap (interp_loadmap_addr);
706
      if (ldm == NULL)
707
        {
708
          warning (_("Unable to load dynamic linker loadmap at address %s."),
709
                   hex_string_custom (interp_loadmap_addr, 8));
710
          enable_break_failure_warning ();
711
          bfd_close (tmp_bfd);
712
          return 0;
713
        }
714
 
715
      /* Record the relocated start and end address of the dynamic linker
716
         text and plt section for svr4_in_dynsym_resolve_code.  */
717
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
718
      if (interp_sect)
719
        {
720
          interp_text_sect_low
721
            = bfd_section_vma (tmp_bfd, interp_sect);
722
          interp_text_sect_low
723
            += displacement_from_map (ldm, interp_text_sect_low);
724
          interp_text_sect_high
725
            = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
726
        }
727
      interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
728
      if (interp_sect)
729
        {
730
          interp_plt_sect_low =
731
            bfd_section_vma (tmp_bfd, interp_sect);
732
          interp_plt_sect_low
733
            += displacement_from_map (ldm, interp_plt_sect_low);
734
          interp_plt_sect_high =
735
            interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
736
        }
737
 
738
      addr = bfd_lookup_symbol (tmp_bfd, "_dl_debug_addr");
739
      if (addr == 0)
740
        {
741
          warning (_("Could not find symbol _dl_debug_addr in dynamic linker"));
742
          enable_break_failure_warning ();
743
          bfd_close (tmp_bfd);
744
          return 0;
745
        }
746
 
747
      if (solib_frv_debug)
748
        fprintf_unfiltered (gdb_stdlog,
749
                            "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
750
                            hex_string_custom (addr, 8));
751
 
752
      addr += displacement_from_map (ldm, addr);
753
 
754
      if (solib_frv_debug)
755
        fprintf_unfiltered (gdb_stdlog,
756
                            "enable_break: _dl_debug_addr (after relocation) = %s\n",
757
                            hex_string_custom (addr, 8));
758
 
759
      /* Fetch the address of the r_debug struct.  */
760
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
761
        {
762
          warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"),
763
                   hex_string_custom (addr, 8));
764
        }
765
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
766
 
767
      /* Fetch the r_brk field.  It's 8 bytes from the start of
768
         _dl_debug_addr.  */
769
      if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
770
        {
771
          warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"),
772
                   hex_string_custom (addr + 8, 8));
773
          enable_break_failure_warning ();
774
          bfd_close (tmp_bfd);
775
          return 0;
776
        }
777
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
778
 
779
      /* Now fetch the function entry point.  */
780
      if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
781
        {
782
          warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"),
783
                   hex_string_custom (addr, 8));
784
          enable_break_failure_warning ();
785
          bfd_close (tmp_bfd);
786
          return 0;
787
        }
788
      addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
789
 
790
      /* We're done with the temporary bfd.  */
791
      bfd_close (tmp_bfd);
792
 
793
      /* We're also done with the loadmap.  */
794
      xfree (ldm);
795
 
796
      /* Now (finally!) create the solib breakpoint.  */
797
      create_solib_event_breakpoint (addr);
798
 
799
      return 1;
800
    }
801
 
802
  /* Tell the user we couldn't set a dynamic linker breakpoint.  */
803
  enable_break_failure_warning ();
804
 
805
  /* Failure return.  */
806
  return 0;
807
}
808
 
809
static int
810
enable_break (void)
811
{
812
  asection *interp_sect;
813
 
814
  /* Remove all the solib event breakpoints.  Their addresses
815
     may have changed since the last time we ran the program.  */
816
  remove_solib_event_breakpoints ();
817
 
818
  /* Check for the presence of a .interp section.  If there is no
819
     such section, the executable is statically linked.  */
820
 
821
  interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
822
 
823
  if (interp_sect)
824
    {
825
      enable_break1_done = 1;
826
      create_solib_event_breakpoint (symfile_objfile->ei.entry_point);
827
 
828
      if (solib_frv_debug)
829
        fprintf_unfiltered (gdb_stdlog,
830
                            "enable_break: solib event breakpoint placed at entry point: %s\n",
831
                            hex_string_custom
832
                              (symfile_objfile->ei.entry_point, 8));
833
    }
834
  else
835
    {
836
      if (solib_frv_debug)
837
        fprintf_unfiltered (gdb_stdlog,
838
                            "enable_break: No .interp section found.\n");
839
    }
840
 
841
  return 1;
842
}
843
 
844
/*
845
 
846
   LOCAL FUNCTION
847
 
848
   special_symbol_handling -- additional shared library symbol handling
849
 
850
   SYNOPSIS
851
 
852
   void special_symbol_handling ()
853
 
854
   DESCRIPTION
855
 
856
   Once the symbols from a shared object have been loaded in the usual
857
   way, we are called to do any system specific symbol handling that
858
   is needed.
859
 
860
 */
861
 
862
static void
863
frv_special_symbol_handling (void)
864
{
865
  /* Nothing needed (yet) for FRV. */
866
}
867
 
868
static void
869
frv_relocate_main_executable (void)
870
{
871
  int status;
872
  CORE_ADDR exec_addr;
873
  struct int_elf32_fdpic_loadmap *ldm;
874
  struct cleanup *old_chain;
875
  struct section_offsets *new_offsets;
876
  int changed;
877
  struct obj_section *osect;
878
 
879
  status = frv_fdpic_loadmap_addresses (current_gdbarch, 0, &exec_addr);
880
 
881
  if (status < 0)
882
    {
883
      /* Not using FDPIC ABI, so do nothing.  */
884
      return;
885
    }
886
 
887
  /* Fetch the loadmap located at ``exec_addr''.  */
888
  ldm = fetch_loadmap (exec_addr);
889
  if (ldm == NULL)
890
    error (_("Unable to load the executable's loadmap."));
891
 
892
  if (main_executable_lm_info)
893
    xfree (main_executable_lm_info);
894
  main_executable_lm_info = xcalloc (1, sizeof (struct lm_info));
895
  main_executable_lm_info->map = ldm;
896
 
897
  new_offsets = xcalloc (symfile_objfile->num_sections,
898
                         sizeof (struct section_offsets));
899
  old_chain = make_cleanup (xfree, new_offsets);
900
  changed = 0;
901
 
902
  ALL_OBJFILE_OSECTIONS (symfile_objfile, osect)
903
    {
904
      CORE_ADDR orig_addr, addr, offset;
905
      int osect_idx;
906
      int seg;
907
 
908
      osect_idx = osect->the_bfd_section->index;
909
 
910
      /* Current address of section.  */
911
      addr = osect->addr;
912
      /* Offset from where this section started.  */
913
      offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
914
      /* Original address prior to any past relocations.  */
915
      orig_addr = addr - offset;
916
 
917
      for (seg = 0; seg < ldm->nsegs; seg++)
918
        {
919
          if (ldm->segs[seg].p_vaddr <= orig_addr
920
              && orig_addr < ldm->segs[seg].p_vaddr + ldm->segs[seg].p_memsz)
921
            {
922
              new_offsets->offsets[osect_idx]
923
                = ldm->segs[seg].addr - ldm->segs[seg].p_vaddr;
924
 
925
              if (new_offsets->offsets[osect_idx] != offset)
926
                changed = 1;
927
              break;
928
            }
929
        }
930
    }
931
 
932
  if (changed)
933
    objfile_relocate (symfile_objfile, new_offsets);
934
 
935
  do_cleanups (old_chain);
936
 
937
  /* Now that symfile_objfile has been relocated, we can compute the
938
     GOT value and stash it away.  */
939
  main_executable_lm_info->got_value = main_got ();
940
}
941
 
942
/*
943
 
944
   GLOBAL FUNCTION
945
 
946
   frv_solib_create_inferior_hook -- shared library startup support
947
 
948
   SYNOPSIS
949
 
950
   void frv_solib_create_inferior_hook ()
951
 
952
   DESCRIPTION
953
 
954
   When gdb starts up the inferior, it nurses it along (through the
955
   shell) until it is ready to execute it's first instruction.  At this
956
   point, this function gets called via expansion of the macro
957
   SOLIB_CREATE_INFERIOR_HOOK.
958
 
959
   For the FR-V shared library ABI (FDPIC), the main executable
960
   needs to be relocated.  The shared library breakpoints also need
961
   to be enabled.
962
 */
963
 
964
static void
965
frv_solib_create_inferior_hook (void)
966
{
967
  /* Relocate main executable.  */
968
  frv_relocate_main_executable ();
969
 
970
  /* Enable shared library breakpoints.  */
971
  if (!enable_break ())
972
    {
973
      warning (_("shared library handler failed to enable breakpoint"));
974
      return;
975
    }
976
}
977
 
978
static void
979
frv_clear_solib (void)
980
{
981
  lm_base_cache = 0;
982
  enable_break1_done = 0;
983
  enable_break2_done = 0;
984
  main_lm_addr = 0;
985
  if (main_executable_lm_info != 0)
986
    {
987
      xfree (main_executable_lm_info->map);
988
      xfree (main_executable_lm_info->dyn_syms);
989
      xfree (main_executable_lm_info->dyn_relocs);
990
      xfree (main_executable_lm_info);
991
      main_executable_lm_info = 0;
992
    }
993
}
994
 
995
static void
996
frv_free_so (struct so_list *so)
997
{
998
  xfree (so->lm_info->map);
999
  xfree (so->lm_info->dyn_syms);
1000
  xfree (so->lm_info->dyn_relocs);
1001
  xfree (so->lm_info);
1002
}
1003
 
1004
static void
1005
frv_relocate_section_addresses (struct so_list *so,
1006
                                 struct section_table *sec)
1007
{
1008
  int seg;
1009
  struct int_elf32_fdpic_loadmap *map;
1010
 
1011
  map = so->lm_info->map;
1012
 
1013
  for (seg = 0; seg < map->nsegs; seg++)
1014
    {
1015
      if (map->segs[seg].p_vaddr <= sec->addr
1016
          && sec->addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
1017
        {
1018
          CORE_ADDR displ = map->segs[seg].addr - map->segs[seg].p_vaddr;
1019
          sec->addr += displ;
1020
          sec->endaddr += displ;
1021
          break;
1022
        }
1023
    }
1024
}
1025
 
1026
/* Return the GOT address associated with the main executable.  Return
1027
 
1028
 
1029
static CORE_ADDR
1030
main_got (void)
1031
{
1032
  struct minimal_symbol *got_sym;
1033
 
1034
  got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL, symfile_objfile);
1035
  if (got_sym == 0)
1036
    return 0;
1037
 
1038
  return SYMBOL_VALUE_ADDRESS (got_sym);
1039
}
1040
 
1041
/* Find the global pointer for the given function address ADDR.  */
1042
 
1043
CORE_ADDR
1044
frv_fdpic_find_global_pointer (CORE_ADDR addr)
1045
{
1046
  struct so_list *so;
1047
 
1048
  so = master_so_list ();
1049
  while (so)
1050
    {
1051
      int seg;
1052
      struct int_elf32_fdpic_loadmap *map;
1053
 
1054
      map = so->lm_info->map;
1055
 
1056
      for (seg = 0; seg < map->nsegs; seg++)
1057
        {
1058
          if (map->segs[seg].addr <= addr
1059
              && addr < map->segs[seg].addr + map->segs[seg].p_memsz)
1060
            return so->lm_info->got_value;
1061
        }
1062
 
1063
      so = so->next;
1064
    }
1065
 
1066
  /* Didn't find it it any of the shared objects.  So assume it's in the
1067
     main executable.  */
1068
  return main_got ();
1069
}
1070
 
1071
/* Forward declarations for frv_fdpic_find_canonical_descriptor().  */
1072
static CORE_ADDR find_canonical_descriptor_in_load_object
1073
  (CORE_ADDR, CORE_ADDR, char *, bfd *, struct lm_info *);
1074
 
1075
/* Given a function entry point, attempt to find the canonical descriptor
1076
   associated with that entry point.  Return 0 if no canonical descriptor
1077
   could be found.  */
1078
 
1079
CORE_ADDR
1080
frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point)
1081
{
1082
  char *name;
1083
  CORE_ADDR addr;
1084
  CORE_ADDR got_value;
1085
  struct int_elf32_fdpic_loadmap *ldm = 0;
1086
  struct symbol *sym;
1087
  int status;
1088
  CORE_ADDR exec_loadmap_addr;
1089
 
1090
  /* Fetch the corresponding global pointer for the entry point.  */
1091
  got_value = frv_fdpic_find_global_pointer (entry_point);
1092
 
1093
  /* Attempt to find the name of the function.  If the name is available,
1094
     it'll be used as an aid in finding matching functions in the dynamic
1095
     symbol table.  */
1096
  sym = find_pc_function (entry_point);
1097
  if (sym == 0)
1098
    name = 0;
1099
  else
1100
    name = SYMBOL_LINKAGE_NAME (sym);
1101
 
1102
  /* Check the main executable.  */
1103
  addr = find_canonical_descriptor_in_load_object
1104
           (entry_point, got_value, name, symfile_objfile->obfd,
1105
            main_executable_lm_info);
1106
 
1107
  /* If descriptor not found via main executable, check each load object
1108
     in list of shared objects.  */
1109
  if (addr == 0)
1110
    {
1111
      struct so_list *so;
1112
 
1113
      so = master_so_list ();
1114
      while (so)
1115
        {
1116
          addr = find_canonical_descriptor_in_load_object
1117
                   (entry_point, got_value, name, so->abfd, so->lm_info);
1118
 
1119
          if (addr != 0)
1120
            break;
1121
 
1122
          so = so->next;
1123
        }
1124
    }
1125
 
1126
  return addr;
1127
}
1128
 
1129
static CORE_ADDR
1130
find_canonical_descriptor_in_load_object
1131
  (CORE_ADDR entry_point, CORE_ADDR got_value, char *name, bfd *abfd,
1132
   struct lm_info *lm)
1133
{
1134
  arelent *rel;
1135
  unsigned int i;
1136
  CORE_ADDR addr = 0;
1137
 
1138
  /* Nothing to do if no bfd.  */
1139
  if (abfd == 0)
1140
    return 0;
1141
 
1142
  /* Nothing to do if no link map.  */
1143
  if (lm == 0)
1144
    return 0;
1145
 
1146
  /* We want to scan the dynamic relocs for R_FRV_FUNCDESC relocations.
1147
     (More about this later.)  But in order to fetch the relocs, we
1148
     need to first fetch the dynamic symbols.  These symbols need to
1149
     be cached due to the way that bfd_canonicalize_dynamic_reloc()
1150
     works.  (See the comments in the declaration of struct lm_info
1151
     for more information.)  */
1152
  if (lm->dyn_syms == NULL)
1153
    {
1154
      long storage_needed;
1155
      unsigned int number_of_symbols;
1156
 
1157
      /* Determine amount of space needed to hold the dynamic symbol table.  */
1158
      storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
1159
 
1160
      /* If there are no dynamic symbols, there's nothing to do.  */
1161
      if (storage_needed <= 0)
1162
        return 0;
1163
 
1164
      /* Allocate space for the dynamic symbol table.  */
1165
      lm->dyn_syms = (asymbol **) xmalloc (storage_needed);
1166
 
1167
      /* Fetch the dynamic symbol table.  */
1168
      number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, lm->dyn_syms);
1169
 
1170
      if (number_of_symbols == 0)
1171
        return 0;
1172
    }
1173
 
1174
  /* Fetch the dynamic relocations if not already cached.  */
1175
  if (lm->dyn_relocs == NULL)
1176
    {
1177
      long storage_needed;
1178
 
1179
      /* Determine amount of space needed to hold the dynamic relocs.  */
1180
      storage_needed = bfd_get_dynamic_reloc_upper_bound (abfd);
1181
 
1182
      /* Bail out if there are no dynamic relocs.  */
1183
      if (storage_needed <= 0)
1184
        return 0;
1185
 
1186
      /* Allocate space for the relocs.  */
1187
      lm->dyn_relocs = (arelent **) xmalloc (storage_needed);
1188
 
1189
      /* Fetch the dynamic relocs.  */
1190
      lm->dyn_reloc_count
1191
        = bfd_canonicalize_dynamic_reloc (abfd, lm->dyn_relocs, lm->dyn_syms);
1192
    }
1193
 
1194
  /* Search the dynamic relocs.  */
1195
  for (i = 0; i < lm->dyn_reloc_count; i++)
1196
    {
1197
      rel = lm->dyn_relocs[i];
1198
 
1199
      /* Relocs of interest are those which meet the following
1200
         criteria:
1201
 
1202
           - the names match (assuming the caller could provide
1203
             a name which matches ``entry_point'').
1204
           - the relocation type must be R_FRV_FUNCDESC.  Relocs
1205
             of this type are used (by the dynamic linker) to
1206
             look up the address of a canonical descriptor (allocating
1207
             it if need be) and initializing the GOT entry referred
1208
             to by the offset to the address of the descriptor.
1209
 
1210
         These relocs of interest may be used to obtain a
1211
         candidate descriptor by first adjusting the reloc's
1212
         address according to the link map and then dereferencing
1213
         this address (which is a GOT entry) to obtain a descriptor
1214
         address.  */
1215
      if ((name == 0 || strcmp (name, (*rel->sym_ptr_ptr)->name) == 0)
1216
          && rel->howto->type == R_FRV_FUNCDESC)
1217
        {
1218
          gdb_byte buf [FRV_PTR_SIZE];
1219
 
1220
          /* Compute address of address of candidate descriptor.  */
1221
          addr = rel->address + displacement_from_map (lm->map, rel->address);
1222
 
1223
          /* Fetch address of candidate descriptor.  */
1224
          if (target_read_memory (addr, buf, sizeof buf) != 0)
1225
            continue;
1226
          addr = extract_unsigned_integer (buf, sizeof buf);
1227
 
1228
          /* Check for matching entry point.  */
1229
          if (target_read_memory (addr, buf, sizeof buf) != 0)
1230
            continue;
1231
          if (extract_unsigned_integer (buf, sizeof buf) != entry_point)
1232
            continue;
1233
 
1234
          /* Check for matching got value.  */
1235
          if (target_read_memory (addr + 4, buf, sizeof buf) != 0)
1236
            continue;
1237
          if (extract_unsigned_integer (buf, sizeof buf) != got_value)
1238
            continue;
1239
 
1240
          /* Match was successful!  Exit loop.  */
1241
          break;
1242
        }
1243
    }
1244
 
1245
  return addr;
1246
}
1247
 
1248
/* Given an objfile, return the address of its link map.  This value is
1249
   needed for TLS support.  */
1250
CORE_ADDR
1251
frv_fetch_objfile_link_map (struct objfile *objfile)
1252
{
1253
  struct so_list *so;
1254
 
1255
  /* Cause frv_current_sos() to be run if it hasn't been already.  */
1256
  if (main_lm_addr == 0)
1257
    solib_add (0, 0, 0, 1);
1258
 
1259
  /* frv_current_sos() will set main_lm_addr for the main executable.  */
1260
  if (objfile == symfile_objfile)
1261
    return main_lm_addr;
1262
 
1263
  /* The other link map addresses may be found by examining the list
1264
     of shared libraries.  */
1265
  for (so = master_so_list (); so; so = so->next)
1266
    {
1267
      if (so->objfile == objfile)
1268
        return so->lm_info->lm_addr;
1269
    }
1270
 
1271
  /* Not found!  */
1272
  return 0;
1273
}
1274
 
1275
struct target_so_ops frv_so_ops;
1276
 
1277
void
1278
_initialize_frv_solib (void)
1279
{
1280
  frv_so_ops.relocate_section_addresses = frv_relocate_section_addresses;
1281
  frv_so_ops.free_so = frv_free_so;
1282
  frv_so_ops.clear_solib = frv_clear_solib;
1283
  frv_so_ops.solib_create_inferior_hook = frv_solib_create_inferior_hook;
1284
  frv_so_ops.special_symbol_handling = frv_special_symbol_handling;
1285
  frv_so_ops.current_sos = frv_current_sos;
1286
  frv_so_ops.open_symbol_file_object = open_symbol_file_object;
1287
  frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;
1288
 
1289
  /* Debug this file's internals.  */
1290
  add_setshow_zinteger_cmd ("solib-frv", class_maintenance,
1291
                            &solib_frv_debug, _("\
1292
Set internal debugging of shared library code for FR-V."), _("\
1293
Show internal debugging of shared library code for FR-V."), _("\
1294
When non-zero, FR-V solib specific internal debugging is enabled."),
1295
                            NULL,
1296
                            NULL, /* FIXME: i18n: */
1297
                            &setdebuglist, &showdebuglist);
1298
}

powered by: WebSVN 2.1.0

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