From 6e056c817845f3d736a1be6b68c69b439c6c6d25 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 12 Mar 2019 13:39:02 -0700 Subject: [PATCH] Add a new gdbarch method to resolve the address of TLS variables. Permit TLS variable addresses to be resolved purely by an ABI rather than requiring a target method. This doesn't try the target method if the ABI function is present (even if the ABI function fails) to simplify error handling. gdb/ChangeLog: * gdbarch.sh (get_thread_local_address): New method. * gdbarch.h, gdbarch.c: Regenerate. * target.c (target_translate_tls_address): Use gdbarch_get_thread_local_address if present instead of target::get_thread_local_address. --- gdb/ChangeLog | 8 ++++++++ gdb/gdbarch.c | 32 ++++++++++++++++++++++++++++++++ gdb/gdbarch.h | 12 ++++++++++++ gdb/gdbarch.sh | 8 ++++++++ gdb/target.c | 13 ++++++++----- 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 2edc6d543bf..f6447231e1e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2019-03-12 John Baldwin + + * gdbarch.sh (get_thread_local_address): New method. + * gdbarch.h, gdbarch.c: Regenerate. + * target.c (target_translate_tls_address): Use + gdbarch_get_thread_local_address if present instead of + target::get_thread_local_address. + 2019-03-12 John Baldwin * target.h (target::get_thread_local_address): Update comment. diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 434ee3bfcf0..2b3fcef004f 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -251,6 +251,7 @@ struct gdbarch CORE_ADDR deprecated_function_start_offset; gdbarch_remote_register_number_ftype *remote_register_number; gdbarch_fetch_tls_load_module_address_ftype *fetch_tls_load_module_address; + gdbarch_get_thread_local_address_ftype *get_thread_local_address; CORE_ADDR frame_args_skip; gdbarch_unwind_pc_ftype *unwind_pc; gdbarch_unwind_sp_ftype *unwind_sp; @@ -613,6 +614,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of deprecated_function_start_offset, invalid_p == 0 */ /* Skip verify of remote_register_number, invalid_p == 0 */ /* Skip verify of fetch_tls_load_module_address, has predicate. */ + /* Skip verify of get_thread_local_address, has predicate. */ /* Skip verify of frame_args_skip, invalid_p == 0 */ /* Skip verify of unwind_pc, invalid_p == 0 */ /* Skip verify of unwind_sp, invalid_p == 0 */ @@ -1073,6 +1075,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: get_syscall_number = <%s>\n", host_address_to_string (gdbarch->get_syscall_number)); + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_get_thread_local_address_p() = %d\n", + gdbarch_get_thread_local_address_p (gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: get_thread_local_address = <%s>\n", + host_address_to_string (gdbarch->get_thread_local_address)); fprintf_unfiltered (file, "gdbarch_dump: gnu_triplet_regexp = <%s>\n", host_address_to_string (gdbarch->gnu_triplet_regexp)); @@ -3018,6 +3026,30 @@ set_gdbarch_fetch_tls_load_module_address (struct gdbarch *gdbarch, gdbarch->fetch_tls_load_module_address = fetch_tls_load_module_address; } +int +gdbarch_get_thread_local_address_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->get_thread_local_address != NULL; +} + +CORE_ADDR +gdbarch_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->get_thread_local_address != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_get_thread_local_address called\n"); + return gdbarch->get_thread_local_address (gdbarch, ptid, lm_addr, offset); +} + +void +set_gdbarch_get_thread_local_address (struct gdbarch *gdbarch, + gdbarch_get_thread_local_address_ftype get_thread_local_address) +{ + gdbarch->get_thread_local_address = get_thread_local_address; +} + CORE_ADDR gdbarch_frame_args_skip (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 75618376abb..abb72e752b1 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -649,6 +649,18 @@ typedef CORE_ADDR (gdbarch_fetch_tls_load_module_address_ftype) (struct objfile extern CORE_ADDR gdbarch_fetch_tls_load_module_address (struct gdbarch *gdbarch, struct objfile *objfile); extern void set_gdbarch_fetch_tls_load_module_address (struct gdbarch *gdbarch, gdbarch_fetch_tls_load_module_address_ftype *fetch_tls_load_module_address); +/* Return the thread-local address at OFFSET in the thread-local + storage for the thread PTID and the shared library or executable + file given by LM_ADDR. If that block of thread-local storage hasn't + been allocated yet, this function may throw an error. LM_ADDR may + be zero for statically linked multithreaded inferiors. */ + +extern int gdbarch_get_thread_local_address_p (struct gdbarch *gdbarch); + +typedef CORE_ADDR (gdbarch_get_thread_local_address_ftype) (struct gdbarch *gdbarch, ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset); +extern CORE_ADDR gdbarch_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset); +extern void set_gdbarch_get_thread_local_address (struct gdbarch *gdbarch, gdbarch_get_thread_local_address_ftype *get_thread_local_address); + extern CORE_ADDR gdbarch_frame_args_skip (struct gdbarch *gdbarch); extern void set_gdbarch_frame_args_skip (struct gdbarch *gdbarch, CORE_ADDR frame_args_skip); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 48fcebd19a0..63bfbad7d9e 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -602,6 +602,14 @@ m;int;remote_register_number;int regno;regno;;default_remote_register_number;;0 # Fetch the target specific address used to represent a load module. F;CORE_ADDR;fetch_tls_load_module_address;struct objfile *objfile;objfile + +# Return the thread-local address at OFFSET in the thread-local +# storage for the thread PTID and the shared library or executable +# file given by LM_ADDR. If that block of thread-local storage hasn't +# been allocated yet, this function may throw an error. LM_ADDR may +# be zero for statically linked multithreaded inferiors. + +M;CORE_ADDR;get_thread_local_address;ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset;ptid, lm_addr, offset # v;CORE_ADDR;frame_args_skip;;;0;;;0 m;CORE_ADDR;unwind_pc;struct frame_info *next_frame;next_frame;;default_unwind_pc;;0 diff --git a/gdb/target.c b/gdb/target.c index 8579c19d053..c27157d209f 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -698,8 +698,9 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) { volatile CORE_ADDR addr = 0; struct target_ops *target = current_top_target (); + struct gdbarch *gdbarch = target_gdbarch (); - if (gdbarch_fetch_tls_load_module_address_p (target_gdbarch ())) + if (gdbarch_fetch_tls_load_module_address_p (gdbarch)) { ptid_t ptid = inferior_ptid; @@ -708,10 +709,14 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) CORE_ADDR lm_addr; /* Fetch the load module address for this objfile. */ - lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch (), + lm_addr = gdbarch_fetch_tls_load_module_address (gdbarch, objfile); - addr = target->get_thread_local_address (ptid, lm_addr, offset); + if (gdbarch_get_thread_local_address_p (gdbarch)) + addr = gdbarch_get_thread_local_address (gdbarch, ptid, lm_addr, + offset); + else + addr = target->get_thread_local_address (ptid, lm_addr, offset); } /* If an error occurred, print TLS related messages here. Otherwise, throw the error to some higher catcher. */ @@ -766,8 +771,6 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset) } END_CATCH } - /* It wouldn't be wrong here to try a gdbarch method, too; finding - TLS is an ABI-specific thing. But we don't do that yet. */ else error (_("Cannot find thread-local variables on this target")); -- 2.30.2