[v2,11/11] Support TLS variables on FreeBSD/powerpc.

Message ID b6a17e3e36bbad377989c525d7532f3b6a2bf307.1549672588.git.jhb@FreeBSD.org
State New, archived
Headers

Commit Message

John Baldwin Feb. 9, 2019, 12:40 a.m. UTC
  Derive the pointer to the DTV array from the %r2 register on 32-bit
powerpc and %r13 on 64-bit powerpc.

gdb/ChangeLog:

	* ppc-fbsd-tdep.c (ppcfbsd_get_thread_local_address): New.
	(ppcfbsd_init_abi): Install gdbarch
	"fetch_tls_load_module_address" and "get_thread_local_address"
	methods.
---
 gdb/ChangeLog       |  7 +++++++
 gdb/ppc-fbsd-tdep.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)
  

Comments

Simon Marchi March 7, 2019, 4:26 p.m. UTC | #1
On 2019-02-08 7:40 p.m., John Baldwin wrote:
> Derive the pointer to the DTV array from the %r2 register on 32-bit
> powerpc and %r13 on 64-bit powerpc.

Hi John,

Patches 8-11 LGTM. So I think there's just patch 4/11 that remains, 
which I have asked for somebody else to take a look.

Simon
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6fa12ff815..90070b4039 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@ 
+2019-02-08  John Baldwin  <jhb@FreeBSD.org>
+
+	* ppc-fbsd-tdep.c (ppcfbsd_get_thread_local_address): New.
+	(ppcfbsd_init_abi): Install gdbarch
+	"fetch_tls_load_module_address" and "get_thread_local_address"
+	methods.
+
 2019-02-08  John Baldwin  <jhb@FreeBSD.org>
 
 	* riscv-fbsd-tdep.c (riscv_fbsd_get_thread_local_address): New.
diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c
index c21a52c898..290bd1fd88 100644
--- a/gdb/ppc-fbsd-tdep.c
+++ b/gdb/ppc-fbsd-tdep.c
@@ -279,6 +279,39 @@  ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function,
 					   regcache, readbuf, writebuf);
 }
 
+/* Implement the "get_thread_local_address" gdbarch method.  */
+
+static CORE_ADDR
+ppcfbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
+				  CORE_ADDR lm_addr, CORE_ADDR offset)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct regcache *regcache;
+  int tp_offset, tp_regnum;
+
+  regcache = get_thread_arch_regcache (ptid, gdbarch);
+
+  if (tdep->wordsize == 4)
+    {
+      tp_offset = 0x7008;
+      tp_regnum = PPC_R0_REGNUM + 2;
+    }
+  else
+    {
+      tp_offset = 0x7010;
+      tp_regnum = PPC_R0_REGNUM + 13;
+    }
+  target_fetch_registers (regcache, tp_regnum);
+
+  ULONGEST tp;
+  if (regcache->cooked_read (tp_regnum, &tp) != REG_VALID)
+    error (_("Unable to fetch tcb pointer"));
+
+  /* tp points to the end of the TCB block.  The first member of the
+     TCB is the pointer to the DTV array.  */
+  CORE_ADDR dtv_addr = tp - tp_offset;
+  return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
+}
 
 static void
 ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -322,6 +355,8 @@  ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
 					     svr4_fetch_objfile_link_map);
+  set_gdbarch_get_thread_local_address (gdbarch,
+					ppcfbsd_get_thread_local_address);
 }
 
 void