X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsolib-svr4.c;h=4bc459c6c11fbfdbd090ad60ab120663a2ea8b70;hb=4ee62156d969867d3d3ffedf656a74643f77279e;hp=654c90687e906a6fd25d09d7fd1dfafa79ca9f86;hpb=1cf3db46a678ced9d729572de9232fab9c00350d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 654c90687e..4bc459c6c1 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -1,7 +1,8 @@ /* Handle SVR4 shared libraries for GDB, the GNU Debugger. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GDB. @@ -31,6 +32,9 @@ #include "gdbcore.h" #include "target.h" #include "inferior.h" +#include "regcache.h" +#include "gdbthread.h" +#include "observer.h" #include "gdb_assert.h" @@ -42,6 +46,7 @@ #include "elf-bfd.h" #include "exec.h" #include "auxv.h" +#include "exceptions.h" static struct link_map_offsets *svr4_fetch_link_map_offsets (void); static int svr4_have_link_map_offsets (void); @@ -139,13 +144,14 @@ static CORE_ADDR LM_ADDR_FROM_LINK_MAP (struct so_list *so) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, - builtin_type_void_data_ptr); + ptr_type); } static int -HAS_LM_DYNAMIC_FROM_LINK_MAP () +HAS_LM_DYNAMIC_FROM_LINK_MAP (void) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); @@ -156,9 +162,10 @@ static CORE_ADDR LM_DYNAMIC_FROM_LINK_MAP (struct so_list *so) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; return extract_typed_address (so->lm_info->lm + lmo->l_ld_offset, - builtin_type_void_data_ptr); + ptr_type); } static CORE_ADDR @@ -235,47 +242,89 @@ static CORE_ADDR LM_NEXT (struct so_list *so) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; return extract_typed_address (so->lm_info->lm + lmo->l_next_offset, - builtin_type_void_data_ptr); + ptr_type); } static CORE_ADDR LM_NAME (struct so_list *so) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; return extract_typed_address (so->lm_info->lm + lmo->l_name_offset, - builtin_type_void_data_ptr); + ptr_type); } static int IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; /* Assume that everything is a library if the dynamic loader was loaded late by a static executable. */ - if (bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) + if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) return 0; return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset, - builtin_type_void_data_ptr) == 0; + ptr_type) == 0; } -static CORE_ADDR debug_base; /* Base of dynamic linker structures */ +/* Per pspace SVR4 specific data. */ -/* Validity flag for debug_loader_offset. */ -static int debug_loader_offset_p; +struct svr4_info +{ + CORE_ADDR debug_base; /* Base of dynamic linker structures */ + + /* Validity flag for debug_loader_offset. */ + int debug_loader_offset_p; + + /* Load address for the dynamic linker, inferred. */ + CORE_ADDR debug_loader_offset; -/* Load address for the dynamic linker, inferred. */ -static CORE_ADDR debug_loader_offset; + /* Name of the dynamic linker, valid if debug_loader_offset_p. */ + char *debug_loader_name; -/* Name of the dynamic linker, valid if debug_loader_offset_p. */ -static char *debug_loader_name; + /* Load map address for the main executable. */ + CORE_ADDR main_lm_addr; + + CORE_ADDR interp_text_sect_low; + CORE_ADDR interp_text_sect_high; + CORE_ADDR interp_plt_sect_low; + CORE_ADDR interp_plt_sect_high; +}; -/* Load map address for the main executable. */ -static CORE_ADDR main_lm_addr; +/* Per-program-space data key. */ +static const struct program_space_data *solib_svr4_pspace_data; + +static void +svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) +{ + struct svr4_info *info; + + info = program_space_data (pspace, solib_svr4_pspace_data); + xfree (info); +} + +/* Get the current svr4 data. If none is found yet, add it now. This + function always returns a valid object. */ + +static struct svr4_info * +get_svr4_info (void) +{ + struct svr4_info *info; + + info = program_space_data (current_program_space, solib_svr4_pspace_data); + if (info != NULL) + return info; + + info = XZALLOC (struct svr4_info); + set_program_space_data (current_program_space, solib_svr4_pspace_data, info); + return info; +} /* Local function prototypes */ @@ -373,6 +422,144 @@ bfd_lookup_symbol (bfd *abfd, char *symname) return symaddr; } + +/* Read program header TYPE from inferior memory. The header is found + by scanning the OS auxillary vector. + + Return a pointer to allocated memory holding the program header contents, + or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the + size of those contents is returned to P_SECT_SIZE. Likewise, the target + architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE. */ + +static gdb_byte * +read_program_header (int type, int *p_sect_size, int *p_arch_size) +{ + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); + CORE_ADDR at_phdr, at_phent, at_phnum; + int arch_size, sect_size; + CORE_ADDR sect_addr; + gdb_byte *buf; + + /* Get required auxv elements from target. */ + if (target_auxv_search (¤t_target, AT_PHDR, &at_phdr) <= 0) + return 0; + if (target_auxv_search (¤t_target, AT_PHENT, &at_phent) <= 0) + return 0; + if (target_auxv_search (¤t_target, AT_PHNUM, &at_phnum) <= 0) + return 0; + if (!at_phdr || !at_phnum) + return 0; + + /* Determine ELF architecture type. */ + if (at_phent == sizeof (Elf32_External_Phdr)) + arch_size = 32; + else if (at_phent == sizeof (Elf64_External_Phdr)) + arch_size = 64; + else + return 0; + + /* Find .dynamic section via the PT_DYNAMIC PHDR. */ + if (arch_size == 32) + { + Elf32_External_Phdr phdr; + int i; + + /* Search for requested PHDR. */ + for (i = 0; i < at_phnum; i++) + { + if (target_read_memory (at_phdr + i * sizeof (phdr), + (gdb_byte *)&phdr, sizeof (phdr))) + return 0; + + if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, + 4, byte_order) == type) + break; + } + + if (i == at_phnum) + return 0; + + /* Retrieve address and size. */ + sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr, + 4, byte_order); + sect_size = extract_unsigned_integer ((gdb_byte *)phdr.p_memsz, + 4, byte_order); + } + else + { + Elf64_External_Phdr phdr; + int i; + + /* Search for requested PHDR. */ + for (i = 0; i < at_phnum; i++) + { + if (target_read_memory (at_phdr + i * sizeof (phdr), + (gdb_byte *)&phdr, sizeof (phdr))) + return 0; + + if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, + 4, byte_order) == type) + break; + } + + if (i == at_phnum) + return 0; + + /* Retrieve address and size. */ + sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr, + 8, byte_order); + sect_size = extract_unsigned_integer ((gdb_byte *)phdr.p_memsz, + 8, byte_order); + } + + /* Read in requested program header. */ + buf = xmalloc (sect_size); + if (target_read_memory (sect_addr, buf, sect_size)) + { + xfree (buf); + return NULL; + } + + if (p_arch_size) + *p_arch_size = arch_size; + if (p_sect_size) + *p_sect_size = sect_size; + + return buf; +} + + +/* Return program interpreter string. */ +static gdb_byte * +find_program_interpreter (void) +{ + gdb_byte *buf = NULL; + + /* If we have an exec_bfd, use its section table. */ + if (exec_bfd + && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour) + { + struct bfd_section *interp_sect; + + interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); + if (interp_sect != NULL) + { + CORE_ADDR sect_addr = bfd_section_vma (exec_bfd, interp_sect); + int sect_size = bfd_section_size (exec_bfd, interp_sect); + + buf = xmalloc (sect_size); + bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, sect_size); + } + } + + /* If we didn't find it, use the target auxillary vector. */ + if (!buf) + buf = read_program_header (PT_INTERP, NULL, NULL); + + return buf; +} + + /* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is returned and the corresponding PTR is set. */ @@ -389,9 +576,13 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) if (abfd == NULL) return 0; + + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return 0; + arch_size = bfd_get_arch_size (abfd); if (arch_size == -1) - return 0; + return 0; /* Find the start address of the .dynamic section. */ sect = bfd_get_section_by_name (abfd, ".dynamic"); @@ -434,13 +625,14 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) entry. */ if (ptr) { + struct type *ptr_type; gdb_byte ptr_buf[8]; CORE_ADDR ptr_addr; + ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) - dyn_ptr = extract_typed_address (ptr_buf, - builtin_type_void_data_ptr); + dyn_ptr = extract_typed_address (ptr_buf, ptr_type); *ptr = dyn_ptr; } return 1; @@ -450,6 +642,64 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) return 0; } +/* Scan for DYNTAG in .dynamic section of the target's main executable, + found by consulting the OS auxillary vector. If DYNTAG is found 1 is + returned and the corresponding PTR is set. */ + +static int +scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr) +{ + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); + int sect_size, arch_size, step; + long dyn_tag; + CORE_ADDR dyn_ptr; + gdb_byte *bufend, *bufstart, *buf; + + /* Read in .dynamic section. */ + buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size); + if (!buf) + return 0; + + /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */ + step = (arch_size == 32) ? sizeof (Elf32_External_Dyn) + : sizeof (Elf64_External_Dyn); + for (bufend = buf + sect_size; + buf < bufend; + buf += step) + { + if (arch_size == 32) + { + Elf32_External_Dyn *dynp = (Elf32_External_Dyn *) buf; + dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag, + 4, byte_order); + dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr, + 4, byte_order); + } + else + { + Elf64_External_Dyn *dynp = (Elf64_External_Dyn *) buf; + dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag, + 8, byte_order); + dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr, + 8, byte_order); + } + if (dyn_tag == DT_NULL) + break; + + if (dyn_tag == dyntag) + { + if (ptr) + *ptr = dyn_ptr; + + xfree (bufstart); + return 1; + } + } + + xfree (bufstart); + return 0; +} + /* @@ -484,20 +734,23 @@ elf_locate_base (void) /* Look for DT_MIPS_RLD_MAP first. MIPS executables use this instead of DT_DEBUG, although they sometimes contain an unused DT_DEBUG. */ - if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr)) + if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr) + || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr)) { + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; gdb_byte *pbuf; - int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr); + int pbuf_size = TYPE_LENGTH (ptr_type); pbuf = alloca (pbuf_size); /* DT_MIPS_RLD_MAP contains a pointer to the address of the dynamic link structure. */ if (target_read_memory (dyn_ptr, pbuf, pbuf_size)) return 0; - return extract_typed_address (pbuf, builtin_type_void_data_ptr); + return extract_typed_address (pbuf, ptr_type); } /* Find DT_DEBUG. */ - if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr)) + if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr) + || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr)) return dyn_ptr; /* This may be a static executable. Look for the symbol @@ -518,7 +771,7 @@ elf_locate_base (void) SYNOPSIS - CORE_ADDR locate_base (void) + CORE_ADDR locate_base (struct svr4_info *) DESCRIPTION @@ -548,7 +801,7 @@ elf_locate_base (void) */ static CORE_ADDR -locate_base (void) +locate_base (struct svr4_info *info) { /* Check to see if we have a currently valid address, and if so, avoid doing all this work again and just return the cached address. If @@ -556,13 +809,9 @@ locate_base (void) section for ELF executables. There's no point in doing any of this though if we don't have some link map offsets to work with. */ - if (debug_base == 0 && svr4_have_link_map_offsets ()) - { - if (exec_bfd != NULL - && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour) - debug_base = elf_locate_base (); - } - return (debug_base); + if (info->debug_base == 0 && svr4_have_link_map_offsets ()) + info->debug_base = elf_locate_base (); + return info->debug_base; } /* Find the first element in the inferior's dynamic link map, and @@ -573,43 +822,92 @@ locate_base (void) RT_CONSISTENT. */ static CORE_ADDR -solib_svr4_r_map (void) +solib_svr4_r_map (struct svr4_info *info) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - return read_memory_typed_address (debug_base + lmo->r_map_offset, - builtin_type_void_data_ptr); + return read_memory_typed_address (info->debug_base + lmo->r_map_offset, + ptr_type); } /* Find r_brk from the inferior's debug base. */ static CORE_ADDR -solib_svr4_r_brk (void) +solib_svr4_r_brk (struct svr4_info *info) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - return read_memory_typed_address (debug_base + lmo->r_brk_offset, - builtin_type_void_data_ptr); + return read_memory_typed_address (info->debug_base + lmo->r_brk_offset, + ptr_type); } /* Find the link map for the dynamic linker (if it is not in the normal list of loaded shared objects). */ static CORE_ADDR -solib_svr4_r_ldsomap (void) +solib_svr4_r_ldsomap (struct svr4_info *info) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; + enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); ULONGEST version; /* Check version, and return zero if `struct r_debug' doesn't have the r_ldsomap member. */ - version = read_memory_unsigned_integer (debug_base + lmo->r_version_offset, - lmo->r_version_size); + version + = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset, + lmo->r_version_size, byte_order); if (version < 2 || lmo->r_ldsomap_offset == -1) return 0; - return read_memory_typed_address (debug_base + lmo->r_ldsomap_offset, - builtin_type_void_data_ptr); + return read_memory_typed_address (info->debug_base + lmo->r_ldsomap_offset, + ptr_type); +} + +/* On Solaris systems with some versions of the dynamic linker, + ld.so's l_name pointer points to the SONAME in the string table + rather than into writable memory. So that GDB can find shared + libraries when loading a core file generated by gcore, ensure that + memory areas containing the l_name string are saved in the core + file. */ + +static int +svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) +{ + struct svr4_info *info; + CORE_ADDR ldsomap; + struct so_list *new; + struct cleanup *old_chain; + struct link_map_offsets *lmo; + CORE_ADDR lm_name; + + info = get_svr4_info (); + + info->debug_base = 0; + locate_base (info); + if (!info->debug_base) + return 0; + + ldsomap = solib_svr4_r_ldsomap (info); + if (!ldsomap) + return 0; + + lmo = svr4_fetch_link_map_offsets (); + new = XZALLOC (struct so_list); + old_chain = make_cleanup (xfree, new); + new->lm_info = xmalloc (sizeof (struct lm_info)); + make_cleanup (xfree, new->lm_info); + new->lm_info->l_addr = (CORE_ADDR)-1; + new->lm_info->lm_addr = ldsomap; + new->lm_info->lm = xzalloc (lmo->link_map_size); + make_cleanup (xfree, new->lm_info->lm); + read_memory (ldsomap, new->lm_info->lm, lmo->link_map_size); + lm_name = LM_NAME (new); + do_cleanups (old_chain); + + return (lm_name >= vaddr && lm_name < vaddr + size); } /* @@ -642,21 +940,23 @@ open_symbol_file_object (void *from_ttyp) int errcode; int from_tty = *(int *)from_ttyp; struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - int l_name_size = TYPE_LENGTH (builtin_type_void_data_ptr); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; + int l_name_size = TYPE_LENGTH (ptr_type); gdb_byte *l_name_buf = xmalloc (l_name_size); struct cleanup *cleanups = make_cleanup (xfree, l_name_buf); + struct svr4_info *info = get_svr4_info (); if (symfile_objfile) - if (!query ("Attempt to reload symbols from process? ")) + if (!query (_("Attempt to reload symbols from process? "))) return 0; /* Always locate the debug struct, in case it has moved. */ - debug_base = 0; - if (locate_base () == 0) + info->debug_base = 0; + if (locate_base (info) == 0) return 0; /* failed somehow... */ /* First link map member should be the executable. */ - lm = solib_svr4_r_map (); + lm = solib_svr4_r_map (info); if (lm == 0) return 0; /* failed somehow... */ @@ -664,7 +964,7 @@ open_symbol_file_object (void *from_ttyp) read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size); /* Convert the address to host format. */ - l_name = extract_typed_address (l_name_buf, builtin_type_void_data_ptr); + l_name = extract_typed_address (l_name_buf, ptr_type); /* Free l_name_buf. */ do_cleanups (cleanups); @@ -695,10 +995,12 @@ open_symbol_file_object (void *from_ttyp) static struct so_list * svr4_default_sos (void) { + struct svr4_info *info = get_svr4_info (); + struct so_list *head = NULL; struct so_list **link_ptr = &head; - if (debug_loader_offset_p) + if (info->debug_loader_offset_p) { struct so_list *new = XZALLOC (struct so_list); @@ -706,11 +1008,12 @@ svr4_default_sos (void) /* Nothing will ever check the cached copy of the link map if we set l_addr. */ - new->lm_info->l_addr = debug_loader_offset; + new->lm_info->l_addr = info->debug_loader_offset; new->lm_info->lm_addr = 0; new->lm_info->lm = NULL; - strncpy (new->so_name, debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1); + strncpy (new->so_name, info->debug_loader_name, + SO_NAME_MAX_PATH_SIZE - 1); new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; strcpy (new->so_original_name, new->so_name); @@ -747,19 +1050,22 @@ svr4_current_sos (void) struct so_list *head = 0; struct so_list **link_ptr = &head; CORE_ADDR ldsomap = 0; + struct svr4_info *info; + + info = get_svr4_info (); /* Always locate the debug struct, in case it has moved. */ - debug_base = 0; - locate_base (); + info->debug_base = 0; + locate_base (info); /* If we can't find the dynamic linker's base structure, this must not be a dynamically linked executable. Hmm. */ - if (! debug_base) + if (! info->debug_base) return svr4_default_sos (); /* Walk the inferior's link map list, and build our list of `struct so_list' nodes. */ - lm = solib_svr4_r_map (); + lm = solib_svr4_r_map (info); while (lm) { @@ -786,7 +1092,7 @@ svr4_current_sos (void) decide when to ignore it. */ if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0) { - main_lm_addr = new->lm_info->lm_addr; + info->main_lm_addr = new->lm_info->lm_addr; free_so (new); } else @@ -826,7 +1132,7 @@ svr4_current_sos (void) symbol information for the dynamic linker is quite crucial for skipping dynamic linker resolver code. */ if (lm == 0 && ldsomap == 0) - lm = ldsomap = solib_svr4_r_ldsomap (); + lm = ldsomap = solib_svr4_r_ldsomap (info); discard_cleanups (old_chain); } @@ -843,14 +1149,15 @@ CORE_ADDR svr4_fetch_objfile_link_map (struct objfile *objfile) { struct so_list *so; + struct svr4_info *info = get_svr4_info (); /* Cause svr4_current_sos() to be run if it hasn't been already. */ - if (main_lm_addr == 0) + if (info->main_lm_addr == 0) solib_add (NULL, 0, ¤t_target, auto_solib_add); /* svr4_current_sos() will set main_lm_addr for the main executable. */ if (objfile == symfile_objfile) - return main_lm_addr; + return info->main_lm_addr; /* The other link map addresses may be found by examining the list of shared libraries. */ @@ -882,16 +1189,16 @@ match_main (char *soname) /* Return 1 if PC lies in the dynamic symbol resolution code of the SVR4 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; int svr4_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) + struct svr4_info *info = get_svr4_info (); + + return ((pc >= info->interp_text_sect_low + && pc < info->interp_text_sect_high) + || (pc >= info->interp_plt_sect_low + && pc < info->interp_plt_sect_high) || in_plt_section (pc, NULL)); } @@ -958,19 +1265,20 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ) */ static int -enable_break (void) +enable_break (struct svr4_info *info) { struct minimal_symbol *msymbol; char **bkpt_namep; asection *interp_sect; + gdb_byte *interp_name; CORE_ADDR sym_addr; /* 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; + info->interp_text_sect_low = info->interp_text_sect_high = 0; + info->interp_plt_sect_low = info->interp_plt_sect_high = 0; /* If we already have a shared library list in the target, and r_debug contains r_brk, set the breakpoint there - this should @@ -979,8 +1287,8 @@ enable_break (void) solib_add (NULL, 0, ¤t_target, auto_solib_add); sym_addr = 0; - if (debug_base && solib_svr4_r_map () != 0) - sym_addr = solib_svr4_r_brk (); + if (info->debug_base && solib_svr4_r_map (info) != 0) + sym_addr = solib_svr4_r_brk (info); if (sym_addr != 0) { @@ -1006,48 +1314,41 @@ enable_break (void) interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { - interp_text_sect_low = + info->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); + info->interp_text_sect_high = + info->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 = + info->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); + info->interp_plt_sect_high = + info->interp_plt_sect_low + + bfd_section_size (tmp_bfd, interp_sect); } - create_solib_event_breakpoint (sym_addr); + create_solib_event_breakpoint (target_gdbarch, sym_addr); return 1; } } - /* Find the .interp section; if not found, warn the user and drop + /* Find the program interpreter; 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) + interp_name = find_program_interpreter (); + if (interp_name) { - unsigned int interp_sect_size; - char *buf; CORE_ADDR load_addr = 0; int load_addr_found = 0; int loader_found_in_list = 0; struct so_list *so; bfd *tmp_bfd = NULL; struct target_ops *tmp_bfd_target; - int tmp_fd = -1; - char *tmp_pathname = NULL; + volatile struct gdb_exception ex; - /* Read the contents of the .interp section into a local buffer; - the contents specify the dynamic linker this program uses. */ sym_addr = 0; - 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 @@ -1058,21 +1359,13 @@ enable_break (void) be trivial on GNU/Linux). Therefore, we have to try an alternate mechanism to find the dynamic linker's base address. */ - tmp_fd = solib_open (buf, &tmp_pathname); - if (tmp_fd >= 0) - tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd); - + TRY_CATCH (ex, RETURN_MASK_ALL) + { + tmp_bfd = solib_bfd_open (interp_name); + } 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; - } - /* Now convert the TMP_BFD into a target. That way target, as well as BFD operations can be used. Note that closing the target will also close the underlying bfd. */ @@ -1083,7 +1376,7 @@ enable_break (void) so = master_so_list (); while (so) { - if (svr4_same_1 (buf, so->so_original_name)) + if (svr4_same_1 (interp_name, so->so_original_name)) { load_addr_found = 1; loader_found_in_list = 1; @@ -1107,14 +1400,18 @@ enable_break (void) fallback method because it has actually been working well in most cases. */ if (!load_addr_found) - load_addr = (read_pc () - - exec_entry_point (tmp_bfd, tmp_bfd_target)); + { + struct regcache *regcache + = get_thread_arch_regcache (inferior_ptid, target_gdbarch); + load_addr = (regcache_read_pc (regcache) + - exec_entry_point (tmp_bfd, tmp_bfd_target)); + } if (!loader_found_in_list) { - debug_loader_name = xstrdup (buf); - debug_loader_offset_p = 1; - debug_loader_offset = load_addr; + info->debug_loader_name = xstrdup (interp_name); + info->debug_loader_offset_p = 1; + info->debug_loader_offset = load_addr; solib_add (NULL, 0, ¤t_target, auto_solib_add); } @@ -1123,18 +1420,20 @@ enable_break (void) interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { - interp_text_sect_low = + info->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); + info->interp_text_sect_high = + info->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 = + info->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); + info->interp_plt_sect_high = + info->interp_plt_sect_low + + bfd_section_size (tmp_bfd, interp_sect); } /* Now try to set a breakpoint in the dynamic linker. */ @@ -1159,14 +1458,15 @@ enable_break (void) if (sym_addr != 0) { - create_solib_event_breakpoint (load_addr + sym_addr); + create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr); + xfree (interp_name); 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: - xfree (tmp_pathname); + xfree (interp_name); warning (_("Unable to find dynamic linker breakpoint function.\n" "GDB will be unable to debug shared library initializers\n" "and track explicitly loaded dynamic code.")); @@ -1180,7 +1480,11 @@ enable_break (void) msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) { - create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol)); + sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); + sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + sym_addr, + ¤t_target); + create_solib_event_breakpoint (target_gdbarch, sym_addr); return 1; } } @@ -1190,7 +1494,11 @@ enable_break (void) msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) { - create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol)); + sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); + sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + sym_addr, + ¤t_target); + create_solib_event_breakpoint (target_gdbarch, sym_addr); return 1; } } @@ -1241,7 +1549,9 @@ static void svr4_relocate_main_executable (void) { asection *interp_sect; - CORE_ADDR pc = read_pc (); + struct regcache *regcache + = get_thread_arch_regcache (inferior_ptid, target_gdbarch); + CORE_ADDR pc = regcache_read_pc (regcache); /* Decide if the objfile needs to be relocated. As indicated above, we will only be here when execution is stopped at the beginning @@ -1388,13 +1698,19 @@ svr4_relocate_main_executable (void) static void svr4_solib_create_inferior_hook (void) { + struct inferior *inf; + struct thread_info *tp; + struct svr4_info *info; + + info = get_svr4_info (); + /* Relocate the main executable if necessary. */ svr4_relocate_main_executable (); if (!svr4_have_link_map_offsets ()) return; - if (!enable_break ()) + if (!enable_break (info)) return; #if defined(_SCO_DS) @@ -1407,28 +1723,33 @@ svr4_solib_create_inferior_hook (void) can go groveling around in the dynamic linker structures to find out what we need to know about them. */ + inf = current_inferior (); + tp = inferior_thread (); + clear_proceed_status (); - stop_soon = STOP_QUIETLY; - stop_signal = TARGET_SIGNAL_0; + inf->stop_soon = STOP_QUIETLY; + tp->stop_signal = TARGET_SIGNAL_0; do { - target_resume (pid_to_ptid (-1), 0, stop_signal); + target_resume (pid_to_ptid (-1), 0, tp->stop_signal); wait_for_inferior (0); } - while (stop_signal != TARGET_SIGNAL_TRAP); - stop_soon = NO_STOP_QUIETLY; + while (tp->stop_signal != TARGET_SIGNAL_TRAP); + inf->stop_soon = NO_STOP_QUIETLY; #endif /* defined(_SCO_DS) */ } static void svr4_clear_solib (void) { - debug_base = 0; - debug_loader_offset_p = 0; - debug_loader_offset = 0; - xfree (debug_loader_name); - debug_loader_name = NULL; - main_lm_addr = 0; + struct svr4_info *info; + + info = get_svr4_info (); + info->debug_base = 0; + info->debug_loader_offset_p = 0; + info->debug_loader_offset = 0; + xfree (info->debug_loader_name); + info->debug_loader_name = NULL; } static void @@ -1466,7 +1787,7 @@ svr4_truncate_ptr (CORE_ADDR addr) static void svr4_relocate_section_addresses (struct so_list *so, - struct section_table *sec) + struct target_section *sec) { sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR_CHECK (so, sec->bfd)); @@ -1627,6 +1948,8 @@ void _initialize_svr4_solib (void) { solib_svr4_data = gdbarch_data_register_pre_init (solib_svr4_init); + solib_svr4_pspace_data + = register_program_space_data_with_cleanup (svr4_pspace_data_cleanup); svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses; svr4_so_ops.free_so = svr4_free_so; @@ -1636,6 +1959,8 @@ _initialize_svr4_solib (void) svr4_so_ops.current_sos = svr4_current_sos; svr4_so_ops.open_symbol_file_object = open_symbol_file_object; svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code; + svr4_so_ops.bfd_open = solib_bfd_open; svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; svr4_so_ops.same = svr4_same; + svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; }