Patchwork [v2,04/11] Add a new gdbarch method to resolve the address of TLS variables.

login
register
mail settings
Submitter John Baldwin
Date Feb. 9, 2019, 12:40 a.m.
Message ID <4db33aead3f31532b7d4e165d9786df792a4d925.1549672588.git.jhb@FreeBSD.org>
Download mbox | patch
Permalink /patch/31385/
State New
Headers show

Comments

John Baldwin - Feb. 9, 2019, 12:40 a.m.
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  |  6 ++++++
 gdb/gdbarch.sh |  1 +
 gdb/target.c   | 13 ++++++++-----
 5 files changed, 55 insertions(+), 5 deletions(-)
Simon Marchi - March 7, 2019, 4:08 p.m.
On 2019-02-08 7:40 p.m., John Baldwin wrote:
> 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.

I don't see anything wrong with the patch (and the comment you removed 
in target_translate_tls_address hints it is right), but again I am not 
very familiar with how TLS works, so I wouldn't spot if anything was 
conceptually wrong with this approach.  I would appreciate if another 
maintainer could take a look and give their opinion.

> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index afc4da7cdd..09097bcbaf 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -602,6 +602,7 @@ 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
> +M;CORE_ADDR;get_thread_local_address;ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset;ptid, lm_addr, offset

Could you document the method, especially the meaning of the parameters?

Simon

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7f4e912ad3..621b9af800 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@ 
+2019-02-08  John Baldwin  <jhb@FreeBSD.org>
+
+	* 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-02-08  John Baldwin  <jhb@FreeBSD.org>
 
 	* solib-svr4.c (svr4_fetch_objfile_link_map): Look for
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 434ee3bfcf..2b3fcef004 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 5b265a462a..e11144941f 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -649,6 +649,12 @@  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);
 
+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 afc4da7cdd..09097bcbaf 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -602,6 +602,7 @@  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
+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 c1ab07f760..9864103826 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -691,8 +691,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;
 
@@ -701,10 +702,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.  */
@@ -759,8 +764,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"));