android: refine custom ucontext_t definitions.
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Aug 2012 10:03:21 +0000 (10:03 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 2 Aug 2012 10:03:21 +0000 (10:03 +0000)
This is a forward-compatible change to avoid type/naming
conflicts when the Android platform/NDK will update its
<signal.h> header to properly define 'struct sigcontext',
'mcontext_t' and 'ucontext_t'.

In particular:

  - Do not define 'struct sigcontext.h' to avoid
    conflicts with the C library definition (which
    is different, see below).

  - Only provide custom ucontext_t declarations if
    the Android <signal.h> doesn't provide it. This can
    be tested with a macro check (__BIONIC_HAVE_UCONTEXT_T)

+ Use 'gettid()' on Android since it is available (at all
  API levels).

See http://code.google.com/p/android/issues/detail?id=34784

Review URL: https://chromiumcodereview.appspot.com/10829122
Patch from David Turner <digit@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12250 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/platform-linux.cc

index 5da9000..d022448 100644 (file)
 #include <errno.h>
 #include <stdarg.h>
 
+// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'.
+// Old versions of the C library <signal.h> didn't define the type.
+#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \
+    defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
+#include <asm/sigcontext.h>
+#endif
+
 #undef MAP_TYPE
 
 #include "v8.h"
@@ -907,32 +914,30 @@ Semaphore* OS::CreateSemaphore(int count) {
 }
 
 
-#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
-// Android runs a fairly new Linux kernel, so signal info is there,
-// but the C library doesn't have the structs defined.
+#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
+
+// Not all versions of Android's C library provide ucontext_t.
+// Detect this and provide custom but compatible definitions. Note that these
+// follow the GLibc naming convention to access register values from
+// mcontext_t.
+//
+// See http://code.google.com/p/android/issues/detail?id=34784
+
+#if defined(__arm__)
 
-struct sigcontext {
-  uint32_t trap_no;
-  uint32_t error_code;
-  uint32_t oldmask;
-  uint32_t gregs[16];
-  uint32_t arm_cpsr;
-  uint32_t fault_address;
-};
-typedef uint32_t __sigset_t;
 typedef struct sigcontext mcontext_t;
+
 typedef struct ucontext {
   uint32_t uc_flags;
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  __sigset_t uc_sigmask;
+  // Other fields are not used by V8, don't define them here.
 } ucontext_t;
-enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
 
-#elif !defined(__GLIBC__) && defined(__mips__)
+#elif defined(__mips__)
 // MIPS version of sigcontext, for Android bionic.
-struct sigcontext {
+typedef struct {
   uint32_t regmask;
   uint32_t status;
   uint64_t pc;
@@ -951,44 +956,44 @@ struct sigcontext {
   uint32_t lo2;
   uint32_t hi3;
   uint32_t lo3;
-};
-typedef uint32_t __sigset_t;
-typedef struct sigcontext mcontext_t;
+} mcontext_t;
+
 typedef struct ucontext {
   uint32_t uc_flags;
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  __sigset_t uc_sigmask;
+  // Other fields are not used by V8, don't define them here.
 } ucontext_t;
 
-#elif !defined(__GLIBC__) && defined(__i386__)
+#elif defined(__i386__)
 // x86 version for Android.
-struct sigcontext {
+typedef struct {
   uint32_t gregs[19];
   void* fpregs;
   uint32_t oldmask;
   uint32_t cr2;
-};
+} mcontext_t;
 
-typedef uint32_t __sigset_t;
-typedef struct sigcontext mcontext_t;
+typedef uint32_t kernel_sigset_t[2];  // x86 kernel uses 64-bit signal masks
 typedef struct ucontext {
   uint32_t uc_flags;
   struct ucontext* uc_link;
   stack_t uc_stack;
   mcontext_t uc_mcontext;
-  __sigset_t uc_sigmask;
+  // Other fields are not used by V8, don't define them here.
 } ucontext_t;
 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
 #endif
 
+#endif  // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
 
 static int GetThreadID() {
-  // Glibc doesn't provide a wrapper for gettid(2).
-#if defined(ANDROID)
-  return syscall(__NR_gettid);
+#if defined(__ANDROID__)
+  // Android's C library provides gettid(2).
+  return gettid();
 #else
+  // Glibc doesn't provide a wrapper for gettid(2).
   return syscall(SYS_gettid);
 #endif
 }
@@ -1027,9 +1032,10 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
   sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
 #elif V8_HOST_ARCH_ARM
-// An undefined macro evaluates to 0, so this applies to Android's Bionic also.
-#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3) && \
-     !defined(__UCLIBC__))
+#if defined(__GLIBC__) && !defined(__UCLIBC__) && \
+    (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
+  // Old GLibc ARM versions used a gregs[] array to access the register
+  // values from mcontext_t.
   sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
   sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
   sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
@@ -1037,8 +1043,8 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
   sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
   sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
-#endif  // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3) &&
-        //  !defined(__UCLIBC__))
+#endif  // defined(__GLIBC__) && !defined(__UCLIBC__) &&
+        // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
 #elif V8_HOST_ARCH_MIPS
   sample->pc = reinterpret_cast<Address>(mcontext.pc);
   sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);