X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fsolib-svr4.c;h=4bc459c6c11fbfdbd090ad60ab120663a2ea8b70;hb=4ee62156d969867d3d3ffedf656a74643f77279e;hp=07e4f76a54a99aed4835571831ad7801d85ce226;hpb=a6d9a66e2318b2002461996aeb5d4f18a0a9d3d6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 07e4f76a54..4bc459c6c1 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -273,12 +273,10 @@ IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so) ptr_type) == 0; } -/* Per-inferior SVR4 specific data. */ +/* Per pspace SVR4 specific data. */ struct svr4_info { - int pid; - CORE_ADDR debug_base; /* Base of dynamic linker structures */ /* Validity flag for debug_loader_offset. */ @@ -292,69 +290,40 @@ struct svr4_info /* Load map address for the main executable. */ CORE_ADDR main_lm_addr; -}; - -/* List of known processes using solib-svr4 shared libraries, storing - the required bookkeeping for each. */ -typedef struct svr4_info *svr4_info_p; -DEF_VEC_P(svr4_info_p); -VEC(svr4_info_p) *svr4_info = NULL; + CORE_ADDR interp_text_sect_low; + CORE_ADDR interp_text_sect_high; + CORE_ADDR interp_plt_sect_low; + CORE_ADDR interp_plt_sect_high; +}; -/* Get svr4 data for inferior PID (target id). If none is found yet, - add it now. This function always returns a valid object. */ +/* Per-program-space data key. */ +static const struct program_space_data *solib_svr4_pspace_data; -struct svr4_info * -get_svr4_info (int pid) +static void +svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) { - int ix; - struct svr4_info *it; - - gdb_assert (pid != 0); - - for (ix = 0; VEC_iterate (svr4_info_p, svr4_info, ix, it); ++ix) - { - if (it->pid == pid) - return it; - } - - it = XZALLOC (struct svr4_info); - it->pid = pid; - - VEC_safe_push (svr4_info_p, svr4_info, it); + struct svr4_info *info; - return it; + info = program_space_data (pspace, solib_svr4_pspace_data); + xfree (info); } -/* Get rid of any svr4 related bookkeeping for inferior PID (target - id). */ +/* Get the current svr4 data. If none is found yet, add it now. This + function always returns a valid object. */ -static void -remove_svr4_info (int pid) +static struct svr4_info * +get_svr4_info (void) { - int ix; - struct svr4_info *it; - - for (ix = 0; VEC_iterate (svr4_info_p, svr4_info, ix, it); ++ix) - { - if (it->pid == pid) - { - VEC_unordered_remove (svr4_info_p, svr4_info, ix); - return; - } - } -} + struct svr4_info *info; -/* This is an "inferior_exit" observer. Inferior PID (target id) is - being removed from the inferior list, because it exited, was - killed, detached, or we just dropped the connection to the debug - interface --- discard any solib-svr4 related bookkeeping for this - inferior. */ + info = program_space_data (current_program_space, solib_svr4_pspace_data); + if (info != NULL) + return info; -static void -solib_svr4_inferior_exit (int pid) -{ - remove_svr4_info (pid); + info = XZALLOC (struct svr4_info); + set_program_space_data (current_program_space, solib_svr4_pspace_data, info); + return info; } /* Local function prototypes */ @@ -465,6 +434,7 @@ bfd_lookup_symbol (bfd *abfd, char *symname) 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; @@ -501,7 +471,8 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) (gdb_byte *)&phdr, sizeof (phdr))) return 0; - if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, 4) == type) + if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, + 4, byte_order) == type) break; } @@ -509,8 +480,10 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) return 0; /* Retrieve address and size. */ - sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr, 4); - sect_size = extract_unsigned_integer ((gdb_byte *)phdr.p_memsz, 4); + 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 { @@ -524,7 +497,8 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) (gdb_byte *)&phdr, sizeof (phdr))) return 0; - if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, 4) == type) + if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, + 4, byte_order) == type) break; } @@ -532,8 +506,10 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) return 0; /* Retrieve address and size. */ - sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr, 8); - sect_size = extract_unsigned_integer ((gdb_byte *)phdr.p_memsz, 8); + 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. */ @@ -673,6 +649,7 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) 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; @@ -693,14 +670,18 @@ scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr) if (arch_size == 32) { Elf32_External_Dyn *dynp = (Elf32_External_Dyn *) buf; - dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag, 4); - dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr, 4); + 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); - dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr, 8); + 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; @@ -870,13 +851,14 @@ 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 (info->debug_base + lmo->r_version_offset, - lmo->r_version_size); + lmo->r_version_size, byte_order); if (version < 2 || lmo->r_ldsomap_offset == -1) return 0; @@ -884,6 +866,50 @@ solib_svr4_r_ldsomap (struct svr4_info *info) 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); +} + /* LOCAL FUNCTION @@ -918,7 +944,7 @@ open_symbol_file_object (void *from_ttyp) 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 (PIDGET (inferior_ptid)); + struct svr4_info *info = get_svr4_info (); if (symfile_objfile) if (!query (_("Attempt to reload symbols from process? "))) @@ -969,8 +995,7 @@ open_symbol_file_object (void *from_ttyp) static struct so_list * svr4_default_sos (void) { - struct inferior *inf = current_inferior (); - struct svr4_info *info = get_svr4_info (inf->pid); + struct svr4_info *info = get_svr4_info (); struct so_list *head = NULL; struct so_list **link_ptr = &head; @@ -1025,14 +1050,9 @@ svr4_current_sos (void) struct so_list *head = 0; struct so_list **link_ptr = &head; CORE_ADDR ldsomap = 0; - struct inferior *inf; struct svr4_info *info; - if (ptid_equal (inferior_ptid, null_ptid)) - return NULL; - - inf = current_inferior (); - info = get_svr4_info (inf->pid); + info = get_svr4_info (); /* Always locate the debug struct, in case it has moved. */ info->debug_base = 0; @@ -1129,7 +1149,7 @@ CORE_ADDR svr4_fetch_objfile_link_map (struct objfile *objfile) { struct so_list *so; - struct svr4_info *info = get_svr4_info (PIDGET (inferior_ptid)); + struct svr4_info *info = get_svr4_info (); /* Cause svr4_current_sos() to be run if it hasn't been already. */ if (info->main_lm_addr == 0) @@ -1169,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)); } @@ -1252,14 +1272,13 @@ enable_break (struct svr4_info *info) asection *interp_sect; gdb_byte *interp_name; CORE_ADDR sym_addr; - struct inferior *inf = current_inferior (); /* 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 @@ -1295,18 +1314,20 @@ enable_break (struct svr4_info *info) 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 (target_gdbarch, sym_addr); @@ -1399,18 +1420,20 @@ enable_break (struct svr4_info *info) 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. */ @@ -1457,8 +1480,11 @@ enable_break (struct svr4_info *info) msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) { - create_solib_event_breakpoint (target_gdbarch, - 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; } } @@ -1468,8 +1494,11 @@ enable_break (struct svr4_info *info) msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile); if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) { - create_solib_event_breakpoint (target_gdbarch, - 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; } } @@ -1673,7 +1702,7 @@ svr4_solib_create_inferior_hook (void) struct thread_info *tp; struct svr4_info *info; - info = get_svr4_info (PIDGET (inferior_ptid)); + info = get_svr4_info (); /* Relocate the main executable if necessary. */ svr4_relocate_main_executable (); @@ -1713,7 +1742,14 @@ svr4_solib_create_inferior_hook (void) static void svr4_clear_solib (void) { - remove_svr4_info (PIDGET (inferior_ptid)); + 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 @@ -1912,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; @@ -1921,8 +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; - - observer_attach_inferior_exit (solib_svr4_inferior_exit); + svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; }