aarch64 multi-arch (part 3): get thread area
authorYao Qi <yao.qi@linaro.org>
Fri, 18 Sep 2015 12:59:42 +0000 (13:59 +0100)
committerYao Qi <yao.qi@linaro.org>
Fri, 18 Sep 2015 12:59:42 +0000 (13:59 +0100)
With the kernle fix <http://lists.infradead.org/pipermail/linux-arm-kernel/2015-July/356511.html>,
aarch64 GDB is able to read the base of thread area of 32-bit arm
program through NT_ARM_TLS.

This patch is to teach both GDB and GDBserver to read the base of
thread area correctly in the multi-arch case.  A new function
aarch64_ps_get_thread_area is added, and is shared between GDB and
GDBserver.

With this patch applied, the following fails in multi-arch testing
(GDB is aarch64 but the test cases are arm) are fixed,

 -FAIL: gdb.threads/tls-nodebug.exp: thread local storage
 -FAIL: gdb.threads/tls-shared.exp: print thread local storage variable
 -FAIL: gdb.threads/tls-so_extern.exp: print thread local storage variable
 -FAIL: gdb.threads/tls-var.exp: print tls_var
 -FAIL: gdb.threads/tls.exp: first thread local storage
 -FAIL: gdb.threads/tls.exp: first another thread local storage
 -FAIL: gdb.threads/tls.exp: p a_thread_local
 -FAIL: gdb.threads/tls.exp: p file2_thread_local
 -FAIL: gdb.threads/tls.exp: p a_thread_local second time

gdb:

2015-09-18  Yao Qi  <yao.qi@linaro.org>

* nat/aarch64-linux.c: Include elf/common.h,
nat/gdb_ptrace.h, asm/ptrace.h and sys/uio.h.
(aarch64_ps_get_thread_area): New function.
* nat/aarch64-linux.h: Include gdb_proc_service.h.
(aarch64_ps_get_thread_area): Declare.
* aarch64-linux-nat.c (ps_get_thread_area): Call
aarch64_ps_get_thread_area.

gdb/gdbserver:

2015-09-18  Yao Qi  <yao.qi@linaro.org>

* linux-aarch64-low.c: Don't include sys/uio.h.
(ps_get_thread_area): Call aarch64_ps_get_thread_area.

gdb/ChangeLog
gdb/aarch64-linux-nat.c
gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-aarch64-low.c
gdb/nat/aarch64-linux.c
gdb/nat/aarch64-linux.h

index 61e435e9d9b234d96d48f6cfe77c2759279ab631..074417d2182a7b769a732ff59380e93bc287c887 100644 (file)
@@ -1,3 +1,13 @@
+2015-09-18  Yao Qi  <yao.qi@linaro.org>
+
+       * nat/aarch64-linux.c: Include elf/common.h,
+       nat/gdb_ptrace.h, asm/ptrace.h and sys/uio.h.
+       (aarch64_ps_get_thread_area): New function.
+       * nat/aarch64-linux.h: Include gdb_proc_service.h.
+       (aarch64_ps_get_thread_area): Declare.
+       * aarch64-linux-nat.c (ps_get_thread_area): Call
+       aarch64_ps_get_thread_area.
+
 2015-09-18  Markus Metzger  <markus.t.metzger@intel.com>
 
        * record-btrace.c (record_btrace_resume): Honour scheduler-locking.
index d7ac19eb5a366d35d35811c1491ff962d61b256d..c9f439f75e66d9618c36c452e88a21b309966068 100644 (file)
@@ -460,21 +460,10 @@ ps_err_e
 ps_get_thread_area (const struct ps_prochandle *ph,
                    lwpid_t lwpid, int idx, void **base)
 {
-  struct iovec iovec;
-  uint64_t reg;
-
-  iovec.iov_base = &reg;
-  iovec.iov_len = sizeof (reg);
-
-  if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
-    return PS_ERR;
-
-  /* IDX is the bias from the thread pointer to the beginning of the
-     thread descriptor.  It has to be subtracted due to implementation
-     quirks in libthread_db.  */
-  *base = (void *) (reg - idx);
+  int is_64bit_p
+    = (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 64);
 
-  return PS_OK;
+  return aarch64_ps_get_thread_area (ph, lwpid, idx, base, is_64bit_p);
 }
 \f
 
index c018f28472418d6eee1422542d973495e5c65460..bef1d5720840c01928c012bd7e1f917b4de2728a 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-18  Yao Qi  <yao.qi@linaro.org>
+
+       * linux-aarch64-low.c: Don't include sys/uio.h.
+       (ps_get_thread_area): Call aarch64_ps_get_thread_area.
+
 2015-09-16  Wei-cheng Wang  <cole945@gmail.com>
 
        * tracepoint.c (eval_result_type): Change prototype.
index 73b248c5ed03d5862f7cc179be37f22ba52f4c72..0ba58ddcb8498ed63b2bab42f12df95cd681252d 100644 (file)
@@ -30,7 +30,6 @@
 #include <sys/user.h>
 #include "nat/gdb_ptrace.h"
 #include <asm/ptrace.h>
-#include <sys/uio.h>
 
 #include "gdb_proc_service.h"
 
@@ -413,21 +412,8 @@ ps_err_e
 ps_get_thread_area (const struct ps_prochandle *ph,
                    lwpid_t lwpid, int idx, void **base)
 {
-  struct iovec iovec;
-  uint64_t reg;
-
-  iovec.iov_base = &reg;
-  iovec.iov_len = sizeof (reg);
-
-  if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
-    return PS_ERR;
-
-  /* IDX is the bias from the thread pointer to the beginning of the
-     thread descriptor.  It has to be subtracted due to implementation
-     quirks in libthread_db.  */
-  *base = (void *) (reg - idx);
-
-  return PS_OK;
+  return aarch64_ps_get_thread_area (ph, lwpid, idx, base,
+                                    is_64bit_tdesc ());
 }
 
 /* Implementation of linux_target_ops method "siginfo_fixup".  */
index 0634094a2d452d3ce281d8bc8eb87010cdc3abcf..dbd7dff1f02a44c3687eb1b560688df97863c453 100644 (file)
 #include "nat/aarch64-linux-hw-point.h"
 #include "nat/aarch64-linux.h"
 
+#include "elf/common.h"
+#include "nat/gdb_ptrace.h"
+#include <asm/ptrace.h>
+#include <sys/uio.h>
+
 /* Called when resuming a thread LWP.
    The hardware debug registers are updated when there is any change.  */
 
@@ -195,3 +200,40 @@ aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
        }
     }
 }
+
+/* Called by libthread_db.  Returns a pointer to the thread local
+   storage (or its descriptor).  */
+
+ps_err_e
+aarch64_ps_get_thread_area (const struct ps_prochandle *ph,
+                           lwpid_t lwpid, int idx, void **base,
+                           int is_64bit_p)
+{
+  struct iovec iovec;
+  uint64_t reg64;
+  uint32_t reg32;
+
+  if (is_64bit_p)
+    {
+      iovec.iov_base = &reg64;
+      iovec.iov_len = sizeof (reg64);
+    }
+  else
+    {
+      iovec.iov_base = &reg32;
+      iovec.iov_len = sizeof (reg32);
+    }
+
+  if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  if (is_64bit_p)
+    *base = (void *) (reg64 - idx);
+  else
+    *base = (void *) (uintptr_t) (reg32 - idx);
+
+  return PS_OK;
+}
index 89eb4e3c2fdb82577b753a3dfe5503531a644986..07f85b9f6e55cfddbe3161b8a298eaeb0ad56e8c 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <signal.h>
 
+/* Defines ps_err_e, struct ps_prochandle.  */
+#include "gdb_proc_service.h"
+
 typedef int compat_int_t;
 typedef unsigned int compat_uptr_t;
 
@@ -119,4 +122,8 @@ void aarch64_linux_prepare_to_resume (struct lwp_info *lwp);
 
 void aarch64_linux_new_thread (struct lwp_info *lwp);
 
+ps_err_e aarch64_ps_get_thread_area (const struct ps_prochandle *ph,
+                                      lwpid_t lwpid, int idx, void **base,
+                                      int is_64bit_p);
+
 #endif /* AARCH64_LINUX_H */