+ do_cleanups (back_to);
+ return 0;
+}
+
+/* Attempt to get so_list from target via qXfer:libraries-svr4:read packet.
+
+ Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such
+ case. Return 1 if *SO_LIST_RETURN contains the library list, it may be
+ empty, caller is responsible for freeing all its entries.
+
+ Note that ANNEX must be NULL if the remote does not explicitly allow
+ qXfer:libraries-svr4:read packets with non-empty annexes. Support for
+ this can be checked using target_augmented_libraries_svr4_read (). */
+
+static int
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
+ const char *annex)
+{
+ char *svr4_library_document;
+ int result;
+ struct cleanup *back_to;
+
+ gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ());
+
+ /* Fetch the list of shared libraries. */
+ svr4_library_document = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_LIBRARIES_SVR4,
+ annex);
+ if (svr4_library_document == NULL)
+ return 0;
+
+ back_to = make_cleanup (xfree, svr4_library_document);
+ result = svr4_parse_libraries (svr4_library_document, list);
+ do_cleanups (back_to);
+
+ return result;
+}
+
+#else
+
+static int
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
+ const char *annex)
+{
+ return 0;
+}
+
+#endif
+
+/* If no shared library information is available from the dynamic
+ linker, build a fallback list from other sources. */
+
+static struct so_list *
+svr4_default_sos (void)
+{
+ struct svr4_info *info = get_svr4_info ();
+ struct so_list *newobj;
+
+ if (!info->debug_loader_offset_p)
+ return NULL;
+
+ newobj = XCNEW (struct so_list);
+
+ newobj->lm_info = XCNEW (struct lm_info);
+
+ /* Nothing will ever check the other fields if we set l_addr_p. */
+ newobj->lm_info->l_addr = info->debug_loader_offset;
+ newobj->lm_info->l_addr_p = 1;
+
+ strncpy (newobj->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (newobj->so_original_name, newobj->so_name);
+
+ return newobj;
+}
+
+/* Read the whole inferior libraries chain starting at address LM.
+ Expect the first entry in the chain's previous entry to be PREV_LM.
+ Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the
+ first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according
+ to it. Returns nonzero upon success. If zero is returned the
+ entries stored to LINK_PTR_PTR are still valid although they may
+ represent only part of the inferior library list. */
+
+static int
+svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
+ struct so_list ***link_ptr_ptr, int ignore_first)
+{
+ CORE_ADDR first_l_name = 0;
+ CORE_ADDR next_lm;
+
+ for (; lm != 0; prev_lm = lm, lm = next_lm)
+ {
+ struct so_list *newobj;
+ struct cleanup *old_chain;
+ int errcode;
+ char *buffer;
+
+ newobj = XCNEW (struct so_list);
+ old_chain = make_cleanup_free_so (newobj);
+
+ newobj->lm_info = lm_info_read (lm);
+ if (newobj->lm_info == NULL)
+ {
+ do_cleanups (old_chain);
+ return 0;
+ }
+
+ next_lm = newobj->lm_info->l_next;
+
+ if (newobj->lm_info->l_prev != prev_lm)
+ {
+ warning (_("Corrupted shared library list: %s != %s"),
+ paddress (target_gdbarch (), prev_lm),
+ paddress (target_gdbarch (), newobj->lm_info->l_prev));
+ do_cleanups (old_chain);
+ return 0;
+ }
+
+ /* For SVR4 versions, the first entry in the link map is for the
+ inferior executable, so we must ignore it. For some versions of
+ SVR4, it has no name. For others (Solaris 2.3 for example), it
+ does have a name, so we can no longer use a missing name to
+ decide when to ignore it. */
+ if (ignore_first && newobj->lm_info->l_prev == 0)
+ {
+ struct svr4_info *info = get_svr4_info ();
+
+ first_l_name = newobj->lm_info->l_name;
+ info->main_lm_addr = newobj->lm_info->lm_addr;
+ do_cleanups (old_chain);
+ continue;
+ }
+
+ /* Extract this shared object's name. */
+ target_read_string (newobj->lm_info->l_name, &buffer,
+ SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ {
+ /* If this entry's l_name address matches that of the
+ inferior executable, then this is not a normal shared
+ object, but (most likely) a vDSO. In this case, silently
+ skip it; otherwise emit a warning. */
+ if (first_l_name == 0 || newobj->lm_info->l_name != first_l_name)
+ warning (_("Can't read pathname for load map: %s."),
+ safe_strerror (errcode));
+ do_cleanups (old_chain);
+ continue;
+ }
+
+ strncpy (newobj->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (newobj->so_original_name, newobj->so_name);
+ xfree (buffer);
+
+ /* If this entry has no name, or its name matches the name
+ for the main executable, don't include it in the list. */
+ if (! newobj->so_name[0] || match_main (newobj->so_name))
+ {
+ do_cleanups (old_chain);
+ continue;
+ }
+
+ discard_cleanups (old_chain);
+ newobj->next = 0;
+ **link_ptr_ptr = newobj;
+ *link_ptr_ptr = &newobj->next;
+ }
+
+ return 1;
+}
+
+/* Read the full list of currently loaded shared objects directly
+ from the inferior, without referring to any libraries read and
+ stored by the probes interface. Handle special cases relating
+ to the first elements of the list. */
+
+static struct so_list *
+svr4_current_sos_direct (struct svr4_info *info)
+{
+ CORE_ADDR lm;
+ struct so_list *head = NULL;
+ struct so_list **link_ptr = &head;
+ struct cleanup *back_to;
+ int ignore_first;
+ struct svr4_library_list library_list;
+
+ /* Fall back to manual examination of the target if the packet is not
+ supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp
+ tests a case where gdbserver cannot find the shared libraries list while
+ GDB itself is able to find it via SYMFILE_OBJFILE.
+
+ Unfortunately statically linked inferiors will also fall back through this
+ suboptimal code path. */
+
+ info->using_xfer = svr4_current_sos_via_xfer_libraries (&library_list,
+ NULL);
+ if (info->using_xfer)
+ {
+ if (library_list.main_lm)
+ info->main_lm_addr = library_list.main_lm;
+
+ return library_list.head ? library_list.head : svr4_default_sos ();
+ }
+
+ /* Always locate the debug struct, in case it has moved. */
+ 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 (! info->debug_base)
+ return svr4_default_sos ();
+
+ /* Assume that everything is a library if the dynamic loader was loaded
+ late by a static executable. */
+ if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL)
+ ignore_first = 0;
+ else
+ ignore_first = 1;
+
+ back_to = make_cleanup (svr4_free_library_list, &head);
+
+ /* Walk the inferior's link map list, and build our list of
+ `struct so_list' nodes. */
+ lm = solib_svr4_r_map (info);
+ if (lm)
+ svr4_read_so_list (lm, 0, &link_ptr, ignore_first);
+
+ /* On Solaris, the dynamic linker is not in the normal list of
+ shared objects, so make sure we pick it up too. Having
+ symbol information for the dynamic linker is quite crucial
+ for skipping dynamic linker resolver code. */
+ lm = solib_svr4_r_ldsomap (info);
+ if (lm)
+ svr4_read_so_list (lm, 0, &link_ptr, 0);
+
+ discard_cleanups (back_to);
+
+ if (head == NULL)
+ return svr4_default_sos ();
+
+ return head;
+}
+
+/* Implement the main part of the "current_sos" target_so_ops
+ method. */
+
+static struct so_list *
+svr4_current_sos_1 (void)
+{
+ struct svr4_info *info = get_svr4_info ();
+
+ /* If the solib list has been read and stored by the probes
+ interface then we return a copy of the stored list. */
+ if (info->solib_list != NULL)
+ return svr4_copy_library_list (info->solib_list);
+
+ /* Otherwise obtain the solib list directly from the inferior. */
+ return svr4_current_sos_direct (info);
+}
+
+/* Implement the "current_sos" target_so_ops method. */
+
+static struct so_list *
+svr4_current_sos (void)
+{
+ struct so_list *so_head = svr4_current_sos_1 ();
+ struct mem_range vsyscall_range;
+
+ /* Filter out the vDSO module, if present. Its symbol file would
+ not be found on disk. The vDSO/vsyscall's OBJFILE is instead
+ managed by symfile-mem.c:add_vsyscall_page. */
+ if (gdbarch_vsyscall_range (target_gdbarch (), &vsyscall_range)
+ && vsyscall_range.length != 0)
+ {
+ struct so_list **sop;
+
+ sop = &so_head;
+ while (*sop != NULL)
+ {
+ struct so_list *so = *sop;
+
+ /* We can't simply match the vDSO by starting address alone,
+ because lm_info->l_addr_inferior (and also l_addr) do not
+ necessarily represent the real starting address of the
+ ELF if the vDSO's ELF itself is "prelinked". The l_ld
+ field (the ".dynamic" section of the shared object)
+ always points at the absolute/resolved address though.
+ So check whether that address is inside the vDSO's
+ mapping instead.
+
+ E.g., on Linux 3.16 (x86_64) the vDSO is a regular
+ 0-based ELF, and we see:
+
+ (gdb) info auxv
+ 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffb000
+ (gdb) p/x *_r_debug.r_map.l_next
+ $1 = {l_addr = 0x7ffff7ffb000, ..., l_ld = 0x7ffff7ffb318, ...}
+
+ And on Linux 2.6.32 (x86_64) we see:
+
+ (gdb) info auxv
+ 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffe000
+ (gdb) p/x *_r_debug.r_map.l_next
+ $5 = {l_addr = 0x7ffff88fe000, ..., l_ld = 0x7ffff7ffe580, ... }
+
+ Dumping that vDSO shows:
+
+ (gdb) info proc mappings
+ 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0 [vdso]
+ (gdb) dump memory vdso.bin 0x7ffff7ffe000 0x7ffff7fff000
+ # readelf -Wa vdso.bin
+ [...]
+ Entry point address: 0xffffffffff700700
+ [...]
+ Section Headers:
+ [Nr] Name Type Address Off Size
+ [ 0] NULL 0000000000000000 000000 000000
+ [ 1] .hash HASH ffffffffff700120 000120 000038
+ [ 2] .dynsym DYNSYM ffffffffff700158 000158 0000d8
+ [...]
+ [ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0
+ */
+ if (address_in_mem_range (so->lm_info->l_ld, &vsyscall_range))
+ {
+ *sop = so->next;
+ free_so (so);
+ break;
+ }
+
+ sop = &so->next;
+ }
+ }
+
+ return so_head;
+}
+
+/* Get the address of the link_map for a given OBJFILE. */
+
+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 (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 info->main_lm_addr;
+
+ /* The other link map addresses may be found by examining the list
+ of shared libraries. */
+ for (so = master_so_list (); so; so = so->next)
+ if (so->objfile == objfile)
+ return so->lm_info->lm_addr;
+
+ /* Not found! */
+ return 0;
+}
+
+/* On some systems, the only way to recognize the link map entry for
+ the main executable file is by looking at its name. Return
+ non-zero iff SONAME matches one of the known main executable names. */
+
+static int
+match_main (const char *soname)
+{
+ const char * const *mainp;
+
+ for (mainp = main_name_list; *mainp != NULL; mainp++)
+ {
+ if (strcmp (soname, *mainp) == 0)
+ return (1);
+ }
+
+ return (0);
+}
+
+/* Return 1 if PC lies in the dynamic symbol resolution code of the
+ SVR4 run time loader. */
+
+int
+svr4_in_dynsym_resolve_code (CORE_ADDR pc)
+{
+ 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)
+ || in_gnu_ifunc_stub (pc));
+}
+
+/* Given an executable's ABFD and target, compute the entry-point
+ address. */
+
+static CORE_ADDR
+exec_entry_point (struct bfd *abfd, struct target_ops *targ)
+{
+ CORE_ADDR addr;
+
+ /* KevinB wrote ... for most targets, the address returned by
+ bfd_get_start_address() is the entry point for the start
+ function. But, for some targets, bfd_get_start_address() returns
+ the address of a function descriptor from which the entry point
+ address may be extracted. This address is extracted by
+ gdbarch_convert_from_func_ptr_addr(). The method
+ gdbarch_convert_from_func_ptr_addr() is the merely the identify
+ function for targets which don't use function descriptors. */
+ addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
+ bfd_get_start_address (abfd),
+ targ);
+ return gdbarch_addr_bits_remove (target_gdbarch (), addr);
+}
+
+/* A probe and its associated action. */
+
+struct probe_and_action
+{
+ /* The probe. */
+ struct probe *probe;
+
+ /* The relocated address of the probe. */
+ CORE_ADDR address;
+
+ /* The action. */
+ enum probe_action action;
+};
+
+/* Returns a hash code for the probe_and_action referenced by p. */
+
+static hashval_t
+hash_probe_and_action (const void *p)
+{
+ const struct probe_and_action *pa = (const struct probe_and_action *) p;
+
+ return (hashval_t) pa->address;
+}
+
+/* Returns non-zero if the probe_and_actions referenced by p1 and p2
+ are equal. */
+
+static int
+equal_probe_and_action (const void *p1, const void *p2)
+{
+ const struct probe_and_action *pa1 = (const struct probe_and_action *) p1;
+ const struct probe_and_action *pa2 = (const struct probe_and_action *) p2;
+
+ return pa1->address == pa2->address;
+}
+
+/* Register a solib event probe and its associated action in the
+ probes table. */
+
+static void
+register_solib_event_probe (struct probe *probe, CORE_ADDR address,
+ enum probe_action action)
+{
+ struct svr4_info *info = get_svr4_info ();
+ struct probe_and_action lookup, *pa;
+ void **slot;
+
+ /* Create the probes table, if necessary. */
+ if (info->probes_table == NULL)
+ info->probes_table = htab_create_alloc (1, hash_probe_and_action,
+ equal_probe_and_action,
+ xfree, xcalloc, xfree);
+
+ lookup.probe = probe;
+ lookup.address = address;
+ slot = htab_find_slot (info->probes_table, &lookup, INSERT);
+ gdb_assert (*slot == HTAB_EMPTY_ENTRY);
+
+ pa = XCNEW (struct probe_and_action);
+ pa->probe = probe;
+ pa->address = address;
+ pa->action = action;
+
+ *slot = pa;
+}
+
+/* Get the solib event probe at the specified location, and the
+ action associated with it. Returns NULL if no solib event probe
+ was found. */
+
+static struct probe_and_action *
+solib_event_probe_at (struct svr4_info *info, CORE_ADDR address)
+{
+ struct probe_and_action lookup;
+ void **slot;
+
+ lookup.address = address;
+ slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT);
+
+ if (slot == NULL)
+ return NULL;
+
+ return (struct probe_and_action *) *slot;
+}
+
+/* Decide what action to take when the specified solib event probe is
+ hit. */
+
+static enum probe_action
+solib_event_probe_action (struct probe_and_action *pa)
+{
+ enum probe_action action;
+ unsigned probe_argc = 0;
+ struct frame_info *frame = get_current_frame ();
+
+ action = pa->action;
+ if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED)
+ return action;
+
+ gdb_assert (action == FULL_RELOAD || action == UPDATE_OR_RELOAD);
+
+ /* Check that an appropriate number of arguments has been supplied.
+ We expect:
+ arg0: Lmid_t lmid (mandatory)
+ arg1: struct r_debug *debug_base (mandatory)
+ arg2: struct link_map *new (optional, for incremental updates) */
+ TRY
+ {
+ probe_argc = get_probe_argument_count (pa->probe, frame);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ probe_argc = 0;
+ }
+ END_CATCH
+
+ /* If get_probe_argument_count throws an exception, probe_argc will
+ be set to zero. However, if pa->probe does not have arguments,
+ then get_probe_argument_count will succeed but probe_argc will
+ also be zero. Both cases happen because of different things, but
+ they are treated equally here: action will be set to
+ PROBES_INTERFACE_FAILED. */
+ if (probe_argc == 2)
+ action = FULL_RELOAD;
+ else if (probe_argc < 2)
+ action = PROBES_INTERFACE_FAILED;
+
+ return action;
+}
+
+/* Populate the shared object list by reading the entire list of
+ shared objects from the inferior. Handle special cases relating
+ to the first elements of the list. Returns nonzero on success. */
+
+static int
+solist_update_full (struct svr4_info *info)
+{
+ free_solib_list (info);
+ info->solib_list = svr4_current_sos_direct (info);
+
+ return 1;
+}
+
+/* Update the shared object list starting from the link-map entry
+ passed by the linker in the probe's third argument. Returns
+ nonzero if the list was successfully updated, or zero to indicate
+ failure. */
+
+static int
+solist_update_incremental (struct svr4_info *info, CORE_ADDR lm)
+{
+ struct so_list *tail;
+ CORE_ADDR prev_lm;
+
+ /* svr4_current_sos_direct contains logic to handle a number of
+ special cases relating to the first elements of the list. To
+ avoid duplicating this logic we defer to solist_update_full
+ if the list is empty. */
+ if (info->solib_list == NULL)
+ return 0;
+
+ /* Fall back to a full update if we are using a remote target
+ that does not support incremental transfers. */
+ if (info->using_xfer && !target_augmented_libraries_svr4_read ())
+ return 0;
+
+ /* Walk to the end of the list. */
+ for (tail = info->solib_list; tail->next != NULL; tail = tail->next)
+ /* Nothing. */;
+ prev_lm = tail->lm_info->lm_addr;
+
+ /* Read the new objects. */
+ if (info->using_xfer)
+ {
+ struct svr4_library_list library_list;
+ char annex[64];
+
+ xsnprintf (annex, sizeof (annex), "start=%s;prev=%s",
+ phex_nz (lm, sizeof (lm)),
+ phex_nz (prev_lm, sizeof (prev_lm)));
+ if (!svr4_current_sos_via_xfer_libraries (&library_list, annex))
+ return 0;
+
+ tail->next = library_list.head;
+ }
+ else
+ {
+ struct so_list **link = &tail->next;
+
+ /* IGNORE_FIRST may safely be set to zero here because the
+ above check and deferral to solist_update_full ensures
+ that this call to svr4_read_so_list will never see the
+ first element. */
+ if (!svr4_read_so_list (lm, prev_lm, &link, 0))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Disable the probes-based linker interface and revert to the
+ original interface. We don't reset the breakpoints as the
+ ones set up for the probes-based interface are adequate. */
+
+static void
+disable_probes_interface_cleanup (void *arg)
+{
+ struct svr4_info *info = get_svr4_info ();
+
+ warning (_("Probes-based dynamic linker interface failed.\n"
+ "Reverting to original interface.\n"));
+
+ free_probes_table (info);
+ free_solib_list (info);
+}