Fix X86/MIPS gdbserver's event_getmsg_helper

Cherry-pick from bionic
  8e551a6319e45dd5c8d03864f3330b45cf8551b7
  726800e8f42f25a1bf7a36b1603ded29266e8ac6

Change-Id: Iaaffa81d9177ed0735153fc34b6e98e9f257822e
diff --git a/sources/android/libthread_db/gdb-6.6/libthread_db.c b/sources/android/libthread_db/gdb-6.6/libthread_db.c
index 6939780..64d7256 100644
--- a/sources/android/libthread_db/gdb-6.6/libthread_db.c
+++ b/sources/android/libthread_db/gdb-6.6/libthread_db.c
@@ -215,10 +215,8 @@
 static int
 _event_getmsg_helper(td_thrhandle_t const * handle, void * bkpt_addr)
 {
-    void * pc;
-
-    pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
-
+#if defined(__arm__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
     if (pc == bkpt_addr) {
         // The hook function takes the id of the new thread as it's first param,
         // so grab it from r0.
@@ -226,6 +224,31 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
+#elif defined(__i386__)
+    // Get the eip from offset 12*4 = 48 as defined in the struct
+    // user_regs_struct in user_32.h
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)48 /* eip */, NULL);
+    // FIXME - pc is a non-decremented breakpoint address, hence the
+    // addition of 1 on test.  This seems to work for the thread hook
+    // function in libc.so but should be properly fixed.
+    if (pc == ((int)bkpt_addr + 1)) {
+        // The hook function takes the id of the new thread as it's first
+        // param, so grab it from ecx at offset 4 in struct user_regs_struct
+        // (using fastcall convention for x86)
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)4 /* ecx */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#elif defined(__mips__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(64*4) /* pc */, NULL);
+    if (pc == bkpt_addr) {
+        // The hook function takes the id of the new thread as it's first param,
+        // so grab it from a0
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(4*4) /* a0 */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#endif
     return 0;
 }
 
diff --git a/sources/android/libthread_db/gdb-7.3.x/libthread_db.c b/sources/android/libthread_db/gdb-7.3.x/libthread_db.c
index 6d57f01..864f426 100644
--- a/sources/android/libthread_db/gdb-7.3.x/libthread_db.c
+++ b/sources/android/libthread_db/gdb-7.3.x/libthread_db.c
@@ -226,10 +226,8 @@
 static int
 _event_getmsg_helper(td_thrhandle_t const * handle, void * bkpt_addr)
 {
-    void * pc;
-
-    pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
-
+#if defined(__arm__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
     if (pc == bkpt_addr) {
         // The hook function takes the id of the new thread as it's first param,
         // so grab it from r0.
@@ -237,6 +235,31 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
+#elif defined(__i386__)
+    // Get the eip from offset 12*4 = 48 as defined in the struct
+    // user_regs_struct in user_32.h
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)48 /* eip */, NULL);
+    // FIXME - pc is a non-decremented breakpoint address, hence the
+    // addition of 1 on test.  This seems to work for the thread hook
+    // function in libc.so but should be properly fixed.
+    if (pc == ((int)bkpt_addr + 1)) {
+        // The hook function takes the id of the new thread as it's first
+        // param, so grab it from ecx at offset 4 in struct user_regs_struct
+        // (using fastcall convention for x86)
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)4 /* ecx */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#elif defined(__mips__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(64*4) /* pc */, NULL);
+    if (pc == bkpt_addr) {
+        // The hook function takes the id of the new thread as it's first param,
+        // so grab it from a0
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(4*4) /* a0 */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#endif
     return 0;
 }
 
diff --git a/sources/android/libthread_db/gdb-7.6/libthread_db.c b/sources/android/libthread_db/gdb-7.6/libthread_db.c
index 9c95a07..a25ce87 100644
--- a/sources/android/libthread_db/gdb-7.6/libthread_db.c
+++ b/sources/android/libthread_db/gdb-7.6/libthread_db.c
@@ -239,10 +239,8 @@
 static int
 _event_getmsg_helper(td_thrhandle_t const * handle, void * bkpt_addr)
 {
-    void * pc;
-
-    pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
-
+#if defined(__arm__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
     if (pc == bkpt_addr) {
         // The hook function takes the id of the new thread as it's first param,
         // so grab it from r0.
@@ -250,6 +248,31 @@
         gEventMsgHandle.tid = gEventMsgHandle.pid;
         return 0x42;
     }
+#elif defined(__i386__)
+    // Get the eip from offset 12*4 = 48 as defined in the struct
+    // user_regs_struct in user_32.h
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)48 /* eip */, NULL);
+    // FIXME - pc is a non-decremented breakpoint address, hence the
+    // addition of 1 on test.  This seems to work for the thread hook
+    // function in libc.so but should be properly fixed.
+    if (pc == ((int)bkpt_addr + 1)) {
+        // The hook function takes the id of the new thread as it's first
+        // param, so grab it from ecx at offset 4 in struct user_regs_struct
+        // (using fastcall convention for x86)
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)4 /* ecx */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#elif defined(__mips__)
+    void* pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(64*4) /* pc */, NULL);
+    if (pc == bkpt_addr) {
+        // The hook function takes the id of the new thread as it's first param,
+        // so grab it from a0
+        gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)(4*4) /* a0 */, NULL);
+        gEventMsgHandle.tid = gEventMsgHandle.pid;
+        return 0x42;
+    }
+#endif
     return 0;
 }