Merge "Add camera focus move message."
diff --git a/debuggerd/utility.c b/debuggerd/utility.c
index 64e5980..2ccf947 100644
--- a/debuggerd/utility.c
+++ b/debuggerd/utility.c
@@ -65,16 +65,10 @@
     backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
     get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
     for (size_t i = 0; i < frames; i++) {
-        const backtrace_symbol_t* symbol = &backtrace_symbols[i];
-        const char* map_name = symbol->map_name ? symbol->map_name : "<unknown>";
-        const char* symbol_name = symbol->demangled_name ? symbol->demangled_name : symbol->name;
-        if (symbol_name) {
-            _LOG(tfd, !at_fault, "    #%02d  pc %08x  %s (%s)\n",
-                    (int)i, symbol->relative_pc, map_name, symbol_name);
-        } else {
-            _LOG(tfd, !at_fault, "    #%02d  pc %08x  %s\n",
-                    (int)i, symbol->relative_pc, map_name);
-        }
+        char line[MAX_BACKTRACE_LINE_LENGTH];
+        format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
+                line, MAX_BACKTRACE_LINE_LENGTH);
+        _LOG(tfd, !at_fault, "    %s\n", line);
     }
     free_backtrace_symbols(backtrace_symbols, frames);
 }
@@ -94,12 +88,23 @@
         if (symbol) {
             char* demangled_name = demangle_symbol_name(symbol->name);
             const char* symbol_name = demangled_name ? demangled_name : symbol->name;
+            uint32_t offset = stack_content - (mi->start + symbol->start);
             if (!i && label >= 0) {
-                _LOG(tfd, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s)\n",
-                        label, *sp, stack_content, mi ? mi->name : "", symbol_name);
+                if (offset) {
+                    _LOG(tfd, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s+%u)\n",
+                            label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
+                } else {
+                    _LOG(tfd, only_in_tombstone, "    #%02d  %08x  %08x  %s (%s)\n",
+                            label, *sp, stack_content, mi ? mi->name : "", symbol_name);
+                }
             } else {
-                _LOG(tfd, only_in_tombstone, "         %08x  %08x  %s (%s)\n",
-                        *sp, stack_content, mi ? mi->name : "", symbol_name);
+                if (offset) {
+                    _LOG(tfd, only_in_tombstone, "         %08x  %08x  %s (%s+%u)\n",
+                            *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
+                } else {
+                    _LOG(tfd, only_in_tombstone, "         %08x  %08x  %s (%s)\n",
+                            *sp, stack_content, mi ? mi->name : "", symbol_name);
+                }
             }
             free(demangled_name);
         } else {
diff --git a/include/corkscrew/backtrace.h b/include/corkscrew/backtrace.h
index 157d029..556ad04 100644
--- a/include/corkscrew/backtrace.h
+++ b/include/corkscrew/backtrace.h
@@ -41,10 +41,12 @@
  * Describes the symbols associated with a backtrace frame.
  */
 typedef struct {
-    uintptr_t relative_pc;       /* relative PC offset from the start of the library,
+    uintptr_t relative_pc;       /* relative frame PC offset from the start of the library,
                                     or the absolute PC if the library is unknown */
+    uintptr_t relative_symbol_addr; /* relative offset of the symbol from the start of the
+                                    library or 0 if the library is unknown */
     char* map_name;              /* executable or library name, or NULL if unknown */
-    char* name;                  /* symbol name, or NULL if unknown */
+    char* symbol_name;           /* symbol name, or NULL if unknown */
     char* demangled_name;        /* demangled symbol name, or NULL if unknown */
 } backtrace_symbol_t;
 
@@ -95,6 +97,17 @@
  */
 void free_backtrace_symbols(backtrace_symbol_t* backtrace_symbols, size_t frames);
 
+enum {
+    // A hint for how big to make the line buffer for format_backtrace_line
+    MAX_BACKTRACE_LINE_LENGTH = 800,
+};
+
+/**
+ * Formats a line from a backtrace as a zero-terminated string into the specified buffer.
+ */
+void format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame,
+        const backtrace_symbol_t* symbol, char* buffer, size_t bufferSize);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libcorkscrew/arch-arm/backtrace-arm.c b/libcorkscrew/arch-arm/backtrace-arm.c
index cf9a5ab..5b91164 100644
--- a/libcorkscrew/arch-arm/backtrace-arm.c
+++ b/libcorkscrew/arch-arm/backtrace-arm.c
@@ -146,6 +146,7 @@
     }
 
     uintptr_t handler = 0;
+    int32_t handler_index = -1;
     if (exidx_start) {
         uint32_t low = 0;
         uint32_t high = exidx_size;
@@ -153,10 +154,12 @@
             uint32_t index = (low + high) / 2;
             uintptr_t entry = exidx_start + index * 8;
             uint32_t entry_prel_pc;
+            ALOGV("XXX low=%u, high=%u, index=%u", low, high, index);
             if (!try_get_word(memory, entry, &entry_prel_pc)) {
                 break;
             }
             uintptr_t entry_pc = prel_to_absolute(entry, entry_prel_pc);
+            ALOGV("XXX entry_pc=0x%08x", entry_pc);
             if (pc < entry_pc) {
                 high = index;
                 continue;
@@ -168,6 +171,7 @@
                     break;
                 }
                 uintptr_t next_entry_pc = prel_to_absolute(next_entry, next_entry_prel_pc);
+                ALOGV("XXX next_entry_pc=0x%08x", next_entry_pc);
                 if (pc >= next_entry_pc) {
                     low = index + 1;
                     continue;
@@ -184,17 +188,18 @@
             } else if (entry_handler != EXIDX_CANTUNWIND) {
                 handler = prel_to_absolute(entry_handler_ptr, entry_handler);
             }
+            handler_index = index;
             break;
         }
     }
     if (mi) {
         ALOGV("get_exception_handler: pc=0x%08x, module='%s', module_start=0x%08x, "
-                "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x",
-                pc, mi->name, mi->start, exidx_start, exidx_size, handler);
+                "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x, handler_index=%d",
+                pc, mi->name, mi->start, exidx_start, exidx_size, handler, handler_index);
     } else {
         ALOGV("get_exception_handler: pc=0x%08x, "
-                "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x",
-                pc, exidx_start, exidx_size, handler);
+                "exidx_start=0x%08x, exidx_size=%d, handler=0x%08x, handler_index=%d",
+                pc, exidx_start, exidx_size, handler, handler_index);
     }
     return handler;
 }
@@ -464,11 +469,10 @@
          * 18896:       4798            blx     r3
          * 18898:       b001            add     sp, #4
          */
-        pc &= ~1;
         uint16_t prev1, prev2;
-        if (try_get_half_word(memory, pc - 4, &prev1)
+        if (try_get_half_word(memory, pc - 5, &prev1)
             && ((prev1 & 0xf000) == 0xf000)
-            && try_get_half_word(memory, pc - 2, &prev2)
+            && try_get_half_word(memory, pc - 3, &prev2)
             && ((prev2 & 0xe000) == 0xe000)) {
             pc -= 4; // long offset
         } else {
diff --git a/libcorkscrew/backtrace.c b/libcorkscrew/backtrace.c
index 857b741..fa21574 100644
--- a/libcorkscrew/backtrace.c
+++ b/libcorkscrew/backtrace.c
@@ -213,8 +213,9 @@
 
 static void init_backtrace_symbol(backtrace_symbol_t* symbol, uintptr_t pc) {
     symbol->relative_pc = pc;
+    symbol->relative_symbol_addr = 0;
     symbol->map_name = NULL;
-    symbol->name = NULL;
+    symbol->symbol_name = NULL;
     symbol->demangled_name = NULL;
 }
 
@@ -235,8 +236,10 @@
 #if HAVE_DLADDR
             Dl_info info;
             if (dladdr((const void*)frame->absolute_pc, &info) && info.dli_sname) {
-                symbol->name = strdup(info.dli_sname);
-                symbol->demangled_name = demangle_symbol_name(symbol->name);
+                symbol->relative_symbol_addr = (uintptr_t)info.dli_saddr
+                        - (uintptr_t)info.dli_fbase;
+                symbol->symbol_name = strdup(info.dli_sname);
+                symbol->demangled_name = demangle_symbol_name(symbol->symbol_name);
             }
 #endif
         }
@@ -262,8 +265,9 @@
             }
         }
         if (s) {
-            symbol->name = strdup(s->name);
-            symbol->demangled_name = demangle_symbol_name(symbol->name);
+            symbol->relative_symbol_addr = s->start;
+            symbol->symbol_name = strdup(s->name);
+            symbol->demangled_name = demangle_symbol_name(symbol->symbol_name);
         }
     }
 }
@@ -272,8 +276,30 @@
     for (size_t i = 0; i < frames; i++) {
         backtrace_symbol_t* symbol = &backtrace_symbols[i];
         free(symbol->map_name);
-        free(symbol->name);
+        free(symbol->symbol_name);
         free(symbol->demangled_name);
         init_backtrace_symbol(symbol, 0);
     }
 }
+
+void format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame,
+        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;
+    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,
+                    fieldWidth, symbolName, pc_offset);
+        } else {
+            snprintf(buffer, bufferSize, "#%02d  pc %08x  %.*s (%.*s)",
+                    frameNumber, symbol->relative_pc, fieldWidth, mapName,
+                    fieldWidth, symbolName);
+        }
+    } else {
+        snprintf(buffer, bufferSize, "#%02d  pc %08x  %.*s",
+                frameNumber, symbol->relative_pc, fieldWidth, mapName);
+    }
+}
diff --git a/libcorkscrew/symbol_table.c b/libcorkscrew/symbol_table.c
index 8257c77..1b97180 100644
--- a/libcorkscrew/symbol_table.c
+++ b/libcorkscrew/symbol_table.c
@@ -47,6 +47,7 @@
 
 symbol_table_t* load_symbol_table(const char *filename) {
     symbol_table_t* table = NULL;
+    ALOGV("Loading symbol table from '%s'.", filename);
 
     int fd = open(filename, O_RDONLY);
     if (fd < 0) {
@@ -154,6 +155,9 @@
                 table->symbols[symbol_index].name = strdup(dynstr + dynsyms[i].st_name);
                 table->symbols[symbol_index].start = dynsyms[i].st_value;
                 table->symbols[symbol_index].end = dynsyms[i].st_value + dynsyms[i].st_size;
+                ALOGV("  [%d] '%s' 0x%08x-0x%08x (DYNAMIC)",
+                        symbol_index, table->symbols[symbol_index].name,
+                        table->symbols[symbol_index].start, table->symbols[symbol_index].end);
                 symbol_index += 1;
             }
         }
@@ -169,6 +173,9 @@
                 table->symbols[symbol_index].name = strdup(str + syms[i].st_name);
                 table->symbols[symbol_index].start = syms[i].st_value;
                 table->symbols[symbol_index].end = syms[i].st_value + syms[i].st_size;
+                ALOGV("  [%d] '%s' 0x%08x-0x%08x",
+                        symbol_index, table->symbols[symbol_index].name,
+                        table->symbols[symbol_index].start, table->symbols[symbol_index].end);
                 symbol_index += 1;
             }
         }
diff --git a/toolbox/getevent.c b/toolbox/getevent.c
index 352f6f9..5f5e16b 100644
--- a/toolbox/getevent.c
+++ b/toolbox/getevent.c
@@ -643,7 +643,7 @@
                         return 1;
                     }
                     if(get_time) {
-                        printf("%ld-%ld: ", event.time.tv_sec, event.time.tv_usec);
+                        printf("[%8ld.%06ld] ", event.time.tv_sec, event.time.tv_usec);
                     }
                     if(print_device)
                         printf("%s: ", device_names[i]);