/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GDB.
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
+static void svr4_relocate_main_executable (void);
/* Link map info to include in an allocated so_list entry */
"_r_debug_state",
"_dl_debug_state",
"rtld_db_dlactivity",
+ "__dl_rtld_db_dlactivity",
"_rtld_debug_state",
NULL
if (so->lm_info->l_addr == (CORE_ADDR)-1)
{
struct bfd_section *dyninfo_sect;
- CORE_ADDR l_addr, l_dynaddr, dynaddr, align = 0x1000;
+ CORE_ADDR l_addr, l_dynaddr, dynaddr;
l_addr = LM_ADDR_FROM_LINK_MAP (so);
if (dynaddr + l_addr != l_dynaddr)
{
+ CORE_ADDR align = 0x1000;
+ CORE_ADDR minpagesize = align;
+
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
Elf_Internal_Ehdr *ehdr = elf_tdata (abfd)->elf_header;
for (i = 0; i < ehdr->e_phnum; i++)
if (phdr[i].p_type == PT_LOAD && phdr[i].p_align > align)
align = phdr[i].p_align;
+
+ minpagesize = get_elf_backend_data (abfd)->minpagesize;
}
/* Turn it into a mask. */
location, or anything, really. To avoid regressions,
don't adjust the base offset in the latter case, although
odds are that, if things really changed, debugging won't
- quite work. */
- if ((l_addr & align) == ((l_dynaddr - dynaddr) & align))
+ quite work.
+
+ One could expect more the condition
+ ((l_addr & align) == 0 && ((l_dynaddr - dynaddr) & align) == 0)
+ but the one below is relaxed for PPC. The PPC kernel supports
+ either 4k or 64k page sizes. To be prepared for 64k pages,
+ PPC ELF files are built using an alignment requirement of 64k.
+ However, when running on a kernel supporting 4k pages, the memory
+ mapping of the library may not actually happen on a 64k boundary!
+
+ (In the usual case where (l_addr & align) == 0, this check is
+ equivalent to the possibly expected check above.)
+
+ Even on PPC it must be zero-aligned at least for MINPAGESIZE. */
+
+ if ((l_addr & (minpagesize - 1)) == 0
+ && (l_addr & align) == ((l_dynaddr - dynaddr) & align))
{
l_addr = l_dynaddr - dynaddr;
- warning (_(".dynamic section for \"%s\" "
- "is not at the expected address"), so->so_name);
- warning (_("difference appears to be caused by prelink, "
- "adjusting expectations"));
+ if (info_verbose)
+ printf_unfiltered (_("Using PIC (Position Independent Code) "
+ "prelink displacement %s for \"%s\".\n"),
+ paddress (target_gdbarch, l_addr),
+ so->so_name);
}
else
warning (_(".dynamic section for \"%s\" "
/* Read program header TYPE from inferior memory. The header is found
by scanning the OS auxillary vector.
+ If TYPE == -1, return the program headers instead of the contents of
+ one program header.
+
Return a pointer to allocated memory holding the program header contents,
or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the
size of those contents is returned to P_SECT_SIZE. Likewise, the target
else
return 0;
- /* Find .dynamic section via the PT_DYNAMIC PHDR. */
- if (arch_size == 32)
+ /* Find the requested segment. */
+ if (type == -1)
+ {
+ sect_addr = at_phdr;
+ sect_size = at_phent * at_phnum;
+ }
+ else if (arch_size == 32)
{
Elf32_External_Phdr phdr;
int i;
Elf32_External_Dyn *x_dynp_32;
Elf64_External_Dyn *x_dynp_64;
struct bfd_section *sect;
+ struct target_section *target_section;
if (abfd == NULL)
return 0;
sect = bfd_get_section_by_name (abfd, ".dynamic");
if (sect == NULL)
return 0;
- dyn_addr = bfd_section_vma (abfd, sect);
+
+ for (target_section = current_target_sections->sections;
+ target_section < current_target_sections->sections_end;
+ target_section++)
+ if (sect == target_section->the_bfd_section)
+ break;
+ if (target_section < current_target_sections->sections_end)
+ dyn_addr = target_section->addr;
+ else
+ {
+ /* ABFD may come from OBJFILE acting only as a symbol file without being
+ loaded into the target (see add_symbol_file_command). This case is
+ such fallback to the file VMA address without the possibility of
+ having the section relocated to its actual in-memory address. */
+
+ dyn_addr = bfd_section_vma (abfd, sect);
+ }
/* Read in .dynamic from the BFD. We will get the actual value
from memory later. */
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
+ CORE_ADDR addr = 0;
+ volatile struct gdb_exception ex;
- return read_memory_typed_address (info->debug_base + lmo->r_map_offset,
- ptr_type);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
+ ptr_type);
+ }
+ exception_print (gdb_stderr, ex);
+ return addr;
}
/* Find r_brk from the inferior's debug base. */
ptr_type);
}
+/* On Solaris systems with some versions of the dynamic linker,
+ ld.so's l_name pointer points to the SONAME in the string table
+ rather than into writable memory. So that GDB can find shared
+ libraries when loading a core file generated by gcore, ensure that
+ memory areas containing the l_name string are saved in the core
+ file. */
+
+static int
+svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
+{
+ struct svr4_info *info;
+ CORE_ADDR ldsomap;
+ struct so_list *new;
+ struct cleanup *old_chain;
+ struct link_map_offsets *lmo;
+ CORE_ADDR lm_name;
+
+ info = get_svr4_info ();
+
+ info->debug_base = 0;
+ locate_base (info);
+ if (!info->debug_base)
+ return 0;
+
+ ldsomap = solib_svr4_r_ldsomap (info);
+ if (!ldsomap)
+ return 0;
+
+ lmo = svr4_fetch_link_map_offsets ();
+ new = XZALLOC (struct so_list);
+ old_chain = make_cleanup (xfree, new);
+ new->lm_info = xmalloc (sizeof (struct lm_info));
+ make_cleanup (xfree, new->lm_info);
+ new->lm_info->l_addr = (CORE_ADDR)-1;
+ new->lm_info->lm_addr = ldsomap;
+ new->lm_info->lm = xzalloc (lmo->link_map_size);
+ make_cleanup (xfree, new->lm_info->lm);
+ read_memory (ldsomap, new->lm_info->lm, lmo->link_map_size);
+ lm_name = LM_NAME (new);
+ do_cleanups (old_chain);
+
+ return (lm_name >= vaddr && lm_name < vaddr + size);
+}
+
/*
LOCAL FUNCTION
*/
static int
-enable_break (struct svr4_info *info)
+enable_break (struct svr4_info *info, int from_tty)
{
struct minimal_symbol *msymbol;
char **bkpt_namep;
gdb_byte *interp_name;
CORE_ADDR sym_addr;
- /* First, remove all the solib event breakpoints. Their addresses
- may have changed since the last time we ran the program. */
- remove_solib_event_breakpoints ();
-
info->interp_text_sect_low = info->interp_text_sect_high = 0;
info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
mean r_brk has already been relocated. Assume the dynamic linker
is the object containing r_brk. */
- solib_add (NULL, 0, ¤t_target, auto_solib_add);
+ solib_add (NULL, from_tty, ¤t_target, auto_solib_add);
sym_addr = 0;
if (info->debug_base && solib_svr4_r_map (info) != 0)
sym_addr = solib_svr4_r_brk (info);
sym_addr,
¤t_target));
+ /* On at least some versions of Solaris there's a dynamic relocation
+ on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if
+ we get control before the dynamic linker has self-relocated.
+ Check if SYM_ADDR is in a known section, if it is assume we can
+ trust its value. This is just a heuristic though, it could go away
+ or be replaced if it's getting in the way.
+
+ On ARM we need to know whether the ISA of rtld_db_dlactivity (or
+ however it's spelled in your particular system) is ARM or Thumb.
+ That knowledge is encoded in the address, if it's Thumb the low bit
+ is 1. However, we've stripped that info above and it's not clear
+ what all the consequences are of passing a non-addr_bits_remove'd
+ address to create_solib_event_breakpoint. The call to
+ find_pc_section verifies we know about the address and have some
+ hope of computing the right kind of breakpoint to use (via
+ symbol info). It does mean that GDB needs to be pointed at a
+ non-stripped version of the dynamic linker in order to obtain
+ information it already knows about. Sigh. */
+
os = find_pc_section (sym_addr);
if (os != NULL)
{
from our so_list, then try using the AT_BASE auxilliary entry. */
if (!load_addr_found)
if (target_auxv_search (¤t_target, AT_BASE, &load_addr) > 0)
- load_addr_found = 1;
+ {
+ int addr_bit = gdbarch_addr_bit (target_gdbarch);
+
+ /* Ensure LOAD_ADDR has proper sign in its possible upper bits so
+ that `+ load_addr' will overflow CORE_ADDR width not creating
+ invalid addresses like 0x101234567 for 32bit inferiors on 64bit
+ GDB. */
+
+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
+ {
+ CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
+ CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd,
+ tmp_bfd_target);
+
+ gdb_assert (load_addr < space_size);
+
+ /* TMP_ENTRY_POINT exceeding SPACE_SIZE would be for prelinked
+ 64bit ld.so with 32bit executable, it should not happen. */
+
+ if (tmp_entry_point < space_size
+ && tmp_entry_point + load_addr >= space_size)
+ load_addr -= space_size;
+ }
+
+ load_addr_found = 1;
+ }
/* Otherwise we find the dynamic linker's base address by examining
the current pc (which should point at the entry point for the
info->debug_loader_name = xstrdup (interp_name);
info->debug_loader_offset_p = 1;
info->debug_loader_offset = load_addr;
- solib_add (NULL, 0, ¤t_target, auto_solib_add);
+ solib_add (NULL, from_tty, ¤t_target, auto_solib_add);
}
/* Record the relocated start and end address of the dynamic linker
static void
svr4_special_symbol_handling (void)
{
+ svr4_relocate_main_executable ();
+}
+
+/* Read the ELF program headers from ABFD. Return the contents and
+ set *PHDRS_SIZE to the size of the program headers. */
+
+static gdb_byte *
+read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
+{
+ Elf_Internal_Ehdr *ehdr;
+ gdb_byte *buf;
+
+ ehdr = elf_elfheader (abfd);
+
+ *phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
+ if (*phdrs_size == 0)
+ return NULL;
+
+ buf = xmalloc (*phdrs_size);
+ if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
+ || bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
+ {
+ xfree (buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
+/* Return 1 and fill *DISPLACEMENTP with detected PIE offset of inferior
+ exec_bfd. Otherwise return 0.
+
+ We relocate all of the sections by the same amount. This
+ behavior is mandated by recent editions of the System V ABI.
+ According to the System V Application Binary Interface,
+ Edition 4.1, page 5-5:
+
+ ... Though the system chooses virtual addresses for
+ individual processes, it maintains the segments' relative
+ positions. Because position-independent code uses relative
+ addressesing between segments, the difference between
+ virtual addresses in memory must match the difference
+ between virtual addresses in the file. The difference
+ between the virtual address of any segment in memory and
+ the corresponding virtual address in the file is thus a
+ single constant value for any one executable or shared
+ object in a given process. This difference is the base
+ address. One use of the base address is to relocate the
+ memory image of the program during dynamic linking.
+
+ The same language also appears in Edition 4.0 of the System V
+ ABI and is left unspecified in some of the earlier editions.
+
+ Decide if the objfile needs to be relocated. As indicated above, we will
+ only be here when execution is stopped. But during attachment PC can be at
+ arbitrary address therefore regcache_read_pc can be misleading (contrary to
+ the auxv AT_ENTRY value). Moreover for executable with interpreter section
+ regcache_read_pc would point to the interpreter and not the main executable.
+
+ So, to summarize, relocations are necessary when the start address obtained
+ from the executable is different from the address in auxv AT_ENTRY entry.
+
+ [ The astute reader will note that we also test to make sure that
+ the executable in question has the DYNAMIC flag set. It is my
+ opinion that this test is unnecessary (undesirable even). It
+ was added to avoid inadvertent relocation of an executable
+ whose e_type member in the ELF header is not ET_DYN. There may
+ be a time in the future when it is desirable to do relocations
+ on other types of files as well in which case this condition
+ should either be removed or modified to accomodate the new file
+ type. - Kevin, Nov 2000. ] */
+
+static int
+svr4_exec_displacement (CORE_ADDR *displacementp)
+{
+ /* ENTRY_POINT is a possible function descriptor - before
+ a call to gdbarch_convert_from_func_ptr_addr. */
+ CORE_ADDR entry_point, displacement;
+
+ if (exec_bfd == NULL)
+ return 0;
+
+ /* Therefore for ELF it is ET_EXEC and not ET_DYN. Both shared libraries
+ being executed themselves and PIE (Position Independent Executable)
+ executables are ET_DYN. */
+
+ if ((bfd_get_file_flags (exec_bfd) & DYNAMIC) == 0)
+ return 0;
+
+ if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) <= 0)
+ return 0;
+
+ displacement = entry_point - bfd_get_start_address (exec_bfd);
+
+ /* Verify the DISPLACEMENT candidate complies with the required page
+ alignment. It is cheaper than the program headers comparison below. */
+
+ if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+ {
+ const struct elf_backend_data *elf = get_elf_backend_data (exec_bfd);
+
+ /* p_align of PT_LOAD segments does not specify any alignment but
+ only congruency of addresses:
+ p_offset % p_align == p_vaddr % p_align
+ Kernel is free to load the executable with lower alignment. */
+
+ if ((displacement & (elf->minpagesize - 1)) != 0)
+ return 0;
+ }
+
+ /* Verify that the auxilliary vector describes the same file as exec_bfd, by
+ comparing their program headers. If the program headers in the auxilliary
+ vector do not match the program headers in the executable, then we are
+ looking at a different file than the one used by the kernel - for
+ instance, "gdb program" connected to "gdbserver :PORT ld.so program". */
+
+ if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+ {
+ /* Be optimistic and clear OK only if GDB was able to verify the headers
+ really do not match. */
+ int phdrs_size, phdrs2_size, ok = 1;
+ gdb_byte *buf, *buf2;
+
+ buf = read_program_header (-1, &phdrs_size, NULL);
+ buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
+ if (buf != NULL && buf2 != NULL
+ && (phdrs_size != phdrs2_size
+ || memcmp (buf, buf2, phdrs_size) != 0))
+ ok = 0;
+
+ xfree (buf);
+ xfree (buf2);
+
+ if (!ok)
+ return 0;
+ }
+
+ if (info_verbose)
+ {
+ /* It can be printed repeatedly as there is no easy way to check
+ the executable symbols/file has been already relocated to
+ displacement. */
+
+ printf_unfiltered (_("Using PIE (Position Independent Executable) "
+ "displacement %s for \"%s\".\n"),
+ paddress (target_gdbarch, displacement),
+ bfd_get_filename (exec_bfd));
+ }
+
+ *displacementp = displacement;
+ return 1;
}
/* Relocate the main executable. This function should be called upon
stopping the inferior process at the entry point to the program.
- The entry point from BFD is compared to the PC and if they are
- different, the main executable is relocated by the proper amount.
-
- As written it will only attempt to relocate executables which
- lack interpreter sections. It seems likely that only dynamic
- linker executables will get relocated, though it should work
- properly for a position-independent static executable as well. */
+ The entry point from BFD is compared to the AT_ENTRY of AUXV and if they are
+ different, the main executable is relocated by the proper amount. */
static void
svr4_relocate_main_executable (void)
{
- asection *interp_sect;
- struct regcache *regcache
- = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
- CORE_ADDR pc = regcache_read_pc (regcache);
-
- /* Decide if the objfile needs to be relocated. As indicated above,
- we will only be here when execution is stopped at the beginning
- of the program. Relocation is necessary if the address at which
- we are presently stopped differs from the start address stored in
- the executable AND there's no interpreter section. The condition
- regarding the interpreter section is very important because if
- there *is* an interpreter section, execution will begin there
- instead. When there is an interpreter section, the start address
- is (presumably) used by the interpreter at some point to start
- execution of the program.
-
- If there is an interpreter, it is normal for it to be set to an
- arbitrary address at the outset. The job of finding it is
- handled in enable_break().
-
- So, to summarize, relocations are necessary when there is no
- interpreter section and the start address obtained from the
- executable is different from the address at which GDB is
- currently stopped.
-
- [ The astute reader will note that we also test to make sure that
- the executable in question has the DYNAMIC flag set. It is my
- opinion that this test is unnecessary (undesirable even). It
- was added to avoid inadvertent relocation of an executable
- whose e_type member in the ELF header is not ET_DYN. There may
- be a time in the future when it is desirable to do relocations
- on other types of files as well in which case this condition
- should either be removed or modified to accomodate the new file
- type. (E.g, an ET_EXEC executable which has been built to be
- position-independent could safely be relocated by the OS if
- desired. It is true that this violates the ABI, but the ABI
- has been known to be bent from time to time.) - Kevin, Nov 2000. ]
- */
-
- interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
- if (interp_sect == NULL
- && (bfd_get_file_flags (exec_bfd) & DYNAMIC) != 0
- && (exec_entry_point (exec_bfd, &exec_ops) != pc))
+ CORE_ADDR displacement;
+
+ if (symfile_objfile)
+ {
+ int i;
+
+ /* Remote target may have already set specific offsets by `qOffsets'
+ which should be preferred. */
+
+ for (i = 0; i < symfile_objfile->num_sections; i++)
+ if (ANOFFSET (symfile_objfile->section_offsets, i) != 0)
+ return;
+ }
+
+ if (! svr4_exec_displacement (&displacement))
+ return;
+
+ /* Even DISPLACEMENT 0 is a valid new difference of in-memory vs. in-file
+ addresses. */
+
+ if (symfile_objfile)
{
- struct cleanup *old_chain;
struct section_offsets *new_offsets;
- int i, changed;
- CORE_ADDR displacement;
-
- /* It is necessary to relocate the objfile. The amount to
- relocate by is simply the address at which we are stopped
- minus the starting address from the executable.
-
- We relocate all of the sections by the same amount. This
- behavior is mandated by recent editions of the System V ABI.
- According to the System V Application Binary Interface,
- Edition 4.1, page 5-5:
-
- ... Though the system chooses virtual addresses for
- individual processes, it maintains the segments' relative
- positions. Because position-independent code uses relative
- addressesing between segments, the difference between
- virtual addresses in memory must match the difference
- between virtual addresses in the file. The difference
- between the virtual address of any segment in memory and
- the corresponding virtual address in the file is thus a
- single constant value for any one executable or shared
- object in a given process. This difference is the base
- address. One use of the base address is to relocate the
- memory image of the program during dynamic linking.
-
- The same language also appears in Edition 4.0 of the System V
- ABI and is left unspecified in some of the earlier editions. */
-
- displacement = pc - exec_entry_point (exec_bfd, &exec_ops);
- changed = 0;
-
- new_offsets = xcalloc (symfile_objfile->num_sections,
- sizeof (struct section_offsets));
- old_chain = make_cleanup (xfree, new_offsets);
+ int i;
+
+ new_offsets = alloca (symfile_objfile->num_sections
+ * sizeof (*new_offsets));
for (i = 0; i < symfile_objfile->num_sections; i++)
- {
- if (displacement != ANOFFSET (symfile_objfile->section_offsets, i))
- changed = 1;
- new_offsets->offsets[i] = displacement;
- }
+ new_offsets->offsets[i] = displacement;
- if (changed)
- objfile_relocate (symfile_objfile, new_offsets);
+ objfile_relocate (symfile_objfile, new_offsets);
+ }
+ else if (exec_bfd)
+ {
+ asection *asect;
- do_cleanups (old_chain);
+ for (asect = exec_bfd->sections; asect != NULL; asect = asect->next)
+ exec_set_section_address (bfd_get_filename (exec_bfd), asect->index,
+ (bfd_section_vma (exec_bfd, asect)
+ + displacement));
}
}
SYNOPSIS
- void svr4_solib_create_inferior_hook ()
+ void svr4_solib_create_inferior_hook (int from_tty)
DESCRIPTION
*/
static void
-svr4_solib_create_inferior_hook (void)
+svr4_solib_create_inferior_hook (int from_tty)
{
struct inferior *inf;
struct thread_info *tp;
info = get_svr4_info ();
/* Relocate the main executable if necessary. */
- svr4_relocate_main_executable ();
+ if (current_inferior ()->attach_flag == 0)
+ svr4_relocate_main_executable ();
if (!svr4_have_link_map_offsets ())
return;
- if (!enable_break (info))
+ if (!enable_break (info, from_tty))
return;
#if defined(_SCO_DS)
static struct symbol *
elf_lookup_lib_symbol (const struct objfile *objfile,
const char *name,
- const char *linkage_name,
const domain_enum domain)
{
- if (objfile->obfd == NULL
- || scan_dyntag (DT_SYMBOLIC, objfile->obfd, NULL) != 1)
+ bfd *abfd;
+
+ if (objfile == symfile_objfile)
+ abfd = exec_bfd;
+ else
+ {
+ /* OBJFILE should have been passed as the non-debug one. */
+ gdb_assert (objfile->separate_debug_objfile_backlink == NULL);
+
+ abfd = objfile->obfd;
+ }
+
+ if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL) != 1)
return NULL;
- return lookup_global_symbol_from_objfile
- (objfile, name, linkage_name, domain);
+ return lookup_global_symbol_from_objfile (objfile, name, domain);
}
extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
svr4_so_ops.bfd_open = solib_bfd_open;
svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
svr4_so_ops.same = svr4_same;
+ svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
}