* solib.c (solib_break_names): Define for Solaris and Linux.
(enable_break): For SVR4 systems, first try to use the debugger interfaces in the dynamic linker to track shared library events as they happen, then fall back to BKPT_AT_SYMBOL code. Convert BKPT_AT_SYMBOL code to use shared library event breakpoints. (solib_create_inferior_hook): Simplify BKPT_AT_SYMBOL code, it no longer needs to restart/wait on the inferior. * symfile.c (find_lowest_section): No longer static. * symfile.h (find_lowest_section): Corresponding changes. Wraps up 7763 work, simplifies BKPT_AT_SYMBOL code somewhat, and allows debugging of startup code.
This commit is contained in:
parent
9263da6f13
commit
464c6c5f3f
|
@ -1,3 +1,15 @@
|
||||||
|
Tue Feb 20 23:59:19 1996 Jeffrey A Law (law@cygnus.com)
|
||||||
|
|
||||||
|
* solib.c (solib_break_names): Define for Solaris and Linux.
|
||||||
|
(enable_break): For SVR4 systems, first try to use the debugger
|
||||||
|
interfaces in the dynamic linker to track shared library events
|
||||||
|
as they happen, then fall back to BKPT_AT_SYMBOL code. Convert
|
||||||
|
BKPT_AT_SYMBOL code to use shared library event breakpoints.
|
||||||
|
(solib_create_inferior_hook): Simplify BKPT_AT_SYMBOL code,
|
||||||
|
it no longer needs to restart/wait on the inferior.
|
||||||
|
* symfile.c (find_lowest_section): No longer static.
|
||||||
|
* symfile.h (find_lowest_section): Corresponding changes.
|
||||||
|
|
||||||
Tue Feb 20 18:54:08 1996 Fred Fish <fnf@rtl.cygnus.com>
|
Tue Feb 20 18:54:08 1996 Fred Fish <fnf@rtl.cygnus.com>
|
||||||
|
|
||||||
* valops.c (COERCE_FLOAT_TO_DOUBLE): Define default value.
|
* valops.c (COERCE_FLOAT_TO_DOUBLE): Define default value.
|
||||||
|
|
204
gdb/solib.c
204
gdb/solib.c
|
@ -1,5 +1,5 @@
|
||||||
/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
|
/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
|
||||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995
|
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
|
||||||
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GDB.
|
This file is part of GDB.
|
||||||
|
@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "regex.h"
|
#include "gnu-regex.h"
|
||||||
#include "inferior.h"
|
#include "inferior.h"
|
||||||
#include "environ.h"
|
#include "environ.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
|
@ -53,15 +53,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
#define MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
|
#define MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
|
||||||
|
|
||||||
/* On SVR4 systems, for the initial implementation, use some runtime startup
|
/* On SVR4 systems, a list of symbols in the dynamic linker where
|
||||||
symbol as the "startup mapping complete" breakpoint address. The models
|
GDB can try to place a breakpoint to monitor shared library
|
||||||
for SunOS and SVR4 dynamic linking debugger support are different in that
|
events.
|
||||||
SunOS hits one breakpoint when all mapping is complete while using the SVR4
|
|
||||||
debugger support takes two breakpoint hits for each file mapped, and
|
If none of these symbols are found, or other errors occur, then
|
||||||
there is no way to know when the "last" one is hit. Both these
|
SVR4 systems will fall back to using a symbol as the "startup
|
||||||
mechanisms should be tied to a "breakpoint service routine" that
|
mapping complete" breakpoint address. */
|
||||||
gets automatically executed whenever one of the breakpoints indicating
|
|
||||||
a change in mapping is hit. This is a future enhancement. (FIXME) */
|
#ifdef SVR4_SHARED_LIBS
|
||||||
|
static char *solib_break_names[] = {
|
||||||
|
"r_debug_state",
|
||||||
|
"_dl_debug_state",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#define BKPT_AT_SYMBOL 1
|
#define BKPT_AT_SYMBOL 1
|
||||||
|
|
||||||
|
@ -93,17 +99,6 @@ static char *main_name_list[] = {
|
||||||
|
|
||||||
/* local data declarations */
|
/* local data declarations */
|
||||||
|
|
||||||
/* If true, then shared library symbols will be added automatically
|
|
||||||
when the inferior is created. This is almost always what users
|
|
||||||
will want to have happen; but for very large programs, the startup
|
|
||||||
time will be excessive, and so if this is a problem, the user can
|
|
||||||
clear this flag and then add the shared library symbols as needed.
|
|
||||||
Note that there is a potential for confusion, since if the shared
|
|
||||||
library symbols are not loaded, commands like "info fun" will *not*
|
|
||||||
report all the functions that are actually present. */
|
|
||||||
|
|
||||||
int auto_solib_add_at_startup = 1;
|
|
||||||
|
|
||||||
#ifndef SVR4_SHARED_LIBS
|
#ifndef SVR4_SHARED_LIBS
|
||||||
|
|
||||||
#define LM_ADDR(so) ((so) -> lm.lm_addr)
|
#define LM_ADDR(so) ((so) -> lm.lm_addr)
|
||||||
|
@ -312,6 +307,8 @@ allocate_rt_common_objfile ()
|
||||||
objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
|
objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
|
||||||
memset (objfile, 0, sizeof (struct objfile));
|
memset (objfile, 0, sizeof (struct objfile));
|
||||||
objfile -> md = NULL;
|
objfile -> md = NULL;
|
||||||
|
obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
|
||||||
|
xmalloc, free);
|
||||||
obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, xmalloc,
|
obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, xmalloc,
|
||||||
free);
|
free);
|
||||||
obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, xmalloc,
|
obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, xmalloc,
|
||||||
|
@ -1013,6 +1010,13 @@ solib_add (arg_string, from_tty, target)
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
|
int update_coreops;
|
||||||
|
|
||||||
|
/* We must update the to_sections field in the core_ops structure
|
||||||
|
here, otherwise we dereference a potential dangling pointer
|
||||||
|
for each call to target_read/write_memory within this routine. */
|
||||||
|
update_coreops = core_ops.to_sections == target->to_sections;
|
||||||
|
|
||||||
/* Reallocate the target's section table including the new size. */
|
/* Reallocate the target's section table including the new size. */
|
||||||
if (target -> to_sections)
|
if (target -> to_sections)
|
||||||
{
|
{
|
||||||
|
@ -1029,6 +1033,14 @@ solib_add (arg_string, from_tty, target)
|
||||||
}
|
}
|
||||||
target -> to_sections_end = target -> to_sections + (count + old);
|
target -> to_sections_end = target -> to_sections + (count + old);
|
||||||
|
|
||||||
|
/* Update the to_sections field in the core_ops structure
|
||||||
|
if needed. */
|
||||||
|
if (update_coreops)
|
||||||
|
{
|
||||||
|
core_ops.to_sections = target->to_sections;
|
||||||
|
core_ops.to_sections_end = target->to_sections_end;
|
||||||
|
}
|
||||||
|
|
||||||
/* Add these section table entries to the target's table. */
|
/* Add these section table entries to the target's table. */
|
||||||
while ((so = find_solib (so)) != NULL)
|
while ((so = find_solib (so)) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1143,7 +1155,7 @@ GLOBAL FUNCTION
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
|
|
||||||
int solib_address (CORE_ADDR address)
|
char * solib_address (CORE_ADDR address)
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
|
@ -1159,7 +1171,7 @@ DESCRIPTION
|
||||||
mapped in.
|
mapped in.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
char *
|
||||||
solib_address (address)
|
solib_address (address)
|
||||||
CORE_ADDR address;
|
CORE_ADDR address;
|
||||||
{
|
{
|
||||||
|
@ -1171,9 +1183,7 @@ solib_address (address)
|
||||||
{
|
{
|
||||||
if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
|
if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
|
||||||
(address < (CORE_ADDR) so -> lmend))
|
(address < (CORE_ADDR) so -> lmend))
|
||||||
{
|
return (so->so_name);
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -1361,8 +1371,105 @@ enable_break ()
|
||||||
#ifdef BKPT_AT_SYMBOL
|
#ifdef BKPT_AT_SYMBOL
|
||||||
|
|
||||||
struct minimal_symbol *msymbol;
|
struct minimal_symbol *msymbol;
|
||||||
|
struct objfile *objfile;
|
||||||
char **bkpt_namep;
|
char **bkpt_namep;
|
||||||
CORE_ADDR bkpt_addr;
|
CORE_ADDR bkpt_addr;
|
||||||
|
asection *interp_sect;
|
||||||
|
|
||||||
|
/* First, remove all the solib event breakpoints. Their addresses
|
||||||
|
may have changed since the last time we ran the program. */
|
||||||
|
remove_solib_event_breakpoints ();
|
||||||
|
|
||||||
|
#ifdef SVR4_SHARED_LIBS
|
||||||
|
/* 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");
|
||||||
|
if (interp_sect)
|
||||||
|
{
|
||||||
|
unsigned int interp_sect_size;
|
||||||
|
char *buf;
|
||||||
|
CORE_ADDR load_addr;
|
||||||
|
bfd *tmp_bfd;
|
||||||
|
asection *lowest_sect;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
bfd_get_section_contents (exec_bfd, interp_sect,
|
||||||
|
buf, 0, interp_sect_size);
|
||||||
|
|
||||||
|
/* Now we need to figure out where the dynamic linker was
|
||||||
|
loaded so that we can load its symbols and place a breakpoint
|
||||||
|
in the dynamic linker itself.
|
||||||
|
|
||||||
|
This address is stored on the stack. However, I've been unable
|
||||||
|
to find any magic formula to find it for Solaris (appears to
|
||||||
|
be trivial on Linux). Therefore, we have to try an alternate
|
||||||
|
mechanism to find the dynamic linker's base address. */
|
||||||
|
tmp_bfd = bfd_openr (buf, gnutarget);
|
||||||
|
if (tmp_bfd == NULL)
|
||||||
|
goto bkpt_at_symbol;
|
||||||
|
|
||||||
|
/* Make sure the dynamic linker's really a useful object. */
|
||||||
|
if (!bfd_check_format (tmp_bfd, bfd_object))
|
||||||
|
{
|
||||||
|
warning ("Unable to grok dynamic linker %s as an object file", buf);
|
||||||
|
bfd_close (tmp_bfd);
|
||||||
|
goto bkpt_at_symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We find the dynamic linker's base address by examining the
|
||||||
|
current pc (which point at the entry point for the dynamic
|
||||||
|
linker) and subtracting the offset of the entry point. */
|
||||||
|
load_addr = read_pc () - tmp_bfd->start_address;
|
||||||
|
|
||||||
|
/* load_addr now has the base address of the dynamic linker;
|
||||||
|
however, due to severe braindamage in syms_from_objfile
|
||||||
|
we need to add the address of the .text section, or the
|
||||||
|
lowest section of .text doesn't exist to work around the
|
||||||
|
braindamage. Gross. */
|
||||||
|
lowest_sect = bfd_get_section_by_name (tmp_bfd, ".text");
|
||||||
|
if (lowest_sect == NULL)
|
||||||
|
bfd_map_over_sections (tmp_bfd, find_lowest_section,
|
||||||
|
(PTR) &lowest_sect);
|
||||||
|
|
||||||
|
if (lowest_sect == NULL)
|
||||||
|
{
|
||||||
|
warning ("Unable to find base address for dynamic linker %s\n", buf);
|
||||||
|
bfd_close (tmp_bfd);
|
||||||
|
goto bkpt_at_symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
load_addr += bfd_section_vma (tmp_bfd, lowest_sect);
|
||||||
|
|
||||||
|
/* We're done with the temporary bfd. */
|
||||||
|
bfd_close (tmp_bfd);
|
||||||
|
|
||||||
|
/* Now make GDB aware of the symbols in the dynamic linker. Some
|
||||||
|
might complain about namespace pollution, but as a developer I've
|
||||||
|
often wanted these symbols available from within the debugger. */
|
||||||
|
objfile = symbol_file_add (buf, 0, load_addr, 0, 0, 1);
|
||||||
|
|
||||||
|
/* Now try to set a breakpoint in the dynamic linker. */
|
||||||
|
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
|
||||||
|
{
|
||||||
|
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, objfile);
|
||||||
|
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
|
||||||
|
{
|
||||||
|
create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For whatever reason we couldn't set a breakpoint in the dynamic
|
||||||
|
linker. Warn and drop into the old code. */
|
||||||
|
bkpt_at_symbol:
|
||||||
|
warning ("Unable to find dynamic linker breakpoint function.");
|
||||||
|
warning ("GDB will be unable to debug shared library initializers");
|
||||||
|
warning ("and track explicitly loaded dynamic code.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Scan through the list of symbols, trying to look up the symbol and
|
/* Scan through the list of symbols, trying to look up the symbol and
|
||||||
set a breakpoint there. Terminate loop when we/if we succeed. */
|
set a breakpoint there. Terminate loop when we/if we succeed. */
|
||||||
|
@ -1373,31 +1480,13 @@ enable_break ()
|
||||||
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
|
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
|
||||||
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
|
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
|
||||||
{
|
{
|
||||||
bkpt_addr = SYMBOL_VALUE_ADDRESS (msymbol);
|
create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
|
||||||
if (target_insert_breakpoint (bkpt_addr, shadow_contents) == 0)
|
return 1;
|
||||||
{
|
|
||||||
breakpoint_addr = bkpt_addr;
|
|
||||||
success = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !BKPT_AT_SYMBOL */
|
/* Nothing good happened. */
|
||||||
|
return 0;
|
||||||
struct symtab_and_line sal;
|
|
||||||
|
|
||||||
/* Read the debugger interface structure directly. */
|
|
||||||
|
|
||||||
read_memory (debug_base, (char *) &debug_copy, sizeof (debug_copy));
|
|
||||||
|
|
||||||
/* Set breakpoint at the debugger interface stub routine that will
|
|
||||||
be called just prior to each mapping change and again after the
|
|
||||||
mapping change is complete. Set up the (nonexistent) handler to
|
|
||||||
deal with hitting these breakpoints. (FIXME). */
|
|
||||||
|
|
||||||
warning ("'%s': line %d: missing SVR4 support code", __FILE__, __LINE__);
|
|
||||||
success = 1;
|
|
||||||
|
|
||||||
#endif /* BKPT_AT_SYMBOL */
|
#endif /* BKPT_AT_SYMBOL */
|
||||||
|
|
||||||
|
@ -1479,7 +1568,12 @@ solib_create_inferior_hook()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now run the target. It will eventually hit the breakpoint, at
|
#ifndef BKPT_AT_SYMBOL
|
||||||
|
/* Only SunOS needs the loop below, other systems should be using the
|
||||||
|
special shared library breakpoints and the shared library breakpoint
|
||||||
|
service routine.
|
||||||
|
|
||||||
|
Now run the target. It will eventually hit the breakpoint, at
|
||||||
which point all of the libraries will have been mapped in and we
|
which point all of the libraries will have been mapped in and we
|
||||||
can go groveling around in the dynamic linker structures to find
|
can go groveling around in the dynamic linker structures to find
|
||||||
out what we need to know about them. */
|
out what we need to know about them. */
|
||||||
|
@ -1511,8 +1605,9 @@ solib_create_inferior_hook()
|
||||||
warning ("shared library handler failed to disable breakpoint");
|
warning ("shared library handler failed to disable breakpoint");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto_solib_add_at_startup)
|
if (auto_solib_add)
|
||||||
solib_add ((char *) 0, 0, (struct target_ops *) 0);
|
solib_add ((char *) 0, 0, (struct target_ops *) 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1617,10 +1712,11 @@ _initialize_solib()
|
||||||
|
|
||||||
add_show_from_set
|
add_show_from_set
|
||||||
(add_set_cmd ("auto-solib-add", class_support, var_zinteger,
|
(add_set_cmd ("auto-solib-add", class_support, var_zinteger,
|
||||||
(char *) &auto_solib_add_at_startup,
|
(char *) &auto_solib_add,
|
||||||
"Set autoloading of shared library symbols at startup.\n\
|
"Set autoloading of shared library symbols.\n\
|
||||||
If nonzero, symbols from all shared object libraries will be loaded\n\
|
If nonzero, symbols from all shared object libraries will be loaded\n\
|
||||||
automatically when the inferior begins execution. Otherwise, symbols\n\
|
automatically when the inferior begins execution or when the dynamic linker\n\
|
||||||
|
informs gdb that a new library has been loaded. Otherwise, symbols\n\
|
||||||
must be loaded manually, using `sharedlibrary'.",
|
must be loaded manually, using `sharedlibrary'.",
|
||||||
&setlist),
|
&setlist),
|
||||||
&showlist);
|
&showlist);
|
||||||
|
|
|
@ -350,7 +350,7 @@ entry_point_address()
|
||||||
If the vmas and sizes are equal, the last section is considered the
|
If the vmas and sizes are equal, the last section is considered the
|
||||||
lowest-addressed loadable section. */
|
lowest-addressed loadable section. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
find_lowest_section (abfd, sect, obj)
|
find_lowest_section (abfd, sect, obj)
|
||||||
bfd *abfd;
|
bfd *abfd;
|
||||||
asection *sect;
|
asection *sect;
|
||||||
|
|
Loading…
Reference in New Issue