/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
- Copyright (C) 2004-2013 Free Software Foundation, Inc.
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
-#include "gdb_string.h"
#include "inferior.h"
#include "gdbcore.h"
#include "solib.h"
#include "command.h"
#include "gdbcmd.h"
#include "elf/frv.h"
-#include "exceptions.h"
#include "gdb_bfd.h"
/* Flag which indicates whether internal debug messages should be printed. */
/* Allocate space for the complete (external) loadmap. */
ext_ldmbuf_size = sizeof (struct ext_elf32_fdpic_loadmap)
+ (nsegs - 1) * sizeof (struct ext_elf32_fdpic_loadseg);
- ext_ldmbuf = xmalloc (ext_ldmbuf_size);
+ ext_ldmbuf = (struct ext_elf32_fdpic_loadmap *) xmalloc (ext_ldmbuf_size);
/* Copy over the portion of the loadmap that's already been read. */
memcpy (ext_ldmbuf, &ext_ldmbuf_partial, sizeof ext_ldmbuf_partial);
external loadsegs. I.e, allocate the internal loadsegs. */
int_ldmbuf_size = sizeof (struct int_elf32_fdpic_loadmap)
+ (nsegs - 1) * sizeof (struct int_elf32_fdpic_loadseg);
- int_ldmbuf = xmalloc (int_ldmbuf_size);
+ int_ldmbuf = (struct int_elf32_fdpic_loadmap *) xmalloc (int_ldmbuf_size);
/* Place extracted information in internal structs. */
int_ldmbuf->version = version;
/* Link map info to include in an allocated so_list entry. */
-struct lm_info
+struct lm_info_frv : public lm_info_base
+{
+ ~lm_info_frv ()
{
- /* The loadmap, digested into an easier to use form. */
- struct int_elf32_fdpic_loadmap *map;
- /* The GOT address for this link map entry. */
- CORE_ADDR got_value;
- /* The link map address, needed for frv_fetch_objfile_link_map(). */
- CORE_ADDR lm_addr;
-
- /* Cached dynamic symbol table and dynamic relocs initialized and
- used only by find_canonical_descriptor_in_load_object().
-
- Note: kevinb/2004-02-26: It appears that calls to
- bfd_canonicalize_dynamic_reloc() will use the same symbols as
- those supplied to the first call to this function. Therefore,
- it's important to NOT free the asymbol ** data structure
- supplied to the first call. Thus the caching of the dynamic
- symbols (dyn_syms) is critical for correct operation. The
- caching of the dynamic relocations could be dispensed with. */
- asymbol **dyn_syms;
- arelent **dyn_relocs;
- int dyn_reloc_count; /* Number of dynamic relocs. */
-
- };
+ xfree (this->map);
+ xfree (this->dyn_syms);
+ xfree (this->dyn_relocs);
+ }
+
+ /* The loadmap, digested into an easier to use form. */
+ int_elf32_fdpic_loadmap *map = NULL;
+ /* The GOT address for this link map entry. */
+ CORE_ADDR got_value = 0;
+ /* The link map address, needed for frv_fetch_objfile_link_map(). */
+ CORE_ADDR lm_addr = 0;
+
+ /* Cached dynamic symbol table and dynamic relocs initialized and
+ used only by find_canonical_descriptor_in_load_object().
+
+ Note: kevinb/2004-02-26: It appears that calls to
+ bfd_canonicalize_dynamic_reloc() will use the same symbols as
+ those supplied to the first call to this function. Therefore,
+ it's important to NOT free the asymbol ** data structure
+ supplied to the first call. Thus the caching of the dynamic
+ symbols (dyn_syms) is critical for correct operation. The
+ caching of the dynamic relocations could be dispensed with. */
+ asymbol **dyn_syms = NULL;
+ arelent **dyn_relocs = NULL;
+ int dyn_reloc_count = 0; /* Number of dynamic relocs. */
+};
/* The load map, got value, etc. are not available from the chain
of loaded shared objects. ``main_executable_lm_info'' provides
a way to get at this information so that it doesn't need to be
frequently recomputed. Initialized by frv_relocate_main_executable(). */
-static struct lm_info *main_executable_lm_info;
+static lm_info_frv *main_executable_lm_info;
static void frv_relocate_main_executable (void);
static CORE_ADDR main_got (void);
lm_base (void)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- struct minimal_symbol *got_sym;
+ struct bound_minimal_symbol got_sym;
CORE_ADDR addr;
gdb_byte buf[FRV_PTR_SIZE];
got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL,
symfile_objfile);
- if (got_sym == 0)
+ if (got_sym.minsym == 0)
{
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
return 0;
}
- addr = SYMBOL_VALUE_ADDRESS (got_sym) + 8;
+ addr = BMSYMBOL_VALUE_ADDRESS (got_sym) + 8;
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
for details.)
Note that the relocation of the main executable is also performed
- by SOLIB_CREATE_INFERIOR_HOOK(), however, in the case of core
+ by solib_create_inferior_hook(), however, in the case of core
files, this hook is called too late in order to be of benefit to
- SOLIB_ADD. SOLIB_ADD eventually calls this this function,
+ solib_add. solib_add eventually calls this this function,
frv_current_sos, and also precedes the call to
- SOLIB_CREATE_INFERIOR_HOOK(). (See post_create_inferior() in
+ solib_create_inferior_hook(). (See post_create_inferior() in
infcmd.c.) */
if (main_executable_lm_info == 0 && core_bfd != NULL)
frv_relocate_main_executable ();
break;
}
- sop = xcalloc (1, sizeof (struct so_list));
- sop->lm_info = xcalloc (1, sizeof (struct lm_info));
- sop->lm_info->map = loadmap;
- sop->lm_info->got_value = got_addr;
- sop->lm_info->lm_addr = lm_addr;
+ sop = XCNEW (struct so_list);
+ lm_info_frv *li = new lm_info_frv;
+ sop->lm_info = li;
+ li->map = loadmap;
+ li->got_value = got_addr;
+ li->lm_addr = lm_addr;
/* Fetch the name. */
addr = extract_unsigned_integer (lm_buf.l_name,
sizeof (lm_buf.l_name),
{
return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
|| (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
- || in_plt_section (pc, NULL));
+ || in_plt_section (pc));
}
/* Given a loadmap and an address, return the displacement needed
/* Helper function for gdb_bfd_lookup_symbol. */
static int
-cmp_name (asymbol *sym, void *data)
+cmp_name (const asymbol *sym, const void *data)
{
return (strcmp (sym->name, (const char *) data) == 0);
}
enable_break2 (void)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- int success = 0;
- char **bkpt_namep;
asection *interp_sect;
if (enable_break2_done)
if (interp_sect)
{
unsigned int interp_sect_size;
- gdb_byte *buf;
- bfd *tmp_bfd = NULL;
+ char *buf;
int status;
CORE_ADDR addr, interp_loadmap_addr;
gdb_byte addr_buf[FRV_PTR_SIZE];
struct int_elf32_fdpic_loadmap *ldm;
- volatile struct gdb_exception ex;
/* Read the contents of the .interp section into a local buffer;
the contents specify the dynamic linker this program uses. */
interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
- buf = alloca (interp_sect_size);
+ buf = (char *) alloca (interp_sect_size);
bfd_get_section_contents (exec_bfd, interp_sect,
buf, 0, interp_sect_size);
be trivial on GNU/Linux). Therefore, we have to try an alternate
mechanism to find the dynamic linker's base address. */
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ gdb_bfd_ref_ptr tmp_bfd;
+ TRY
{
tmp_bfd = solib_bfd_open (buf);
}
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ }
+ END_CATCH
+
if (tmp_bfd == NULL)
{
enable_break_failure_warning ();
{
warning (_("Unable to determine dynamic linker loadmap address."));
enable_break_failure_warning ();
- gdb_bfd_unref (tmp_bfd);
return 0;
}
warning (_("Unable to load dynamic linker loadmap at address %s."),
hex_string_custom (interp_loadmap_addr, 8));
enable_break_failure_warning ();
- gdb_bfd_unref (tmp_bfd);
return 0;
}
/* Record the relocated start and end address of the dynamic linker
text and plt section for svr4_in_dynsym_resolve_code. */
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+ interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
if (interp_sect)
{
interp_text_sect_low
- = bfd_section_vma (tmp_bfd, interp_sect);
+ = bfd_section_vma (tmp_bfd.get (), interp_sect);
interp_text_sect_low
+= displacement_from_map (ldm, interp_text_sect_low);
interp_text_sect_high
- = interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ = interp_text_sect_low + bfd_section_size (tmp_bfd.get (),
+ interp_sect);
}
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+ interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
if (interp_sect)
{
interp_plt_sect_low =
- bfd_section_vma (tmp_bfd, interp_sect);
+ bfd_section_vma (tmp_bfd.get (), interp_sect);
interp_plt_sect_low
+= displacement_from_map (ldm, interp_plt_sect_low);
interp_plt_sect_high =
- interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ interp_plt_sect_low + bfd_section_size (tmp_bfd.get (),
+ interp_sect);
}
- addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr");
+ addr = gdb_bfd_lookup_symbol (tmp_bfd.get (), cmp_name, "_dl_debug_addr");
if (addr == 0)
{
warning (_("Could not find symbol _dl_debug_addr "
"in dynamic linker"));
enable_break_failure_warning ();
- gdb_bfd_unref (tmp_bfd);
return 0;
}
"(at address %s) from dynamic linker"),
hex_string_custom (addr + 8, 8));
enable_break_failure_warning ();
- gdb_bfd_unref (tmp_bfd);
return 0;
}
addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
"(at address %s) from dynamic linker"),
hex_string_custom (addr, 8));
enable_break_failure_warning ();
- gdb_bfd_unref (tmp_bfd);
return 0;
}
addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
- /* We're done with the temporary bfd. */
- gdb_bfd_unref (tmp_bfd);
-
- /* We're also done with the loadmap. */
+ /* We're done with the loadmap. */
xfree (ldm);
/* Remove all the solib event breakpoints. Their addresses
enable_break (void)
{
asection *interp_sect;
+ CORE_ADDR entry_point;
if (symfile_objfile == NULL)
{
return 0;
}
- if (!symfile_objfile->ei.entry_point_p)
+ if (!entry_point_address_query (&entry_point))
{
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
return 0;
}
- create_solib_event_breakpoint (target_gdbarch (),
- symfile_objfile->ei.entry_point);
+ create_solib_event_breakpoint (target_gdbarch (), entry_point);
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
"enable_break: solib event breakpoint "
"placed at entry point: %s\n",
- hex_string_custom (symfile_objfile->ei.entry_point,
- 8));
+ hex_string_custom (entry_point, 8));
return 1;
}
-/* Implement the "special_symbol_handling" target_so_ops method. */
-
-static void
-frv_special_symbol_handling (void)
-{
- /* Nothing needed for FRV. */
-}
-
static void
frv_relocate_main_executable (void)
{
if (ldm == NULL)
error (_("Unable to load the executable's loadmap."));
- if (main_executable_lm_info)
- xfree (main_executable_lm_info);
- main_executable_lm_info = xcalloc (1, sizeof (struct lm_info));
+ delete main_executable_lm_info;
+ main_executable_lm_info = new lm_info_frv;
main_executable_lm_info->map = ldm;
- new_offsets = xcalloc (symfile_objfile->num_sections,
- sizeof (struct section_offsets));
+ new_offsets = XCNEWVEC (struct section_offsets,
+ symfile_objfile->num_sections);
old_chain = make_cleanup (xfree, new_offsets);
changed = 0;
int osect_idx;
int seg;
- osect_idx = osect->the_bfd_section->index;
+ osect_idx = osect - symfile_objfile->sections;
/* Current address of section. */
addr = obj_section_addr (osect);
lm_base_cache = 0;
enable_break2_done = 0;
main_lm_addr = 0;
- if (main_executable_lm_info != 0)
- {
- xfree (main_executable_lm_info->map);
- xfree (main_executable_lm_info->dyn_syms);
- xfree (main_executable_lm_info->dyn_relocs);
- xfree (main_executable_lm_info);
- main_executable_lm_info = 0;
- }
+
+ delete main_executable_lm_info;
+ main_executable_lm_info = NULL;
}
static void
frv_free_so (struct so_list *so)
{
- xfree (so->lm_info->map);
- xfree (so->lm_info->dyn_syms);
- xfree (so->lm_info->dyn_relocs);
- xfree (so->lm_info);
+ lm_info_frv *li = (lm_info_frv *) so->lm_info;
+
+ delete li;
}
static void
struct target_section *sec)
{
int seg;
- struct int_elf32_fdpic_loadmap *map;
-
- map = so->lm_info->map;
+ lm_info_frv *li = (lm_info_frv *) so->lm_info;
+ int_elf32_fdpic_loadmap *map = li->map;
for (seg = 0; seg < map->nsegs; seg++)
{
static CORE_ADDR
main_got (void)
{
- struct minimal_symbol *got_sym;
+ struct bound_minimal_symbol got_sym;
got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_",
NULL, symfile_objfile);
- if (got_sym == 0)
+ if (got_sym.minsym == 0)
return 0;
- return SYMBOL_VALUE_ADDRESS (got_sym);
+ return BMSYMBOL_VALUE_ADDRESS (got_sym);
}
/* Find the global pointer for the given function address ADDR. */
while (so)
{
int seg;
- struct int_elf32_fdpic_loadmap *map;
-
- map = so->lm_info->map;
+ lm_info_frv *li = (lm_info_frv *) so->lm_info;
+ int_elf32_fdpic_loadmap *map = li->map;
for (seg = 0; seg < map->nsegs; seg++)
{
if (map->segs[seg].addr <= addr
&& addr < map->segs[seg].addr + map->segs[seg].p_memsz)
- return so->lm_info->got_value;
+ return li->got_value;
}
so = so->next;
/* Forward declarations for frv_fdpic_find_canonical_descriptor(). */
static CORE_ADDR find_canonical_descriptor_in_load_object
- (CORE_ADDR, CORE_ADDR, const char *, bfd *, struct lm_info *);
+ (CORE_ADDR, CORE_ADDR, const char *, bfd *, lm_info_frv *);
/* Given a function entry point, attempt to find the canonical descriptor
associated with that entry point. Return 0 if no canonical descriptor
const char *name;
CORE_ADDR addr;
CORE_ADDR got_value;
- struct int_elf32_fdpic_loadmap *ldm = 0;
struct symbol *sym;
/* Fetch the corresponding global pointer for the entry point. */
so = master_so_list ();
while (so)
{
+ lm_info_frv *li = (lm_info_frv *) so->lm_info;
+
addr = find_canonical_descriptor_in_load_object
- (entry_point, got_value, name, so->abfd, so->lm_info);
+ (entry_point, got_value, name, so->abfd, li);
if (addr != 0)
break;
static CORE_ADDR
find_canonical_descriptor_in_load_object
(CORE_ADDR entry_point, CORE_ADDR got_value, const char *name, bfd *abfd,
- struct lm_info *lm)
+ lm_info_frv *lm)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
arelent *rel;
/* Cause frv_current_sos() to be run if it hasn't been already. */
if (main_lm_addr == 0)
- solib_add (0, 0, 0, 1);
+ solib_add (0, 0, 1);
/* frv_current_sos() will set main_lm_addr for the main executable. */
if (objfile == symfile_objfile)
of shared libraries. */
for (so = master_so_list (); so; so = so->next)
{
+ lm_info_frv *li = (lm_info_frv *) so->lm_info;
+
if (so->objfile == objfile)
- return so->lm_info->lm_addr;
+ return li->lm_addr;
}
/* Not found! */
frv_so_ops.free_so = frv_free_so;
frv_so_ops.clear_solib = frv_clear_solib;
frv_so_ops.solib_create_inferior_hook = frv_solib_create_inferior_hook;
- frv_so_ops.special_symbol_handling = frv_special_symbol_handling;
frv_so_ops.current_sos = frv_current_sos;
frv_so_ops.open_symbol_file_object = open_symbol_file_object;
frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;