diff options
Diffstat (limited to 'gdb/solib-osf.c')
-rw-r--r-- | gdb/solib-osf.c | 638 |
1 files changed, 0 insertions, 638 deletions
diff --git a/gdb/solib-osf.c b/gdb/solib-osf.c deleted file mode 100644 index 24915cb..0000000 --- a/gdb/solib-osf.c +++ /dev/null @@ -1,638 +0,0 @@ -/* Handle OSF/1, Digital UNIX, and Tru64 shared libraries - for GDB, the GNU Debugger. - Copyright (C) 1993-2014 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 3 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, see <http://www.gnu.org/licenses/>. */ - -/* When handling shared libraries, GDB has to find out the pathnames - of all shared libraries that are currently loaded (to read in their - symbols) and where the shared libraries are loaded in memory - (to relocate them properly from their prelinked addresses to the - current load address). - - Under OSF/1 there are two possibilities to get at this information: - - 1) Peek around in the runtime loader structures. - These are not documented, and they are not defined in the system - header files. The definitions below were obtained by experimentation, - but they seem stable enough. - - 2) Use the libxproc.a library, which contains the equivalent ldr_* - routines. The library is documented in Tru64 5.x, but as of 5.1, it - only allows a process to examine itself. On earlier versions, it - may require that the GDB executable be dynamically linked and that - NAT_CLIBS include -lxproc -Wl,-expect_unresolved,ldr_process_context - for GDB and all applications that are using libgdb. - - We will use the peeking approach until libxproc.a works for other - processes. */ - -#include "defs.h" - -#include <sys/types.h> -#include <signal.h> -#include "bfd.h" -#include "symtab.h" -#include "symfile.h" -#include "objfiles.h" -#include "target.h" -#include "inferior.h" -#include "infrun.h" -#include "gdbthread.h" -#include "solist.h" -#include "solib.h" - -#ifdef USE_LDR_ROUTINES -# include <loader.h> -#endif - -#ifndef USE_LDR_ROUTINES -/* Definition of runtime loader structures, found by experimentation. */ -#define RLD_CONTEXT_ADDRESS 0x3ffc0000000 - -/* Per-module information structure referenced by ldr_context_t.head. */ - -typedef struct - { - CORE_ADDR next; - CORE_ADDR previous; - CORE_ADDR unknown1; - CORE_ADDR module_name; - CORE_ADDR modinfo_addr; /* Used by next_link_map_member() to detect - the end of the shared module list. */ - long module_id; - CORE_ADDR unknown2; - CORE_ADDR unknown3; - long region_count; - CORE_ADDR regioninfo_addr; - } -ldr_module_info_t; - -/* Per-region structure referenced by ldr_module_info_t.regioninfo_addr. */ - -typedef struct - { - long unknown1; - CORE_ADDR regionname_addr; - long protection; - CORE_ADDR vaddr; - CORE_ADDR mapaddr; - long size; - long unknown2[5]; - } -ldr_region_info_t; - -/* Structure at RLD_CONTEXT_ADDRESS specifying the start and finish addresses - of the shared module list. */ - -typedef struct - { - CORE_ADDR unknown1; - CORE_ADDR unknown2; - CORE_ADDR head; - CORE_ADDR tail; - } -ldr_context_t; -#endif /* !USE_LDR_ROUTINES */ - -/* Per-section information, stored in struct lm_info.secs. */ - -struct lm_sec - { - CORE_ADDR offset; /* difference between default and actual - virtual addresses of section .name */ - CORE_ADDR nameaddr; /* address in inferior of section name */ - const char *name; /* name of section, null if not fetched */ - }; - -/* Per-module information, stored in struct so_list.lm_info. */ - -struct lm_info - { - int isloader; /* whether the module is /sbin/loader */ - int nsecs; /* length of .secs */ - struct lm_sec secs[1]; /* variable-length array of sections, sorted - by name */ - }; - -/* Context for iterating through the inferior's shared module list. */ - -struct read_map_ctxt - { -#ifdef USE_LDR_ROUTINES - ldr_process_t proc; - ldr_module_t next; -#else - CORE_ADDR next; /* next element in module list */ - CORE_ADDR tail; /* last element in module list */ -#endif - }; - -/* Forward declaration for this module's autoinit function. */ - -extern void _initialize_osf_solib (void); - -#ifdef USE_LDR_ROUTINES -# if 0 -/* This routine is intended to be called by ldr_* routines to read memory from - the current target. Usage: - - ldr_process = ldr_core_process (); - ldr_set_core_reader (ldr_read_memory); - ldr_xdetach (ldr_process); - ldr_xattach (ldr_process); - - ldr_core_process() and ldr_read_memory() are neither documented nor - declared in system header files. They work with OSF/1 2.x, and they might - work with later versions as well. */ - -static int -ldr_read_memory (CORE_ADDR memaddr, char *myaddr, int len, int readstring) -{ - int result; - char *buffer; - - if (readstring) - { - target_read_string (memaddr, &buffer, len, &result); - if (result == 0) - strcpy (myaddr, buffer); - xfree (buffer); - } - else - result = target_read_memory (memaddr, myaddr, len); - - if (result != 0) - result = -result; - return result; -} -# endif /* 0 */ -#endif /* USE_LDR_ROUTINES */ - -/* Comparison for qsort() and bsearch(): return -1, 0, or 1 according to - whether lm_sec *P1's name is lexically less than, equal to, or greater - than that of *P2. */ - -static int -lm_sec_cmp (const void *p1, const void *p2) -{ - const struct lm_sec *lms1 = p1, *lms2 = p2; - - return strcmp (lms1->name, lms2->name); -} - -/* Sort LMI->secs so that osf_relocate_section_addresses() can binary-search - it. */ - -static void -lm_secs_sort (struct lm_info *lmi) -{ - qsort (lmi->secs, lmi->nsecs, sizeof *lmi->secs, lm_sec_cmp); -} - -/* Populate name fields of LMI->secs. */ - -static void -fetch_sec_names (struct lm_info *lmi) -{ -#ifndef USE_LDR_ROUTINES - int i, errcode; - struct lm_sec *lms; - char *name; - - for (i = 0; i < lmi->nsecs; i++) - { - lms = lmi->secs + i; - target_read_string (lms->nameaddr, &name, PATH_MAX, &errcode); - if (errcode != 0) - { - warning (_("unable to read shared sec name at 0x%lx"), - lms->nameaddr); - name = xstrdup (""); - } - lms->name = name; - } - lm_secs_sort (lmi); -#endif -} - -/* target_so_ops callback. Adjust SEC's addresses after it's been mapped into - the process. */ - -static void -osf_relocate_section_addresses (struct so_list *so, - struct target_section *sec) -{ - struct lm_info *lmi; - struct lm_sec lms_key, *lms; - - /* Fetch SO's section names if we haven't done so already. */ - lmi = so->lm_info; - if (lmi->nsecs && !lmi->secs[0].name) - fetch_sec_names (lmi); - - /* Binary-search for offset information corresponding to SEC. */ - lms_key.name = sec->the_bfd_section->name; - lms = bsearch (&lms_key, lmi->secs, lmi->nsecs, sizeof *lms, lm_sec_cmp); - if (lms) - { - sec->addr += lms->offset; - sec->endaddr += lms->offset; - } -} - -/* target_so_ops callback. Free parts of SO allocated by this file. */ - -static void -osf_free_so (struct so_list *so) -{ - int i; - const char *name; - - for (i = 0; i < so->lm_info->nsecs; i++) - { - name = so->lm_info->secs[i].name; - if (name) - xfree ((void *) name); - } - xfree (so->lm_info); -} - -/* target_so_ops callback. Discard information accumulated by this file and - not freed by osf_free_so(). */ - -static void -osf_clear_solib (void) -{ - return; -} - -/* target_so_ops callback. Prepare to handle shared libraries after the - inferior process has been created but before it's executed any - instructions. - - For a statically bound executable, the inferior's 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. */ - -static void -osf_solib_create_inferior_hook (int from_tty) -{ - struct inferior *inf; - struct thread_info *tp; - - inf = current_inferior (); - - /* If we are attaching to the inferior, the shared libraries - have already been mapped, so nothing more to do. */ - if (inf->attach_flag) - return; - - /* Nothing to do for statically bound executables. */ - - if (symfile_objfile == NULL - || symfile_objfile->obfd == NULL - || ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0)) - 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. - - If debugging from a core file, we cannot resume the execution - of the inferior. But this is actually not an issue, because - shared libraries have already been mapped anyways, which means - we have nothing more to do. */ - if (!target_can_run (¤t_target)) - return; - - tp = inferior_thread (); - clear_proceed_status (0); - inf->control.stop_soon = STOP_QUIETLY; - tp->suspend.stop_signal = GDB_SIGNAL_0; - do - { - target_resume (minus_one_ptid, 0, tp->suspend.stop_signal); - wait_for_inferior (); - } - while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP); - - /* solib_add will call reinit_frame_cache. - But we are stopped in the runtime loader and we do not have symbols - for the runtime loader. So heuristic_proc_start will be called - and will put out an annoying warning. - Delaying the resetting of stop_soon until after symbol loading - suppresses the warning. */ - solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add); - inf->control.stop_soon = NO_STOP_QUIETLY; -} - -/* target_so_ops callback. Do additional symbol handling, lookup, etc. after - symbols for a shared object have been loaded. */ - -static void -osf_special_symbol_handling (void) -{ - return; -} - -/* Initialize CTXT in preparation for iterating through the inferior's module - list using read_map(). Return success. */ - -static int -open_map (struct read_map_ctxt *ctxt) -{ -#ifdef USE_LDR_ROUTINES - /* Note: As originally written, ldr_my_process() was used to obtain - the value for ctxt->proc. This is incorrect, however, since - ldr_my_process() retrieves the "unique identifier" associated - with the current process (i.e. GDB) and not the one being - debugged. Presumably, the pid of the process being debugged is - compatible with the "unique identifier" used by the ldr_ - routines, so we use that. */ - ctxt->proc = ptid_get_pid (inferior_ptid); - if (ldr_xattach (ctxt->proc) != 0) - return 0; - ctxt->next = LDR_NULL_MODULE; -#else - CORE_ADDR ldr_context_addr, prev, next; - ldr_context_t ldr_context; - - if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS, - (char *) &ldr_context_addr, - sizeof (CORE_ADDR)) != 0) - return 0; - if (target_read_memory (ldr_context_addr, - (char *) &ldr_context, - sizeof (ldr_context_t)) != 0) - return 0; - ctxt->next = ldr_context.head; - ctxt->tail = ldr_context.tail; -#endif - return 1; -} - -/* Initialize SO to have module NAME, /sbin/loader indicator ISLOADR, and - space for NSECS sections. */ - -static void -init_so (struct so_list *so, char *name, int isloader, int nsecs) -{ - int namelen, i; - - /* solib.c requires various fields to be initialized to 0. */ - memset (so, 0, sizeof *so); - - /* Copy the name. */ - namelen = strlen (name); - if (namelen >= SO_NAME_MAX_PATH_SIZE) - namelen = SO_NAME_MAX_PATH_SIZE - 1; - - memcpy (so->so_original_name, name, namelen); - so->so_original_name[namelen] = '\0'; - memcpy (so->so_name, so->so_original_name, namelen + 1); - - /* Allocate section space. */ - so->lm_info = xmalloc (sizeof (struct lm_info) - + (nsecs - 1) * sizeof (struct lm_sec)); - so->lm_info->isloader = isloader; - so->lm_info->nsecs = nsecs; - for (i = 0; i < nsecs; i++) - so->lm_info->secs[i].name = NULL; -} - -/* Initialize SO's section SECIDX with name address NAMEADDR, name string - NAME, default virtual address VADDR, and actual virtual address - MAPADDR. */ - -static void -init_sec (struct so_list *so, int secidx, CORE_ADDR nameaddr, - const char *name, CORE_ADDR vaddr, CORE_ADDR mapaddr) -{ - struct lm_sec *lms; - - lms = so->lm_info->secs + secidx; - lms->nameaddr = nameaddr; - lms->name = name; - lms->offset = mapaddr - vaddr; -} - -/* If there are more elements starting at CTXT in inferior's module list, - store the next element in SO, advance CTXT to the next element, and return - 1, else return 0. */ - -static int -read_map (struct read_map_ctxt *ctxt, struct so_list *so) -{ - ldr_module_info_t minf; - ldr_region_info_t rinf; - -#ifdef USE_LDR_ROUTINES - size_t size; - ldr_region_t i; - - /* Retrieve the next element. */ - if (ldr_next_module (ctxt->proc, &ctxt->next) != 0) - return 0; - if (ctxt->next == LDR_NULL_MODULE) - return 0; - if (ldr_inq_module (ctxt->proc, ctxt->next, &minf, sizeof minf, &size) != 0) - return 0; - - /* Initialize the module name and section count. */ - init_so (so, minf.lmi_name, 0, minf.lmi_nregion); - - /* Retrieve section names and offsets. */ - for (i = 0; i < minf.lmi_nregion; i++) - { - if (ldr_inq_region (ctxt->proc, ctxt->next, i, &rinf, - sizeof rinf, &size) != 0) - goto err; - init_sec (so, (int) i, 0, xstrdup (rinf.lri_name), - (CORE_ADDR) rinf.lri_vaddr, (CORE_ADDR) rinf.lri_mapaddr); - } - lm_secs_sort (so->lm_info); -#else - char *name; - int errcode, i; - - /* Retrieve the next element. */ - if (!ctxt->next) - return 0; - if (target_read_memory (ctxt->next, (char *) &minf, sizeof minf) != 0) - return 0; - if (ctxt->next == ctxt->tail) - ctxt->next = 0; - else - ctxt->next = minf.next; - - /* Initialize the module name and section count. */ - target_read_string (minf.module_name, &name, PATH_MAX, &errcode); - if (errcode != 0) - return 0; - init_so (so, name, !minf.modinfo_addr, minf.region_count); - xfree (name); - - /* Retrieve section names and offsets. */ - for (i = 0; i < minf.region_count; i++) - { - if (target_read_memory (minf.regioninfo_addr + i * sizeof rinf, - (char *) &rinf, sizeof rinf) != 0) - goto err; - init_sec (so, i, rinf.regionname_addr, NULL, rinf.vaddr, rinf.mapaddr); - } -#endif /* !USE_LDR_ROUTINES */ - return 1; - - err: - osf_free_so (so); - return 0; -} - -/* Free resources allocated by open_map (CTXT). */ - -static void -close_map (struct read_map_ctxt *ctxt) -{ -#ifdef USE_LDR_ROUTINES - ldr_xdetach (ctxt->proc); -#endif -} - -/* target_so_ops callback. Return a list of shared objects currently loaded - in the inferior. */ - -static struct so_list * -osf_current_sos (void) -{ - struct so_list *head = NULL, *tail = NULL, *newtail, so; - struct read_map_ctxt ctxt; - int skipped_main; - - if (!open_map (&ctxt)) - return NULL; - - /* Read subsequent elements. */ - for (skipped_main = 0;;) - { - if (!read_map (&ctxt, &so)) - break; - - /* Skip the main program module, which is first in the list after - /sbin/loader. */ - if (!so.lm_info->isloader && !skipped_main) - { - osf_free_so (&so); - skipped_main = 1; - continue; - } - - newtail = xmalloc (sizeof *newtail); - if (!head) - head = newtail; - else - tail->next = newtail; - tail = newtail; - - memcpy (tail, &so, sizeof so); - tail->next = NULL; - } - - close_map (&ctxt); - return head; -} - -/* target_so_ops callback. Attempt to locate and open the main symbol - file. */ - -static int -osf_open_symbol_file_object (void *from_ttyp) -{ - struct read_map_ctxt ctxt; - struct so_list so; - int found; - - if (symfile_objfile) - if (!query (_("Attempt to reload symbols from process? "))) - return 0; - - /* The first module after /sbin/loader is the main program. */ - if (!open_map (&ctxt)) - return 0; - for (found = 0; !found;) - { - if (!read_map (&ctxt, &so)) - break; - found = !so.lm_info->isloader; - osf_free_so (&so); - } - close_map (&ctxt); - - if (found) - symbol_file_add_main (so.so_name, *(int *) from_ttyp); - return found; -} - -/* target_so_ops callback. Return whether PC is in the dynamic linker. */ - -static int -osf_in_dynsym_resolve_code (CORE_ADDR pc) -{ - /* This function currently always return False. This is a temporary - solution which only consequence is to introduce a minor incovenience - for the user: When stepping inside a subprogram located in a shared - library, gdb might stop inside the dynamic loader code instead of - inside the subprogram itself. See the explanations in infrun.c about - the in_solib_dynsym_resolve_code() function for more details. */ - return 0; -} - -static struct target_so_ops osf_so_ops; - -void -_initialize_osf_solib (void) -{ - osf_so_ops.relocate_section_addresses = osf_relocate_section_addresses; - osf_so_ops.free_so = osf_free_so; - osf_so_ops.clear_solib = osf_clear_solib; - osf_so_ops.solib_create_inferior_hook = osf_solib_create_inferior_hook; - osf_so_ops.special_symbol_handling = osf_special_symbol_handling; - osf_so_ops.current_sos = osf_current_sos; - osf_so_ops.open_symbol_file_object = osf_open_symbol_file_object; - osf_so_ops.in_dynsym_resolve_code = osf_in_dynsym_resolve_code; - osf_so_ops.bfd_open = solib_bfd_open; - - /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ - current_target_so_ops = &osf_so_ops; -} |