diff options
author | Peter Schauer <Peter.Schauer@mytum.de> | 1993-10-05 19:44:57 +0000 |
---|---|---|
committer | Peter Schauer <Peter.Schauer@mytum.de> | 1993-10-05 19:44:57 +0000 |
commit | cef4c2e7a5f2d3426a8255f74b6c7f4e795fd9a4 (patch) | |
tree | 89bc0058548c4a5ef634989a13e0a9ce0f51e3a0 /gdb/osfsolib.c | |
parent | a72e9833652c3a2e3c616b75522f7dfb462533e6 (diff) | |
download | gdb-cef4c2e7a5f2d3426a8255f74b6c7f4e795fd9a4.zip gdb-cef4c2e7a5f2d3426a8255f74b6c7f4e795fd9a4.tar.gz gdb-cef4c2e7a5f2d3426a8255f74b6c7f4e795fd9a4.tar.bz2 |
Changes to support alpha OSF/1 in native mode.
* alpha-nat.c, alpha-tdep.c, config/alpha/alpha-osf1.mt,
config/alpha/nm-alpha.h, config/alpha/tm-alpha.h, osfsolib.c:
New files.
* Makefile.in: Add new files and dependencies.
* configure.in: Add alpha target.
* config/alpha/alpha-osf1.mh (NATDEPFILES): Add osfsolib.o
* config/alpha/alpha-osf1.mh (MH_CFLAGS): Remove, we can handle
shared libraries now.
* config/alpha/xm-alpha.h: Cleanup, get MAKEVA_* defines right.
* defs.h (CORE_ADDR): Make its type overridable via CORE_ADDR_TYPE,
provide `unsigned int' default.
* breakpoint.c (breakpoint_auto_delete): Delete only if we really
stopped for the breakpoint.
* stabsread.c, stabsread.h (define_symbol): Change valu parameter
to a CORE_ADDR.
* stabsread.c (read_range_type): Handle the case where the lower
bound overflows and the upper doesn't and the range is legal.
* infrun.c (resume): Do not step a breakpoint instruction if
CANNOT_STEP_BREAKPOINT is defined.
* inferior.h (CALL_DUMMY_LOCATION): New variant AT_ENTRY_POINT.
Now that we have the bp_call_dummy breakpoint the call dummy code
is no longer needed. PUSH_DUMMY_FRAME, PUSH_ARGUMENTS and
FIX_CALL_DUMMY can be used to set up everything for the dummy.
The breakpoint for the dummy is set at the entry point and thats it.
* blockframe.c (inside_entry_file, inside_entry_func): Do not stop
backtraces if pc is in the call dummy at the entry point.
* infcmd.c (run_stack_dummy): Handle AT_ENTRY_POINT case. Use
the expected breakpoint pc when setting up the frame for
set_momentary_breakpoint.
* symfile.c (entry_point_address): New function for AT_ENTRY_POINT
support.
* valops.c (call_function_by_hand): Handle AT_ENTRY_POINT case.
Diffstat (limited to 'gdb/osfsolib.c')
-rw-r--r-- | gdb/osfsolib.c | 786 |
1 files changed, 786 insertions, 0 deletions
diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c new file mode 100644 index 0000000..a27243d --- /dev/null +++ b/gdb/osfsolib.c @@ -0,0 +1,786 @@ +/* Handle OSF/1 shared libraries for GDB, the GNU Debugger. + Copyright 1993 Free Software Foundation, Inc. + +This file is part of GDB. + +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 2 of the License, or +(at your option) any later version. + +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 this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* FIXME: Most of this code could be merged with solib.c by using + next_link_map_member and xfer_link_map_member in solib.c. */ + +#include "defs.h" + +#include <sys/types.h> +#include <signal.h> +#include <string.h> +#include <fcntl.h> + +#include "symtab.h" +#include "bfd.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdbcore.h" +#include "command.h" +#include "target.h" +#include "frame.h" +#include "regex.h" +#include "inferior.h" +#include "language.h" + +#define MAX_PATH_SIZE 256 /* FIXME: Should be dynamic */ + +/* FIXME: This is a terrible hack for shared library support under OSF/1. + The main problem is that the needed definitions are not contained in + the system header files. + The ldr_* routines described in loader(3) would be the way to go here. + But they do not work for arbitrary target processes (as documented). */ + +#ifndef USE_LDR_ROUTINES +#define RLD_CONTEXT_ADDRESS 0x3ffc0000000 + +typedef struct +{ + CORE_ADDR next; + CORE_ADDR previous; + CORE_ADDR unknown; + char *module_name; + CORE_ADDR modinfo_addr; +} ldr_module_info_t; + +typedef struct +{ + CORE_ADDR unknown1; + CORE_ADDR unknown2; + CORE_ADDR head; + CORE_ADDR tail; +} ldr_context_t; + +static ldr_context_t ldr_context; +#else +#include <loader.h> +#endif + +/* Define our own link_map structure. + This will help to share code with solib.c. */ + +struct link_map { + CORE_ADDR l_addr; /* address at which object mapped */ + char *l_name; /* full name of loaded object */ + ldr_module_info_t module_info; /* corresponding module info */ +}; + +#define LM_ADDR(so) ((so) -> lm.l_addr) +#define LM_NAME(so) ((so) -> lm.l_name) + +struct so_list { + struct so_list *next; /* next structure in linked list */ + struct link_map lm; /* copy of link map from inferior */ + struct link_map *lmaddr; /* addr in inferior lm was read from */ + CORE_ADDR lmend; /* upper addr bound of mapped object */ + char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */ + char symbols_loaded; /* flag: symbols read in yet? */ + char from_tty; /* flag: print msgs? */ + struct objfile *objfile; /* objfile for loaded lib */ + struct section_table *sections; + struct section_table *sections_end; + struct section_table *textsection; + bfd *bfd; +}; + +static struct so_list *so_list_head; /* List of known shared objects */ + +extern int +fdmatch PARAMS ((int, int)); /* In libiberty */ + +/* Local function prototypes */ + +static void +sharedlibrary_command PARAMS ((char *, int)); + +static void +info_sharedlibrary_command PARAMS ((char *, int)); + +static int +symbol_add_stub PARAMS ((char *)); + +static struct so_list * +find_solib PARAMS ((struct so_list *)); + +static struct link_map * +first_link_map_member PARAMS ((void)); + +static struct link_map * +next_link_map_member PARAMS ((struct so_list *)); + +static void +xfer_link_map_member PARAMS ((struct so_list *, struct link_map *)); + +static void +solib_map_sections PARAMS ((struct so_list *)); + +void +_initialize_solib PARAMS ((void)); + +/* + +LOCAL FUNCTION + + solib_map_sections -- open bfd and build sections for shared lib + +SYNOPSIS + + static void solib_map_sections (struct so_list *so) + +DESCRIPTION + + Given a pointer to one of the shared objects in our list + of mapped objects, use the recorded name to open a bfd + descriptor for the object, build a section table, and then + relocate all the section addresses by the base address at + which the shared object was mapped. + +FIXMES + + In most (all?) cases the shared object file name recorded in the + dynamic linkage tables will be a fully qualified pathname. For + cases where it isn't, do we really mimic the systems search + mechanism correctly in the below code (particularly the tilde + expansion stuff?). + */ + +static void +solib_map_sections (so) + struct so_list *so; +{ + char *filename; + char *scratch_pathname; + int scratch_chan; + struct section_table *p; + struct cleanup *old_chain; + bfd *abfd; + + filename = tilde_expand (so -> so_name); + old_chain = make_cleanup (free, filename); + + scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0, + &scratch_pathname); + if (scratch_chan < 0) + { + scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename, + O_RDONLY, 0, &scratch_pathname); + } + if (scratch_chan < 0) + { + perror_with_name (filename); + } + /* Leave scratch_pathname allocated. bfd->name will point to it. */ + + abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan); + if (!abfd) + { + close (scratch_chan); + error ("Could not open `%s' as an executable file: %s", + scratch_pathname, bfd_errmsg (bfd_error)); + } + /* Leave bfd open, core_xfer_memory and "info files" need it. */ + so -> bfd = abfd; + abfd -> cacheable = true; + + if (!bfd_check_format (abfd, bfd_object)) + { + error ("\"%s\": not in executable format: %s.", + scratch_pathname, bfd_errmsg (bfd_error)); + } + if (build_section_table (abfd, &so -> sections, &so -> sections_end)) + { + error ("Can't find the file sections in `%s': %s", + bfd_get_filename (exec_bfd), bfd_errmsg (bfd_error)); + } + + for (p = so -> sections; p < so -> sections_end; p++) + { + /* Relocate the section binding addresses as recorded in the shared + object's file by the base address to which the object was actually + mapped. */ + p -> addr += (CORE_ADDR) LM_ADDR (so); + p -> endaddr += (CORE_ADDR) LM_ADDR (so); + so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend); + if (STREQ (p -> sec_ptr -> name, ".text")) + { + so -> textsection = p; + } + } + + /* Free the file names, close the file now. */ + do_cleanups (old_chain); +} + +/* + +LOCAL FUNCTION + + first_link_map_member -- locate first member in dynamic linker's map + +SYNOPSIS + + static struct link_map *first_link_map_member (void) + +DESCRIPTION + + Read in a copy of the first member in the inferior's dynamic + link map from the inferior's dynamic linker structures, and return + a pointer to the copy in our address space. +*/ + +static struct link_map * +first_link_map_member () +{ + struct link_map *lm = NULL; + static struct link_map first_lm; + +#ifdef USE_LDR_ROUTINES + ldr_module_t mod_id = LDR_NULL_MODULE; + size_t retsize; + + if (ldr_next_module(inferior_pid, &mod_id) != 0 + || mod_id == LDR_NULL_MODULE + || ldr_inq_module(inferior_pid, mod_id, + &first_lm.module_info, sizeof(ldr_module_info_t), + &retsize) != 0) + return lm; +#else + CORE_ADDR ldr_context_addr; + + if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS, + (char *) &ldr_context_addr, + sizeof (CORE_ADDR)) != 0 + || target_read_memory (ldr_context_addr, + (char *) &ldr_context, + sizeof (ldr_context_t)) != 0 + || target_read_memory ((CORE_ADDR) ldr_context.head, + (char *) &first_lm.module_info, + sizeof (ldr_module_info_t)) != 0) + return lm; +#endif + + lm = &first_lm; + + /* The first entry is for the main program and should be skipped. */ + lm->l_name = NULL; + + return lm; +} + +static struct link_map * +next_link_map_member (so_list_ptr) + struct so_list *so_list_ptr; +{ + struct link_map *lm = NULL; + static struct link_map next_lm; +#ifdef USE_LDR_ROUTINES + ldr_module_t mod_id = lm->module_info.lmi_modid; + size_t retsize; + + if (ldr_next_module(inferior_pid, &mod_id) != 0 + || mod_id == LDR_NULL_MODULE + || ldr_inq_module(inferior_pid, mod_id, + &next_lm.module_info, sizeof(ldr_module_info_t), + &retsize) != 0) + return lm; + + lm = &next_lm; + lm->l_name = lm->module_info.lmi_name; +#else + CORE_ADDR ldr_context_addr; + + /* Reread context in case ldr_context.tail was updated. */ + + if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS, + (char *) &ldr_context_addr, + sizeof (CORE_ADDR)) != 0 + || target_read_memory (ldr_context_addr, + (char *) &ldr_context, + sizeof (ldr_context_t)) != 0 + || so_list_ptr->lm.module_info.modinfo_addr == ldr_context.tail + || target_read_memory (so_list_ptr->lm.module_info.next, + (char *) &next_lm.module_info, + sizeof (ldr_module_info_t)) != 0) + return lm; + + lm = &next_lm; + lm->l_name = lm->module_info.module_name; +#endif + return lm; +} + +static void +xfer_link_map_member (so_list_ptr, lm) + struct so_list *so_list_ptr; + struct link_map *lm; +{ + so_list_ptr->lm = *lm; + + /* OSF/1 has absolute addresses in shared libraries. */ + LM_ADDR (so_list_ptr) = 0; + + /* There is one entry that has no name (for the inferior executable) + since it is not a shared object. */ + if (LM_NAME (so_list_ptr) != 0) + { + +#ifdef USE_LDR_ROUTINES + int len = strlen (LM_NAME (so_list_ptr) + 1); + + if (len > MAX_PATH_SIZE) + len = MAX_PATH_SIZE; + strncpy (so_list_ptr->so_name, LM_NAME (so_list_ptr), MAX_PATH_SIZE); +#else + if (!target_read_string((CORE_ADDR) LM_NAME (so_list_ptr), + so_list_ptr->so_name, MAX_PATH_SIZE - 1)) + error ("xfer_link_map_member: Can't read pathname for load map\n"); +#endif + so_list_ptr->so_name[MAX_PATH_SIZE - 1] = 0; + + solib_map_sections (so_list_ptr); + } +} + +/* + +LOCAL FUNCTION + + find_solib -- step through list of shared objects + +SYNOPSIS + + struct so_list *find_solib (struct so_list *so_list_ptr) + +DESCRIPTION + + This module contains the routine which finds the names of any + loaded "images" in the current process. The argument in must be + NULL on the first call, and then the returned value must be passed + in on subsequent calls. This provides the capability to "step" down + the list of loaded objects. On the last object, a NULL value is + returned. + + The arg and return value are "struct link_map" pointers, as defined + in <link.h>. + */ + +static struct so_list * +find_solib (so_list_ptr) + struct so_list *so_list_ptr; /* Last lm or NULL for first one */ +{ + struct so_list *so_list_next = NULL; + struct link_map *lm = NULL; + struct so_list *new; + + if (so_list_ptr == NULL) + { + /* We are setting up for a new scan through the loaded images. */ + if ((so_list_next = so_list_head) == NULL) + { + /* Find the first link map list member. */ + lm = first_link_map_member (); + } + } + else + { + /* We have been called before, and are in the process of walking + the shared library list. Advance to the next shared object. */ + lm = next_link_map_member (so_list_ptr); + so_list_next = so_list_ptr -> next; + } + if ((so_list_next == NULL) && (lm != NULL)) + { + /* Get next link map structure from inferior image and build a local + abbreviated load_map structure */ + new = (struct so_list *) xmalloc (sizeof (struct so_list)); + memset ((char *) new, 0, sizeof (struct so_list)); + new -> lmaddr = lm; + /* Add the new node as the next node in the list, or as the root + node if this is the first one. */ + if (so_list_ptr != NULL) + { + so_list_ptr -> next = new; + } + else + { + so_list_head = new; + } + so_list_next = new; + xfer_link_map_member (new, lm); + } + return (so_list_next); +} + +/* A small stub to get us past the arg-passing pinhole of catch_errors. */ + +static int +symbol_add_stub (arg) + char *arg; +{ + register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */ + + so -> objfile = symbol_file_add (so -> so_name, so -> from_tty, + so -> textsection -> addr, + 0, 0, 0); + return (1); +} + +/* + +GLOBAL FUNCTION + + solib_add -- add a shared library file to the symtab and section list + +SYNOPSIS + + void solib_add (char *arg_string, int from_tty, + struct target_ops *target) + +DESCRIPTION + +*/ + +void +solib_add (arg_string, from_tty, target) + char *arg_string; + int from_tty; + struct target_ops *target; +{ + register struct so_list *so = NULL; /* link map state variable */ + + /* Last shared library that we read. */ + struct so_list *so_last = NULL; + + char *re_err; + int count; + int old; + + if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL) + { + error ("Invalid regexp: %s", re_err); + } + + + /* Add the shared library sections to the section table of the + specified target, if any. We have to do this before reading the + symbol files as symbol_file_add calls reinit_frame_cache and + creating a new frame might access memory in the shared library. */ + if (target) + { + /* Count how many new section_table entries there are. */ + so = NULL; + count = 0; + while ((so = find_solib (so)) != NULL) + { + if (so -> so_name[0]) + { + count += so -> sections_end - so -> sections; + } + } + + if (count) + { + /* Reallocate the target's section table including the new size. */ + if (target -> to_sections) + { + old = target -> to_sections_end - target -> to_sections; + target -> to_sections = (struct section_table *) + xrealloc ((char *)target -> to_sections, + (sizeof (struct section_table)) * (count + old)); + } + else + { + old = 0; + target -> to_sections = (struct section_table *) + xmalloc ((sizeof (struct section_table)) * count); + } + target -> to_sections_end = target -> to_sections + (count + old); + + /* Add these section table entries to the target's table. */ + while ((so = find_solib (so)) != NULL) + { + if (so -> so_name[0]) + { + count = so -> sections_end - so -> sections; + memcpy ((char *) (target -> to_sections + old), + so -> sections, + (sizeof (struct section_table)) * count); + old += count; + } + } + } + } + + /* Now add the symbol files. */ + so = NULL; + while ((so = find_solib (so)) != NULL) + { + if (so -> so_name[0] && re_exec (so -> so_name)) + { + so -> from_tty = from_tty; + if (so -> symbols_loaded) + { + if (from_tty) + { + printf ("Symbols already loaded for %s\n", so -> so_name); + } + } + else if (catch_errors + (symbol_add_stub, (char *) so, + "Error while reading shared library symbols:\n", + RETURN_MASK_ALL)) + { + so_last = so; + so -> symbols_loaded = 1; + } + } + } +} + +/* + +LOCAL FUNCTION + + info_sharedlibrary_command -- code for "info sharedlibrary" + +SYNOPSIS + + static void info_sharedlibrary_command () + +DESCRIPTION + + Walk through the shared library list and print information + about each attached library. +*/ + +static void +info_sharedlibrary_command (ignore, from_tty) + char *ignore; + int from_tty; +{ + register struct so_list *so = NULL; /* link map state variable */ + int header_done = 0; + + if (exec_bfd == NULL) + { + printf ("No exec file.\n"); + return; + } + while ((so = find_solib (so)) != NULL) + { + if (so -> so_name[0]) + { + unsigned long txt_start = 0; + unsigned long txt_end = 0; + + if (!header_done) + { + printf("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read", + "Shared Object Library"); + header_done++; + } + if (so -> textsection) + { + txt_start = (unsigned long) so -> textsection -> addr; + txt_end = (unsigned long) so -> textsection -> endaddr; + } + printf ("%-20s", local_hex_string_custom (txt_start, "08l")); + printf ("%-20s", local_hex_string_custom (txt_end, "08l")); + printf ("%-12s", so -> symbols_loaded ? "Yes" : "No"); + printf ("%s\n", so -> so_name); + } + } + if (so_list_head == NULL) + { + printf ("No shared libraries loaded at this time.\n"); + } +} + +/* + +GLOBAL FUNCTION + + solib_address -- check to see if an address is in a shared lib + +SYNOPSIS + + int solib_address (CORE_ADDR address) + +DESCRIPTION + + Provides a hook for other gdb routines to discover whether or + not a particular address is within the mapped address space of + a shared library. Any address between the base mapping address + and the first address beyond the end of the last mapping, is + considered to be within the shared library address space, for + our purposes. + + For example, this routine is called at one point to disable + breakpoints which are in shared libraries that are not currently + mapped in. + */ + +int +solib_address (address) + CORE_ADDR address; +{ + register struct so_list *so = 0; /* link map state variable */ + + while ((so = find_solib (so)) != NULL) + { + if (so -> so_name[0] && so -> textsection) + { + if ((address >= (CORE_ADDR) so -> textsection -> addr) && + (address < (CORE_ADDR) so -> textsection -> endaddr)) + { + return (1); + } + } + } + return (0); +} + +/* Called by free_all_symtabs */ + +void +clear_solib() +{ + struct so_list *next; + char *bfd_filename; + + while (so_list_head) + { + if (so_list_head -> sections) + { + free ((PTR)so_list_head -> sections); + } + if (so_list_head -> bfd) + { + bfd_filename = bfd_get_filename (so_list_head -> bfd); + bfd_close (so_list_head -> bfd); + } + else + /* This happens for the executable on SVR4. */ + bfd_filename = NULL; + + next = so_list_head -> next; + if (bfd_filename) + free ((PTR)bfd_filename); + free ((PTR)so_list_head); + so_list_head = next; + } +} + +/* + +GLOBAL FUNCTION + + solib_create_inferior_hook -- shared library startup support + +SYNOPSIS + + void solib_create_inferior_hook() + +DESCRIPTION + + When gdb starts up the inferior, it nurses it along (through the + shell) until it is ready to execute it's first instruction. At this + point, this function gets called via expansion of the macro + SOLIB_CREATE_INFERIOR_HOOK. + For a statically bound executable, this first instruction is the + one at "_start", or a similar text label. No further processing is + needed in that case. + For a dynamically bound executable, this first instruction is somewhere + in the rld, and the actual user executable is not yet mapped in. + We continue the inferior again, rld then maps in the actual user + executable and any needed shared libraries and then sends + itself a SIGTRAP. + At that point we discover the names of all shared libraries and + read their symbols in. + +FIXME + + This code does not properly handle hitting breakpoints which the + user might have set in the rld itself. Proper handling would have + to check if the SIGTRAP happened due to a kill call. + + Also, what if child has exit()ed? Must exit loop somehow. + */ + +void +solib_create_inferior_hook() +{ + + /* Nothing to do for statically bound executables. */ + + if (symfile_objfile == 0 || symfile_objfile->ei.entry_file_lowpc == stop_pc) + return; + + /* Now run the target. It will eventually get a SIGTRAP, at + which point all of the libraries will have been mapped in and we + can go groveling around in the rld structures to find + out what we need to know about them. */ + + clear_proceed_status (); + stop_soon_quietly = 1; + stop_signal = 0; + do + { + target_resume (inferior_pid, 0, stop_signal); + wait_for_inferior (); + } + while (stop_signal != SIGTRAP); + stop_soon_quietly = 0; + + solib_add ((char *) 0, 0, (struct target_ops *) 0); +} + + +/* + +LOCAL FUNCTION + + sharedlibrary_command -- handle command to explicitly add library + +SYNOPSIS + + static void sharedlibrary_command (char *args, int from_tty) + +DESCRIPTION + +*/ + +static void +sharedlibrary_command (args, from_tty) +char *args; +int from_tty; +{ + dont_repeat (); + solib_add (args, from_tty, (struct target_ops *) 0); +} + +void +_initialize_solib() +{ + + add_com ("sharedlibrary", class_files, sharedlibrary_command, + "Load shared object library symbols for files matching REGEXP."); + add_info ("sharedlibrary", info_sharedlibrary_command, + "Status of loaded shared object libraries."); +} |