/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998
Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
+/* This file is only compilable if link.h is available. */
+
+#ifdef HAVE_LINK_H
+
#include <sys/types.h>
#include <signal.h>
#include "gdb_string.h"
#ifdef SVR4_SHARED_LIBS
static char *solib_break_names[] = {
"r_debug_state",
+ "_r_debug_state",
"_dl_debug_state",
+ "rtld_db_dlactivity",
NULL
};
#endif
static CORE_ADDR debug_base; /* Base of dynamic linker structures */
static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
+static int solib_cleanup_queued = 0; /* make_run_cleanup called */
+
extern int
fdmatch PARAMS ((int, int)); /* In libiberty */
/* Local function prototypes */
+static void
+do_clear_solib PARAMS ((PTR));
+
+static int
+match_main PARAMS ((char *));
+
static void
special_symbol_handling PARAMS ((struct so_list *));
static int
enable_break PARAMS ((void));
-static int
-disable_break PARAMS ((void));
-
static void
info_sharedlibrary_command PARAMS ((char *, int));
#else
+static int
+disable_break PARAMS ((void));
+
static void
allocate_rt_common_objfile PARAMS ((void));
#endif
+/* If non-zero, this is a prefix that will be added to the front of the name
+ shared libraries with an absolute filename for loading. */
+static char *solib_absolute_prefix = NULL;
+
+/* If non-empty, this is a search path for loading non-absolute shared library
+ symbol files. This takes precedence over the environment variables PATH
+ and LD_LIBRARY_PATH. */
+static char *solib_search_path = NULL;
+
/*
LOCAL FUNCTION
bfd *abfd;
filename = tilde_expand (so -> so_name);
- old_chain = make_cleanup (free, filename);
- scratch_chan = openp (get_in_environ (inferior_environ, "PATH"),
- 1, filename, O_RDONLY, 0, &scratch_pathname);
+ if (solib_absolute_prefix && ROOTED_P (filename))
+ /* Prefix shared libraries with absolute filenames with
+ SOLIB_ABSOLUTE_PREFIX. */
+ {
+ char *pfxed_fn;
+ int pfx_len;
+
+ pfx_len = strlen (solib_absolute_prefix);
+
+ /* Remove trailing slashes. */
+ while (pfx_len > 0 && SLASH_P (solib_absolute_prefix[pfx_len - 1]))
+ pfx_len--;
+
+ pfxed_fn = xmalloc (pfx_len + strlen (filename) + 1);
+ strcpy (pfxed_fn, solib_absolute_prefix);
+ strcat (pfxed_fn, filename);
+ free (filename);
+
+ filename = pfxed_fn;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = -1;
+
+ if (solib_search_path)
+ scratch_chan = openp (solib_search_path,
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
+ if (scratch_chan < 0)
+ scratch_chan = openp (get_in_environ (inferior_environ, "PATH"),
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
if (scratch_chan < 0)
{
scratch_chan = openp (get_in_environ
struct nlist inferior_rtc_nlist;
int len;
char *name;
- char *origname;
/* Remove any runtime common symbols from previous runs. */
behind the name of the symbol. */
len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
- origname = name = xmalloc (len);
+ name = xmalloc (len);
read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);
/* Allocate the runtime common objfile if necessary. */
if (rt_common_objfile == NULL)
allocate_rt_common_objfile ();
- name = obsavestring (name, strlen (name),
- &rt_common_objfile -> symbol_obstack);
prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value,
mst_bss, rt_common_objfile);
- free (origname);
+ free (name);
}
rtc_symp = inferior_rtc_symb.rtc_next;
}
#ifdef SVR4_SHARED_LIBS
-#ifdef HANDLE_SVR4_EXEC_EMULATORS
-
-/*
- Solaris BCP (the part of Solaris which allows it to run SunOS4
- a.out files) throws in another wrinkle. Solaris does not fill
- in the usual a.out link map structures when running BCP programs,
- the only way to get at them is via groping around in the dynamic
- linker.
- The dynamic linker and it's structures are located in the shared
- C library, which gets run as the executable's "interpreter" by
- the kernel.
-
- Note that we can assume nothing about the process state at the time
- we need to find these structures. We may be stopped on the first
- instruction of the interpreter (C shared library), the first
- instruction of the executable itself, or somewhere else entirely
- (if we attached to the process for example).
-*/
-
-static char *debug_base_symbols[] = {
- "r_debug", /* Solaris 2.3 */
- "_r_debug", /* Solaris 2.1, 2.2 */
- NULL
-};
-
-static int
-look_for_base PARAMS ((int, CORE_ADDR));
-
static CORE_ADDR
bfd_lookup_symbol PARAMS ((bfd *, char *));
return (symaddr);
}
+#ifdef HANDLE_SVR4_EXEC_EMULATORS
+
+/*
+ Solaris BCP (the part of Solaris which allows it to run SunOS4
+ a.out files) throws in another wrinkle. Solaris does not fill
+ in the usual a.out link map structures when running BCP programs,
+ the only way to get at them is via groping around in the dynamic
+ linker.
+ The dynamic linker and it's structures are located in the shared
+ C library, which gets run as the executable's "interpreter" by
+ the kernel.
+
+ Note that we can assume nothing about the process state at the time
+ we need to find these structures. We may be stopped on the first
+ instruction of the interpreter (C shared library), the first
+ instruction of the executable itself, or somewhere else entirely
+ (if we attached to the process for example).
+*/
+
+static char *debug_base_symbols[] = {
+ "r_debug", /* Solaris 2.3 */
+ "_r_debug", /* Solaris 2.1, 2.2 */
+ NULL
+};
+
+static int
+look_for_base PARAMS ((int, CORE_ADDR));
+
/*
LOCAL FUNCTION
/* Find the DT_DEBUG entry in the the .dynamic section.
For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
no DT_DEBUG entries. */
- /* FIXME: In lack of a 64 bit ELF ABI the following code assumes
- a 32 bit ELF ABI target. */
+#ifndef TARGET_ELF64
for (bufend = buf + dyninfo_sect_size;
buf < bufend;
buf += sizeof (Elf32_External_Dyn))
}
#endif
}
+#else /* ELF64 */
+ for (bufend = buf + dyninfo_sect_size;
+ buf < bufend;
+ buf += sizeof (Elf64_External_Dyn))
+ {
+ Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *)buf;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr;
+
+ dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
+ if (dyn_tag == DT_NULL)
+ break;
+ else if (dyn_tag == DT_DEBUG)
+ {
+ dyn_ptr = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ return dyn_ptr;
+ }
+ }
+#endif
/* DT_DEBUG entry not found. */
return 0;
debug_base = elf_locate_base ();
#ifdef HANDLE_SVR4_EXEC_EMULATORS
/* Try it the hard way for emulated executables. */
- else if (inferior_pid != 0)
+ else if (inferior_pid != 0 && target_has_execution)
proc_iterate_over_mappings (look_for_base);
#endif
}
else
{
so_list_head = new;
+
+ if (! solib_cleanup_queued)
+ {
+ make_run_cleanup (do_clear_solib);
+ solib_cleanup_queued = 1;
+ }
+
}
so_list_next = new;
read_memory ((CORE_ADDR) lm, (char *) &(new -> lm),
char *arg;
{
register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+ CORE_ADDR text_addr = 0;
+
+ if (so -> textsection)
+ text_addr = so -> textsection -> addr;
+ else
+ {
+ asection *lowest_sect;
+
+ /* If we didn't find a mapped non zero sized .text section, set up
+ text_addr so that the relocation in symbol_file_add does no harm. */
+
+ lowest_sect = bfd_get_section_by_name (so -> abfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (so -> abfd, find_lowest_section,
+ (PTR) &lowest_sect);
+ if (lowest_sect)
+ text_addr = bfd_section_vma (so -> abfd, lowest_sect)
+ + (CORE_ADDR) LM_ADDR (so);
+ }
+ ALL_OBJFILES (so -> objfile)
+ {
+ if (strcmp (so -> objfile -> name, so -> so_name) == 0)
+ return 1;
+ }
so -> objfile =
symbol_file_add (so -> so_name, so -> from_tty,
- (so->textsection == NULL
- ? 0
- : (unsigned int) so -> textsection -> addr),
+ text_addr,
0, 0, 0);
return (1);
}
{
register struct so_list *so = NULL; /* link map state variable */
int header_done = 0;
-
+ int addr_width;
+ char *addr_fmt;
+
if (exec_bfd == NULL)
{
printf_unfiltered ("No exec file.\n");
return;
}
+
+#ifndef TARGET_ELF64
+ addr_width = 8+4;
+ addr_fmt = "08l";
+#else
+ addr_width = 16+4;
+ addr_fmt = "016l";
+#endif
+
while ((so = find_solib (so)) != NULL)
{
if (so -> so_name[0])
{
if (!header_done)
{
- printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
- "Shared Object Library");
+ printf_unfiltered("%-*s%-*s%-12s%s\n", addr_width, "From",
+ addr_width, "To", "Syms Read",
+ "Shared Object Library");
header_done++;
}
- /* FIXME-32x64: need print_address_numeric with field width or
- some such. */
- printf_unfiltered ("%-12s",
+
+ printf_unfiltered ("%-*s", addr_width,
local_hex_string_custom ((unsigned long) LM_ADDR (so),
- "08l"));
- printf_unfiltered ("%-12s",
+ addr_fmt));
+ printf_unfiltered ("%-*s", addr_width,
local_hex_string_custom ((unsigned long) so -> lmend,
- "08l"));
+ addr_fmt));
printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
printf_unfiltered ("%s\n", so -> so_name);
}
debug_base = 0;
}
+static void
+do_clear_solib (dummy)
+ PTR dummy;
+{
+ solib_cleanup_queued = 0;
+ clear_solib ();
+}
+
+#ifdef SVR4_SHARED_LIBS
+
+/* Return 1 if PC lies in the dynamic symbol resolution code of the
+ SVR4 run time loader. */
+
+static CORE_ADDR interp_text_sect_low;
+static CORE_ADDR interp_text_sect_high;
+static CORE_ADDR interp_plt_sect_low;
+static CORE_ADDR interp_plt_sect_high;
+
+int
+in_svr4_dynsym_resolve_code (pc)
+ CORE_ADDR pc;
+{
+ 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));
+}
+#endif
+
/*
LOCAL FUNCTION
*/
+#ifndef SVR4_SHARED_LIBS
+
static int
disable_break ()
{
return (status);
}
+#endif /* #ifdef SVR4_SHARED_LIBS */
+
/*
LOCAL FUNCTION
remove_solib_event_breakpoints ();
#ifdef SVR4_SHARED_LIBS
+ interp_text_sect_low = interp_text_sect_high = 0;
+ interp_plt_sect_low = interp_plt_sect_high = 0;
+
/* Find the .interp section; if not found, warn the user and drop
into the old breakpoint at symbol code. */
interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
linker) and subtracting the offset of the entry point. */
load_addr = read_pc () - tmp_bfd->start_address;
+ /* Record the relocated start and end address of the dynamic linker
+ text and plt section for in_svr4_dynsym_resolve_code. */
+ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+ if (interp_sect)
+ {
+ interp_text_sect_low =
+ bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ interp_text_sect_high =
+ interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ }
+ interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+ if (interp_sect)
+ {
+ interp_plt_sect_low =
+ bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ interp_plt_sect_high =
+ interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
+ }
+
/* Now try to set a breakpoint in the dynamic linker. */
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
}
/* Nothing good happened. */
- return 0;
+ success = 0;
#endif /* BKPT_AT_SYMBOL */
Also, what if child has exit()ed? Must exit loop somehow.
*/
-void
+void
solib_create_inferior_hook()
{
+ static int dyn_relocated;
+
/* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
yet. In fact, in the case of a SunOS4 executable being run on
Solaris, we can't get it yet. find_solib will get it when it needs
return;
}
+ if (!dyn_relocated && exec_bfd->start_address != stop_pc)
+ {
+ /* We have to relocate the debug information. */
+ CORE_ADDR displacement = stop_pc - exec_bfd->start_address;
+ struct section_offsets *new_offsets;
+ int i;
+
+ new_offsets = alloca (symfile_objfile->num_sections
+ * sizeof (*new_offsets));
+
+ for (i = 0; i < symfile_objfile->num_sections; ++i)
+ ANOFFSET (new_offsets, i) =
+ ANOFFSET (symfile_objfile->section_offsets, i);
+
+ ANOFFSET (new_offsets, SECT_OFF_TEXT) += displacement;
+ ANOFFSET (new_offsets, SECT_OFF_DATA) += displacement;
+ ANOFFSET (new_offsets, SECT_OFF_BSS) += displacement;
+ ANOFFSET (new_offsets, SECT_OFF_RODATA) += displacement;
+
+ objfile_relocate (symfile_objfile, new_offsets);
+ breakpoint_re_set ();
+
+ /* Make sure this relocation is done only once. */
+ dyn_relocated = 1;
+ }
+
#ifndef SVR4_SHARED_LIBS
/* Only SunOS needs the loop below, other systems should be using the
special shared library breakpoints and the shared library breakpoint
solib_add (args, from_tty, (struct target_ops *) 0);
}
+#endif /* HAVE_LINK_H */
+
void
_initialize_solib()
{
-
+#ifdef HAVE_LINK_H
+
add_com ("sharedlibrary", class_files, sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
add_info ("sharedlibrary", info_sharedlibrary_command,
must be loaded manually, using `sharedlibrary'.",
&setlist),
&showlist);
+
+ add_show_from_set
+ (add_set_cmd ("solib-absolute-prefix", class_support, var_filename,
+ (char *) &solib_absolute_prefix,
+ "Set prefix for loading absolute shared library symbol files.\n\
+For other (relative) files, you can add values using `set solib-search-path'.",
+ &setlist),
+ &showlist);
+ add_show_from_set
+ (add_set_cmd ("solib-search-path", class_support, var_string,
+ (char *) &solib_search_path,
+ "Set the search path for loading non-absolute shared library symbol files.\n\
+This takes precedence over the environment variables PATH and LD_LIBRARY_PATH.",
+ &setlist),
+ &showlist);
+
+#endif /* HAVE_LINK_H */
}