diff options
author | John Gilmore <gnu@cygnus> | 1991-09-04 07:43:50 +0000 |
---|---|---|
committer | John Gilmore <gnu@cygnus> | 1991-09-04 07:43:50 +0000 |
commit | bdbd5f508635fa9581f85bd6ba7ec3620970674d (patch) | |
tree | 15b699530b87aa2ae144216c734ecd2bcb9c474a /gdb/solib.c | |
parent | 7c589d2562b1b91366f01b95daa7b47a81ccb19d (diff) | |
download | gdb-bdbd5f508635fa9581f85bd6ba7ec3620970674d.zip gdb-bdbd5f508635fa9581f85bd6ba7ec3620970674d.tar.gz gdb-bdbd5f508635fa9581f85bd6ba7ec3620970674d.tar.bz2 |
Make writing to files work properly. (Fixes to BFD are also needed.)
* core.c (core_open): Open file ourselves, read or r/w, depending on
write_files. Use bfd_fdopenr.
* gdbcore.h (write_files): New variable.
* exec.c (write_files): Define variable, add set&show for it.
(exec_file_command): Use write_files to open for read or r/write.
Make shared library reading happen automatically. These changes
are mostly from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>.
* inferior.h (stop_soon_quietly): Add to exported variables.
* infrun.c (child_create_inferior): call solib hook, if defined.
(child_attach): call solib hook, if defined.
* solib.c: Include inferior.h. Add from_tty to so_list as kludge.
(find_solib): Use lookup_misc_func rather than hand-rolled.
(symbol_add_stub): New stub for catch_errors.
(solib_add): Avoid output if !from_tty. Catch errors rather
than just calling symbol_file_add and bombing.
(solib_create_inferior_hook): Interface with the target process
to let it read and alloc shared libs, then figure out what it did.
* core.c (validate_files): Fix typo, soften warning.
(Fix from Hiroto Kagotani <kagotani@cs.titech.ac.jp>.)
* utils.c (fputs_demangled): Avoid duplicate printing if
demangling is off. (Fix from J.T. Conklin <jtc@cayenne.com>.)
* infrun.c (proceed): Cast -1 to (CORE_ADDR) before comparing.
(Fix from pierre@la.tce.com (Pierre Willard).)
* main.c (catch_errors): Change argument to a char * from an int,
since a char * can point to a struct full of glop, but an int
is not guaranteed to be able to hold a pointer.
* breakpoint.c (breakpoint_cond_eval, bpstat_stop_status,
breakpoint_re_set_one, breakpoint_re_set): Adapt.
* core.c (core_open, solib_add_stub): Adapt.
* remote-vx.c (symbol_stub, add_symbol_stub, callers): Adapt.
Diffstat (limited to 'gdb/solib.c')
-rw-r--r-- | gdb/solib.c | 262 |
1 files changed, 187 insertions, 75 deletions
diff --git a/gdb/solib.c b/gdb/solib.c index 66f5bea..f6a9628 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -2,19 +2,19 @@ This file is part of GDB. -GDB is free software; you can redistribute it and/or modify +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 1, or (at your option) -any later version. +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. -GDB is distributed in the hope that it will be useful, +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GDB; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* ** symbol definitions @@ -32,6 +32,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "command.h" #include "target.h" #include "frame.h" +#include "regex.h" +#include "inferior.h" + +extern char *getenv(); /* ** local data declarations @@ -43,10 +47,11 @@ struct so_list { long ld_text; char inferior_so_name[MAX_PATH_SIZE]; /* Shared Object Library Name */ struct so_list *next; /* Next Structure */ - int symbols_loaded; + char symbols_loaded; /* Flag: loaded? */ + char from_tty; /* Flag: print msgs? */ bfd *so_bfd; - struct section_table *so_sections; - struct section_table *so_sections_end; + struct section_table *sections; + struct section_table *sections_end; }; static struct so_list *so_list_head = 0; @@ -82,11 +87,11 @@ struct so_list *so; if (!bfd_check_format (so->so_bfd, bfd_object)) error ("\"%s\": not in executable format: %s.", scratch_pathname, bfd_errmsg (bfd_error)); - if (build_section_table (so->so_bfd, &so->so_sections, &so->so_sections_end)) + if (build_section_table (so->so_bfd, &so->sections, &so->sections_end)) error ("Can't find the file sections in `%s': %s", exec_bfd->filename, bfd_errmsg (bfd_error)); - for (p = so->so_sections; p < so->so_sections_end; p++) + for (p = so->sections; p < so->sections_end; p++) { if (strcmp (bfd_section_name (so->so_bfd, p->sec_ptr), ".text") == 0) { @@ -122,7 +127,6 @@ struct so_list *find_solib(so_list_ptr) struct so_list *so_list_ptr; /* so_list_head position ptr */ { struct so_list *so_list_next = 0; -CORE_ADDR inferior_dynamic_ptr = 0; struct link_map *inferior_lm = 0; struct link_dynamic inferior_dynamic_cpy; struct link_dynamic_2 inferior_ld_2_cpy; @@ -131,14 +135,11 @@ int i; if (!so_list_ptr) { if (!(so_list_next = so_list_head)) { - for (i = 0; i < misc_function_count; i++) { - if (!strcmp (misc_function_vector[i].name, "_DYNAMIC")) { - inferior_dynamic_ptr = misc_function_vector[i].address; - break; - } - } - if (inferior_dynamic_ptr) { - read_memory(inferior_dynamic_ptr, &inferior_dynamic_cpy, sizeof(struct link_dynamic)); + i = lookup_misc_func ("_DYNAMIC"); + if (i >= 0) { + read_memory(misc_function_vector[i].address, + &inferior_dynamic_cpy, + sizeof(struct link_dynamic)); if (inferior_dynamic_cpy.ld_version == 3) { read_memory((CORE_ADDR)inferior_dynamic_cpy.ld_un.ld_2, &inferior_ld_2_cpy, @@ -200,7 +201,7 @@ int i; new->next = 0; new->symbols_loaded = 0; new->so_bfd = NULL; - new->so_sections = NULL; + new->sections = NULL; if (so_list_ptr) so_list_ptr->next = new; else @@ -213,67 +214,101 @@ int i; return(so_list_next); } -/* -** Called by core_xfer_memory if the transfer form the core file failed. -** We try to satisfy the request from the text sections of the shared libs. -*/ -int -solib_xfer_memory (memaddr, myaddr, len, write) - CORE_ADDR memaddr; - char *myaddr; - int len; - int write; +/* A small stub to get us past the arg-passing pinhole of catch_errors. */ + +static int +symbol_add_stub (arg) + char *arg; { - int res; - register struct so_list *so = 0; + register struct so_list *so = (struct so_list *)arg; /* catch_errs bogon */ - while (so = find_solib(so)) - { - res = xfer_memory (memaddr, myaddr, len, write, - so->so_bfd, so->so_sections, so->so_sections_end); - if (res) - return res; - } - return 0; + symbol_file_add (so->inferior_so_name, so->from_tty, + (unsigned int)so->inferior_lm.lm_addr, 0); + return 1; } -/*=======================================================================*/ -void solib_add(arg_string, from_tty) -char *arg_string; -int from_tty; +/* The real work of adding a shared library file to the symtab and + the section list. */ + +void +solib_add (arg_string, from_tty, target) + char *arg_string; + int from_tty; + struct target_ops *target; { - register struct so_list *so = 0; /* link map state variable */ - char *val; + register struct so_list *so = 0; /* link map state variable */ + char *val; + int count, old; + struct section_table *sec; + + if (arg_string == 0) + re_comp ("."); + else if (val = (char *) re_comp (arg_string)) { + error ("Invalid regexp: %s", val); + } - if (arg_string == 0) - re_comp ("."); - else if (val = (char *) re_comp (arg_string)) { - error ("Invalid regexp: %s", val); - } + /* Getting new symbols may change our opinion about what is + frameless. */ + reinit_frame_cache (); - /* Getting new symbols may change our opinion about what is - frameless. */ - reinit_frame_cache (); - - printf_filtered ("All shared libraries"); + if (from_tty) { + printf_filtered ("Shared libraries"); if (arg_string) printf_filtered (" matching regular expresion \"%s\"", arg_string); printf_filtered (":\n"); - - dont_repeat(); + } + + dont_repeat(); + + while (so = find_solib(so)) { + if (re_exec(so->inferior_so_name)) { + if (so->symbols_loaded) { + if (from_tty) + printf("Symbols already loaded for %s\n", so->inferior_so_name); + } else { + so->symbols_loaded = 1; + so->from_tty = from_tty; + catch_errors (symbol_add_stub, (char *)so, + "Error while reading shared library symbols; continuing."); + } + } + } - while (so = find_solib(so)) { - if (re_exec(so->inferior_so_name)) { - if (so->symbols_loaded) { - printf("Symbols already loaded for %s\n", so->inferior_so_name); - } else { - symbol_file_add (so->inferior_so_name, from_tty, - (unsigned int)so->inferior_lm.lm_addr, 0); - so->symbols_loaded = 1; - } - } + /* Now add the shared library sections to the section table of the + specified target, if any. */ + if (target) { + /* Count how many new section_table entries there are. */ + so = 0; + count = 0; + while (0 != (so = find_solib (so))) { + count += so->sections_end - so->sections; } + + if (count) { + /* Reallocate the target's section table including the new size. */ + if (target->sections) { + old = target->sections_end - target->sections; + target->sections = (struct section_table *) + realloc ((char *)target->sections, + (sizeof (struct section_table)) * (count + old)); + } else { + old = 0; + target->sections = (struct section_table *) + malloc ((sizeof (struct section_table)) * count); + } + target->sections_end = target->sections + (count + old); + + /* Add these section table entries to the target's table. */ + while (0 != (so = find_solib (so))) { + count = so->sections_end - so->sections; + bcopy (so->sections, (char *)(target->sections + old), + (sizeof (struct section_table)) * count); + old += count; + } + } + } } + /*=======================================================================*/ static void solib_info() @@ -282,7 +317,7 @@ register struct so_list *so = 0; /* link map state variable */ while (so = find_solib(so)) { if (so == so_list_head) { - printf(" Address Range Symbols Shared Object Library\n"); + printf(" Address Range Syms Read Shared Object Library\n"); } printf(" 0x%08x - 0x%08x %s %s\n", so->inferior_lm.lm_addr, @@ -321,24 +356,101 @@ clear_solib() struct so_list *next; while (so_list_head) { - if (so_list_head->so_sections) - free (so_list_head->so_sections); + if (so_list_head->sections) + free (so_list_head->sections); if (so_list_head->so_bfd) bfd_close (so_list_head->so_bfd); next = so_list_head->next; free(so_list_head); so_list_head = next; } - +} + +/* Called by child_create_inferior when the inferior is stopped at its + first instruction. */ + +void +solib_create_inferior_hook() +{ + struct link_dynamic inferior_dynamic_cpy; + CORE_ADDR inferior_debug_addr; + struct ld_debug inferior_debug_cpy; + int in_debugger; + CORE_ADDR in_debugger_addr; + CORE_ADDR breakpoint_addr; + int i; + + /* FIXME: We should look around in the executable code to find _DYNAMIC, + if it isn't in the symbol table. It's not that hard to find... + Then we can debug stripped executables using shared library symbols. */ + i = lookup_misc_func ("_DYNAMIC"); + if (i < 0) /* Can't find shared lib ptr. */ + return; + + /* Get link_dynamic structure */ + read_memory(misc_function_vector[i].address, + &inferior_dynamic_cpy, + sizeof(struct link_dynamic)); + /* Calc address of debugger interface structure */ + inferior_debug_addr = (CORE_ADDR)inferior_dynamic_cpy.ldd; + /* Calc address of `in_debugger' member of debugger interface structure */ + in_debugger_addr = inferior_debug_addr + (CORE_ADDR)((char *)&inferior_debug_cpy.ldd_in_debugger - (char *)&inferior_debug_cpy); + /* Write a value of 1 to this member. */ + in_debugger = 1; + write_memory(in_debugger_addr, &in_debugger, sizeof(in_debugger)); + + /* Now run the target. Seeing `in_debugger' set, it will set a + breakpoint at some convenient place, remember the original contents + of that place, and eventually take a SIGTRAP when it runs into the + breakpoint. We handle this by restoring the contents of the + breakpointed location (which is only known after it stops), + chasing around to locate the shared libraries that have been + loaded, then resuming. */ + + clear_proceed_status (); + stop_soon_quietly = 1; + target_resume (0, 0); + wait_for_inferior (); + while (stop_signal != SIGTRAP) + { + /* FIXME, what if child has exit()ed? Must exit loop somehow */ + target_resume (0, stop_signal); + wait_for_inferior (); + } + stop_soon_quietly = 0; + + /* Set `in_debugger' to zero now. WHY, is this needed? */ + in_debugger = 0; + write_memory(in_debugger_addr, &in_debugger, sizeof(in_debugger)); + read_memory(inferior_debug_addr, &inferior_debug_cpy, sizeof(inferior_debug_cpy)); + /* FIXME: maybe we should add the common symbols from the ldd_cp chain + * to the misc_function_vector ? + */ + breakpoint_addr = (CORE_ADDR)inferior_debug_cpy.ldd_bp_addr; + if (stop_pc - DECR_PC_AFTER_BREAK == breakpoint_addr) + { + write_memory(breakpoint_addr, &inferior_debug_cpy.ldd_bp_inst, sizeof(inferior_debug_cpy.ldd_bp_inst)); + if (DECR_PC_AFTER_BREAK) + { + stop_pc -= DECR_PC_AFTER_BREAK; + write_register (PC_REGNUM, stop_pc); + } + } + solib_add ((char *)0, 0, (struct target_ops *)0); +} + +void +sharedlibrary_command (args, from_tty) +{ + solib_add (args, from_tty, (struct target_ops *)0); } void _initialize_solib() { - add_com("sharedlibrary", class_files, solib_add, + add_com("sharedlibrary", class_files, sharedlibrary_command, "Load shared object library symbols for files matching REGEXP."); add_info("sharedlibrary", solib_info, "Status of loaded shared object libraries"); - } |