diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/Makefile.in | 4 | ||||
-rw-r--r-- | gdb/solib-aix5.c | 957 |
3 files changed, 5 insertions, 961 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 450bbee..60bbf19 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2007-05-28 Joel Brobecker <brobecker@adacore.com> + + * solib-aix5.c: Delete. + * Makefile.in (solib-aix5.o): Delete rule. + 2007-05-23 Daniel Jacobowitz <dan@codesourcery.com> * breakpoint.h (enum bpstat_what_main_action): Remove diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5077e67..4704cf8 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2564,10 +2564,6 @@ sh-tdep.o: sh-tdep.c $(defs_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \ $(doublest_h) $(osabi_h) $(sh_tdep_h) $(elf_bfd_h) $(solib_svr4_h) \ $(elf_sh_h) $(gdb_sim_sh_h) $(reggroups_h) sol2-tdep.o: sol2-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(sol2_tdep_h) -solib-aix5.o: solib-aix5.c $(defs_h) $(gdb_string_h) $(elf_external_h) \ - $(symtab_h) $(bfd_h) $(symfile_h) $(objfiles_h) $(gdbcore_h) \ - $(command_h) $(target_h) $(frame_h) $(gdb_regex_h) $(inferior_h) \ - $(environ_h) $(language_h) $(gdbcmd_h) $(solist_h) solib.o: solib.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) $(symfile_h) \ $(objfiles_h) $(exceptions_h) $(gdbcore_h) $(command_h) $(target_h) \ $(frame_h) $(gdb_regex_h) $(inferior_h) $(environ_h) $(language_h) \ diff --git a/gdb/solib-aix5.c b/gdb/solib-aix5.c deleted file mode 100644 index 3cff043..0000000 --- a/gdb/solib-aix5.c +++ /dev/null @@ -1,957 +0,0 @@ -/* Handle AIX5 shared libraries for GDB, the GNU Debugger. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2007 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., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ - -#include "defs.h" - -#include <sys/types.h> -#include <signal.h> -#include "gdb_string.h" -#include <sys/param.h> -#include <fcntl.h> -#include <sys/procfs.h> - -#include "elf/external.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 "gdb_regex.h" -#include "inferior.h" -#include "environ.h" -#include "language.h" -#include "gdbcmd.h" - -#include "solist.h" - -/* Link map info to include in an allocated so_list entry */ - -struct lm_info - { - int nmappings; /* number of mappings */ - struct lm_mapping - { - CORE_ADDR addr; /* base address */ - CORE_ADDR size; /* size of mapped object */ - CORE_ADDR offset; /* offset into mapped object */ - long flags; /* MA_ protection and attribute flags */ - CORE_ADDR gp; /* global pointer value */ - } *mapping; - char *mapname; /* name in /proc/pid/object */ - char *pathname; /* full pathname to object */ - char *membername; /* member name in archive file */ - }; - -/* List of symbols in the dynamic linker where GDB can try to place - a breakpoint to monitor shared library events. */ - -static char *solib_break_names[] = -{ - "_r_debug_state", - NULL -}; - -static void aix5_relocate_main_executable (void); - -/* - - LOCAL FUNCTION - - bfd_lookup_symbol -- lookup the value for a specific symbol - - SYNOPSIS - - CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname) - - DESCRIPTION - - An expensive way to lookup the value of a single symbol for - bfd's that are only temporary anyway. This is used by the - shared library support to find the address of the debugger - interface structures in the shared library. - - Note that 0 is specifically allowed as an error return (no - such symbol). - */ - -static CORE_ADDR -bfd_lookup_symbol (bfd *abfd, char *symname) -{ - long storage_needed; - asymbol *sym; - asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; - struct cleanup *back_to; - CORE_ADDR symaddr = 0; - - storage_needed = bfd_get_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (xfree, symbol_table); - number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - if (strcmp (sym->name, symname) == 0) - { - /* Bfd symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - - if (symaddr) - return symaddr; - - /* Look for the symbol in the dynamic string table too. */ - - storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (xfree, symbol_table); - number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - if (strcmp (sym->name, symname) == 0) - { - /* Bfd symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - - return symaddr; -} - - -/* Read /proc/PID/map and build a list of shared objects such that - the pr_mflags value AND'd with MATCH_MASK is equal to MATCH_VAL. - This gives us a convenient way to find all of the mappings that - don't belong to the main executable or vice versa. Here are - some of the possibilities: - - - Fetch all mappings: - MATCH_MASK: 0 - MATCH_VAL: 0 - - Fetch all mappings except for main executable: - MATCH_MASK: MA_MAINEXEC - MATCH_VAL: 0 - - Fetch only main executable: - MATCH_MASK: MA_MAINEXEC - MATCH_VAL: MA_MAINEXEC - - A cleanup chain for the list allocations done by this function should - be established prior to calling build_so_list_from_mapfile(). */ - -static struct so_list * -build_so_list_from_mapfile (int pid, long match_mask, long match_val) -{ - char *mapbuf = NULL; - struct prmap *prmap; - int mapbuf_size; - struct so_list *sos = NULL; - - { - int mapbuf_allocation_size = 8192; - char *map_pathname; - int map_fd; - - /* Open the map file */ - - map_pathname = xstrprintf ("/proc/%d/map", pid); - map_fd = open (map_pathname, O_RDONLY); - xfree (map_pathname); - if (map_fd < 0) - return 0; - - /* Read the entire map file in */ - do - { - if (mapbuf) - { - xfree (mapbuf); - mapbuf_allocation_size *= 2; - lseek (map_fd, 0, SEEK_SET); - } - mapbuf = xmalloc (mapbuf_allocation_size); - mapbuf_size = read (map_fd, mapbuf, mapbuf_allocation_size); - if (mapbuf_size < 0) - { - xfree (mapbuf); - /* FIXME: This warrants an error or a warning of some sort */ - return 0; - } - } while (mapbuf_size == mapbuf_allocation_size); - - close (map_fd); - } - - for (prmap = (struct prmap *) mapbuf; - (char *) prmap < mapbuf + mapbuf_size; - prmap++) - { - char *mapname, *pathname, *membername; - struct so_list *sop; - int mapidx; - - if (prmap->pr_size == 0) - break; - - /* Skip to the next entry if there's no path associated with the - map, unless we're looking for the kernel text region, in which - case it's okay if there's no path. */ - if ((prmap->pr_pathoff == 0 || prmap->pr_pathoff >= mapbuf_size) - && ((match_mask & MA_KERNTEXT) == 0)) - continue; - - /* Skip to the next entry if our match conditions don't hold. */ - if ((prmap->pr_mflags & match_mask) != match_val) - continue; - - mapname = prmap->pr_mapname; - if (prmap->pr_pathoff == 0) - { - pathname = ""; - membername = ""; - } - else - { - pathname = mapbuf + prmap->pr_pathoff; - membername = pathname + strlen (pathname) + 1; - } - - for (sop = sos; sop != NULL; sop = sop->next) - if (strcmp (pathname, sop->lm_info->pathname) == 0 - && strcmp (membername, sop->lm_info->membername) == 0) - break; - - if (sop == NULL) - { - sop = xcalloc (1, sizeof (struct so_list)); - make_cleanup (xfree, sop); - sop->lm_info = xcalloc (1, sizeof (struct lm_info)); - make_cleanup (xfree, sop->lm_info); - sop->lm_info->mapname = xstrdup (mapname); - make_cleanup (xfree, sop->lm_info->mapname); - /* FIXME: Eliminate the pathname field once length restriction - is lifted on so_name and so_original_name. */ - sop->lm_info->pathname = xstrdup (pathname); - make_cleanup (xfree, sop->lm_info->pathname); - sop->lm_info->membername = xstrdup (membername); - make_cleanup (xfree, sop->lm_info->membername); - - strncpy (sop->so_name, pathname, SO_NAME_MAX_PATH_SIZE - 1); - sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - strcpy (sop->so_original_name, sop->so_name); - - sop->next = sos; - sos = sop; - } - - mapidx = sop->lm_info->nmappings; - sop->lm_info->nmappings += 1; - sop->lm_info->mapping - = xrealloc (sop->lm_info->mapping, - sop->lm_info->nmappings * sizeof (struct lm_mapping)); - sop->lm_info->mapping[mapidx].addr = (CORE_ADDR) prmap->pr_vaddr; - sop->lm_info->mapping[mapidx].size = prmap->pr_size; - sop->lm_info->mapping[mapidx].offset = prmap->pr_off; - sop->lm_info->mapping[mapidx].flags = prmap->pr_mflags; - sop->lm_info->mapping[mapidx].gp = (CORE_ADDR) prmap->pr_gp; - } - - xfree (mapbuf); - return sos; -} - -/* - - LOCAL FUNCTION - - open_symbol_file_object - - SYNOPSIS - - void open_symbol_file_object (void *from_tty) - - DESCRIPTION - - If no open symbol file, attempt to locate and open the main symbol - file. - - If FROM_TTYP dereferences to a non-zero integer, allow messages to - be printed. This parameter is a pointer rather than an int because - open_symbol_file_object() is called via catch_errors() and - catch_errors() requires a pointer argument. */ - -static int -open_symbol_file_object (void *from_ttyp) -{ - CORE_ADDR lm, l_name; - char *filename; - int errcode; - int from_tty = *(int *)from_ttyp; - struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - struct so_list *sos; - - sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), - MA_MAINEXEC, MA_MAINEXEC); - - - if (sos == NULL) - { - warning (_("Could not find name of main executable in map file")); - return 0; - } - - symbol_file_command (sos->lm_info->pathname, from_tty); - - do_cleanups (old_chain); - - aix5_relocate_main_executable (); - - return 1; -} - -/* LOCAL FUNCTION - - aix5_current_sos -- build a list of currently loaded shared objects - - SYNOPSIS - - struct so_list *aix5_current_sos () - - DESCRIPTION - - Build a list of `struct so_list' objects describing the shared - objects currently loaded in the inferior. This list does not - include an entry for the main executable file. - - Note that we only gather information directly available from the - inferior --- we don't examine any of the shared library files - themselves. The declaration of `struct so_list' says which fields - we provide values for. */ - -static struct so_list * -aix5_current_sos (void) -{ - struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - struct so_list *sos; - - /* Fetch the list of mappings, excluding the main executable. */ - sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, 0); - - /* Reverse the list; it looks nicer when we print it if the mappings - are in the same order as in the map file. */ - if (sos) - { - struct so_list *next = sos->next; - - sos->next = 0; - while (next) - { - struct so_list *prev = sos; - - sos = next; - next = next->next; - sos->next = prev; - } - } - discard_cleanups (old_chain); - return sos; -} - - -/* Return 1 if PC lies in the dynamic symbol resolution code of the - run time loader. */ - -static CORE_ADDR interp_text_sect_low; -static CORE_ADDR interp_text_sect_high; -static CORE_ADDR interp_plt_sect_low; -static CORE_ADDR interp_plt_sect_high; - -static int -aix5_in_dynsym_resolve_code (CORE_ADDR pc) -{ - return ((pc >= interp_text_sect_low && pc < interp_text_sect_high) - || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high) - || in_plt_section (pc, NULL)); -} - -/* - - LOCAL FUNCTION - - enable_break -- arrange for dynamic linker to hit breakpoint - - SYNOPSIS - - int enable_break (void) - - DESCRIPTION - - The dynamic linkers has, as part of its debugger interface, support - for arranging for the inferior to hit a breakpoint after mapping in - the shared libraries. This function enables that breakpoint. - - */ - -static int -enable_break (void) -{ - int success = 0; - - struct minimal_symbol *msymbol; - char **bkpt_namep; - asection *interp_sect; - - /* First, remove all the solib event breakpoints. Their addresses - may have changed since the last time we ran the program. */ - remove_solib_event_breakpoints (); - - interp_text_sect_low = interp_text_sect_high = 0; - interp_plt_sect_low = interp_plt_sect_high = 0; - - /* Find the .interp section; if not found, warn the user and drop - into the old breakpoint at symbol code. */ - interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); - if (interp_sect) - { - unsigned int interp_sect_size; - char *buf; - CORE_ADDR load_addr; - bfd *tmp_bfd; - CORE_ADDR sym_addr = 0; - - /* Read the contents of the .interp section into a local buffer; - the contents specify the dynamic linker this program uses. */ - interp_sect_size = bfd_section_size (exec_bfd, interp_sect); - buf = alloca (interp_sect_size); - bfd_get_section_contents (exec_bfd, interp_sect, - buf, 0, interp_sect_size); - - /* Now we need to figure out where the dynamic linker was - loaded so that we can load its symbols and place a breakpoint - in the dynamic linker itself. - - This address is stored on the stack. However, I've been unable - to find any magic formula to find it for Solaris (appears to - be trivial on GNU/Linux). Therefore, we have to try an alternate - mechanism to find the dynamic linker's base address. */ - tmp_bfd = bfd_openr (buf, gnutarget); - if (tmp_bfd == NULL) - goto bkpt_at_symbol; - - /* Make sure the dynamic linker's really a useful object. */ - if (!bfd_check_format (tmp_bfd, bfd_object)) - { - warning (_("Unable to grok dynamic linker %s as an object file"), buf); - bfd_close (tmp_bfd); - goto bkpt_at_symbol; - } - - /* We find the dynamic linker's base address by examining the - current pc (which point at the entry point for the dynamic - linker) and subtracting the offset of the entry point. */ - load_addr = read_pc () - tmp_bfd->start_address; - - /* Record the relocated start and end address of the dynamic linker - text and plt section for aix5_in_dynsym_resolve_code. */ - interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); - if (interp_sect) - { - interp_text_sect_low = - bfd_section_vma (tmp_bfd, interp_sect) + load_addr; - interp_text_sect_high = - interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); - } - interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); - if (interp_sect) - { - interp_plt_sect_low = - bfd_section_vma (tmp_bfd, interp_sect) + load_addr; - interp_plt_sect_high = - interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); - } - - /* Now try to set a breakpoint in the dynamic linker. */ - for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++) - { - sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep); - if (sym_addr != 0) - break; - } - - /* We're done with the temporary bfd. */ - bfd_close (tmp_bfd); - - if (sym_addr != 0) - { - create_solib_event_breakpoint (load_addr + sym_addr); - return 1; - } - - /* For whatever reason we couldn't set a breakpoint in the dynamic - linker. Warn and drop into the old code. */ - bkpt_at_symbol: - warning (_("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.")); - } - - /* Nothing good happened. */ - success = 0; - - return (success); -} - -/* - - LOCAL FUNCTION - - special_symbol_handling -- additional shared library symbol handling - - SYNOPSIS - - void special_symbol_handling () - - DESCRIPTION - - Once the symbols from a shared object have been loaded in the usual - way, we are called to do any system specific symbol handling that - is needed. - - */ - -static void -aix5_special_symbol_handling (void) -{ - /* Nothing needed (yet) for AIX5. */ -} - -/* On AIX5, the /proc/PID/map information is used to determine - the relocation offsets needed for relocating the main executable. - There is no problem determining which map entries correspond - to the main executable, because these will have the MA_MAINEXEC - flag set. The tricky part is determining which sections correspond - to which map entries. To date, the following approaches have - been tried: - - - Use the MA_WRITE attribute of pr_mflags to distinguish the read-only - mapping from the read/write mapping. (This assumes that there are - only two mappings for the main executable.) All writable sections - are associated with the read/write mapping and all non-writable - sections are associated with the read-only mapping. - - This approach worked quite well until we came across executables - which didn't have a read-only mapping. Both mappings had the - same attributes represented in pr_mflags and it was impossible - to tell them apart. - - - Use the pr_off field (which represents the offset into the - executable) to determine the section-to-mapping relationship. - Unfortunately, this approach doesn't work either, because the - offset value contained in the mapping is rounded down by some - moderately large power-of-2 value (4096 is a typical value). - A small (e.g. "Hello World") program will appear to have all - of its sections belonging to both mappings. - - Also, the following approach has been considered, but dismissed: - - - The section vma values typically look (something) like - 0x00000001xxxxxxxx or 0x00000002xxxxxxxx. Furthermore, the - 0x00000001xxxxxxxx values always belong to one mapping and - the 0x00000002xxxxxxxx values always belong to the other. - Thus it seems conceivable that GDB could use the bit patterns - in the upper portion (for some definition of "upper") in a - section's vma to help determine the section-to-mapping - relationship. - - This approach was dismissed because there is nothing to prevent - the linker from lumping the section vmas together in one large - contiguous space and still expecting the dynamic linker to - separate them and relocate them independently. Also, different - linkers have been observed to use different patterns for the - upper portions of the vma addresses and it isn't clear what the - mask ought to be for distinguishing these patterns. - - The current (admittedly inelegant) approach uses a lookup - table which associates section names with the map index that - they're permitted to be in. This is inelegant because we are - making the following assumptions: - - 1) There will only be two mappings. - 2) The relevant (i.e. main executable) mappings will always appear - in the same order in the map file. - 3) The sections named in the table will always belong to the - indicated mapping. - 4) The table completely enumerates all possible section names. - - IMO, any of these deficiencies alone will normally be sufficient - to disqualify this approach, but I haven't been able to think of - a better way to do it. - - map_index_vs_section_name_okay() is a predicate which returns - true iff the section name NAME is associated with the map index - IDX in its builtin table. Of course, there's no guarantee that - this association is actually valid... */ - -static int -map_index_vs_section_name_okay (int idx, const char *name) -{ - static struct - { - char *name; - int idx; - } okay[] = - { - { ".interp", 0 }, - { ".hash", 0 }, - { ".dynsym", 0 }, - { ".dynstr", 0 }, - { ".rela.text", 0 }, - { ".rela.rodata", 0 }, - { ".rela.data", 0 }, - { ".rela.ctors", 0 }, - { ".rela.dtors", 0 }, - { ".rela.got", 0 }, - { ".rela.sdata", 0 }, - { ".rela.IA_64.pltoff", 0 }, - { ".rel.data", 0 }, - { ".rel.sdata", 0 }, - { ".rel.got", 0 }, - { ".rel.AIX.pfdesc", 0 }, - { ".rel.IA_64.pltoff", 0 }, - { ".dynamic", 0 }, - { ".init", 0 }, - { ".plt", 0 }, - { ".text", 0 }, - { ".fini", 0 }, - { ".rodata", 0 }, - { ".IA_64.unwind_info", 0 }, - { ".IA_64.unwind", 0 }, - { ".AIX.mustrel", 0 }, - - { ".data", 1 }, - { ".ctors", 1 }, - { ".dtors", 1 }, - { ".got", 1 }, - { ".dynamic", 1}, - { ".sdata", 1 }, - { ".IA_64.pltoff", 1 }, - { ".sbss", 1 }, - { ".bss", 1 }, - { ".AIX.pfdesc", 1 } - }; - int i; - - for (i = 0; i < sizeof (okay) / sizeof (okay[0]); i++) - { - if (strcmp (name, okay[i].name) == 0) - return idx == okay[i].idx; - } - - warning (_("Ignoring section %s when relocating the executable."), - name); - return 0; -} - -#define SECTMAPMASK (~ (CORE_ADDR) 0x03ffffff) - -static void -aix5_relocate_main_executable (void) -{ - struct so_list *so; - struct section_offsets *new_offsets; - int i; - int changed = 0; - struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - - /* Fetch the mappings for the main executable from the map file. */ - so = build_so_list_from_mapfile (PIDGET (inferior_ptid), - MA_MAINEXEC, MA_MAINEXEC); - - /* Make sure we actually have some mappings to work with. */ - if (so == NULL) - { - warning (_("Could not find main executable in map file")); - do_cleanups (old_chain); - return; - } - - /* Allocate the data structure which'll contain the new offsets to - relocate by. Initialize it so it contains the current offsets. */ - new_offsets = xcalloc (symfile_objfile->num_sections, - sizeof (struct section_offsets)); - make_cleanup (xfree, new_offsets); - for (i = 0; i < symfile_objfile->num_sections; i++) - new_offsets->offsets[i] = ANOFFSET (symfile_objfile->section_offsets, i); - - /* Iterate over the mappings in the main executable and compute - the new offset value as appropriate. */ - for (i = 0; i < so->lm_info->nmappings; i++) - { - CORE_ADDR increment = 0; - struct obj_section *sect; - bfd *obfd = symfile_objfile->obfd; - struct lm_mapping *mapping = &so->lm_info->mapping[i]; - - ALL_OBJFILE_OSECTIONS (symfile_objfile, sect) - { - int flags = bfd_get_section_flags (obfd, sect->the_bfd_section); - if (flags & SEC_ALLOC) - { - file_ptr filepos = sect->the_bfd_section->filepos; - if (map_index_vs_section_name_okay (i, - bfd_get_section_name (obfd, sect->the_bfd_section))) - { - int idx = sect->the_bfd_section->index; - - if (increment == 0) - increment = mapping->addr - - (bfd_section_vma (obfd, sect->the_bfd_section) - & SECTMAPMASK); - - if (increment != ANOFFSET (new_offsets, idx)) - { - new_offsets->offsets[idx] = increment; - changed = 1; - } - } - } - } - } - - /* If any of the offsets have changed, then relocate the objfile. */ - if (changed) - objfile_relocate (symfile_objfile, new_offsets); - - /* Free up all the space we've allocated. */ - do_cleanups (old_chain); -} - -/* - - GLOBAL FUNCTION - - aix5_solib_create_inferior_hook -- shared library startup support - - SYNOPSIS - - void aix5_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 AIX5 executables, this first instruction is the first - instruction in the dynamic linker (for dynamically linked - executables) or the instruction at "start" for statically linked - executables. For dynamically linked executables, the system - first exec's libc.so.N, which contains the dynamic linker, - and starts it running. The dynamic linker maps in any needed - shared libraries, maps in the actual user executable, and then - jumps to "start" in the user executable. - - */ - -static void -aix5_solib_create_inferior_hook (void) -{ - aix5_relocate_main_executable (); - - if (!enable_break ()) - { - warning (_("shared library handler failed to enable breakpoint")); - return; - } -} - -static void -aix5_clear_solib (void) -{ -} - -static void -aix5_free_so (struct so_list *so) -{ - xfree (so->lm_info->mapname); - xfree (so->lm_info->pathname); - xfree (so->lm_info->membername); - xfree (so->lm_info); -} - -static void -aix5_relocate_section_addresses (struct so_list *so, - struct section_table *sec) -{ - int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section); - file_ptr filepos = sec->the_bfd_section->filepos; - - if (flags & SEC_ALLOC) - { - int idx; - CORE_ADDR addr; - - for (idx = 0; idx < so->lm_info->nmappings; idx++) - { - struct lm_mapping *mapping = &so->lm_info->mapping[idx]; - if (mapping->offset <= filepos - && filepos <= mapping->offset + mapping->size) - break; - } - - if (idx >= so->lm_info->nmappings) - internal_error (__FILE__, __LINE__, - _("aix_relocate_section_addresses: Can't find mapping for section %s"), - bfd_get_section_name (sec->bfd, sec->the_bfd_section)); - - addr = so->lm_info->mapping[idx].addr; - - sec->addr += addr; - sec->endaddr += addr; - } -} - -/* Find the global pointer for the given function address ADDR. */ - -static CORE_ADDR -aix5_find_global_pointer (CORE_ADDR addr) -{ - struct so_list *sos, *so; - CORE_ADDR global_pointer = 0; - struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - - sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), 0, 0); - - for (so = sos; so != NULL; so = so->next) - { - int idx; - for (idx = 0; idx < so->lm_info->nmappings; idx++) - if (so->lm_info->mapping[idx].addr <= addr - && addr <= so->lm_info->mapping[idx].addr - + so->lm_info->mapping[idx].size) - { - break; - } - - if (idx < so->lm_info->nmappings) - { - /* Look for a non-zero global pointer in the current set of - mappings. */ - for (idx = 0; idx < so->lm_info->nmappings; idx++) - if (so->lm_info->mapping[idx].gp != 0) - { - global_pointer = so->lm_info->mapping[idx].gp; - break; - } - /* Get out regardless of whether we found one or not. Mappings - don't overlap, so it would be pointless to continue. */ - break; - } - } - - do_cleanups (old_chain); - - return global_pointer; -} - -/* Find the execute-only kernel region known as the gate page. This - page is where the signal trampoline lives. It may be found by - querying the map file and looking for the MA_KERNTEXT flag. */ -static void -aix5_find_gate_addresses (CORE_ADDR *start, CORE_ADDR *end) -{ - struct so_list *so; - struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - - /* Fetch the mappings for the main executable from the map file. */ - so = build_so_list_from_mapfile (PIDGET (inferior_ptid), - MA_KERNTEXT, MA_KERNTEXT); - - /* Make sure we actually have some mappings to work with. */ - if (so == NULL) - { - warning (_("Could not find gate page in map file")); - *start = 0; - *end = 0; - do_cleanups (old_chain); - return; - } - - /* There should only be on kernel mapping for the gate page and - it'll be in the read-only (even though it's execute-only) - mapping in the lm_info struct. */ - - *start = so->lm_info->mapping[0].addr; - *end = *start + so->lm_info->mapping[0].size; - - /* Free up all the space we've allocated. */ - do_cleanups (old_chain); -} - -/* From ia64-tdep.c. FIXME: If we end up using this for rs6000 too, - we'll need to make the names match. */ -extern CORE_ADDR (*native_find_global_pointer) (CORE_ADDR); - -/* From ia64-aix-tdep.c. Hook for finding the starting and - ending gate page addresses. The only reason that this hook - is in this file is because this is where the map file reading - code is located. */ -extern void (*aix5_find_gate_addresses_hook) (CORE_ADDR *, CORE_ADDR *); - -static struct target_so_ops aix5_so_ops; - -void -_initialize_aix5_solib (void) -{ - aix5_so_ops.relocate_section_addresses = aix5_relocate_section_addresses; - aix5_so_ops.free_so = aix5_free_so; - aix5_so_ops.clear_solib = aix5_clear_solib; - aix5_so_ops.solib_create_inferior_hook = aix5_solib_create_inferior_hook; - aix5_so_ops.special_symbol_handling = aix5_special_symbol_handling; - aix5_so_ops.current_sos = aix5_current_sos; - aix5_so_ops.open_symbol_file_object = open_symbol_file_object; - aix5_so_ops.in_dynsym_resolve_code = aix5_in_dynsym_resolve_code; - - native_find_global_pointer = aix5_find_global_pointer; - aix5_find_gate_addresses_hook = aix5_find_gate_addresses; - - /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ - current_target_so_ops = &aix5_so_ops; -} |