/* Handle FR-V (FDPIC) shared libraries for GDB, the GNU Debugger.
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#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 "gdb_bfd.h"
/* Flag which indicates whether internal debug messages should be printed. */
-static int solib_frv_debug;
+static unsigned int solib_frv_debug;
/* FR-V pointers are four bytes wide. */
enum { FRV_PTR_SIZE = 4 };
static struct int_elf32_fdpic_loadmap *
fetch_loadmap (CORE_ADDR ldmaddr)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
struct ext_elf32_fdpic_loadmap ext_ldmbuf_partial;
struct ext_elf32_fdpic_loadmap *ext_ldmbuf;
struct int_elf32_fdpic_loadmap *int_ldmbuf;
/* Extract the version. */
version = extract_unsigned_integer (ext_ldmbuf_partial.version,
- sizeof ext_ldmbuf_partial.version);
+ sizeof ext_ldmbuf_partial.version,
+ byte_order);
if (version != 0)
{
/* We only handle version 0. */
/* Extract the number of segments. */
nsegs = extract_unsigned_integer (ext_ldmbuf_partial.nsegs,
- sizeof ext_ldmbuf_partial.nsegs);
+ sizeof ext_ldmbuf_partial.nsegs,
+ byte_order);
+
+ if (nsegs <= 0)
+ return NULL;
/* 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;
{
int_ldmbuf->segs[seg].addr
= extract_unsigned_integer (ext_ldmbuf->segs[seg].addr,
- sizeof (ext_ldmbuf->segs[seg].addr));
+ sizeof (ext_ldmbuf->segs[seg].addr),
+ byte_order);
int_ldmbuf->segs[seg].p_vaddr
= extract_unsigned_integer (ext_ldmbuf->segs[seg].p_vaddr,
- sizeof (ext_ldmbuf->segs[seg].p_vaddr));
+ sizeof (ext_ldmbuf->segs[seg].p_vaddr),
+ byte_order);
int_ldmbuf->segs[seg].p_memsz
= extract_unsigned_integer (ext_ldmbuf->segs[seg].p_memsz,
- sizeof (ext_ldmbuf->segs[seg].p_memsz));
+ sizeof (ext_ldmbuf->segs[seg].p_memsz),
+ byte_order);
}
xfree (ext_ldmbuf);
ext_ptr l_next, l_prev; /* struct link_map *l_next, *l_prev; */
};
-/* Link map info to include in an allocated so_list entry */
+/* 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);
static int enable_break2 (void);
-/*
-
- LOCAL FUNCTION
-
- bfd_lookup_symbol -- lookup the value for a specific symbol
-
- SYNOPSIS
-
- CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
-
- DESCRIPTION
-
- An expensive way to lookup the value of a single symbol for
- bfd's that are only temporary anyway. This is used by the
- shared library support to find the address of the debugger
- interface structures in the shared library.
-
- Note that 0 is specifically allowed as an error return (no
- such symbol).
- */
-
-static CORE_ADDR
-bfd_lookup_symbol (bfd *abfd, char *symname)
-{
- long storage_needed;
- asymbol *sym;
- asymbol **symbol_table;
- unsigned int number_of_symbols;
- unsigned int i;
- struct cleanup *back_to;
- CORE_ADDR symaddr = 0;
-
- storage_needed = bfd_get_symtab_upper_bound (abfd);
-
- if (storage_needed > 0)
- {
- symbol_table = (asymbol **) xmalloc (storage_needed);
- back_to = make_cleanup (xfree, symbol_table);
- number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
-
- for (i = 0; i < number_of_symbols; i++)
- {
- sym = *symbol_table++;
- if (strcmp (sym->name, symname) == 0)
- {
- /* Bfd symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
- break;
- }
- }
- do_cleanups (back_to);
- }
-
- if (symaddr)
- return symaddr;
-
- /* Look for the symbol in the dynamic string table too. */
-
- storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
-
- if (storage_needed > 0)
- {
- symbol_table = (asymbol **) xmalloc (storage_needed);
- back_to = make_cleanup (xfree, symbol_table);
- number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table);
-
- for (i = 0; i < number_of_symbols; i++)
- {
- sym = *symbol_table++;
- if (strcmp (sym->name, symname) == 0)
- {
- /* Bfd symbols are section relative. */
- symaddr = sym->value + sym->section->vma;
- break;
- }
- }
- do_cleanups (back_to);
- }
-
- return symaddr;
-}
-
-
-/*
-
- LOCAL FUNCTION
-
- open_symbol_file_object
-
- SYNOPSIS
-
- void open_symbol_file_object (void *from_tty)
-
- DESCRIPTION
-
- If no open symbol file, attempt to locate and open the main symbol
- file.
-
- If FROM_TTYP dereferences to a non-zero integer, allow messages to
- be printed. This parameter is a pointer rather than an int because
- open_symbol_file_object() is called via catch_errors() and
- catch_errors() requires a pointer argument. */
+/* Implement the "open_symbol_file_object" target_so_ops method. */
static int
open_symbol_file_object (void *from_ttyp)
static CORE_ADDR
lm_base (void)
{
- struct minimal_symbol *got_sym;
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+ struct bound_minimal_symbol got_sym;
CORE_ADDR addr;
gdb_byte buf[FRV_PTR_SIZE];
+ /* One of our assumptions is that the main executable has been relocated.
+ Bail out if this has not happened. (Note that post_create_inferior()
+ in infcmd.c will call solib_add prior to solib_create_inferior_hook().
+ If we allow this to happen, lm_base_cache will be initialized with
+ a bogus value. */
+ if (main_executable_lm_info == 0)
+ return 0;
+
/* If we already have a cached value, return it. */
if (lm_base_cache)
return lm_base_cache;
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,
if (target_read_memory (addr, buf, sizeof buf) != 0)
return 0;
- lm_base_cache = extract_unsigned_integer (buf, sizeof buf);
+ lm_base_cache = extract_unsigned_integer (buf, sizeof buf, byte_order);
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
}
-/* LOCAL FUNCTION
-
- frv_current_sos -- build a list of currently loaded shared objects
-
- SYNOPSIS
-
- struct so_list *frv_current_sos ()
-
- DESCRIPTION
-
- Build a list of `struct so_list' objects describing the shared
- objects currently loaded in the inferior. This list does not
- include an entry for the main executable file.
-
- Note that we only gather information directly available from the
- inferior --- we don't examine any of the shared library files
- themselves. The declaration of `struct so_list' says which fields
- we provide values for. */
+/* Implement the "current_sos" target_so_ops method. */
static struct so_list *
frv_current_sos (void)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
CORE_ADDR lm_addr, mgot;
struct so_list *sos_head = NULL;
struct so_list **sos_next_ptr = &sos_head;
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 ();
/* Locate the address of the first link map struct. */
lm_addr = lm_base ();
- /* We have at least one link map entry. Fetch the the lot of them,
+ /* We have at least one link map entry. Fetch the lot of them,
building the solist chain. */
while (lm_addr)
{
"current_sos: reading link_map entry at %s\n",
hex_string_custom (lm_addr, 8));
- if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf, sizeof (lm_buf)) != 0)
+ if (target_read_memory (lm_addr, (gdb_byte *) &lm_buf,
+ sizeof (lm_buf)) != 0)
{
- warning (_("frv_current_sos: Unable to read link map entry. Shared object chain may be incomplete."));
+ warning (_("frv_current_sos: Unable to read link map entry. "
+ "Shared object chain may be incomplete."));
break;
}
got_addr
= extract_unsigned_integer (lm_buf.l_addr.got_value,
- sizeof (lm_buf.l_addr.got_value));
+ sizeof (lm_buf.l_addr.got_value),
+ byte_order);
/* If the got_addr is the same as mgotr, then we're looking at the
entry for the main executable. By convention, we don't include
this in the list of shared objects. */
/* Fetch the load map address. */
addr = extract_unsigned_integer (lm_buf.l_addr.map,
- sizeof lm_buf.l_addr.map);
+ sizeof lm_buf.l_addr.map,
+ byte_order);
loadmap = fetch_loadmap (addr);
if (loadmap == NULL)
{
- warning (_("frv_current_sos: Unable to fetch load map. Shared object chain may be incomplete."));
+ warning (_("frv_current_sos: Unable to fetch load map. "
+ "Shared object chain may be incomplete."));
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));
+ sizeof (lm_buf.l_name),
+ byte_order);
target_read_string (addr, &name_buf, SO_NAME_MAX_PATH_SIZE - 1,
&errcode);
main_lm_addr = lm_addr;
}
- lm_addr = extract_unsigned_integer (lm_buf.l_next, sizeof (lm_buf.l_next));
+ lm_addr = extract_unsigned_integer (lm_buf.l_next,
+ sizeof (lm_buf.l_next), byte_order);
}
enable_break2 ();
{
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
to relocate the address. */
-CORE_ADDR
+static CORE_ADDR
displacement_from_map (struct int_elf32_fdpic_loadmap *map,
CORE_ADDR addr)
{
"and track explicitly loaded dynamic code."));
}
-/*
-
- LOCAL FUNCTION
-
- enable_break -- arrange for dynamic linker to hit breakpoint
+/* Helper function for gdb_bfd_lookup_symbol. */
- SYNOPSIS
-
- int enable_break (void)
+static int
+cmp_name (const asymbol *sym, const void *data)
+{
+ return (strcmp (sym->name, (const char *) data) == 0);
+}
- DESCRIPTION
+/* Arrange for dynamic linker to hit breakpoint.
The dynamic linkers has, as part of its debugger interface, support
for arranging for the inferior to hit a breakpoint after mapping in
using the interpreter's loadmap. Once the relocated address
is known, we fetch the value (address) corresponding to r_brk
and then use that value to fetch the entry point of the function
- we're interested in.
+ we're interested in. */
- */
-
-static int enable_break1_done = 0;
static int enable_break2_done = 0;
static int
enable_break2 (void)
{
- int success = 0;
- char **bkpt_namep;
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
asection *interp_sect;
- if (!enable_break1_done || enable_break2_done)
+ if (enable_break2_done)
return 1;
- enable_break2_done = 1;
-
- /* First, remove all the solib event breakpoints. Their addresses
- may have changed since the last time we ran the program. */
- remove_solib_event_breakpoints ();
-
interp_text_sect_low = interp_text_sect_high = 0;
interp_plt_sect_low = interp_plt_sect_high = 0;
if (interp_sect)
{
unsigned int interp_sect_size;
- gdb_byte *buf;
- bfd *tmp_bfd = NULL;
- int tmp_fd = -1;
- char *tmp_pathname = NULL;
+ char *buf;
int status;
CORE_ADDR addr, interp_loadmap_addr;
gdb_byte addr_buf[FRV_PTR_SIZE];
/* 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. */
- tmp_fd = solib_open (buf, &tmp_pathname);
- if (tmp_fd >= 0)
- tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd);
-
- if (tmp_bfd == NULL)
+ gdb_bfd_ref_ptr tmp_bfd;
+ TRY
+ {
+ tmp_bfd = solib_bfd_open (buf);
+ }
+ CATCH (ex, RETURN_MASK_ALL)
{
- enable_break_failure_warning ();
- return 0;
}
+ END_CATCH
- /* Make sure the dynamic linker is really a useful object. */
- if (!bfd_check_format (tmp_bfd, bfd_object))
+ if (tmp_bfd == NULL)
{
- warning (_("Unable to grok dynamic linker %s as an object file"), buf);
enable_break_failure_warning ();
- bfd_close (tmp_bfd);
return 0;
}
- status = frv_fdpic_loadmap_addresses (current_gdbarch,
+ status = frv_fdpic_loadmap_addresses (target_gdbarch (),
&interp_loadmap_addr, 0);
if (status < 0)
{
warning (_("Unable to determine dynamic linker loadmap address."));
enable_break_failure_warning ();
- bfd_close (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 ();
- bfd_close (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 = bfd_lookup_symbol (tmp_bfd, "_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"));
+ warning (_("Could not find symbol _dl_debug_addr "
+ "in dynamic linker"));
enable_break_failure_warning ();
- bfd_close (tmp_bfd);
return 0;
}
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
- "enable_break: _dl_debug_addr (prior to relocation) = %s\n",
+ "enable_break: _dl_debug_addr "
+ "(prior to relocation) = %s\n",
hex_string_custom (addr, 8));
addr += displacement_from_map (ldm, addr);
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
- "enable_break: _dl_debug_addr (after relocation) = %s\n",
+ "enable_break: _dl_debug_addr "
+ "(after relocation) = %s\n",
hex_string_custom (addr, 8));
/* Fetch the address of the r_debug struct. */
if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
{
- warning (_("Unable to fetch contents of _dl_debug_addr (at address %s) from dynamic linker"),
+ warning (_("Unable to fetch contents of _dl_debug_addr "
+ "(at address %s) from dynamic linker"),
hex_string_custom (addr, 8));
}
- addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
+ addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
+
+ if (solib_frv_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "enable_break: _dl_debug_addr[0..3] = %s\n",
+ hex_string_custom (addr, 8));
+
+ /* If it's zero, then the ldso hasn't initialized yet, and so
+ there are no shared libs yet loaded. */
+ if (addr == 0)
+ {
+ if (solib_frv_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "enable_break: ldso not yet initialized\n");
+ /* Do not warn, but mark to run again. */
+ return 0;
+ }
/* Fetch the r_brk field. It's 8 bytes from the start of
_dl_debug_addr. */
if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0)
{
- warning (_("Unable to fetch _dl_debug_addr->r_brk (at address %s) from dynamic linker"),
+ warning (_("Unable to fetch _dl_debug_addr->r_brk "
+ "(at address %s) from dynamic linker"),
hex_string_custom (addr + 8, 8));
enable_break_failure_warning ();
- bfd_close (tmp_bfd);
return 0;
}
- addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
+ addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
/* Now fetch the function entry point. */
if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0)
{
- warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point (at address %s) from dynamic linker"),
+ warning (_("Unable to fetch _dl_debug_addr->.r_brk entry point "
+ "(at address %s) from dynamic linker"),
hex_string_custom (addr, 8));
enable_break_failure_warning ();
- bfd_close (tmp_bfd);
return 0;
}
- addr = extract_unsigned_integer (addr_buf, sizeof addr_buf);
-
- /* We're done with the temporary bfd. */
- bfd_close (tmp_bfd);
+ addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order);
- /* We're also done with the loadmap. */
+ /* We're done with the loadmap. */
xfree (ldm);
+ /* Remove all the solib event breakpoints. Their addresses
+ may have changed since the last time we ran the program. */
+ remove_solib_event_breakpoints ();
+
/* Now (finally!) create the solib breakpoint. */
- create_solib_event_breakpoint (addr);
+ create_solib_event_breakpoint (target_gdbarch (), addr);
+
+ enable_break2_done = 1;
return 1;
}
enable_break (void)
{
asection *interp_sect;
+ CORE_ADDR entry_point;
- /* Remove all the solib event breakpoints. Their addresses
- may have changed since the last time we ran the program. */
- remove_solib_event_breakpoints ();
-
- /* Check for the presence of a .interp section. If there is no
- such section, the executable is statically linked. */
-
- interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
-
- if (interp_sect)
+ if (symfile_objfile == NULL)
{
- enable_break1_done = 1;
- create_solib_event_breakpoint (symfile_objfile->ei.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));
+ "enable_break: No symbol file found.\n");
+ return 0;
}
- else
+
+ if (!entry_point_address_query (&entry_point))
{
if (solib_frv_debug)
fprintf_unfiltered (gdb_stdlog,
- "enable_break: No .interp section found.\n");
+ "enable_break: Symbol file has no entry point.\n");
+ return 0;
}
- return 1;
-}
-
-/*
-
- LOCAL FUNCTION
-
- special_symbol_handling -- additional shared library symbol handling
-
- SYNOPSIS
-
- void special_symbol_handling ()
+ /* Check for the presence of a .interp section. If there is no
+ such section, the executable is statically linked. */
- DESCRIPTION
+ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
- Once the symbols from a shared object have been loaded in the usual
- way, we are called to do any system specific symbol handling that
- is needed.
+ if (interp_sect == NULL)
+ {
+ if (solib_frv_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "enable_break: No .interp section found.\n");
+ return 0;
+ }
- */
+ create_solib_event_breakpoint (target_gdbarch (), entry_point);
-static void
-frv_special_symbol_handling (void)
-{
- /* Nothing needed (yet) for FRV. */
+ if (solib_frv_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "enable_break: solib event breakpoint "
+ "placed at entry point: %s\n",
+ hex_string_custom (entry_point, 8));
+ return 1;
}
static void
frv_relocate_main_executable (void)
{
int status;
- CORE_ADDR exec_addr;
+ CORE_ADDR exec_addr, interp_addr;
struct int_elf32_fdpic_loadmap *ldm;
struct cleanup *old_chain;
struct section_offsets *new_offsets;
int changed;
struct obj_section *osect;
- status = frv_fdpic_loadmap_addresses (current_gdbarch, 0, &exec_addr);
+ status = frv_fdpic_loadmap_addresses (target_gdbarch (),
+ &interp_addr, &exec_addr);
- if (status < 0)
+ if (status < 0 || (exec_addr == 0 && interp_addr == 0))
{
/* Not using FDPIC ABI, so do nothing. */
return;
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 = osect->addr;
+ addr = obj_section_addr (osect);
/* Offset from where this section started. */
offset = ANOFFSET (symfile_objfile->section_offsets, osect_idx);
/* Original address prior to any past relocations. */
main_executable_lm_info->got_value = main_got ();
}
-/*
-
- GLOBAL FUNCTION
-
- frv_solib_create_inferior_hook -- shared library startup support
+/* Implement the "create_inferior_hook" target_solib_ops method.
- SYNOPSIS
-
- void frv_solib_create_inferior_hook ()
-
- DESCRIPTION
-
- When gdb starts up the inferior, it nurses it along (through the
- shell) until it is ready to execute it's first instruction. At this
- point, this function gets called via expansion of the macro
- SOLIB_CREATE_INFERIOR_HOOK.
-
- For the FR-V shared library ABI (FDPIC), the main executable
- needs to be relocated. The shared library breakpoints also need
- to be enabled.
- */
+ For the FR-V shared library ABI (FDPIC), the main executable needs
+ to be relocated. The shared library breakpoints also need to be
+ enabled. */
static void
-frv_solib_create_inferior_hook (void)
+frv_solib_create_inferior_hook (int from_tty)
{
/* Relocate main executable. */
frv_relocate_main_executable ();
frv_clear_solib (void)
{
lm_base_cache = 0;
- enable_break1_done = 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
frv_relocate_section_addresses (struct so_list *so,
- struct section_table *sec)
+ 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++)
{
&& sec->addr < map->segs[seg].p_vaddr + map->segs[seg].p_memsz)
{
CORE_ADDR displ = map->segs[seg].addr - map->segs[seg].p_vaddr;
+
sec->addr += displ;
sec->endaddr += displ;
break;
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)
+ got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_",
+ NULL, symfile_objfile);
+ 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;
}
- /* Didn't find it it any of the shared objects. So assume it's in the
+ /* Didn't find it in any of the shared objects. So assume it's in the
main executable. */
return main_got ();
}
/* Forward declarations for frv_fdpic_find_canonical_descriptor(). */
static CORE_ADDR find_canonical_descriptor_in_load_object
- (CORE_ADDR, CORE_ADDR, 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
CORE_ADDR
frv_fdpic_find_canonical_descriptor (CORE_ADDR entry_point)
{
- char *name;
+ const char *name;
CORE_ADDR addr;
CORE_ADDR got_value;
- struct int_elf32_fdpic_loadmap *ldm = 0;
struct symbol *sym;
- int status;
- CORE_ADDR exec_loadmap_addr;
/* Fetch the corresponding global pointer for the entry point. */
got_value = frv_fdpic_find_global_pointer (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, char *name, bfd *abfd,
- struct lm_info *lm)
+ (CORE_ADDR entry_point, CORE_ADDR got_value, const char *name, bfd *abfd,
+ lm_info_frv *lm)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
arelent *rel;
unsigned int i;
CORE_ADDR addr = 0;
/* Fetch address of candidate descriptor. */
if (target_read_memory (addr, buf, sizeof buf) != 0)
continue;
- addr = extract_unsigned_integer (buf, sizeof buf);
+ addr = extract_unsigned_integer (buf, sizeof buf, byte_order);
/* Check for matching entry point. */
if (target_read_memory (addr, buf, sizeof buf) != 0)
continue;
- if (extract_unsigned_integer (buf, sizeof buf) != entry_point)
+ if (extract_unsigned_integer (buf, sizeof buf, byte_order)
+ != entry_point)
continue;
/* Check for matching got value. */
if (target_read_memory (addr + 4, buf, sizeof buf) != 0)
continue;
- if (extract_unsigned_integer (buf, sizeof buf) != got_value)
+ if (extract_unsigned_integer (buf, sizeof buf, byte_order)
+ != got_value)
continue;
/* Match was successful! Exit loop. */
/* 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! */
return 0;
}
-static struct target_so_ops frv_so_ops;
+struct target_so_ops frv_so_ops;
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_frv_solib;
void
_initialize_frv_solib (void)
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;
-
- /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */
- current_target_so_ops = &frv_so_ops;
+ frv_so_ops.bfd_open = solib_bfd_open;
/* Debug this file's internals. */
- add_setshow_zinteger_cmd ("solib-frv", class_maintenance,
- &solib_frv_debug, _("\
+ add_setshow_zuinteger_cmd ("solib-frv", class_maintenance,
+ &solib_frv_debug, _("\
Set internal debugging of shared library code for FR-V."), _("\
Show internal debugging of shared library code for FR-V."), _("\
When non-zero, FR-V solib specific internal debugging is enabled."),
- NULL,
- NULL, /* FIXME: i18n: */
- &setdebuglist, &showdebuglist);
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setdebuglist, &showdebuglist);
}