1
0
mirror of https://github.com/openbsd/src.git synced 2025-01-10 06:47:55 -08:00

Enable support for debugging pie programs. Code from Elena Zannoni's

<ezannoni at redhat dot com> pie branch in gdb cvs, less extraneous
parts and with some bug fixes. Debugging w/core files for pie programs
isn't working yet since AUXV data isn't included in our core files at
the moment.

feedback and ok kettenis@
This commit is contained in:
kurt 2008-11-11 22:57:48 +00:00
parent 22c6a57d9b
commit 15135fad20
12 changed files with 285 additions and 50 deletions

View File

@ -2289,7 +2289,7 @@ objc-lang.o: objc-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \
$(objfiles_h) $(gdb_stabs_h) $(target_h) $(bcache_h) $(gdb_assert_h) \
$(gdb_stat_h) $(gdb_obstack_h) $(gdb_string_h) $(hashtab_h) \
$(breakpoint_h) $(block_h) $(dictionary_h)
$(breakpoint_h) $(block_h) $(dictionary_h) $(auxv_h) $(elf_common_h)
observer.o: observer.c $(defs_h) $(observer_h) $(command_h) $(gdbcmd_h) \
$(observer_inc)
obsd-tdep.o: obsd-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(obsd_tdep_h)
@ -2511,7 +2511,7 @@ solib-sunos.o: solib-sunos.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \
solib-svr4.o: solib-svr4.c $(defs_h) $(elf_external_h) $(elf_common_h) \
$(elf_mips_h) $(symtab_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
$(gdbcore_h) $(target_h) $(inferior_h) $(solist_h) $(solib_svr4_h) \
$(bfd_target_h) $(exec_h)
$(bfd_target_h) $(exec_h) $(auxv_h) $(command_h)
sol-thread.o: sol-thread.c $(defs_h) $(gdbthread_h) $(target_h) \
$(inferior_h) $(gdb_stat_h) $(gdbcmd_h) $(gdbcore_h) $(regcache_h) \
$(symfile_h) $(gdb_string_h) $(gregset_h)
@ -2603,7 +2603,7 @@ symfile.o: symfile.c $(defs_h) $(bfdlink_h) $(symtab_h) $(gdbtypes_h) \
$(complaints_h) $(demangle_h) $(inferior_h) $(filenames_h) \
$(gdb_stabs_h) $(gdb_obstack_h) $(completer_h) $(bcache_h) \
$(hashtab_h) $(readline_h) $(gdb_assert_h) $(block_h) \
$(gdb_string_h) $(gdb_stat_h)
$(gdb_string_h) $(gdb_stat_h) $(varobj_h)
symfile-mem.o: symfile-mem.c $(defs_h) $(symtab_h) $(gdbcore_h) \
$(objfiles_h) $(gdbcmd_h) $(target_h) $(value_h) $(symfile_h)
symmisc.o: symmisc.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(bfd_h) \

View File

@ -3783,6 +3783,7 @@ describe_other_breakpoints (CORE_ADDR pc, asection *section)
b->number,
((b->enable_state == bp_disabled ||
b->enable_state == bp_shlib_disabled ||
b->enable_state == bp_startup_disabled ||
b->enable_state == bp_call_disabled)
? " (disabled)"
: b->enable_state == bp_permanent
@ -4457,6 +4458,60 @@ re_enable_breakpoints_in_shlibs (void)
#endif
void
disable_breakpoints_at_startup (int silent)
{
struct breakpoint *b;
int disabled_startup_breaks = 0;
if (bfd_get_start_address (exec_bfd) != entry_point_address ())
{
ALL_BREAKPOINTS (b)
{
if (((b->type == bp_breakpoint) ||
(b->type == bp_hardware_breakpoint)) &&
b->enable_state == bp_enabled &&
!b->loc->duplicate &&
!b->pending)
{
b->enable_state = bp_startup_disabled;
if (!silent)
{
if (!disabled_startup_breaks)
{
target_terminal_ours_for_output ();
warning ("Temporarily disabling breakpoints:");
}
disabled_startup_breaks = 1;
warning ("breakpoint #%d addr 0x%s", b->number, paddr_nz(b->loc->address));
}
}
}
}
}
/* Try to reenable any breakpoints after startup. */
void
re_enable_breakpoints_at_startup (void)
{
struct breakpoint *b;
if (bfd_get_start_address (exec_bfd) != entry_point_address ())
{
ALL_BREAKPOINTS (b)
if (b->enable_state == bp_startup_disabled)
{
char buf[1];
/* Do not reenable the breakpoint if the shared library
is still not mapped in. */
if (target_read_memory (b->loc->address, buf, 1) == 0)
b->enable_state = bp_enabled;
}
}
}
static void
solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname,
char *cond_string, enum bptype bp_kind)
@ -6978,6 +7033,7 @@ delete_breakpoint (struct breakpoint *bpt)
&& !b->loc->duplicate
&& b->enable_state != bp_disabled
&& b->enable_state != bp_shlib_disabled
&& b->enable_state != bp_startup_disabled
&& !b->pending
&& b->enable_state != bp_call_disabled)
{
@ -7191,7 +7247,8 @@ breakpoint_re_set_one (void *bint)
break;
save_enable = b->enable_state;
if (b->enable_state != bp_shlib_disabled)
if (b->enable_state != bp_shlib_disabled
&& b->enable_state != bp_startup_disabled)
b->enable_state = bp_disabled;
else
/* If resetting a shlib-disabled breakpoint, we don't want to

View File

@ -159,6 +159,7 @@ enum enable_state
automatically enabled and reset when the call
"lands" (either completes, or stops at another
eventpoint). */
bp_startup_disabled,
bp_permanent /* There is a breakpoint instruction hard-wired into
the target's code. Don't try to write another
breakpoint instruction on top of it, or restore
@ -765,8 +766,12 @@ extern void remove_thread_event_breakpoints (void);
extern void disable_breakpoints_in_shlibs (int silent);
extern void disable_breakpoints_at_startup (int silent);
extern void re_enable_breakpoints_in_shlibs (void);
void re_enable_breakpoints_at_startup (void);
extern void create_solib_load_event_breakpoint (char *, int, char *, char *);
extern void create_solib_unload_event_breakpoint (char *, int,

View File

@ -2120,6 +2120,11 @@ process_event_stop_test:
code segments in shared libraries might be mapped in now. */
re_enable_breakpoints_in_shlibs ();
/* For PIE executables, we dont really know where the
breakpoints are going to be until we start up the
inferior. */
re_enable_breakpoints_at_startup ();
/* If requested, stop when the dynamic linker notifies
gdb of events. This allows the user to get control
and place breakpoints in initializer routines for

View File

@ -45,6 +45,9 @@
#include "breakpoint.h"
#include "block.h"
#include "dictionary.h"
#include "auxv.h"
#include "elf/common.h"
/* Prototypes for local functions */
@ -257,7 +260,12 @@ init_entry_point_info (struct objfile *objfile)
CORE_ADDR
entry_point_address (void)
{
return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
CORE_ADDR entry_addr = symfile_objfile ? symfile_objfile->ei.entry_point : 0;
/* Find the address of the entry point of the program from the
auxv vector. */
target_auxv_search (&current_target, AT_ENTRY, &entry_addr);
return entry_addr;
}
/* Create the terminating entry of OBJFILE's minimal symbol table.

View File

@ -27,6 +27,7 @@
#include "elf/common.h"
#include "elf/mips.h"
#include "auxv.h"
#include "symtab.h"
#include "bfd.h"
#include "symfile.h"
@ -34,6 +35,7 @@
#include "gdbcore.h"
#include "target.h"
#include "inferior.h"
#include "command.h"
#include "solist.h"
#include "solib-svr4.h"
@ -179,7 +181,9 @@ static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
/* Local function prototypes */
#if 0
static int match_main (char *);
#endif
static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
@ -301,21 +305,32 @@ elf_locate_base (void)
{
struct bfd_section *dyninfo_sect;
int dyninfo_sect_size;
CORE_ADDR dyninfo_addr;
CORE_ADDR dyninfo_addr, relocated_dyninfo_addr, entry_addr;
char *buf;
char *bufend;
int arch_size;
/* Find the address of the entry point of the program from the
auxv vector. */
if (target_auxv_search (&current_target, AT_ENTRY, &entry_addr) != 1)
{
/* No auxv info, maybe an older kernel. Fake our way through. */
entry_addr = bfd_get_start_address (exec_bfd);
}
/* Find the start address of the .dynamic section. */
dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
if (dyninfo_sect == NULL)
return 0;
dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
relocated_dyninfo_addr = dyninfo_addr
+ entry_addr - bfd_get_start_address(exec_bfd);
/* Read in .dynamic section, silently ignore errors. */
dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
buf = alloca (dyninfo_sect_size);
if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
if (target_read_memory (relocated_dyninfo_addr, buf, dyninfo_sect_size))
return 0;
/* Find the DT_DEBUG entry in the the .dynamic section.
@ -636,7 +651,47 @@ svr4_current_sos (void)
does have a name, so we can no longer use a missing name to
decide when to ignore it. */
if (IGNORE_FIRST_LINK_MAP_ENTRY (new))
free_so (new);
{
/* It is the first link map entry, i.e. it is the main executable. */
if (bfd_get_start_address (exec_bfd) == entry_point_address ())
{
/* Non-pie case, main executable has not been relocated. */
free_so (new);
}
else
{
/* Pie case, main executable has been relocated. */
struct so_list *gdb_solib;
strncpy (new->so_name, exec_bfd->filename,
SO_NAME_MAX_PATH_SIZE - 1);
new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
strcpy (new->so_original_name, new->so_name);
new->main_relocated = 0;
for (gdb_solib = master_so_list ();
gdb_solib;
gdb_solib = gdb_solib->next)
{
if (strcmp (gdb_solib->so_name, new->so_name) == 0)
if (gdb_solib->main_relocated)
break;
}
if ((gdb_solib && !gdb_solib->main_relocated) || (!gdb_solib))
{
add_to_target_sections (0 /*from_tty*/, &current_target, new);
new->main = 1;
}
/* We need this in the list of shared libs we return because
solib_add_stub will loop through it and add the symbol file. */
new->next = 0;
*link_ptr = new;
link_ptr = &new->next;
}
} /* End of IGNORE_FIRST_LINK_MAP_ENTRY */
else
{
int errcode;
@ -658,17 +713,10 @@ svr4_current_sos (void)
strcpy (new->so_original_name, new->so_name);
}
/* If this entry has no name, or its name matches the name
for the main executable, don't include it in the list. */
if (! new->so_name[0]
|| match_main (new->so_name))
free_so (new);
else
{
new->next = 0;
*link_ptr = new;
link_ptr = &new->next;
}
new->next = 0;
*link_ptr = new;
link_ptr = &new->next;
}
discard_cleanups (old_chain);
@ -754,6 +802,7 @@ svr4_fetch_objfile_link_map (struct objfile *objfile)
the main executable file is by looking at its name. Return
non-zero iff SONAME matches one of the known main executable names. */
#if 0
static int
match_main (char *soname)
{
@ -767,6 +816,7 @@ match_main (char *soname)
return (0);
}
#endif
/* Return 1 if PC lies in the dynamic symbol resolution code of the
SVR4 run time loader. */
@ -1239,6 +1289,8 @@ svr4_solib_create_inferior_hook (void)
while (stop_signal != TARGET_SIGNAL_TRAP);
stop_soon = NO_STOP_QUIETLY;
#endif /* defined(_SCO_DS) */
disable_breakpoints_at_startup (1);
}
static void

View File

@ -69,6 +69,8 @@ static char *solib_absolute_prefix = NULL;
and LD_LIBRARY_PATH. */
static char *solib_search_path = NULL;
void add_to_target_sections (int, struct target_ops *, struct so_list *);
/*
GLOBAL FUNCTION
@ -355,15 +357,37 @@ symbol_add_stub (void *arg)
/* Have we already loaded this shared object? */
ALL_OBJFILES (so->objfile)
{
if (strcmp (so->objfile->name, so->so_name) == 0)
/* Found an already loaded shared library. */
if (strcmp (so->objfile->name, so->so_name) == 0
&& !so->main)
return 1;
/* Found an already loaded main executable. This could happen in
two circumstances.
First case: the main file has already been read in
as the first thing that gdb does at startup, and the file
hasn't been relocated properly yet. Therefor we need to read
it in with the proper section info.
Second case: it has been read in with the correct relocation,
and therefore we need to skip it. */
if (strcmp (so->objfile->name, so->so_name) == 0
&& so->main
&& so->main_relocated)
return 1;
}
sap = build_section_addr_info_from_section_table (so->sections,
so->sections_end);
so->objfile = symbol_file_add (so->so_name, so->from_tty,
sap, 0, OBJF_SHARED);
if (so->main)
{
so->objfile = symbol_file_add (so->so_name, /*so->from_tty*/ 0,
sap, 1, 0);
so->main_relocated = 1;
}
else
so->objfile = symbol_file_add (so->so_name, so->from_tty,
sap, 0, OBJF_SHARED);
free_section_addr_info (sap);
return (1);
@ -538,36 +562,46 @@ update_solib_list (int from_tty, struct target_ops *target)
/* Fill in the rest of each of the `struct so_list' nodes. */
for (i = inferior; i; i = i->next)
{
i->from_tty = from_tty;
/* Fill in the rest of the `struct so_list' node. */
catch_errors (solib_map_sections, i,
"Error while mapping shared library sections:\n",
RETURN_MASK_ALL);
/* If requested, add the shared object's sections to the TARGET's
section table. Do this immediately after mapping the object so
that later nodes in the list can query this object, as is needed
in solib-osf.c. */
if (target)
{
int count = (i->sections_end - i->sections);
if (count > 0)
{
int space = target_resize_to_sections (target, count);
memcpy (target->to_sections + space,
i->sections,
count * sizeof (i->sections[0]));
}
}
/* Notify any observer that the shared object has been
loaded now that we've added it to GDB's tables. */
observer_notify_solib_loaded (i);
add_to_target_sections (from_tty, target, i);
}
}
}
void
add_to_target_sections (int from_tty, struct target_ops *target, struct so_list *solib)
{
/* If this is set, then the sections have been already added to the
target list. */
if (solib->main)
return;
solib->from_tty = from_tty;
/* Fill in the rest of the `struct so_list' node. */
catch_errors (solib_map_sections, solib,
"Error while mapping shared library sections:\n",
RETURN_MASK_ALL);
/* If requested, add the shared object's sections to the TARGET's
section table. Do this immediately after mapping the object so
that later nodes in the list can query this object, as is needed
in solib-osf.c. */
if (target)
{
int count = (solib->sections_end - solib->sections);
if (count > 0)
{
int space = target_resize_to_sections (target, count);
memcpy (target->to_sections + space,
solib->sections,
count * sizeof (solib->sections[0]));
}
}
/* Notify any observer that the shared object has been
loaded now that we've added it to GDB's tables. */
observer_notify_solib_loaded (solib);
}
/* GLOBAL FUNCTION

View File

@ -62,6 +62,8 @@ struct so_list
bfd *abfd;
char symbols_loaded; /* flag: symbols read in yet? */
char from_tty; /* flag: print msgs? */
char main; /* flag: is this the main executable? */
char main_relocated; /* flag: has it been relocated yet? */
struct objfile *objfile; /* objfile for loaded lib */
struct section_table *sections;
struct section_table *sections_end;
@ -113,9 +115,15 @@ void free_so (struct so_list *so);
/* Return address of first so_list entry in master shared object list. */
struct so_list *master_so_list (void);
/* Return address of first so_list entry in master shared object list. */
struct so_list *master_so_list (void);
/* Find solib binary file and open it. */
extern int solib_open (char *in_pathname, char **found_pathname);
/* Add the list of sections in so_list to the target to_sections. */
extern void add_to_target_sections (int, struct target_ops *, struct so_list *);
/* FIXME: gdbarch needs to control this variable */
extern struct target_so_ops *current_target_so_ops;

View File

@ -100,7 +100,7 @@ symbol_file_add_from_memory (struct bfd *templ, CORE_ADDR addr, int from_tty)
}
objf = symbol_file_add_from_bfd (nbfd, from_tty,
sai, 0, OBJF_SHARED);
sai, 2, OBJF_SHARED);
/* This might change our ideas about frames already looked at. */
reinit_frame_cache ();

View File

@ -48,6 +48,7 @@
#include "readline/readline.h"
#include "gdb_assert.h"
#include "block.h"
#include "varobj.h"
#include <sys/types.h>
#include <fcntl.h>
@ -586,7 +587,7 @@ syms_from_objfile (struct objfile *objfile,
We no longer warn if the lowest section is not a text segment (as
happens for the PA64 port. */
if (!mainline && addrs && addrs->other[0].name)
if (addrs && addrs->other[0].name)
{
asection *lower_sect;
asection *sect;
@ -987,6 +988,10 @@ symbol_file_clear (int from_tty)
&& !query ("Discard symbol table from `%s'? ",
symfile_objfile->name))
error ("Not confirmed.");
#ifdef CLEAR_SOLIB
CLEAR_SOLIB ();
#endif
free_all_objfiles ();
/* solib descriptors may have handles to objfiles. Since their
@ -1979,6 +1984,8 @@ reread_symbols (void)
/* Discard cleanups as symbol reading was successful. */
discard_cleanups (old_cleanups);
init_entry_point_info (objfile);
/* If the mtime has changed between the time we set new_modtime
and now, we *want* this to be out of date, so don't call stat
again now. */
@ -2338,6 +2345,7 @@ clear_symtab_users (void)
clear_pc_function_cache ();
if (deprecated_target_new_objfile_hook)
deprecated_target_new_objfile_hook (NULL);
varobj_refresh ();
}
static void

View File

@ -854,6 +854,62 @@ varobj_list (struct varobj ***varlist)
return rootcount;
}
void
varobj_refresh (void)
{
struct varobj *var;
struct varobj_root *croot;
int mycount = rootcount;
char * name;
croot = rootlist;
while ((croot != NULL) && (mycount > 0))
{
var = croot->rootvar;
/* Get rid of the memory for the old expression. This also
leaves var->root->exp == NULL, which is ok for the parsing
below. */
free_current_contents ((char **) &var->root->exp);
value_free (var->value);
var->type = NULL;
name = xstrdup (var->name);
/* Reparse the expression. Wrap the call to parse expression,
so we can return a sensible error. */
if (!gdb_parse_exp_1 (&name, var->root->valid_block, 0, &var->root->exp))
{
return;
}
/* We definitively need to catch errors here.
If evaluate_expression succeeds we got the value we wanted.
But if it fails, we still go on with a call to evaluate_type() */
if (gdb_evaluate_expression (var->root->exp, &var->value))
{
/* no error */
release_value (var->value);
if (VALUE_LAZY (var->value))
gdb_value_fetch_lazy (var->value);
}
else
var->value = evaluate_type (var->root->exp);
var->type = VALUE_TYPE (var->value);
mycount--;
croot = croot->next;
}
if (mycount || (croot != NULL))
warning
("varobj_refresh: assertion failed - wrong tally of root vars (%d:%d)",
rootcount, mycount);
}
/* Update the values for a variable and its children. This is a
two-pronged attack. First, re-parse the value for the root's
expression to see if it's changed. Then go all the way

View File

@ -97,4 +97,6 @@ extern int varobj_list (struct varobj ***rootlist);
extern int varobj_update (struct varobj **varp, struct varobj ***changelist);
extern void varobj_refresh(void);
#endif /* VAROBJ_H */