X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Ffbsd-tdep.c;h=9e5d23a4bc8def5dd4b7edd309bd123c807a7987;hb=d16c467a501547e37b111f775396e28f8bf27c1e;hp=f96d1d56e35b160dda293861087a02ad93aeae35;hpb=e61667ef1413b9fba1bb9dc78744329f8215de74;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index f96d1d56e3..9e5d23a4bc 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for FreeBSD, architecture-independent. - Copyright (C) 2002-2018 Free Software Foundation, Inc. + Copyright (C) 2002-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -24,6 +24,7 @@ #include "regcache.h" #include "regset.h" #include "gdbthread.h" +#include "objfiles.h" #include "xml-syscall.h" #include #include @@ -100,7 +101,7 @@ enum all architectures. Note that FreeBSD 7.0 used an older version of this structure - (struct kinfo_ovmentry), but the NT_FREEBSD_PROCSTAT_VMMAP core + (struct kinfo_vmentry), but the NT_FREEBSD_PROCSTAT_VMMAP core dump note wasn't introduced until FreeBSD 9.2. As a result, the core dump note has always used the 7.1 and later structure format. */ @@ -444,18 +445,37 @@ get_fbsd_gdbarch_data (struct gdbarch *gdbarch) gdbarch_data (gdbarch, fbsd_gdbarch_data_handle)); } +struct fbsd_pspace_data +{ + /* Offsets in the runtime linker's 'Obj_Entry' structure. */ + LONGEST off_linkmap = 0; + LONGEST off_tlsindex = 0; + bool rtld_offsets_valid = false; +}; + +/* Per-program-space data for FreeBSD architectures. */ +static const struct program_space_key + fbsd_pspace_data_handle; + +static struct fbsd_pspace_data * +get_fbsd_pspace_data (struct program_space *pspace) +{ + struct fbsd_pspace_data *data; + + data = fbsd_pspace_data_handle.get (pspace); + if (data == NULL) + data = fbsd_pspace_data_handle.emplace (pspace); + + return data; +} + /* This is how we want PTIDs from core files to be printed. */ -static const char * +static std::string fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid) { - static char buf[80]; - if (ptid.lwp () != 0) - { - xsnprintf (buf, sizeof buf, "LWP %ld", ptid.lwp ()); - return buf; - } + return string_printf ("LWP %ld", ptid.lwp ()); return normal_pid_to_str (ptid); } @@ -482,10 +502,10 @@ fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) thread_section_name section_name (".thrmisc", thr->ptid); section = bfd_get_section_by_name (core_bfd, section_name.c_str ()); - if (section != NULL && bfd_section_size (core_bfd, section) > 0) + if (section != NULL && bfd_section_size (section) > 0) { /* Truncate the name if it is longer than "buf". */ - size = bfd_section_size (core_bfd, section); + size = bfd_section_size (section); if (size > sizeof buf - 1) size = sizeof buf - 1; if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0, @@ -653,7 +673,8 @@ fbsd_corefile_thread (struct thread_info *info, { struct regcache *regcache; - regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); + regcache = get_thread_arch_regcache (info->inf->process_target (), + info->ptid, args->gdbarch); target_fetch_registers (regcache, -1); @@ -715,15 +736,14 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) } /* Thread register information. */ - TRY + try { update_thread_list (); } - CATCH (e, RETURN_MASK_ERROR) + catch (const gdb_exception_error &e) { exception_print (gdb_stderr, e); } - END_CATCH /* Like the kernel, prefer dumping the signalled thread first. "First thread" is what tools use to infer the signalled thread. @@ -999,12 +1019,12 @@ fbsd_info_proc_files_entry (int kf_type, int kf_fd, int kf_flags, /* For local sockets, print out the first non-nul path rather than both paths. */ - const struct fbsd_sockaddr_un *sun + const struct fbsd_sockaddr_un *saddr_un = reinterpret_cast (kf_sa_local); - if (sun->sun_path[0] == 0) - sun = reinterpret_cast + if (saddr_un->sun_path[0] == 0) + saddr_un = reinterpret_cast (kf_sa_peer); - printf_filtered ("%s", sun->sun_path); + printf_filtered ("%s", saddr_un->sun_path); break; } case FBSD_AF_INET: @@ -1039,7 +1059,7 @@ fbsd_core_info_proc_files (struct gdbarch *gdbarch) return; } - size_t note_size = bfd_get_section_size (section); + size_t note_size = bfd_section_size (section); if (note_size < 4) error (_("malformed core note - too short for header")); @@ -1172,7 +1192,7 @@ fbsd_core_info_proc_mappings (struct gdbarch *gdbarch) return; } - note_size = bfd_get_section_size (section); + note_size = bfd_section_size (section); if (note_size < 4) error (_("malformed core note - too short for header")); @@ -1220,7 +1240,7 @@ fbsd_core_vnode_path (struct gdbarch *gdbarch, int fd) if (section == NULL) return nullptr; - note_size = bfd_get_section_size (section); + note_size = bfd_section_size (section); if (note_size < 4) error (_("malformed core note - too short for header")); @@ -1247,7 +1267,7 @@ fbsd_core_vnode_path (struct gdbarch *gdbarch, int fd) && bfd_get_signed_32 (core_bfd, descdata + KF_FD) == fd) { char *path = (char *) descdata + KF_PATH; - return gdb::unique_xmalloc_ptr (xstrdup (path)); + return make_unique_xstrdup (path); } descdata += structsize; @@ -1325,7 +1345,7 @@ fbsd_core_info_proc_status (struct gdbarch *gdbarch) * structure size, then it must be long enough to access the last * field used (ki_rusage_ch.ru_majflt) which is the size of a long. */ - note_size = bfd_get_section_size (section); + note_size = bfd_section_size (section); if (note_size < (4 + kp->ki_rusage_ch + kp->ru_majflt + long_bit / TARGET_CHAR_BIT)) error (_("malformed core note - too short")); @@ -1414,7 +1434,7 @@ fbsd_core_info_proc_status (struct gdbarch *gdbarch) sec, value); printf_filtered ("stime, children: %s.%06d\n", plongest (sec), (int) value); printf_filtered ("'nice' value: %d\n", - bfd_get_signed_8 (core_bfd, descdata + kp->ki_nice)); + (int) bfd_get_signed_8 (core_bfd, descdata + kp->ki_nice)); fbsd_core_fetch_timeval (gdbarch, descdata + kp->ki_start, sec, value); printf_filtered ("Start time: %s.%06d\n", plongest (sec), (int) value); printf_filtered ("Virtual memory size: %s kB\n", @@ -1932,6 +1952,119 @@ fbsd_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread) internal_error (__FILE__, __LINE__, _("fbsd_get_sycall_number called")); } +/* Read an integer symbol value from the current target. */ + +static LONGEST +fbsd_read_integer_by_name (struct gdbarch *gdbarch, const char *name) +{ + bound_minimal_symbol ms = lookup_minimal_symbol (name, NULL, NULL); + if (ms.minsym == NULL) + error (_("Unable to resolve symbol '%s'"), name); + + gdb_byte buf[4]; + if (target_read_memory (BMSYMBOL_VALUE_ADDRESS (ms), buf, sizeof buf) != 0) + error (_("Unable to read value of '%s'"), name); + + return extract_signed_integer (buf, sizeof buf, gdbarch_byte_order (gdbarch)); +} + +/* Lookup offsets of fields in the runtime linker's 'Obj_Entry' + structure needed to determine the TLS index of an object file. */ + +static void +fbsd_fetch_rtld_offsets (struct gdbarch *gdbarch, struct fbsd_pspace_data *data) +{ + try + { + /* Fetch offsets from debug symbols in rtld. */ + struct symbol *obj_entry_sym + = lookup_symbol_in_language ("Struct_Obj_Entry", NULL, STRUCT_DOMAIN, + language_c, NULL).symbol; + if (obj_entry_sym == NULL) + error (_("Unable to find Struct_Obj_Entry symbol")); + data->off_linkmap = lookup_struct_elt (SYMBOL_TYPE(obj_entry_sym), + "linkmap", 0).offset / 8; + data->off_tlsindex = lookup_struct_elt (SYMBOL_TYPE(obj_entry_sym), + "tlsindex", 0).offset / 8; + data->rtld_offsets_valid = true; + return; + } + catch (const gdb_exception_error &e) + { + data->off_linkmap = -1; + } + + try + { + /* Fetch offsets from global variables in libthr. Note that + this does not work for single-threaded processes that are not + linked against libthr. */ + data->off_linkmap = fbsd_read_integer_by_name (gdbarch, + "_thread_off_linkmap"); + data->off_tlsindex = fbsd_read_integer_by_name (gdbarch, + "_thread_off_tlsindex"); + data->rtld_offsets_valid = true; + return; + } + catch (const gdb_exception_error &e) + { + data->off_linkmap = -1; + } +} + +/* Helper function to read the TLS index of an object file associated + with a link map entry at LM_ADDR. */ + +static LONGEST +fbsd_get_tls_index (struct gdbarch *gdbarch, CORE_ADDR lm_addr) +{ + struct fbsd_pspace_data *data = get_fbsd_pspace_data (current_program_space); + + if (!data->rtld_offsets_valid) + fbsd_fetch_rtld_offsets (gdbarch, data); + + if (data->off_linkmap == -1) + throw_error (TLS_GENERIC_ERROR, + _("Cannot fetch runtime linker structure offsets")); + + /* Simulate container_of to convert from LM_ADDR to the Obj_Entry + pointer and then compute the offset of the tlsindex member. */ + CORE_ADDR tlsindex_addr = lm_addr - data->off_linkmap + data->off_tlsindex; + + gdb_byte buf[4]; + if (target_read_memory (tlsindex_addr, buf, sizeof buf) != 0) + throw_error (TLS_GENERIC_ERROR, + _("Cannot find thread-local variables on this target")); + + return extract_signed_integer (buf, sizeof buf, gdbarch_byte_order (gdbarch)); +} + +/* See fbsd-tdep.h. */ + +CORE_ADDR +fbsd_get_thread_local_address (struct gdbarch *gdbarch, CORE_ADDR dtv_addr, + CORE_ADDR lm_addr, CORE_ADDR offset) +{ + LONGEST tls_index = fbsd_get_tls_index (gdbarch, lm_addr); + + gdb_byte buf[gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT]; + if (target_read_memory (dtv_addr, buf, sizeof buf) != 0) + throw_error (TLS_GENERIC_ERROR, + _("Cannot find thread-local variables on this target")); + + const struct builtin_type *builtin = builtin_type (gdbarch); + CORE_ADDR addr = gdbarch_pointer_to_address (gdbarch, + builtin->builtin_data_ptr, buf); + + addr += (tls_index + 1) * TYPE_LENGTH (builtin->builtin_data_ptr); + if (target_read_memory (addr, buf, sizeof buf) != 0) + throw_error (TLS_GENERIC_ERROR, + _("Cannot find thread-local variables on this target")); + + addr = gdbarch_pointer_to_address (gdbarch, builtin->builtin_data_ptr, buf); + return addr + offset; +} + /* To be called from GDB_OSABI_FREEBSD handlers. */ void