GDB (API)
/home/stan/gdb/src/gdb/solib-frv.c
Go to the documentation of this file.
00001 /* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
00002    Copyright (C) 2004-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 "frv-tdep.h"
00027 #include "objfiles.h"
00028 #include "symtab.h"
00029 #include "language.h"
00030 #include "command.h"
00031 #include "gdbcmd.h"
00032 #include "elf/frv.h"
00033 #include "exceptions.h"
00034 #include "gdb_bfd.h"
00035 
00036 /* Flag which indicates whether internal debug messages should be printed.  */
00037 static unsigned int solib_frv_debug;
00038 
00039 /* FR-V pointers are four bytes wide.  */
00040 enum { FRV_PTR_SIZE = 4 };
00041 
00042 /* Representation of loadmap and related structs for the FR-V FDPIC ABI.  */
00043 
00044 /* External versions; the size and alignment of the fields should be
00045    the same as those on the target.  When loaded, the placement of
00046    the bits in each field will be the same as on the target.  */
00047 typedef gdb_byte ext_Elf32_Half[2];
00048 typedef gdb_byte ext_Elf32_Addr[4];
00049 typedef gdb_byte ext_Elf32_Word[4];
00050 
00051 struct ext_elf32_fdpic_loadseg
00052 {
00053   /* Core address to which the segment is mapped.  */
00054   ext_Elf32_Addr addr;
00055   /* VMA recorded in the program header.  */
00056   ext_Elf32_Addr p_vaddr;
00057   /* Size of this segment in memory.  */
00058   ext_Elf32_Word p_memsz;
00059 };
00060 
00061 struct ext_elf32_fdpic_loadmap {
00062   /* Protocol version number, must be zero.  */
00063   ext_Elf32_Half version;
00064   /* Number of segments in this map.  */
00065   ext_Elf32_Half nsegs;
00066   /* The actual memory map.  */
00067   struct ext_elf32_fdpic_loadseg segs[1 /* nsegs, actually */];
00068 };
00069 
00070 /* Internal versions; the types are GDB types and the data in each
00071    of the fields is (or will be) decoded from the external struct
00072    for ease of consumption.  */
00073 struct int_elf32_fdpic_loadseg
00074 {
00075   /* Core address to which the segment is mapped.  */
00076   CORE_ADDR addr;
00077   /* VMA recorded in the program header.  */
00078   CORE_ADDR p_vaddr;
00079   /* Size of this segment in memory.  */
00080   long p_memsz;
00081 };
00082 
00083 struct int_elf32_fdpic_loadmap {
00084   /* Protocol version number, must be zero.  */
00085   int version;
00086   /* Number of segments in this map.  */
00087   int nsegs;
00088   /* The actual memory map.  */
00089   struct int_elf32_fdpic_loadseg segs[1 /* nsegs, actually */];
00090 };
00091 
00092 /* Given address LDMADDR, fetch and decode the loadmap at that address.
00093    Return NULL if there is a problem reading the target memory or if
00094    there doesn't appear to be a loadmap at the given address.  The
00095    allocated space (representing the loadmap) returned by this
00096    function may be freed via a single call to xfree().  */
00097 
00098 static struct int_elf32_fdpic_loadmap *
00099 fetch_loadmap (CORE_ADDR ldmaddr)
00100 {
00101   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00102   struct ext_elf32_fdpic_loadmap ext_ldmbuf_partial;
00103   struct ext_elf32_fdpic_loadmap *ext_ldmbuf;
00104   struct int_elf32_fdpic_loadmap *int_ldmbuf;
00105   int ext_ldmbuf_size, int_ldmbuf_size;
00106   int version, seg, nsegs;
00107 
00108   /* Fetch initial portion of the loadmap.  */
00109   if (target_read_memory (ldmaddr, (gdb_byte *) &ext_ldmbuf_partial,
00110                           sizeof ext_ldmbuf_partial))
00111     {
00112       /* Problem reading the target's memory.  */
00113       return NULL;
00114     }
00115 
00116   /* Extract the version.  */
00117   version = extract_unsigned_integer (ext_ldmbuf_partial.version,
00118                                       sizeof ext_ldmbuf_partial.version,
00119                                       byte_order);
00120   if (version != 0)
00121     {
00122       /* We only handle version 0.  */
00123       return NULL;
00124     }
00125 
00126   /* Extract the number of segments.  */
00127   nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs,
00128                                     sizeof ext_ldmbuf_partial.nsegs,
00129                                     byte_order);
00130 
00131   if (nsegs <= 0)
00132     return NULL;
00133 
00134   /* Allocate space for the complete (external) loadmap.  */
00135   ext_ldmbuf_size = sizeof (struct ext_elf32_fdpic_loadmap)
00136                + (nsegs - 1) * sizeof (struct ext_elf32_fdpic_loadseg);
00137   ext_ldmbuf = xmalloc (ext_ldmbuf_size);
00138 
00139   /* Copy over the portion of the loadmap that's already been read.  */
00140   memcpy (ext_ldmbuf, &ext_ldmbuf_partial, sizeof ext_ldmbuf_partial);
00141 
00142   /* Read the rest of the loadmap from the target.  */
00143   if (target_read_memory (ldmaddr + sizeof ext_ldmbuf_partial,
00144                           (gdb_byte *) ext_ldmbuf + sizeof ext_ldmbuf_partial,
00145                           ext_ldmbuf_size - sizeof ext_ldmbuf_partial))
00146     {
00147       /* Couldn't read rest of the loadmap.  */
00148       xfree (ext_ldmbuf);
00149       return NULL;
00150     }
00151 
00152   /* Allocate space into which to put information extract from the
00153      external loadsegs.  I.e, allocate the internal loadsegs.  */
00154   int_ldmbuf_size = sizeof (struct int_elf32_fdpic_loadmap)
00155                + (nsegs - 1) * sizeof (struct int_elf32_fdpic_loadseg);
00156   int_ldmbuf = xmalloc (int_ldmbuf_size);
00157 
00158   /* Place extracted information in internal structs.  */
00159   int_ldmbuf->version = version;
00160   int_ldmbuf->nsegs = nsegs;
00161   for (seg = 0; seg < nsegs; seg++)
00162     {
00163       int_ldmbuf->segs[seg].addr
00164         = extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
00165                                     sizeof (ext_ldmbuf->segs[seg].addr),
00166                                     byte_order);
00167       int_ldmbuf->segs[seg].p_vaddr
00168         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
00169                                     sizeof (ext_ldmbuf->segs[seg].p_vaddr),
00170                                     byte_order);
00171       int_ldmbuf->segs[seg].p_memsz
00172         = extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
00173                                     sizeof (ext_ldmbuf->segs[seg].p_memsz),
00174                                     byte_order);
00175     }
00176 
00177   xfree (ext_ldmbuf);
00178   return int_ldmbuf;
00179 }
00180 
00181 /* External link_map and elf32_fdpic_loadaddr struct definitions.  */
00182 
00183 typedef gdb_byte ext_ptr[4];
00184 
00185 struct ext_elf32_fdpic_loadaddr
00186 {
00187   ext_ptr map;                  /* struct elf32_fdpic_loadmap *map; */
00188   ext_ptr got_value;            /* void *got_value; */
00189 };
00190 
00191 struct ext_link_map
00192 {
00193   struct ext_elf32_fdpic_loadaddr l_addr;
00194 
00195   /* Absolute file name object was found in.  */
00196   ext_ptr l_name;               /* char *l_name; */
00197 
00198   /* Dynamic section of the shared object.  */
00199   ext_ptr l_ld;                 /* ElfW(Dyn) *l_ld; */
00200 
00201   /* Chain of loaded objects.  */
00202   ext_ptr l_next, l_prev;       /* struct link_map *l_next, *l_prev; */
00203 };
00204 
00205 /* Link map info to include in an allocated so_list entry.  */
00206 
00207 struct lm_info
00208   {
00209     /* The loadmap, digested into an easier to use form.  */
00210     struct int_elf32_fdpic_loadmap *map;
00211     /* The GOT address for this link map entry.  */
00212     CORE_ADDR got_value;
00213     /* The link map address, needed for frv_fetch_objfile_link_map().  */
00214     CORE_ADDR lm_addr;
00215 
00216     /* Cached dynamic symbol table and dynamic relocs initialized and
00217        used only by find_canonical_descriptor_in_load_object().
00218 
00219        Note: kevinb/2004-02-26: It appears that calls to
00220        bfd_canonicalize_dynamic_reloc() will use the same symbols as
00221        those supplied to the first call to this function.  Therefore,
00222        it's important to NOT free the asymbol ** data structure
00223        supplied to the first call.  Thus the caching of the dynamic
00224        symbols (dyn_syms) is critical for correct operation.  The
00225        caching of the dynamic relocations could be dispensed with.  */
00226     asymbol **dyn_syms;
00227     arelent **dyn_relocs;
00228     int dyn_reloc_count;        /* Number of dynamic relocs.  */
00229 
00230   };
00231 
00232 /* The load map, got value, etc. are not available from the chain
00233    of loaded shared objects.  ``main_executable_lm_info'' provides
00234    a way to get at this information so that it doesn't need to be
00235    frequently recomputed.  Initialized by frv_relocate_main_executable().  */
00236 static struct lm_info *main_executable_lm_info;
00237 
00238 static void frv_relocate_main_executable (void);
00239 static CORE_ADDR main_got (void);
00240 static int enable_break2 (void);
00241 
00242 /* Implement the "open_symbol_file_object" target_so_ops method.  */
00243 
00244 static int
00245 open_symbol_file_object (void *from_ttyp)
00246 {
00247   /* Unimplemented.  */
00248   return 0;
00249 }
00250 
00251 /* Cached value for lm_base(), below.  */
00252 static CORE_ADDR lm_base_cache = 0;
00253 
00254 /* Link map address for main module.  */
00255 static CORE_ADDR main_lm_addr = 0;
00256 
00257 /* Return the address from which the link map chain may be found.  On
00258    the FR-V, this may be found in a number of ways.  Assuming that the
00259    main executable has already been relocated, the easiest way to find
00260    this value is to look up the address of _GLOBAL_OFFSET_TABLE_.  A
00261    pointer to the start of the link map will be located at the word found
00262    at _GLOBAL_OFFSET_TABLE_ + 8.  (This is part of the dynamic linker
00263    reserve area mandated by the ABI.)  */
00264 
00265 static CORE_ADDR
00266 lm_base (void)
00267 {
00268   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00269   struct minimal_symbol *got_sym;
00270   CORE_ADDR addr;
00271   gdb_byte buf[FRV_PTR_SIZE];
00272 
00273   /* One of our assumptions is that the main executable has been relocated.
00274      Bail out if this has not happened.  (Note that post_create_inferior()
00275      in infcmd.c will call solib_add prior to solib_create_inferior_hook().
00276      If we allow this to happen, lm_base_cache will be initialized with
00277      a bogus value.  */
00278   if (main_executable_lm_info == 0)
00279     return 0;
00280 
00281   /* If we already have a cached value, return it.  */
00282   if (lm_base_cache)
00283     return lm_base_cache;
00284 
00285   got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
00286                                    symfile_objfile);
00287   if (got_sym == 0)
00288     {
00289       if (solib_frv_debug)
00290         fprintf_unfiltered (gdb_stdlog,
00291                             "lm_base: _GLOBAL_OFFSET_TABLE_ not found.\n");
00292       return 0;
00293     }
00294 
00295   addr = SYMBOL_VALUE_ADDRESS (got_sym) + 8;
00296 
00297   if (solib_frv_debug)
00298     fprintf_unfiltered (gdb_stdlog,
00299                         "lm_base: _GLOBAL_OFFSET_TABLE_ + 8 = %s\n",
00300                         hex_string_custom (addr, 8));
00301 
00302   if (target_read_memory (addr, buf, sizeof buf) != 0)
00303     return 0;
00304   lm_base_cache = extract_unsigned_integer (buf, sizeof buf, byte_order);
00305 
00306   if (solib_frv_debug)
00307     fprintf_unfiltered (gdb_stdlog,
00308                         "lm_base: lm_base_cache = %s\n",
00309                         hex_string_custom (lm_base_cache, 8));
00310 
00311   return lm_base_cache;
00312 }
00313 
00314 
00315 /* Implement the "current_sos" target_so_ops method.  */
00316 
00317 static struct so_list *
00318 frv_current_sos (void)
00319 {
00320   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00321   CORE_ADDR lm_addr, mgot;
00322   struct so_list *sos_head = NULL;
00323   struct so_list **sos_next_ptr = &sos_head;
00324 
00325   /* Make sure that the main executable has been relocated.  This is
00326      required in order to find the address of the global offset table,
00327      which in turn is used to find the link map info.  (See lm_base()
00328      for details.)
00329 
00330      Note that the relocation of the main executable is also performed
00331      by solib_create_inferior_hook(), however, in the case of core
00332      files, this hook is called too late in order to be of benefit to
00333      solib_add.  solib_add eventually calls this this function,
00334      frv_current_sos, and also precedes the call to
00335      solib_create_inferior_hook().   (See post_create_inferior() in
00336      infcmd.c.)  */
00337   if (main_executable_lm_info == 0 && core_bfd != NULL)
00338     frv_relocate_main_executable ();
00339 
00340   /* Fetch the GOT corresponding to the main executable.  */
00341   mgot = main_got ();
00342 
00343   /* Locate the address of the first link map struct.  */
00344   lm_addr = lm_base ();
00345 
00346   /* We have at least one link map entry.  Fetch the lot of them,
00347      building the solist chain.  */
00348   while (lm_addr)
00349     {
00350       struct ext_link_map lm_buf;
00351       CORE_ADDR got_addr;
00352 
00353       if (solib_frv_debug)
00354         fprintf_unfiltered (gdb_stdlog,
00355                             "current_sos: reading link_map entry at %s\n",
00356                             hex_string_custom (lm_addr, 8));
00357 
00358       if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf,
00359                               sizeof (lm_buf)) != 0)
00360         {
00361           warning (_("frv_current_sos: Unable to read link map entry.  "
00362                      "Shared object chain may be incomplete."));
00363           break;
00364         }
00365 
00366       got_addr
00367         = extract_unsigned_integer (lm_buf.l_addr.got_value,
00368                                     sizeof (lm_buf.l_addr.got_value),
00369                                     byte_order);
00370       /* If the got_addr is the same as mgotr, then we're looking at the
00371          entry for the main executable.  By convention, we don't include
00372          this in the list of shared objects.  */
00373       if (got_addr != mgot)
00374         {
00375           int errcode;
00376           char *name_buf;
00377           struct int_elf32_fdpic_loadmap *loadmap;
00378           struct so_list *sop;
00379           CORE_ADDR addr;
00380 
00381           /* Fetch the load map address.  */
00382           addr = extract_unsigned_integer (lm_buf.l_addr.map,
00383                                            sizeof lm_buf.l_addr.map,
00384                                            byte_order);
00385           loadmap = fetch_loadmap (addr);
00386           if (loadmap == NULL)
00387             {
00388               warning (_("frv_current_sos: Unable to fetch load map.  "
00389                          "Shared object chain may be incomplete."));
00390               break;
00391             }
00392 
00393           sop = xcalloc (1, sizeof (struct so_list));
00394           sop->lm_info = xcalloc (1, sizeof (struct lm_info));
00395           sop->lm_info->map = loadmap;
00396           sop->lm_info->got_value = got_addr;
00397           sop->lm_info->lm_addr = lm_addr;
00398           /* Fetch the name.  */
00399           addr = extract_unsigned_integer (lm_buf.l_name,
00400                                            sizeof (lm_buf.l_name),
00401                                            byte_order);
00402           target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
00403                               &errcode);
00404 
00405           if (solib_frv_debug)
00406             fprintf_unfiltered (gdb_stdlog, "current_sos: name = %s\n",
00407                                 name_buf);
00408           
00409           if (errcode != 0)
00410             warning (_("Can't read pathname for link map entry: %s."),
00411                      safe_strerror (errcode));
00412           else
00413             {
00414               strncpy (sop->so_name, name_buf, SO_NAME_MAX_PATH_SIZE - 1);
00415               sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
00416               xfree (name_buf);
00417               strcpy (sop->so_original_name, sop->so_name);
00418             }
00419 
00420           *sos_next_ptr = sop;
00421           sos_next_ptr = &sop->next;
00422         }
00423       else
00424         {
00425           main_lm_addr = lm_addr;
00426         }
00427 
00428       lm_addr = extract_unsigned_integer (lm_buf.l_next,
00429                                           sizeof (lm_buf.l_next), byte_order);
00430     }
00431 
00432   enable_break2 ();
00433 
00434   return sos_head;
00435 }
00436 
00437 
00438 /* Return 1 if PC lies in the dynamic symbol resolution code of the
00439    run time loader.  */
00440 
00441 static CORE_ADDR interp_text_sect_low;
00442 static CORE_ADDR interp_text_sect_high;
00443 static CORE_ADDR interp_plt_sect_low;
00444 static CORE_ADDR interp_plt_sect_high;
00445 
00446 static int
00447 frv_in_dynsym_resolve_code (CORE_ADDR pc)
00448 {
00449   return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
00450           || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
00451           || in_plt_section (pc));
00452 }
00453 
00454 /* Given a loadmap and an address, return the displacement needed
00455    to relocate the address.  */
00456 
00457 static CORE_ADDR
00458 displacement_from_map (struct int_elf32_fdpic_loadmap *map,
00459                        CORE_ADDR addr)
00460 {
00461   int seg;
00462 
00463   for (seg = 0; seg < map->nsegs; seg++)
00464     {
00465       if (map->segs[seg].p_vaddr <= addr
00466           && addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
00467         {
00468           return map->segs[seg].addr - map->segs[seg].p_vaddr;
00469         }
00470     }
00471 
00472   return 0;
00473 }
00474 
00475 /* Print a warning about being unable to set the dynamic linker
00476    breakpoint.  */
00477 
00478 static void
00479 enable_break_failure_warning (void)
00480 {
00481   warning (_("Unable to find dynamic linker breakpoint function.\n"
00482            "GDB will be unable to debug shared library initializers\n"
00483            "and track explicitly loaded dynamic code."));
00484 }
00485 
00486 /* Helper function for gdb_bfd_lookup_symbol.  */
00487 
00488 static int
00489 cmp_name (asymbol *sym, void *data)
00490 {
00491   return (strcmp (sym->name, (const char *) data) == 0);
00492 }
00493 
00494 /* Arrange for dynamic linker to hit breakpoint.
00495 
00496    The dynamic linkers has, as part of its debugger interface, support
00497    for arranging for the inferior to hit a breakpoint after mapping in
00498    the shared libraries.  This function enables that breakpoint.
00499 
00500    On the FR-V, using the shared library (FDPIC) ABI, the symbol
00501    _dl_debug_addr points to the r_debug struct which contains
00502    a field called r_brk.  r_brk is the address of the function
00503    descriptor upon which a breakpoint must be placed.  Being a
00504    function descriptor, we must extract the entry point in order
00505    to set the breakpoint.
00506 
00507    Our strategy will be to get the .interp section from the
00508    executable.  This section will provide us with the name of the
00509    interpreter.  We'll open the interpreter and then look up
00510    the address of _dl_debug_addr.  We then relocate this address
00511    using the interpreter's loadmap.  Once the relocated address
00512    is known, we fetch the value (address) corresponding to r_brk
00513    and then use that value to fetch the entry point of the function
00514    we're interested in.  */
00515 
00516 static int enable_break2_done = 0;
00517 
00518 static int
00519 enable_break2 (void)
00520 {
00521   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
00522   int success = 0;
00523   char **bkpt_namep;
00524   asection *interp_sect;
00525 
00526   if (enable_break2_done)
00527     return 1;
00528 
00529   interp_text_sect_low = interp_text_sect_high = 0;
00530   interp_plt_sect_low = interp_plt_sect_high = 0;
00531 
00532   /* Find the .interp section; if not found, warn the user and drop
00533      into the old breakpoint at symbol code.  */
00534   interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
00535   if (interp_sect)
00536     {
00537       unsigned int interp_sect_size;
00538       char *buf;
00539       bfd *tmp_bfd = NULL;
00540       int status;
00541       CORE_ADDR addr, interp_loadmap_addr;
00542       gdb_byte addr_buf[FRV_PTR_SIZE];
00543       struct int_elf32_fdpic_loadmap *ldm;
00544       volatile struct gdb_exception ex;
00545 
00546       /* Read the contents of the .interp section into a local buffer;
00547          the contents specify the dynamic linker this program uses.  */
00548       interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
00549       buf = alloca (interp_sect_size);
00550       bfd_get_section_contents (exec_bfd, interp_sect,
00551                                 buf, 0, interp_sect_size);
00552 
00553       /* Now we need to figure out where the dynamic linker was
00554          loaded so that we can load its symbols and place a breakpoint
00555          in the dynamic linker itself.
00556 
00557          This address is stored on the stack.  However, I've been unable
00558          to find any magic formula to find it for Solaris (appears to
00559          be trivial on GNU/Linux).  Therefore, we have to try an alternate
00560          mechanism to find the dynamic linker's base address.  */
00561 
00562       TRY_CATCH (ex, RETURN_MASK_ALL)
00563         {
00564           tmp_bfd = solib_bfd_open (buf);
00565         }
00566       if (tmp_bfd == NULL)
00567         {
00568           enable_break_failure_warning ();
00569           return 0;
00570         }
00571 
00572       status = frv_fdpic_loadmap_addresses (target_gdbarch (),
00573                                             &interp_loadmap_addr, 0);
00574       if (status < 0)
00575         {
00576           warning (_("Unable to determine dynamic linker loadmap address."));
00577           enable_break_failure_warning ();
00578           gdb_bfd_unref (tmp_bfd);
00579           return 0;
00580         }
00581 
00582       if (solib_frv_debug)
00583         fprintf_unfiltered (gdb_stdlog,
00584                             "enable_break: interp_loadmap_addr = %s\n",
00585                             hex_string_custom (interp_loadmap_addr, 8));
00586 
00587       ldm = fetch_loadmap (interp_loadmap_addr);
00588       if (ldm == NULL)
00589         {
00590           warning (_("Unable to load dynamic linker loadmap at address %s."),
00591                    hex_string_custom (interp_loadmap_addr, 8));
00592           enable_break_failure_warning ();
00593           gdb_bfd_unref (tmp_bfd);
00594           return 0;
00595         }
00596 
00597       /* Record the relocated start and end address of the dynamic linker
00598          text and plt section for svr4_in_dynsym_resolve_code.  */
00599       interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
00600       if (interp_sect)
00601         {
00602           interp_text_sect_low
00603             = bfd_section_vma (tmp_bfd, interp_sect);
00604           interp_text_sect_low
00605             += displacement_from_map (ldm, interp_text_sect_low);
00606           interp_text_sect_high
00607             = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
00608         }
00609       interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
00610       if (interp_sect)
00611         {
00612           interp_plt_sect_low =
00613             bfd_section_vma (tmp_bfd, interp_sect);
00614           interp_plt_sect_low
00615             += displacement_from_map (ldm, interp_plt_sect_low);
00616           interp_plt_sect_high =
00617             interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
00618         }
00619 
00620       addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr");
00621 
00622       if (addr == 0)
00623         {
00624           warning (_("Could not find symbol _dl_debug_addr "
00625                      "in dynamic linker"));
00626           enable_break_failure_warning ();
00627           gdb_bfd_unref (tmp_bfd);
00628           return 0;
00629         }
00630 
00631       if (solib_frv_debug)
00632         fprintf_unfiltered (gdb_stdlog,
00633                             "enable_break: _dl_debug_addr "
00634                             "(prior to relocation) = %s\n",
00635                             hex_string_custom (addr, 8));
00636 
00637       addr += displacement_from_map (ldm, addr);
00638 
00639       if (solib_frv_debug)
00640         fprintf_unfiltered (gdb_stdlog,
00641                             "enable_break: _dl_debug_addr "
00642                             "(after relocation) = %s\n",
00643                             hex_string_custom (addr, 8));
00644 
00645       /* Fetch the address of the r_debug struct.  */
00646       if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
00647         {
00648           warning (_("Unable to fetch contents of _dl_debug_addr "
00649                      "(at address %s) from dynamic linker"),
00650                    hex_string_custom (addr, 8));
00651         }
00652       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
00653 
00654       if (solib_frv_debug)
00655         fprintf_unfiltered (gdb_stdlog,
00656                             "enable_break: _dl_debug_addr[0..3] = %s\n",
00657                             hex_string_custom (addr, 8));
00658 
00659       /* If it's zero, then the ldso hasn't initialized yet, and so
00660          there are no shared libs yet loaded.  */
00661       if (addr == 0)
00662         {
00663           if (solib_frv_debug)
00664             fprintf_unfiltered (gdb_stdlog,
00665                                 "enable_break: ldso not yet initialized\n");
00666           /* Do not warn, but mark to run again.  */
00667           return 0;
00668         }
00669 
00670       /* Fetch the r_brk field.  It's 8 bytes from the start of
00671          _dl_debug_addr.  */
00672       if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
00673         {
00674           warning (_("Unable to fetch _dl_debug_addr->r_brk "
00675                      "(at address %s) from dynamic linker"),
00676                    hex_string_custom (addr + 8, 8));
00677           enable_break_failure_warning ();
00678           gdb_bfd_unref (tmp_bfd);
00679           return 0;
00680         }
00681       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
00682 
00683       /* Now fetch the function entry point.  */
00684       if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
00685         {
00686           warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point "
00687                      "(at address %s) from dynamic linker"),
00688                    hex_string_custom (addr, 8));
00689           enable_break_failure_warning ();
00690           gdb_bfd_unref (tmp_bfd);
00691           return 0;
00692         }
00693       addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
00694 
00695       /* We're done with the temporary bfd.  */
00696       gdb_bfd_unref (tmp_bfd);
00697 
00698       /* We're also done with the loadmap.  */
00699       xfree (ldm);
00700 
00701       /* Remove all the solib event breakpoints.  Their addresses
00702          may have changed since the last time we ran the program.  */
00703       remove_solib_event_breakpoints ();
00704 
00705       /* Now (finally!) create the solib breakpoint.  */
00706       create_solib_event_breakpoint (target_gdbarch (), addr);
00707 
00708       enable_break2_done = 1;
00709 
00710       return 1;
00711     }
00712 
00713   /* Tell the user we couldn't set a dynamic linker breakpoint.  */
00714   enable_break_failure_warning ();
00715 
00716   /* Failure return.  */
00717   return 0;
00718 }
00719 
00720 static int
00721 enable_break (void)
00722 {
00723   asection *interp_sect;
00724 
00725   if (symfile_objfile == NULL)
00726     {
00727       if (solib_frv_debug)
00728         fprintf_unfiltered (gdb_stdlog,
00729                             "enable_break: No symbol file found.\n");
00730       return 0;
00731     }
00732 
00733   if (!symfile_objfile->ei.entry_point_p)
00734     {
00735       if (solib_frv_debug)
00736         fprintf_unfiltered (gdb_stdlog,
00737                             "enable_break: Symbol file has no entry point.\n");
00738       return 0;
00739     }
00740 
00741   /* Check for the presence of a .interp section.  If there is no
00742      such section, the executable is statically linked.  */
00743 
00744   interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
00745 
00746   if (interp_sect == NULL)
00747     {
00748       if (solib_frv_debug)
00749         fprintf_unfiltered (gdb_stdlog,
00750                             "enable_break: No .interp section found.\n");
00751       return 0;
00752     }
00753 
00754   create_solib_event_breakpoint (target_gdbarch (),
00755                                  symfile_objfile->ei.entry_point);
00756 
00757   if (solib_frv_debug)
00758     fprintf_unfiltered (gdb_stdlog,
00759                         "enable_break: solib event breakpoint "
00760                         "placed at entry point: %s\n",
00761                         hex_string_custom (symfile_objfile->ei.entry_point,
00762                                            8));
00763   return 1;
00764 }
00765 
00766 /* Implement the "special_symbol_handling" target_so_ops method.  */
00767 
00768 static void
00769 frv_special_symbol_handling (void)
00770 {
00771   /* Nothing needed for FRV.  */
00772 }
00773 
00774 static void
00775 frv_relocate_main_executable (void)
00776 {
00777   int status;
00778   CORE_ADDR exec_addr, interp_addr;
00779   struct int_elf32_fdpic_loadmap *ldm;
00780   struct cleanup *old_chain;
00781   struct section_offsets *new_offsets;
00782   int changed;
00783   struct obj_section *osect;
00784 
00785   status = frv_fdpic_loadmap_addresses (target_gdbarch (),
00786                                         &interp_addr, &exec_addr);
00787 
00788   if (status < 0 || (exec_addr == 0 && interp_addr == 0))
00789     {
00790       /* Not using FDPIC ABI, so do nothing.  */
00791       return;
00792     }
00793 
00794   /* Fetch the loadmap located at ``exec_addr''.  */
00795   ldm = fetch_loadmap (exec_addr);
00796   if (ldm == NULL)
00797     error (_("Unable to load the executable's loadmap."));
00798 
00799   if (main_executable_lm_info)
00800     xfree (main_executable_lm_info);
00801   main_executable_lm_info = xcalloc (1, sizeof (struct lm_info));
00802   main_executable_lm_info->map = ldm;
00803 
00804   new_offsets = xcalloc (symfile_objfile->num_sections,
00805                          sizeof (struct section_offsets));
00806   old_chain = make_cleanup (xfree, new_offsets);
00807   changed = 0;
00808 
00809   ALL_OBJFILE_OSECTIONS (symfile_objfile, osect)
00810     {
00811       CORE_ADDR orig_addr, addr, offset;
00812       int osect_idx;
00813       int seg;
00814       
00815       osect_idx = osect - symfile_objfile->sections;
00816 
00817       /* Current address of section.  */
00818       addr = obj_section_addr (osect);
00819       /* Offset from where this section started.  */
00820       offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
00821       /* Original address prior to any past relocations.  */
00822       orig_addr = addr - offset;
00823 
00824       for (seg = 0; seg < ldm->nsegs; seg++)
00825         {
00826           if (ldm->segs[seg].p_vaddr <= orig_addr
00827               && orig_addr < ldm->segs[seg].p_vaddr + ldm->segs[seg].p_memsz)
00828             {
00829               new_offsets->offsets[osect_idx]
00830                 = ldm->segs[seg].addr - ldm->segs[seg].p_vaddr;
00831 
00832               if (new_offsets->offsets[osect_idx] != offset)
00833                 changed = 1;
00834               break;
00835             }
00836         }
00837     }
00838 
00839   if (changed)
00840     objfile_relocate (symfile_objfile, new_offsets);
00841 
00842   do_cleanups (old_chain);
00843 
00844   /* Now that symfile_objfile has been relocated, we can compute the
00845      GOT value and stash it away.  */
00846   main_executable_lm_info->got_value = main_got ();
00847 }
00848 
00849 /* Implement the "create_inferior_hook" target_solib_ops method.
00850 
00851    For the FR-V shared library ABI (FDPIC), the main executable needs
00852    to be relocated.  The shared library breakpoints also need to be
00853    enabled.  */
00854 
00855 static void
00856 frv_solib_create_inferior_hook (int from_tty)
00857 {
00858   /* Relocate main executable.  */
00859   frv_relocate_main_executable ();
00860 
00861   /* Enable shared library breakpoints.  */
00862   if (!enable_break ())
00863     {
00864       warning (_("shared library handler failed to enable breakpoint"));
00865       return;
00866     }
00867 }
00868 
00869 static void
00870 frv_clear_solib (void)
00871 {
00872   lm_base_cache = 0;
00873   enable_break2_done = 0;
00874   main_lm_addr = 0;
00875   if (main_executable_lm_info != 0)
00876     {
00877       xfree (main_executable_lm_info->map);
00878       xfree (main_executable_lm_info->dyn_syms);
00879       xfree (main_executable_lm_info->dyn_relocs);
00880       xfree (main_executable_lm_info);
00881       main_executable_lm_info = 0;
00882     }
00883 }
00884 
00885 static void
00886 frv_free_so (struct so_list *so)
00887 {
00888   xfree (so->lm_info->map);
00889   xfree (so->lm_info->dyn_syms);
00890   xfree (so->lm_info->dyn_relocs);
00891   xfree (so->lm_info);
00892 }
00893 
00894 static void
00895 frv_relocate_section_addresses (struct so_list *so,
00896                                  struct target_section *sec)
00897 {
00898   int seg;
00899   struct int_elf32_fdpic_loadmap *map;
00900 
00901   map = so->lm_info->map;
00902 
00903   for (seg = 0; seg < map->nsegs; seg++)
00904     {
00905       if (map->segs[seg].p_vaddr <= sec->addr
00906           && sec->addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
00907         {
00908           CORE_ADDR displ = map->segs[seg].addr - map->segs[seg].p_vaddr;
00909 
00910           sec->addr += displ;
00911           sec->endaddr += displ;
00912           break;
00913         }
00914     }
00915 }
00916 
00917 /* Return the GOT address associated with the main executable.  Return
00918    0 if it can't be found.  */
00919 
00920 static CORE_ADDR
00921 main_got (void)
00922 {
00923   struct minimal_symbol *got_sym;
00924 
00925   got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_",
00926                                    NULL, symfile_objfile);
00927   if (got_sym == 0)
00928     return 0;
00929 
00930   return SYMBOL_VALUE_ADDRESS (got_sym);
00931 }
00932 
00933 /* Find the global pointer for the given function address ADDR.  */
00934 
00935 CORE_ADDR
00936 frv_fdpic_find_global_pointer (CORE_ADDR addr)
00937 {
00938   struct so_list *so;
00939 
00940   so = master_so_list ();
00941   while (so)
00942     {
00943       int seg;
00944       struct int_elf32_fdpic_loadmap *map;
00945 
00946       map = so->lm_info->map;
00947 
00948       for (seg = 0; seg < map->nsegs; seg++)
00949         {
00950           if (map->segs[seg].addr <= addr
00951               && addr < map->segs[seg].addr + map->segs[seg].p_memsz)
00952             return so->lm_info->got_value;
00953         }
00954 
00955       so = so->next;
00956     }
00957 
00958   /* Didn't find it in any of the shared objects.  So assume it's in the
00959      main executable.  */
00960   return main_got ();
00961 }
00962 
00963 /* Forward declarations for frv_fdpic_find_canonical_descriptor().  */
00964 static CORE_ADDR find_canonical_descriptor_in_load_object
00965   (CORE_ADDR, CORE_ADDR, const char *, bfd *, struct lm_info *);
00966 
00967 /* Given a function entry point, attempt to find the canonical descriptor
00968    associated with that entry point.  Return 0 if no canonical descriptor
00969    could be found.  */
00970 
00971 CORE_ADDR
00972 frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point)
00973 {
00974   const char *name;
00975   CORE_ADDR addr;
00976   CORE_ADDR got_value;
00977   struct int_elf32_fdpic_loadmap *ldm = 0;
00978   struct symbol *sym;
00979 
00980   /* Fetch the corresponding global pointer for the entry point.  */
00981   got_value = frv_fdpic_find_global_pointer (entry_point);
00982 
00983   /* Attempt to find the name of the function.  If the name is available,
00984      it'll be used as an aid in finding matching functions in the dynamic
00985      symbol table.  */
00986   sym = find_pc_function (entry_point);
00987   if (sym == 0)
00988     name = 0;
00989   else
00990     name = SYMBOL_LINKAGE_NAME (sym);
00991 
00992   /* Check the main executable.  */
00993   addr = find_canonical_descriptor_in_load_object
00994            (entry_point, got_value, name, symfile_objfile->obfd,
00995             main_executable_lm_info);
00996 
00997   /* If descriptor not found via main executable, check each load object
00998      in list of shared objects.  */
00999   if (addr == 0)
01000     {
01001       struct so_list *so;
01002 
01003       so = master_so_list ();
01004       while (so)
01005         {
01006           addr = find_canonical_descriptor_in_load_object
01007                    (entry_point, got_value, name, so->abfd, so->lm_info);
01008 
01009           if (addr != 0)
01010             break;
01011 
01012           so = so->next;
01013         }
01014     }
01015 
01016   return addr;
01017 }
01018 
01019 static CORE_ADDR
01020 find_canonical_descriptor_in_load_object
01021   (CORE_ADDR entry_point, CORE_ADDR got_value, const char *name, bfd *abfd,
01022    struct lm_info *lm)
01023 {
01024   enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
01025   arelent *rel;
01026   unsigned int i;
01027   CORE_ADDR addr = 0;
01028 
01029   /* Nothing to do if no bfd.  */
01030   if (abfd == 0)
01031     return 0;
01032 
01033   /* Nothing to do if no link map.  */
01034   if (lm == 0)
01035     return 0;
01036 
01037   /* We want to scan the dynamic relocs for R_FRV_FUNCDESC relocations.
01038      (More about this later.)  But in order to fetch the relocs, we
01039      need to first fetch the dynamic symbols.  These symbols need to
01040      be cached due to the way that bfd_canonicalize_dynamic_reloc()
01041      works.  (See the comments in the declaration of struct lm_info
01042      for more information.)  */
01043   if (lm->dyn_syms == NULL)
01044     {
01045       long storage_needed;
01046       unsigned int number_of_symbols;
01047 
01048       /* Determine amount of space needed to hold the dynamic symbol table.  */
01049       storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
01050 
01051       /* If there are no dynamic symbols, there's nothing to do.  */
01052       if (storage_needed <= 0)
01053         return 0;
01054 
01055       /* Allocate space for the dynamic symbol table.  */
01056       lm->dyn_syms = (asymbol **) xmalloc (storage_needed);
01057 
01058       /* Fetch the dynamic symbol table.  */
01059       number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, lm->dyn_syms);
01060 
01061       if (number_of_symbols == 0)
01062         return 0;
01063     }
01064 
01065   /* Fetch the dynamic relocations if not already cached.  */
01066   if (lm->dyn_relocs == NULL)
01067     {
01068       long storage_needed;
01069 
01070       /* Determine amount of space needed to hold the dynamic relocs.  */
01071       storage_needed = bfd_get_dynamic_reloc_upper_bound (abfd);
01072 
01073       /* Bail out if there are no dynamic relocs.  */
01074       if (storage_needed <= 0)
01075         return 0;
01076 
01077       /* Allocate space for the relocs.  */
01078       lm->dyn_relocs = (arelent **) xmalloc (storage_needed);
01079 
01080       /* Fetch the dynamic relocs.  */
01081       lm->dyn_reloc_count 
01082         = bfd_canonicalize_dynamic_reloc (abfd, lm->dyn_relocs, lm->dyn_syms);
01083     }
01084 
01085   /* Search the dynamic relocs.  */
01086   for (i = 0; i < lm->dyn_reloc_count; i++)
01087     {
01088       rel = lm->dyn_relocs[i];
01089 
01090       /* Relocs of interest are those which meet the following
01091          criteria:
01092 
01093            - the names match (assuming the caller could provide
01094              a name which matches ``entry_point'').
01095            - the relocation type must be R_FRV_FUNCDESC.  Relocs
01096              of this type are used (by the dynamic linker) to
01097              look up the address of a canonical descriptor (allocating
01098              it if need be) and initializing the GOT entry referred
01099              to by the offset to the address of the descriptor.
01100 
01101          These relocs of interest may be used to obtain a
01102          candidate descriptor by first adjusting the reloc's
01103          address according to the link map and then dereferencing
01104          this address (which is a GOT entry) to obtain a descriptor
01105          address.  */
01106       if ((name == 0 || strcmp (name, (*rel->sym_ptr_ptr)->name) == 0)
01107           && rel->howto->type == R_FRV_FUNCDESC)
01108         {
01109           gdb_byte buf [FRV_PTR_SIZE];
01110 
01111           /* Compute address of address of candidate descriptor.  */
01112           addr = rel->address + displacement_from_map (lm->map, rel->address);
01113 
01114           /* Fetch address of candidate descriptor.  */
01115           if (target_read_memory (addr, buf, sizeof buf) != 0)
01116             continue;
01117           addr = extract_unsigned_integer (buf, sizeof buf, byte_order);
01118 
01119           /* Check for matching entry point.  */
01120           if (target_read_memory (addr, buf, sizeof buf) != 0)
01121             continue;
01122           if (extract_unsigned_integer (buf, sizeof buf, byte_order)
01123               != entry_point)
01124             continue;
01125 
01126           /* Check for matching got value.  */
01127           if (target_read_memory (addr + 4, buf, sizeof buf) != 0)
01128             continue;
01129           if (extract_unsigned_integer (buf, sizeof buf, byte_order)
01130               != got_value)
01131             continue;
01132 
01133           /* Match was successful!  Exit loop.  */
01134           break;
01135         }
01136     }
01137 
01138   return addr;
01139 }
01140 
01141 /* Given an objfile, return the address of its link map.  This value is
01142    needed for TLS support.  */
01143 CORE_ADDR
01144 frv_fetch_objfile_link_map (struct objfile *objfile)
01145 {
01146   struct so_list *so;
01147 
01148   /* Cause frv_current_sos() to be run if it hasn't been already.  */
01149   if (main_lm_addr == 0)
01150     solib_add (0, 0, 0, 1);
01151 
01152   /* frv_current_sos() will set main_lm_addr for the main executable.  */
01153   if (objfile == symfile_objfile)
01154     return main_lm_addr;
01155 
01156   /* The other link map addresses may be found by examining the list
01157      of shared libraries.  */
01158   for (so = master_so_list (); so; so = so->next)
01159     {
01160       if (so->objfile == objfile)
01161         return so->lm_info->lm_addr;
01162     }
01163 
01164   /* Not found!  */
01165   return 0;
01166 }
01167 
01168 struct target_so_ops frv_so_ops;
01169 
01170 /* Provide a prototype to silence -Wmissing-prototypes.  */
01171 extern initialize_file_ftype _initialize_frv_solib;
01172 
01173 void
01174 _initialize_frv_solib (void)
01175 {
01176   frv_so_ops.relocate_section_addresses = frv_relocate_section_addresses;
01177   frv_so_ops.free_so = frv_free_so;
01178   frv_so_ops.clear_solib = frv_clear_solib;
01179   frv_so_ops.solib_create_inferior_hook = frv_solib_create_inferior_hook;
01180   frv_so_ops.special_symbol_handling = frv_special_symbol_handling;
01181   frv_so_ops.current_sos = frv_current_sos;
01182   frv_so_ops.open_symbol_file_object = open_symbol_file_object;
01183   frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;
01184   frv_so_ops.bfd_open = solib_bfd_open;
01185 
01186   /* Debug this file's internals.  */
01187   add_setshow_zuinteger_cmd ("solib-frv", class_maintenance,
01188                              &solib_frv_debug, _("\
01189 Set internal debugging of shared library code for FR-V."), _("\
01190 Show internal debugging of shared library code for FR-V."), _("\
01191 When non-zero, FR-V solib specific internal debugging is enabled."),
01192                              NULL,
01193                              NULL, /* FIXME: i18n: */
01194                              &setdebuglist, &showdebuglist);
01195 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines