aboutsummaryrefslogtreecommitdiff
path: root/gdb/solib.c
diff options
context:
space:
mode:
authorJohn Gilmore <gnu@cygnus>1991-09-04 07:43:50 +0000
committerJohn Gilmore <gnu@cygnus>1991-09-04 07:43:50 +0000
commitbdbd5f508635fa9581f85bd6ba7ec3620970674d (patch)
tree15b699530b87aa2ae144216c734ecd2bcb9c474a /gdb/solib.c
parent7c589d2562b1b91366f01b95daa7b47a81ccb19d (diff)
downloadgdb-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.c262
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");
-
}