Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9524e415 authored by Jeff Brown's avatar Jeff Brown
Browse files

Add support for explicitly dumping native stacks.

This change modifies debuggerd so that it can be used to grab
the native stacks of a process that has hung and not just crashed.
Note that only the root user can do this (for now).

adb shell debuggerd <tid>

Then use logcat to find the tombstone file that was generated
which will have the native stacks of all threads in the
requested process.  The specified thread will be shown first
and will also appear in the main log.

Also made some minor tweaks to libcorkscrew so that we
could handle statically compiled executables in the future
if we compiled the library statically.

Improved the "wait_for_user_action" function to support
volume down as an alternative for devices that do not
have home keys.

Removed a mess of gotos.

Change-Id: Ic149653986b0c2f503c7f0e8b7cb1f3be7c84d1e
parent 13e715b4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ void dump_registers(ptrace_context_t* context __attribute((unused)),
        _LOG(tfd, only_in_tombstone, "    d%-2d %016llx  d%-2d %016llx\n",
                i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
    }
    _LOG(tfd, only_in_tombstone, "    scr %08lx\n\n", vfp_regs.fpscr);
    _LOG(tfd, only_in_tombstone, "    scr %08lx\n", vfp_regs.fpscr);
#endif
}

+316 −205

File changed.

Preview size limit exceeded, changes collapsed.

+25 −15
Original line number Diff line number Diff line
@@ -25,23 +25,13 @@
 * the exception handling table of each function, sorted by program
 * counter address.
 *
 * When the executable is statically linked, the EXIDX section can be
 * accessed by querying the values of the __exidx_start and __exidx_end
 * symbols.  That said, this library is currently only compiled as
 * a dynamic library, so we will not trouble ourselves with statically
 * linked executables any further.
 *
 * When the Bionic dynamic linker is used, it exports a function called
 * dl_unwind_find_exidx that obtains the EXIDX section for a given
 * absolute program counter address.
 *
 * This implementation also supports unwinding other processes via ptrace().
 * In that case, the EXIDX section is found by reading the ELF section table
 * structures using ptrace().
 *
 * Because the tables are used for exception handling, it can happen that
 * a given function will not have an exception handling table.  In particular,
 * exceptions are assumes to only ever be thrown at call sites.  Therefore,
 * exceptions are assumed to only ever be thrown at call sites.  Therefore,
 * by definition leaf functions will not have exception handling tables.
 * This may make unwinding impossible in some cases although we can still get
 * some idea of the call stack by examining the PC and LR registers.
@@ -100,9 +90,29 @@ static const int R_PC = 15;
/* Special EXIDX value that indicates that a frame cannot be unwound. */
static const uint32_t EXIDX_CANTUNWIND = 1;

/* The function exported by the Bionic linker to find the EXIDX
 * table for a given program counter address. */
extern uintptr_t dl_unwind_find_exidx(uintptr_t pc, size_t* out_exidx_size);
/* Get the EXIDX section start and size for the module that contains a
 * given program counter address.
 *
 * When the executable is statically linked, the EXIDX section can be
 * accessed by querying the values of the __exidx_start and __exidx_end
 * symbols.
 *
 * When the executable is dynamically linked, the linker exports a function
 * called dl_unwind_find_exidx that obtains the EXIDX section for a given
 * absolute program counter address.
 *
 * Bionic exports a helpful function called __gnu_Unwind_Find_exidx that
 * handles both cases, so we use that here.
 */
typedef long unsigned int* _Unwind_Ptr;
extern _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount);

static uintptr_t find_exidx(uintptr_t pc, size_t* out_exidx_size) {
    int count;
    uintptr_t start = (uintptr_t)__gnu_Unwind_Find_exidx((_Unwind_Ptr)pc, &count);
    *out_exidx_size = count;
    return start;
}

/* Transforms a 31-bit place-relative offset to an absolute address.
 * We assume the most significant bit is clear. */
@@ -115,7 +125,7 @@ static uintptr_t get_exception_handler(
    uintptr_t exidx_start;
    size_t exidx_size;
    if (tid < 0) {
        exidx_start = dl_unwind_find_exidx(pc, &exidx_size);
        exidx_start = find_exidx(pc, &exidx_size);
    } else {
        const map_info_t* mi = find_map_info(context->map_info_list, pc);
        if (mi && mi->data) {