Add basic Darwin support to libcorkscrew.

This might not seem like much, but it's already better than Mac OS'
backtrace(3).

(cherry picked from commit 2a46f6293f19b9d6100187fbd53088088e671b88)

Change-Id: I197b06c4c19f728ad6f194b2f473bd9dcd99b8a6
diff --git a/libcorkscrew/backtrace.c b/libcorkscrew/backtrace.c
index 03dbd53..b365e5b 100644
--- a/libcorkscrew/backtrace.c
+++ b/libcorkscrew/backtrace.c
@@ -33,7 +33,6 @@
 #include <unwind.h>
 #include <cutils/log.h>
 #include <cutils/atomic.h>
-#include <elf.h>
 
 #define __USE_GNU // For dladdr(3) in glibc.
 #include <dlfcn.h>
@@ -43,6 +42,15 @@
 // Bionic implements and exports gettid but only implements tgkill.
 extern int tgkill(int tgid, int tid, int sig);
 
+#elif defined(__APPLE__)
+
+#include <sys/syscall.h>
+
+// Mac OS >= 10.6 has a system call equivalent to Linux's gettid().
+static pid_t gettid() {
+  return syscall(SYS_thread_selfid);
+}
+
 #else
 
 // glibc doesn't implement or export either gettid or tgkill.
@@ -97,7 +105,7 @@
     state.returned_frames = 0;
     init_memory(&state.memory, milist);
 
-    _Unwind_Reason_Code rc =_Unwind_Backtrace(unwind_backtrace_callback, &state);
+    _Unwind_Reason_Code rc = _Unwind_Backtrace(unwind_backtrace_callback, &state);
 
     release_my_map_info_list(milist);
 
@@ -146,7 +154,9 @@
 
     ALOGV("Unwinding thread %d from thread %d.", tid, gettid());
 
-#ifdef CORKSCREW_HAVE_ARCH
+    // TODO: there's no tgkill(2) on Mac OS, so we'd either need the
+    // mach_port_t or the pthread_t rather than the tid.
+#if defined(CORKSCREW_HAVE_ARCH) && !defined(__APPLE__)
     struct sigaction act;
     struct sigaction oact;
     memset(&act, 0, sizeof(act));
@@ -305,20 +315,20 @@
         const backtrace_symbol_t* symbol, char* buffer, size_t bufferSize) {
     const char* mapName = symbol->map_name ? symbol->map_name : "<unknown>";
     const char* symbolName = symbol->demangled_name ? symbol->demangled_name : symbol->symbol_name;
-    size_t fieldWidth = (bufferSize - 80) / 2;
+    int fieldWidth = (bufferSize - 80) / 2;
     if (symbolName) {
         uint32_t pc_offset = symbol->relative_pc - symbol->relative_symbol_addr;
         if (pc_offset) {
-            snprintf(buffer, bufferSize, "#%02d  pc %08x  %.*s (%.*s+%u)",
-                    frameNumber, symbol->relative_pc, fieldWidth, mapName,
+            snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s (%.*s+%u)",
+                    frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName,
                     fieldWidth, symbolName, pc_offset);
         } else {
-            snprintf(buffer, bufferSize, "#%02d  pc %08x  %.*s (%.*s)",
-                    frameNumber, symbol->relative_pc, fieldWidth, mapName,
+            snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s (%.*s)",
+                    frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName,
                     fieldWidth, symbolName);
         }
     } else {
-        snprintf(buffer, bufferSize, "#%02d  pc %08x  %.*s",
-                frameNumber, symbol->relative_pc, fieldWidth, mapName);
+        snprintf(buffer, bufferSize, "#%02u  pc %p  %.*s",
+                frameNumber, (void*) symbol->relative_pc, fieldWidth, mapName);
     }
 }