This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PowerPC: use libgcc _Unwind functions to get backtrace


On 22-07-2013 18:53, Andreas Schwab wrote:
> Adhemerval Zanella <azanella@linux.vnet.ibm.com> writes:
>
>> @@ -35,6 +38,43 @@ struct layout
>>    void *return_address;
>>  };
>>  
>> +#define __SIGNAL_FRAMESIZE32 64
> No need for namespace safety.
>
>> +
>> +/* signal trampoline saved area.  */
>> +struct signal_frame_32 {
>> +  char               dummy[__SIGNAL_FRAMESIZE32];
>> +  struct sigcontext  sctx;
>> +  mcontext_t         mctx;
>> +  /* We don't care about the rest.  */
>> +}; 
>> +
>> +static inline
>> +int is_sigtramp_address (unsigned int nip, unsigned int fp)
> The function name should start in column 0 with the return type on the
> preceding line.
>
>> +{
>> +#ifdef SHARED
>> +  if (nip == (unsigned long)__vdso_sigtramp32)
> Please be consistent about int vs. long.  Space after cast.
>
> Andreas.
>
Thanks for the review, patch revised below (the ChangeLog is the same as before).
Ok to apply?

---

diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c
index b4b11dd..ac012a4 100644
--- a/sysdeps/powerpc/powerpc32/backtrace.c
+++ b/sysdeps/powerpc/powerpc32/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -35,6 +38,43 @@ struct layout
   void *return_address;
 };
 
+#define SIGNAL_FRAMESIZE 64
+
+/* signal trampoline saved area.  */
+struct signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE];
+  struct sigcontext  sctx;
+  mcontext_t         mctx;
+  /* We don't care about the rest.  */
+}; 
+
+static inline int
+is_sigtramp_address (unsigned int nip, unsigned int fp)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp32)
+    return 1;
+#endif
+  return 0;
+}
+
+struct rt_signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE + 16];
+  siginfo_t          info;
+  struct ucontext    uc;
+  /* We don't care about the rest.  */
+};
+
+static inline int
+is_sigtramp_address_rt (unsigned int nip, unsigned int fp)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp_rt32)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -50,7 +90,30 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      gregset_t *gregset = NULL;
+
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned int)current->return_address,
+                               (unsigned int)current))
+	{
+	  struct signal_frame_32 *sigframe = 
+	    (struct signal_frame_32*) current;
+          gregset = &sigframe->mctx.gregs;
+        }
+      if (is_sigtramp_address ((unsigned int)current->return_address,
+                               (unsigned int)current))
+	{
+	  struct signal_frame_32 *sigframe =
+            (struct signal_frame_32*) current;
+          gregset = &sigframe->mctx.gregs;
+        }
+      if (gregset)
+	array[++count] = (void*)((*gregset)[PT_NIP]);
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c
index 2d3e051..075732f 100644
--- a/sysdeps/powerpc/powerpc64/backtrace.c
+++ b/sysdeps/powerpc/powerpc64/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -38,6 +41,28 @@ struct layout
   void *return_address;
 };
 
+/* signal trampoline saved area.  */
+struct signal_frame_64 {
+#define SIGNAL_FRAMESIZE 128
+  char            dummy[SIGNAL_FRAMESIZE];
+  struct ucontext uc;
+  unsigned long   unused[2];
+  unsigned int    tramp[6];
+  /* We don't care about the rest.  */
+}; 
+
+static inline int
+is_sigtramp_address (unsigned long nip, unsigned long fp)
+{
+  if (nip == fp + offsetof(struct signal_frame_64, tramp))
+    return 1;
+#ifdef SHARED
+  if (nip == (unsigned long)__vdso_sigtramp_rt64)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -53,7 +78,18 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned long)current->return_address,
+                               (unsigned long)current))
+        {
+	  struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
+          array[++count] = (void*)sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
+	}
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index 8b195db..ba54de4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -34,6 +34,13 @@ extern void *__vdso_getcpu;
 
 extern void *__vdso_time;
 
+#if defined(__PPC64__) || defined(__powerpc64__)
+extern void *__vdso_sigtramp_rt64;
+#else
+extern void *__vdso_sigtramp32;
+extern void *__vdso_sigtramp_rt32;
+#endif
+
 /* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
    symbol.  This works because _dl_vdso_vsym always return the function
    address, and no vDSO symbols use the TOC or chain pointers from the OPD
diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c
index f6f05f0..594eb50 100644
--- a/sysdeps/unix/sysv/linux/powerpc/init-first.c
+++ b/sysdeps/unix/sysv/linux/powerpc/init-first.c
@@ -29,6 +29,12 @@ void *__vdso_clock_getres;
 void *__vdso_get_tbfreq;
 void *__vdso_getcpu;
 void *__vdso_time;
+#if defined(__PPC64__) || defined(__powerpc64__)
+void *__vdso_sigtramp_rt64;
+#else
+void *__vdso_sigtramp32;
+void *__vdso_sigtramp_rt32;
+#endif
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -46,6 +52,13 @@ _libc_vdso_platform_setup (void)
   __vdso_getcpu = _dl_vdso_vsym ("__kernel_getcpu", &linux2615);
 
   __vdso_time = _dl_vdso_vsym ("__kernel_time", &linux2615);
+
+#if defined(__PPC64__) || defined(__powerpc64__)
+  __vdso_sigtramp_rt64 = _dl_vdso_vsym ("__kernel_sigtramp_rt64", &linux2615);
+#else
+  __vdso_sigtramp32 = _dl_vdso_vsym ("__kernel_sigtramp32", &linux2615);
+  __vdso_sigtramp_rt32 = _dl_vdso_vsym ("__kernel_sigtramp_rt32", &linux2615);
+#endif
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]