GDB (API)
/home/stan/gdb/src/gdb/solib-dsbt.c
Go to the documentation of this file.
00001 /* Handle TIC6X (DSBT) shared libraries for GDB, the GNU Debugger.
00002    Copyright (C) 2010-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 
00020 #include "defs.h"
00021 #include "gdb_string.h"
00022 #include "inferior.h"
00023 #include "gdbcore.h"
00024 #include "solib.h"
00025 #include "solist.h"
00026 #include "objfiles.h"
00027 #include "symtab.h"
00028 #include "language.h"
00029 #include "command.h"
00030 #include "gdbcmd.h"
00031 #include "elf-bfd.h"
00032 #include "exceptions.h"
00033 #include "gdb_bfd.h"
00034 
00035 #define GOT_MODULE_OFFSET 4
00036 
00037 /* Flag which indicates whether internal debug messages should be printed.  */
00038 static unsigned int solib_dsbt_debug = 0;
00039 
00040 /* TIC6X pointers are four bytes wide.  */
00041 enum { TIC6X_PTR_SIZE = 4 };
00042 
00043 /* Representation of loadmap and related structs for the TIC6X DSBT.  */
00044 
00045 /* External versions; the size and alignment of the fields should be
00046    the same as those on the target.  When loaded, the placement of
00047    the bits in each field will be the same as on the target.  */
00048 typedef gdb_byte ext_Elf32_Half[2];
00049 typedef gdb_byte ext_Elf32_Addr[4];
00050 typedef gdb_byte ext_Elf32_Word[4];
00051 
00052 struct ext_elf32_dsbt_loadseg
00053 {
00054   /* Core address to which the segment is mapped.  */
00055   ext_Elf32_Addr addr;
00056   /* VMA recorded in the program header.  */
00057   ext_Elf32_Addr p_vaddr;
00058   /* Size of this segment in memory.  */
00059   ext_Elf32_Word p_memsz;
00060 };
00061 
00062 struct ext_elf32_dsbt_loadmap {
00063   /* Protocol version number, must be zero.  */
00064   ext_Elf32_Word version;
00065   /* A pointer to the DSBT table; the DSBT size and the index of this
00066      module.  */
00067   ext_Elf32_Word dsbt_table_ptr;
00068   ext_Elf32_Word dsbt_size;
00069   ext_Elf32_Word dsbt_index;
00070   /* Number of segments in this map.  */
00071   ext_Elf32_Word nsegs;
00072   /* The actual memory map.  */
00073   struct ext_elf32_dsbt_loadseg segs[1 /* nsegs, actually */];
00074 };
00075 
00076 /* Internal versions; the types are GDB types and the data in each
00077    of the fields is (or will be) decoded from the external struct
00078    for ease of consumption.  */
00079 struct int_elf32_dsbt_loadseg
00080 {
00081   /* Core address to which the segment is mapped.  */
00082   CORE_ADDR addr;
00083   /* VMA recorded in the program header.  */
00084   CORE_ADDR p_vaddr;
00085   /* Size of this segment in memory.  */
00086   long p_memsz;
00087 };
00088 
00089 struct int_elf32_dsbt_loadmap
00090 {
00091   /* Protocol version number, must be zero.  */
00092   int version;
00093   CORE_ADDR dsbt_table_ptr;
00094   /* A pointer to the DSBT table; the DSBT size and the index of this
00095      module.  */
00096   int dsbt_size, dsbt_index;
00097   /* Number of segments in this map.  */
00098   int nsegs;
00099   /* The actual memory map.  */
00100   struct int_elf32_dsbt_loadseg segs[1 /* nsegs, actually */];
00101 };
00102 
00103 /* External link_map and elf32_dsbt_loadaddr struct definitions.  */
00104 
00105 typedef gdb_byte ext_ptr[4];
00106 
00107 struct ext_elf32_dsbt_loadaddr
00108 {
00109   ext_ptr map;                  /* struct elf32_dsbt_loadmap *map; */
00110 };
00111 
00112 struct ext_link_map
00113 {
00114   struct ext_elf32_dsbt_loadaddr l_addr;
00115 
00116   /* Absolute file name object was found in.  */
00117   ext_ptr l_name;               /* char *l_name; */
00118 
00119   /* Dynamic section of the shared object.  */
00120   ext_ptr l_ld;                 /* ElfW(Dyn) *l_ld; */
00121 
00122   /* Chain of loaded objects.  */
00123   ext_ptr l_next, l_prev;       /* struct link_map *l_next, *l_prev; */
00124 };
00125 
00126 /* Link map info to include in an allocated so_list entry */
00127 
00128 struct lm_info
00129 {
00130   /* The loadmap, digested into an easier to use form.  */
00131   struct int_elf32_dsbt_loadmap *map;
00132 };
00133 
00134 /* Per pspace dsbt specific data.  */
00135 
00136 struct dsbt_info
00137 {
00138   /* The load map, got value, etc. are not available from the chain
00139      of loaded shared objects.  ``main_executable_lm_info'' provides
00140      a way to get at this information so that it doesn't need to be
00141      frequently recomputed.  Initialized by dsbt_relocate_main_executable.  */
00142   struct lm_info *main_executable_lm_info;
00143 
00144   /* Load maps for the main executable and the interpreter.  These are obtained
00145      from ptrace.  They are the starting point for getting into the program,
00146      and are required to find the solib list with the individual load maps for
00147      each module.  */
00148   struct int_elf32_dsbt_loadmap *exec_loadmap;
00149   struct int_elf32_dsbt_loadmap *interp_loadmap;
00150 
00151   /* Cached value for lm_base, below.  */
00152   CORE_ADDR lm_base_cache;
00153 
00154   /* Link map address for main module.  */
00155   CORE_ADDR main_lm_addr;
00156 
00157   CORE_ADDR interp_text_sect_low;
00158   CORE_ADDR interp_text_sect_high;
00159   CORE_ADDR interp_plt_sect_low;
00160   CORE_ADDR interp_plt_sect_high;
00161 };
00162 
00163 /* Per-program-space data key.  */
00164 static const struct program_space_data *solib_dsbt_pspace_data;
00165 
00166 static void
00167 dsbt_pspace_data_cleanup (struct program_space *pspace, void *arg)
00168 {
00169   struct dsbt_info *info;
00170 
00171   info = program_space_data (pspace, solib_dsbt_pspace_data);
00172   xfree (info);
00173 }
00174 
00175 /* Get the current dsbt data.  If none is found yet, add it now.  This
00176    function always returns a valid object.  */
00177 
00178 static struct dsbt_info *
00179 get_dsbt_info (void)
00180 {
00181   struct dsbt_info *info;
00182 
00183   info = program_space_data (current_program_space, solib_dsbt_pspace_data);
00184   if (info != NULL)
00185     return info;
00186 
00187   info = XZALLOC (struct dsbt_info);
00188   set_program_space_data (current_program_space, solib_dsbt_pspace_data, info);
00189 
00190   info->lm_base_cache = 0;
00191   info->main_lm_addr = 0;
00192 
00193   return info;
00194 }
00195 
00196 
00197 static void
00198 dsbt_print_loadmap (struct int_elf32_dsbt_loadmap *map)
00199 {
00200   int i;
00201 
00202   if (map == NULL)
00203     printf_filtered ("(null)\n");
00204   else if (map->version != 0)
00205     printf_filtered (_("Unsupported map version: %d\n"), map->version);
00206   else
00207     {
00208       printf_filtered ("version %d\n", map->version);
00209 
00210       for (i = 0; i < map->nsegs; i++)
00211         printf_filtered ("%s:%s -> %s:%s\n",
00212                          print_core_address (target_gdbarch (),
00213                                              map->segs[i].p_vaddr),
00214                          print_core_address (target_gdbarch (),
00215                                              map->segs[i].p_vaddr
00216                                              + map->segs[i].p_memsz),
00217                          print_core_address (target_gdbarch (), map->segs[i].addr),
00218                          print_core_address (target_gdbarch (), map->segs[i].addr
00219                                              + map->segs[i].p_memsz));
00220     }
00221 }
00222 
00223 /* Decode int_elf32_dsbt_loadmap from BUF.  */
00224 
00225 static struct int_elf32_dsbt_loadmap *
00226 decode_loadmap (gdb_byte *buf)
00227 {
00228   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00229   struct ext_elf32_dsbt_loadmap *ext_ldmbuf;
00230   struct int_elf32_dsbt_loadmap *int_ldmbuf;
00231 
00232   int version, seg, nsegs;
00233   int int_ldmbuf_size;
00234 
00235   ext_ldmbuf = (struct ext_elf32_dsbt_loadmap *) buf;
00236 
00237   /* Extract the version.  */
00238   version = extract_unsigned_integer (ext_ldmbuf->version,
00239                                       sizeof ext_ldmbuf->version,
00240                                       byte_order);
00241   if (version != 0)
00242     {
00243       /* We only handle version 0.  */
00244       return NULL;
00245     }
00246 
00247   /* Extract the number of segments.  */
00248   nsegs = extract_unsigned_integer (ext_ldmbuf->nsegs,
00249                                     sizeof ext_ldmbuf->nsegs,
00250                                     byte_order);
00251 
00252   if (nsegs <= 0)
00253     return NULL;
00254 
00255   /* Allocate space into which to put information extract from the
00256      external loadsegs.  I.e, allocate the internal loadsegs.  */
00257   int_ldmbuf_size = (sizeof (struct int_elf32_dsbt_loadmap)
00258                      + (nsegs - 1) * sizeof (struct int_elf32_dsbt_loadseg));
00259   int_ldmbuf = xmalloc (int_ldmbuf_size);
00260 
00261   /* Place extracted information in internal structs.  */
00262   int_ldmbuf->version = version;
00263   int_ldmbuf->nsegs = nsegs;
00264   for (seg = 0; seg < nsegs; seg++)
00265     {
00266       int_ldmbuf->segs[seg].addr
00267         = extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
00268                                     sizeof (ext_ldmbuf->segs[seg].addr),
00269                                     byte_order);
00270       int_ldmbuf->segs[seg].p_vaddr
00271         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
00272                                     sizeof (ext_ldmbuf->segs[seg].p_vaddr),
00273                                     byte_order);
00274       int_ldmbuf->segs[seg].p_memsz
00275         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
00276                                     sizeof (ext_ldmbuf->segs[seg].p_memsz),
00277                                     byte_order);
00278     }
00279 
00280   xfree (ext_ldmbuf);
00281   return int_ldmbuf;
00282 }
00283 
00284 
00285 static struct dsbt_info *get_dsbt_info (void);
00286 
00287 /* Interrogate the Linux kernel to find out where the program was loaded.
00288    There are two load maps; one for the executable and one for the
00289    interpreter (only in the case of a dynamically linked executable).  */
00290 
00291 static void
00292 dsbt_get_initial_loadmaps (void)
00293 {
00294   gdb_byte *buf;
00295   struct dsbt_info *info = get_dsbt_info ();
00296 
00297   if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
00298                               "exec", &buf))
00299     {
00300       info->exec_loadmap = NULL;
00301       error (_("Error reading DSBT exec loadmap"));
00302     }
00303   info->exec_loadmap = decode_loadmap (buf);
00304   if (solib_dsbt_debug)
00305     dsbt_print_loadmap (info->exec_loadmap);
00306 
00307   if (0 >= target_read_alloc (&current_target, TARGET_OBJECT_FDPIC,
00308                               "interp", &buf))
00309     {
00310       info->interp_loadmap = NULL;
00311       error (_("Error reading DSBT interp loadmap"));
00312     }
00313   info->interp_loadmap = decode_loadmap (buf);
00314   if (solib_dsbt_debug)
00315     dsbt_print_loadmap (info->interp_loadmap);
00316 }
00317 
00318 /* Given address LDMADDR, fetch and decode the loadmap at that address.
00319    Return NULL if there is a problem reading the target memory or if
00320    there doesn't appear to be a loadmap at the given address.  The
00321    allocated space (representing the loadmap) returned by this
00322    function may be freed via a single call to xfree.  */
00323 
00324 static struct int_elf32_dsbt_loadmap *
00325 fetch_loadmap (CORE_ADDR ldmaddr)
00326 {
00327   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00328   struct ext_elf32_dsbt_loadmap ext_ldmbuf_partial;
00329   struct ext_elf32_dsbt_loadmap *ext_ldmbuf;
00330   struct int_elf32_dsbt_loadmap *int_ldmbuf;
00331   int ext_ldmbuf_size, int_ldmbuf_size;
00332   int version, seg, nsegs;
00333 
00334   /* Fetch initial portion of the loadmap.  */
00335   if (target_read_memory (ldmaddr, (gdb_byte *) &ext_ldmbuf_partial,
00336                           sizeof ext_ldmbuf_partial))
00337     {
00338       /* Problem reading the target's memory.  */
00339       return NULL;
00340     }
00341 
00342   /* Extract the version.  */
00343   version = extract_unsigned_integer (ext_ldmbuf_partial.version,
00344                                       sizeof ext_ldmbuf_partial.version,
00345                                       byte_order);
00346   if (version != 0)
00347     {
00348       /* We only handle version 0.  */
00349       return NULL;
00350     }
00351 
00352   /* Extract the number of segments.  */
00353   nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs,
00354                                     sizeof ext_ldmbuf_partial.nsegs,
00355                                     byte_order);
00356 
00357   if (nsegs <= 0)
00358     return NULL;
00359 
00360   /* Allocate space for the complete (external) loadmap.  */
00361   ext_ldmbuf_size = sizeof (struct ext_elf32_dsbt_loadmap)
00362     + (nsegs - 1) * sizeof (struct ext_elf32_dsbt_loadseg);
00363   ext_ldmbuf = xmalloc (ext_ldmbuf_size);
00364 
00365   /* Copy over the portion of the loadmap that's already been read.  */
00366   memcpy (ext_ldmbuf, &ext_ldmbuf_partial, sizeof ext_ldmbuf_partial);
00367 
00368   /* Read the rest of the loadmap from the target.  */
00369   if (target_read_memory (ldmaddr + sizeof ext_ldmbuf_partial,
00370                           (gdb_byte *) ext_ldmbuf + sizeof ext_ldmbuf_partial,
00371                           ext_ldmbuf_size - sizeof ext_ldmbuf_partial))
00372     {
00373       /* Couldn't read rest of the loadmap.  */
00374       xfree (ext_ldmbuf);
00375       return NULL;
00376     }
00377 
00378   /* Allocate space into which to put information extract from the
00379      external loadsegs.  I.e, allocate the internal loadsegs.  */
00380   int_ldmbuf_size = sizeof (struct int_elf32_dsbt_loadmap)
00381     + (nsegs - 1) * sizeof (struct int_elf32_dsbt_loadseg);
00382   int_ldmbuf = xmalloc (int_ldmbuf_size);
00383 
00384   /* Place extracted information in internal structs.  */
00385   int_ldmbuf->version = version;
00386   int_ldmbuf->nsegs = nsegs;
00387   for (seg = 0; seg < nsegs; seg++)
00388     {
00389       int_ldmbuf->segs[seg].addr
00390         = extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
00391                                     sizeof (ext_ldmbuf->segs[seg].addr),
00392                                     byte_order);
00393       int_ldmbuf->segs[seg].p_vaddr
00394         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
00395                                     sizeof (ext_ldmbuf->segs[seg].p_vaddr),
00396                                     byte_order);
00397       int_ldmbuf->segs[seg].p_memsz
00398         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
00399                                     sizeof (ext_ldmbuf->segs[seg].p_memsz),
00400                                     byte_order);
00401     }
00402 
00403   xfree (ext_ldmbuf);
00404   return int_ldmbuf;
00405 }
00406 
00407 static void dsbt_relocate_main_executable (void);
00408 static int enable_break (void);
00409 
00410 /* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
00411    returned and the corresponding PTR is set.  */
00412 
00413 static int
00414 scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
00415 {
00416   int arch_size, step, sect_size;
00417   long dyn_tag;
00418   CORE_ADDR dyn_ptr, dyn_addr;
00419   gdb_byte *bufend, *bufstart, *buf;
00420   Elf32_External_Dyn *x_dynp_32;
00421   Elf64_External_Dyn *x_dynp_64;
00422   struct bfd_section *sect;
00423   struct target_section *target_section;
00424 
00425   if (abfd == NULL)
00426     return 0;
00427 
00428   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
00429     return 0;
00430 
00431   arch_size = bfd_get_arch_size (abfd);
00432   if (arch_size == -1)
00433     return 0;
00434 
00435   /* Find the start address of the .dynamic section.  */
00436   sect = bfd_get_section_by_name (abfd, ".dynamic");
00437   if (sect == NULL)
00438     return 0;
00439 
00440   for (target_section = current_target_sections->sections;
00441        target_section < current_target_sections->sections_end;
00442        target_section++)
00443     if (sect == target_section->the_bfd_section)
00444       break;
00445   if (target_section < current_target_sections->sections_end)
00446     dyn_addr = target_section->addr;
00447   else
00448     {
00449       /* ABFD may come from OBJFILE acting only as a symbol file without being
00450          loaded into the target (see add_symbol_file_command).  This case is
00451          such fallback to the file VMA address without the possibility of
00452          having the section relocated to its actual in-memory address.  */
00453 
00454       dyn_addr = bfd_section_vma (abfd, sect);
00455     }
00456 
00457   /* Read in .dynamic from the BFD.  We will get the actual value
00458      from memory later.  */
00459   sect_size = bfd_section_size (abfd, sect);
00460   buf = bufstart = alloca (sect_size);
00461   if (!bfd_get_section_contents (abfd, sect,
00462                                  buf, 0, sect_size))
00463     return 0;
00464 
00465   /* Iterate over BUF and scan for DYNTAG.  If found, set PTR and return.  */
00466   step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
00467                            : sizeof (Elf64_External_Dyn);
00468   for (bufend = buf + sect_size;
00469        buf < bufend;
00470        buf += step)
00471   {
00472     if (arch_size == 32)
00473       {
00474         x_dynp_32 = (Elf32_External_Dyn *) buf;
00475         dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
00476         dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
00477       }
00478     else
00479       {
00480         x_dynp_64 = (Elf64_External_Dyn *) buf;
00481         dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
00482         dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
00483       }
00484      if (dyn_tag == DT_NULL)
00485        return 0;
00486      if (dyn_tag == dyntag)
00487        {
00488          /* If requested, try to read the runtime value of this .dynamic
00489             entry.  */
00490          if (ptr)
00491            {
00492              struct type *ptr_type;
00493              gdb_byte ptr_buf[8];
00494              CORE_ADDR ptr_addr;
00495 
00496              ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
00497              ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
00498              if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
00499                dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
00500              *ptr = dyn_ptr;
00501            }
00502          return 1;
00503        }
00504   }
00505 
00506   return 0;
00507 }
00508 
00509 /* If no open symbol file, attempt to locate and open the main symbol
00510    file.
00511 
00512    If FROM_TTYP dereferences to a non-zero integer, allow messages to
00513    be printed.  This parameter is a pointer rather than an int because
00514    open_symbol_file_object is called via catch_errors and
00515    catch_errors requires a pointer argument. */
00516 
00517 static int
00518 open_symbol_file_object (void *from_ttyp)
00519 {
00520   /* Unimplemented.  */
00521   return 0;
00522 }
00523 
00524 /* Given a loadmap and an address, return the displacement needed
00525    to relocate the address.  */
00526 
00527 static CORE_ADDR
00528 displacement_from_map (struct int_elf32_dsbt_loadmap *map,
00529                        CORE_ADDR addr)
00530 {
00531   int seg;
00532 
00533   for (seg = 0; seg < map->nsegs; seg++)
00534     if (map->segs[seg].p_vaddr <= addr
00535         && addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
00536       return map->segs[seg].addr - map->segs[seg].p_vaddr;
00537 
00538   return 0;
00539 }
00540 
00541 /* Return the address from which the link map chain may be found.  On
00542    DSBT, a pointer to the start of the link map will be located at the
00543    word found at base of GOT + GOT_MODULE_OFFSET.
00544 
00545    The base of GOT may be found in a number of ways.  Assuming that the
00546    main executable has already been relocated,
00547    1 The easiest way to find this value is to look up the address of
00548    _GLOBAL_OFFSET_TABLE_.
00549    2 The other way is to look for tag DT_PLTGOT, which contains the virtual
00550    address of Global Offset Table.  .*/
00551 
00552 static CORE_ADDR
00553 lm_base (void)
00554 {
00555   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00556   struct minimal_symbol *got_sym;
00557   CORE_ADDR addr;
00558   gdb_byte buf[TIC6X_PTR_SIZE];
00559   struct dsbt_info *info = get_dsbt_info ();
00560 
00561   /* One of our assumptions is that the main executable has been relocated.
00562      Bail out if this has not happened.  (Note that post_create_inferior
00563      in infcmd.c will call solib_add prior to solib_create_inferior_hook.
00564      If we allow this to happen, lm_base_cache will be initialized with
00565      a bogus value.  */
00566   if (info->main_executable_lm_info == 0)
00567     return 0;
00568 
00569   /* If we already have a cached value, return it.  */
00570   if (info->lm_base_cache)
00571     return info->lm_base_cache;
00572 
00573   got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
00574                                    symfile_objfile);
00575 
00576   if (got_sym != 0)
00577     {
00578       addr = SYMBOL_VALUE_ADDRESS (got_sym);
00579       if (solib_dsbt_debug)
00580         fprintf_unfiltered (gdb_stdlog,
00581                             "lm_base: get addr %x by _GLOBAL_OFFSET_TABLE_.\n",
00582                             (unsigned int) addr);
00583     }
00584   else if (scan_dyntag (DT_PLTGOT, exec_bfd, &addr))
00585     {
00586       struct int_elf32_dsbt_loadmap *ldm;
00587 
00588       dsbt_get_initial_loadmaps ();
00589       ldm = info->exec_loadmap;
00590       addr += displacement_from_map (ldm, addr);
00591       if (solib_dsbt_debug)
00592         fprintf_unfiltered (gdb_stdlog,
00593                             "lm_base: get addr %x by DT_PLTGOT.\n",
00594                             (unsigned int) addr);
00595     }
00596   else
00597     {
00598       if (solib_dsbt_debug)
00599         fprintf_unfiltered (gdb_stdlog,
00600                             "lm_base: _GLOBAL_OFFSET_TABLE_ not found.\n");
00601       return 0;
00602     }
00603   addr += GOT_MODULE_OFFSET;
00604 
00605   if (solib_dsbt_debug)
00606     fprintf_unfiltered (gdb_stdlog,
00607                         "lm_base: _GLOBAL_OFFSET_TABLE_ + %d = %s\n",
00608                         GOT_MODULE_OFFSET, hex_string_custom (addr, 8));
00609 
00610   if (target_read_memory (addr, buf, sizeof buf) != 0)
00611     return 0;
00612   info->lm_base_cache = extract_unsigned_integer (buf, sizeof buf, byte_order);
00613 
00614   if (solib_dsbt_debug)
00615     fprintf_unfiltered (gdb_stdlog,
00616                         "lm_base: lm_base_cache = %s\n",
00617                         hex_string_custom (info->lm_base_cache, 8));
00618 
00619   return info->lm_base_cache;
00620 }
00621 
00622 
00623 /* Build a list of `struct so_list' objects describing the shared
00624    objects currently loaded in the inferior.  This list does not
00625    include an entry for the main executable file.
00626 
00627    Note that we only gather information directly available from the
00628    inferior --- we don't examine any of the shared library files
00629    themselves.  The declaration of `struct so_list' says which fields
00630    we provide values for.  */
00631 
00632 static struct so_list *
00633 dsbt_current_sos (void)
00634 {
00635   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00636   CORE_ADDR lm_addr;
00637   struct so_list *sos_head = NULL;
00638   struct so_list **sos_next_ptr = &sos_head;
00639   struct dsbt_info *info = get_dsbt_info ();
00640 
00641   /* Make sure that the main executable has been relocated.  This is
00642      required in order to find the address of the global offset table,
00643      which in turn is used to find the link map info.  (See lm_base
00644      for details.)
00645 
00646      Note that the relocation of the main executable is also performed
00647      by solib_create_inferior_hook, however, in the case of core
00648      files, this hook is called too late in order to be of benefit to
00649      solib_add.  solib_add eventually calls this function,
00650      dsbt_current_sos, and also precedes the call to
00651      solib_create_inferior_hook.   (See post_create_inferior in
00652      infcmd.c.)  */
00653   if (info->main_executable_lm_info == 0 && core_bfd != NULL)
00654     dsbt_relocate_main_executable ();
00655 
00656   /* Locate the address of the first link map struct.  */
00657   lm_addr = lm_base ();
00658 
00659   /* We have at least one link map entry.  Fetch the the lot of them,
00660      building the solist chain.  */
00661   while (lm_addr)
00662     {
00663       struct ext_link_map lm_buf;
00664       ext_Elf32_Word indexword;
00665       CORE_ADDR map_addr;
00666       int dsbt_index;
00667       int ret;
00668 
00669       if (solib_dsbt_debug)
00670         fprintf_unfiltered (gdb_stdlog,
00671                             "current_sos: reading link_map entry at %s\n",
00672                             hex_string_custom (lm_addr, 8));
00673 
00674       ret = target_read_memory (lm_addr, (gdb_byte *) &lm_buf, sizeof (lm_buf));
00675       if (ret)
00676         {
00677           warning (_("dsbt_current_sos: Unable to read link map entry."
00678                      "  Shared object chain may be incomplete."));
00679           break;
00680         }
00681 
00682       /* Fetch the load map address.  */
00683       map_addr = extract_unsigned_integer (lm_buf.l_addr.map,
00684                                            sizeof lm_buf.l_addr.map,
00685                                            byte_order);
00686 
00687       ret = target_read_memory (map_addr + 12, (gdb_byte *) &indexword,
00688                                 sizeof indexword);
00689       if (ret)
00690         {
00691           warning (_("dsbt_current_sos: Unable to read dsbt index."
00692                      "  Shared object chain may be incomplete."));
00693           break;
00694         }
00695       dsbt_index = extract_unsigned_integer (indexword, sizeof indexword,
00696                                              byte_order);
00697 
00698       /* If the DSBT index is zero, then we're looking at the entry
00699          for the main executable.  By convention, we don't include
00700          this in the list of shared objects.  */
00701       if (dsbt_index != 0)
00702         {
00703           int errcode;
00704           char *name_buf;
00705           struct int_elf32_dsbt_loadmap *loadmap;
00706           struct so_list *sop;
00707           CORE_ADDR addr;
00708 
00709           loadmap = fetch_loadmap (map_addr);
00710           if (loadmap == NULL)
00711             {
00712               warning (_("dsbt_current_sos: Unable to fetch load map."
00713                          "  Shared object chain may be incomplete."));
00714               break;
00715             }
00716 
00717           sop = xcalloc (1, sizeof (struct so_list));
00718           sop->lm_info = xcalloc (1, sizeof (struct lm_info));
00719           sop->lm_info->map = loadmap;
00720           /* Fetch the name.  */
00721           addr = extract_unsigned_integer (lm_buf.l_name,
00722                                            sizeof (lm_buf.l_name),
00723                                            byte_order);
00724           target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
00725                               &errcode);
00726 
00727           if (errcode != 0)
00728             warning (_("Can't read pathname for link map entry: %s."),
00729                      safe_strerror (errcode));
00730           else
00731             {
00732               if (solib_dsbt_debug)
00733                 fprintf_unfiltered (gdb_stdlog, "current_sos: name = %s\n",
00734                                     name_buf);
00735 
00736               strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1);
00737               sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
00738               xfree (name_buf);
00739               strcpy (sop->so_original_name, sop->so_name);
00740             }
00741 
00742           *sos_next_ptr = sop;
00743           sos_next_ptr = &sop->next;
00744         }
00745       else
00746         {
00747           info->main_lm_addr = lm_addr;
00748         }
00749 
00750       lm_addr = extract_unsigned_integer (lm_buf.l_next,
00751                                           sizeof (lm_buf.l_next), byte_order);
00752     }
00753 
00754   return sos_head;
00755 }
00756 
00757 /* Return 1 if PC lies in the dynamic symbol resolution code of the
00758    run time loader.  */
00759 
00760 static int
00761 dsbt_in_dynsym_resolve_code (CORE_ADDR pc)
00762 {
00763   struct dsbt_info *info = get_dsbt_info ();
00764 
00765   return ((pc >= info->interp_text_sect_low && pc < info->interp_text_sect_high)
00766           || (pc >= info->interp_plt_sect_low && pc < info->interp_plt_sect_high)
00767           || in_plt_section (pc));
00768 }
00769 
00770 /* Print a warning about being unable to set the dynamic linker
00771    breakpoint.  */
00772 
00773 static void
00774 enable_break_failure_warning (void)
00775 {
00776   warning (_("Unable to find dynamic linker breakpoint function.\n"
00777              "GDB will be unable to debug shared library initializers\n"
00778              "and track explicitly loaded dynamic code."));
00779 }
00780 
00781 /* Helper function for gdb_bfd_lookup_symbol.  */
00782 
00783 static int
00784 cmp_name (asymbol *sym, void *data)
00785 {
00786   return (strcmp (sym->name, (const char *) data) == 0);
00787 }
00788 
00789 /* The dynamic linkers has, as part of its debugger interface, support
00790    for arranging for the inferior to hit a breakpoint after mapping in
00791    the shared libraries.  This function enables that breakpoint.
00792 
00793    On the TIC6X, using the shared library (DSBT), GDB can try to place
00794    a breakpoint on '_dl_debug_state' to monitor the shared library
00795    event.  */
00796 
00797 static int
00798 enable_break (void)
00799 {
00800   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00801   asection *interp_sect;
00802   struct dsbt_info *info;
00803 
00804   if (exec_bfd == NULL)
00805     return 0;
00806 
00807   if (!target_has_execution)
00808     return 0;
00809 
00810   info = get_dsbt_info ();
00811 
00812   info->interp_text_sect_low = 0;
00813   info->interp_text_sect_high = 0;
00814   info->interp_plt_sect_low = 0;
00815   info->interp_plt_sect_high = 0;
00816 
00817   /* Find the .interp section; if not found, warn the user and drop
00818      into the old breakpoint at symbol code.  */
00819   interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
00820   if (interp_sect)
00821     {
00822       unsigned int interp_sect_size;
00823       char *buf;
00824       bfd *tmp_bfd = NULL;
00825       CORE_ADDR addr;
00826       gdb_byte addr_buf[TIC6X_PTR_SIZE];
00827       struct int_elf32_dsbt_loadmap *ldm;
00828       volatile struct gdb_exception ex;
00829       int ret;
00830 
00831       /* Read the contents of the .interp section into a local buffer;
00832          the contents specify the dynamic linker this program uses.  */
00833       interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
00834       buf = alloca (interp_sect_size);
00835       bfd_get_section_contents (exec_bfd, interp_sect,
00836                                 buf, 0, interp_sect_size);
00837 
00838       /* Now we need to figure out where the dynamic linker was
00839          loaded so that we can load its symbols and place a breakpoint
00840          in the dynamic linker itself.  */
00841 
00842       TRY_CATCH (ex, RETURN_MASK_ALL)
00843         {
00844           tmp_bfd = solib_bfd_open (buf);
00845         }
00846       if (tmp_bfd == NULL)
00847         {
00848           enable_break_failure_warning ();
00849           return 0;
00850         }
00851 
00852       dsbt_get_initial_loadmaps ();
00853       ldm = info->interp_loadmap;
00854 
00855       /* Record the relocated start and end address of the dynamic linker
00856          text and plt section for dsbt_in_dynsym_resolve_code.  */
00857       interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
00858       if (interp_sect)
00859         {
00860           info->interp_text_sect_low
00861             = bfd_section_vma (tmp_bfd, interp_sect);
00862           info->interp_text_sect_low
00863             += displacement_from_map (ldm, info->interp_text_sect_low);
00864           info->interp_text_sect_high
00865             = info->interp_text_sect_low
00866             + bfd_section_size (tmp_bfd, interp_sect);
00867         }
00868       interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
00869       if (interp_sect)
00870         {
00871           info->interp_plt_sect_low =
00872             bfd_section_vma (tmp_bfd, interp_sect);
00873           info->interp_plt_sect_low
00874             += displacement_from_map (ldm, info->interp_plt_sect_low);
00875           info->interp_plt_sect_high =
00876             info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
00877         }
00878 
00879       addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_state");
00880       if (addr != 0)
00881         {
00882           if (solib_dsbt_debug)
00883             fprintf_unfiltered (gdb_stdlog,
00884                                 "enable_break: _dl_debug_state (prior to relocation) = %s\n",
00885                                 hex_string_custom (addr, 8));
00886           addr += displacement_from_map (ldm, addr);
00887 
00888           if (solib_dsbt_debug)
00889             fprintf_unfiltered (gdb_stdlog,
00890                                 "enable_break: _dl_debug_state (after relocation) = %s\n",
00891                                 hex_string_custom (addr, 8));
00892 
00893           /* Now (finally!) create the solib breakpoint.  */
00894           create_solib_event_breakpoint (target_gdbarch (), addr);
00895 
00896           ret = 1;
00897         }
00898       else
00899         {
00900           if (solib_dsbt_debug)
00901             fprintf_unfiltered (gdb_stdlog,
00902                                 "enable_break: _dl_debug_state is not found\n");
00903           ret = 0;
00904         }
00905 
00906       /* We're done with the temporary bfd.  */
00907       gdb_bfd_unref (tmp_bfd);
00908 
00909       /* We're also done with the loadmap.  */
00910       xfree (ldm);
00911 
00912       return ret;
00913     }
00914 
00915   /* Tell the user we couldn't set a dynamic linker breakpoint.  */
00916   enable_break_failure_warning ();
00917 
00918   /* Failure return.  */
00919   return 0;
00920 }
00921 
00922 /* Once the symbols from a shared object have been loaded in the usual
00923    way, we are called to do any system specific symbol handling that
00924    is needed.  */
00925 
00926 static void
00927 dsbt_special_symbol_handling (void)
00928 {
00929 }
00930 
00931 static void
00932 dsbt_relocate_main_executable (void)
00933 {
00934   struct int_elf32_dsbt_loadmap *ldm;
00935   struct cleanup *old_chain;
00936   struct section_offsets *new_offsets;
00937   int changed;
00938   struct obj_section *osect;
00939   struct dsbt_info *info = get_dsbt_info ();
00940 
00941   dsbt_get_initial_loadmaps ();
00942   ldm = info->exec_loadmap;
00943 
00944   xfree (info->main_executable_lm_info);
00945   info->main_executable_lm_info = xcalloc (1, sizeof (struct lm_info));
00946   info->main_executable_lm_info->map = ldm;
00947 
00948   new_offsets = xcalloc (symfile_objfile->num_sections,
00949                          sizeof (struct section_offsets));
00950   old_chain = make_cleanup (xfree, new_offsets);
00951   changed = 0;
00952 
00953   ALL_OBJFILE_OSECTIONS (symfile_objfile, osect)
00954     {
00955       CORE_ADDR orig_addr, addr, offset;
00956       int osect_idx;
00957       int seg;
00958 
00959       osect_idx = osect - symfile_objfile->sections;
00960 
00961       /* Current address of section.  */
00962       addr = obj_section_addr (osect);
00963       /* Offset from where this section started.  */
00964       offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
00965       /* Original address prior to any past relocations.  */
00966       orig_addr = addr - offset;
00967 
00968       for (seg = 0; seg < ldm->nsegs; seg++)
00969         {
00970           if (ldm->segs[seg].p_vaddr <= orig_addr
00971               && orig_addr < ldm->segs[seg].p_vaddr + ldm->segs[seg].p_memsz)
00972             {
00973               new_offsets->offsets[osect_idx]
00974                 = ldm->segs[seg].addr - ldm->segs[seg].p_vaddr;
00975 
00976               if (new_offsets->offsets[osect_idx] != offset)
00977                 changed = 1;
00978               break;
00979             }
00980         }
00981     }
00982 
00983   if (changed)
00984     objfile_relocate (symfile_objfile, new_offsets);
00985 
00986   do_cleanups (old_chain);
00987 
00988   /* Now that symfile_objfile has been relocated, we can compute the
00989      GOT value and stash it away.  */
00990 }
00991 
00992 /* When gdb starts up the inferior, it nurses it along (through the
00993    shell) until it is ready to execute it's first instruction.  At this
00994    point, this function gets called via solib_create_inferior_hook.
00995 
00996    For the DSBT shared library, the main executable needs to be relocated.
00997    The shared library breakpoints also need to be enabled.  */
00998 
00999 static void
01000 dsbt_solib_create_inferior_hook (int from_tty)
01001 {
01002   /* Relocate main executable.  */
01003   dsbt_relocate_main_executable ();
01004 
01005   /* Enable shared library breakpoints.  */
01006   if (!enable_break ())
01007     {
01008       warning (_("shared library handler failed to enable breakpoint"));
01009       return;
01010     }
01011 }
01012 
01013 static void
01014 dsbt_clear_solib (void)
01015 {
01016   struct dsbt_info *info = get_dsbt_info ();
01017 
01018   info->lm_base_cache = 0;
01019   info->main_lm_addr = 0;
01020   if (info->main_executable_lm_info != 0)
01021     {
01022       xfree (info->main_executable_lm_info->map);
01023       xfree (info->main_executable_lm_info);
01024       info->main_executable_lm_info = 0;
01025     }
01026 }
01027 
01028 static void
01029 dsbt_free_so (struct so_list *so)
01030 {
01031   xfree (so->lm_info->map);
01032   xfree (so->lm_info);
01033 }
01034 
01035 static void
01036 dsbt_relocate_section_addresses (struct so_list *so,
01037                                  struct target_section *sec)
01038 {
01039   int seg;
01040   struct int_elf32_dsbt_loadmap *map;
01041 
01042   map = so->lm_info->map;
01043 
01044   for (seg = 0; seg < map->nsegs; seg++)
01045     {
01046       if (map->segs[seg].p_vaddr <= sec->addr
01047           && sec->addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
01048         {
01049           CORE_ADDR displ = map->segs[seg].addr - map->segs[seg].p_vaddr;
01050 
01051           sec->addr += displ;
01052           sec->endaddr += displ;
01053           break;
01054         }
01055     }
01056 }
01057 static void
01058 show_dsbt_debug (struct ui_file *file, int from_tty,
01059                  struct cmd_list_element *c, const char *value)
01060 {
01061   fprintf_filtered (file, _("solib-dsbt debugging is %s.\n"), value);
01062 }
01063 
01064 struct target_so_ops dsbt_so_ops;
01065 
01066 /* Provide a prototype to silence -Wmissing-prototypes.  */
01067 extern initialize_file_ftype _initialize_dsbt_solib;
01068 
01069 void
01070 _initialize_dsbt_solib (void)
01071 {
01072   solib_dsbt_pspace_data
01073     = register_program_space_data_with_cleanup (NULL, dsbt_pspace_data_cleanup);
01074 
01075   dsbt_so_ops.relocate_section_addresses = dsbt_relocate_section_addresses;
01076   dsbt_so_ops.free_so = dsbt_free_so;
01077   dsbt_so_ops.clear_solib = dsbt_clear_solib;
01078   dsbt_so_ops.solib_create_inferior_hook = dsbt_solib_create_inferior_hook;
01079   dsbt_so_ops.special_symbol_handling = dsbt_special_symbol_handling;
01080   dsbt_so_ops.current_sos = dsbt_current_sos;
01081   dsbt_so_ops.open_symbol_file_object = open_symbol_file_object;
01082   dsbt_so_ops.in_dynsym_resolve_code = dsbt_in_dynsym_resolve_code;
01083   dsbt_so_ops.bfd_open = solib_bfd_open;
01084 
01085   /* Debug this file's internals.  */
01086   add_setshow_zuinteger_cmd ("solib-dsbt", class_maintenance,
01087                              &solib_dsbt_debug, _("\
01088 Set internal debugging of shared library code for DSBT ELF."), _("\
01089 Show internal debugging of shared library code for DSBT ELF."), _("\
01090 When non-zero, DSBT solib specific internal debugging is enabled."),
01091                              NULL,
01092                              show_dsbt_debug,
01093                              &setdebuglist, &showdebuglist);
01094 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines