Merge changes Iac3d757b,Ic31463d2,I27e95c1d,Ibd6e8769

* changes:
  Revert "adb: Use new libusbhost library for USB support on Linux host."
  Revert "adb: remove unnecessary include"
  Revert "adb: Adjust usb_linux.c for changes in libusbhost API."
  Revert "adb: avoid potential race conditions in detecting device disconnects"
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3c1cf02..ccc001b 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c
+LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c symbol_table.c
 LOCAL_CFLAGS := -Wall
 LOCAL_MODULE := debuggerd
 
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index e850a2e..3b2972a 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -63,7 +63,7 @@
 /* Log information onto the tombstone */
 void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...)
 {
-    char buf[128];
+    char buf[512];
 
     va_list ap;
     va_start(ap, fmt);
@@ -106,10 +106,11 @@
 
     mi->start = strtoul(line, 0, 16);
     mi->end = strtoul(line + 9, 0, 16);
-    /* To be filled in parse_exidx_info if the mapped section starts with
+    /* To be filled in parse_elf_info if the mapped section starts with
      * elf_header
      */
     mi->exidx_start = mi->exidx_end = 0;
+    mi->symbols = 0;
     mi->next = 0;
     strcpy(mi->name, line + 49);
 
@@ -353,7 +354,7 @@
     if(sig) dump_fault_addr(tfd, tid, sig);
 }
 
-static void parse_exidx_info(mapinfo *milist, pid_t pid)
+static void parse_elf_info(mapinfo *milist, pid_t pid)
 {
     mapinfo *mi;
     for (mi = milist; mi != NULL; mi = mi->next) {
@@ -383,6 +384,9 @@
                     break;
                 }
             }
+
+            /* Try to load symbols from this file */
+            mi->symbols = symbol_table_create(mi->name);
         }
     }
 }
@@ -420,7 +424,7 @@
         fclose(fp);
     }
 
-    parse_exidx_info(milist, tid);
+    parse_elf_info(milist, tid);
 
     /* If stack unwinder fails, use the default solution to dump the stack
      * content.
@@ -439,6 +443,7 @@
 
     while(milist) {
         mapinfo *next = milist->next;
+        symbol_table_free(milist->symbols);
         free(milist);
         milist = next;
     }
diff --git a/debuggerd/symbol_table.c b/debuggerd/symbol_table.c
new file mode 100644
index 0000000..150c058
--- /dev/null
+++ b/debuggerd/symbol_table.c
@@ -0,0 +1,178 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "symbol_table.h"
+
+#include <linux/elf.h>
+
+// Compare func for qsort
+static int qcompar(const void *a, const void *b)
+{
+    return ((struct symbol*)a)->addr - ((struct symbol*)b)->addr;
+}
+
+// Compare func for bsearch
+static int bcompar(const void *addr, const void *element)
+{
+    struct symbol *symbol = (struct symbol*)element;
+
+    if((unsigned int)addr < symbol->addr) {
+        return -1;
+    }
+
+    if((unsigned int)addr - symbol->addr >= symbol->size) {
+        return 1;
+    }
+
+    return 0;
+}
+
+/*
+ *  Create a symbol table from a given file
+ *
+ *  Parameters:
+ *      filename - Filename to process
+ *
+ *  Returns:
+ *      A newly-allocated SymbolTable structure, or NULL if error.
+ *      Free symbol table with symbol_table_free()
+ */
+struct symbol_table *symbol_table_create(const char *filename)
+{
+    struct symbol_table *table = NULL;
+
+    // Open the file, and map it into memory
+    struct stat sb;
+    int length;
+    char *base;
+
+    int fd = open(filename, O_RDONLY);
+
+    if(fd < 0) {
+        goto out;
+    }
+
+    fstat(fd, &sb);
+    length = sb.st_size;
+
+    base = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);
+
+    if(!base) {
+        goto out_close;
+    }
+
+    // Parse the file header
+    Elf32_Ehdr *hdr = (Elf32_Ehdr*)base;
+    Elf32_Shdr *shdr = (Elf32_Shdr*)(base + hdr->e_shoff);
+
+    // Search for the dynamic symbols section
+    int dynsym_idx = -1;
+    int i;
+
+    for(i = 0; i < hdr->e_shnum; i++) {
+        if(shdr[i].sh_type == SHT_DYNSYM ) {
+            dynsym_idx = i;
+        }
+    }
+
+    if(dynsym_idx == -1) {
+        goto out_unmap;
+    }
+
+    Elf32_Sym *dynsyms = (Elf32_Sym*)(base + shdr[dynsym_idx].sh_offset);
+    int numsyms = shdr[dynsym_idx].sh_size / shdr[dynsym_idx].sh_entsize;
+
+    table = malloc(sizeof(struct symbol_table));
+    if(!table) {
+        goto out_unmap;
+    }
+    table->num_symbols = 0;
+
+    // Iterate through the dynamic symbol table, and count how many symbols
+    // are actually defined
+    for(i = 0; i < numsyms; i++) {
+        if(dynsyms[i].st_shndx != SHN_UNDEF) {
+            table->num_symbols++;
+        }
+    }
+
+    int dynstr_idx = shdr[dynsym_idx].sh_link;
+    char *dynstr = base + shdr[dynstr_idx].sh_offset;
+
+    // Now, create an entry in our symbol table structure for each symbol...
+    table->symbols = malloc(table->num_symbols * sizeof(struct symbol));
+    if(!table->symbols) {
+        free(table);
+        table = NULL;
+        goto out_unmap;
+    }
+
+    // ...and populate them
+    int j = 0;
+    for(i = 0; i < numsyms; i++) {
+        if(dynsyms[i].st_shndx != SHN_UNDEF) {
+            table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name);
+            table->symbols[j].addr = dynsyms[i].st_value;
+            table->symbols[j].size = dynsyms[i].st_size;
+            j++;
+        }
+    }
+
+    // Sort the symbol table entries, so they can be bsearched later
+    qsort(table->symbols, table->num_symbols, sizeof(struct symbol), qcompar);
+
+out_unmap:
+    munmap(base, length);
+
+out_close:
+    close(fd);
+
+out:
+    return table;
+}
+
+/*
+ * Free a symbol table
+ *
+ * Parameters:
+ *     table - Table to free
+ */
+void symbol_table_free(struct symbol_table *table)
+{
+    int i;
+
+    if(!table) {
+        return;
+    }
+
+    for(i=0; i<table->num_symbols; i++) {
+        free(table->symbols[i].name);
+    }
+
+    free(table->symbols);
+    free(table);
+}
+
+/*
+ * Search for an address in the symbol table
+ *
+ * Parameters:
+ *      table - Table to search in
+ *      addr - Address to search for.
+ *
+ * Returns:
+ *      A pointer to the Symbol structure corresponding to the
+ *      symbol which contains this address, or NULL if no symbol
+ *      contains it.
+ */
+const struct symbol *symbol_table_lookup(struct symbol_table *table, unsigned int addr)
+{
+    if(!table) {
+        return NULL;
+    }
+
+    return bsearch((void*)addr, table->symbols, table->num_symbols, sizeof(struct symbol), bcompar);
+}
diff --git a/debuggerd/symbol_table.h b/debuggerd/symbol_table.h
new file mode 100644
index 0000000..d9d2520
--- /dev/null
+++ b/debuggerd/symbol_table.h
@@ -0,0 +1,19 @@
+#ifndef SYMBOL_TABLE_H
+#define SYMBOL_TABLE_H
+
+struct symbol {
+    unsigned int addr;
+    unsigned int size;
+    char *name;
+};
+
+struct symbol_table {
+    struct symbol *symbols;
+    int num_symbols;
+};
+
+struct symbol_table *symbol_table_create(const char *filename);
+void symbol_table_free(struct symbol_table *table);
+const struct symbol *symbol_table_lookup(struct symbol_table *table, unsigned int addr);
+
+#endif
diff --git a/debuggerd/unwind-arm.c b/debuggerd/unwind-arm.c
index 9642d2e..b081161 100644
--- a/debuggerd/unwind-arm.c
+++ b/debuggerd/unwind-arm.c
@@ -37,6 +37,8 @@
 #include <unwind.h>
 #include "utility.h"
 
+#include "symbol_table.h"
+
 typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
 
 void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
@@ -393,6 +395,7 @@
     phase2_vrs *vrs = (phase2_vrs*) context;
     const mapinfo *mi;
     bool only_in_tombstone = !at_fault;
+    const struct symbol* sym = 0;
 
     if (stack_level < STACK_CONTENT_DEPTH) {
         sp_list[stack_level] = vrs->core.r[R_SP];
@@ -451,9 +454,20 @@
     rel_pc = pc;
     mi = pc_to_mapinfo(map, pc, &rel_pc);
 
-    _LOG(tfd, only_in_tombstone, 
-         "         #%02d  pc %08x  %s\n", stack_level, rel_pc, 
-         mi ? mi->name : "");
+    /* See if we can determine what symbol this stack frame resides in */
+    if (mi != 0 && mi->symbols != 0) {
+        sym = symbol_table_lookup(mi->symbols, rel_pc);
+    }
+
+    if (sym) {
+        _LOG(tfd, only_in_tombstone,
+            "         #%02d  pc %08x  %s (%s)\n", stack_level, rel_pc,
+            mi ? mi->name : "", sym->name);
+    } else {
+        _LOG(tfd, only_in_tombstone,
+            "         #%02d  pc %08x  %s\n", stack_level, rel_pc,
+            mi ? mi->name : "");
+    }
 
     return _URC_NO_REASON;
 }
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index 49f5951..2ffdf56 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -21,6 +21,8 @@
 #include <stddef.h>
 #include <stdbool.h>
 
+#include "symbol_table.h"
+
 #ifndef PT_ARM_EXIDX
 #define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
 #endif
@@ -33,6 +35,7 @@
     unsigned end;
     unsigned exidx_start;
     unsigned exidx_end;
+    struct symbol_table *symbols;
     char name[];
 } mapinfo;