debug_stacktrace.cpp revision 63dd03ccedc316724c40e140067e612932e4420e
11e980b6bc8315d00a07312b25486531247abd98cElliott Hughes/* 21e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * Copyright (C) 2012 The Android Open Source Project 31e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * All rights reserved. 41e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * 51e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * Redistribution and use in source and binary forms, with or without 61e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * modification, are permitted provided that the following conditions 71e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * are met: 81e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * * Redistributions of source code must retain the above copyright 91e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * notice, this list of conditions and the following disclaimer. 101e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * * Redistributions in binary form must reproduce the above copyright 111e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * notice, this list of conditions and the following disclaimer in 121e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * the documentation and/or other materials provided with the 131e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * distribution. 141e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * 151e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261e980b6bc8315d00a07312b25486531247abd98cElliott Hughes * SUCH DAMAGE. 271e980b6bc8315d00a07312b25486531247abd98cElliott Hughes */ 281e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 291e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include "debug_stacktrace.h" 301e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 311e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <dlfcn.h> 321e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <unistd.h> 331e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <unwind.h> 341e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <sys/types.h> 351e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 361e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include "debug_mapinfo.h" 378f2a5a0b40fc82126c691d5c30131d908772aab7Elliott Hughes#include "libc_logging.h" 381e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 391e980b6bc8315d00a07312b25486531247abd98cElliott Hughes/* depends how the system includes define this */ 401e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#ifdef HAVE_UNWIND_CONTEXT_STRUCT 411e980b6bc8315d00a07312b25486531247abd98cElliott Hughestypedef struct _Unwind_Context __unwind_context; 421e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#else 431e980b6bc8315d00a07312b25486531247abd98cElliott Hughestypedef _Unwind_Context __unwind_context; 441e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#endif 451e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 4635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstatic mapinfo_t* gMapInfo = NULL; 4735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstatic void* gDemangler; 4835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughestypedef char* (*DemanglerFn)(const char*, char*, size_t*, int*); 4935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstatic DemanglerFn gDemanglerFn = NULL; 5035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 5135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void backtrace_startup() { 5235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes gMapInfo = mapinfo_create(getpid()); 5335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes gDemangler = dlopen("libgccdemangle.so", RTLD_NOW); 5435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (gDemangler != NULL) { 5535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes void* sym = dlsym(gDemangler, "__cxa_demangle"); 5635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes gDemanglerFn = reinterpret_cast<DemanglerFn>(sym); 5735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 5835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 5935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 6035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void backtrace_shutdown() { 6135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes mapinfo_destroy(gMapInfo); 6235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes dlclose(gDemangler); 6335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 6435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 6535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstatic char* demangle(const char* symbol) { 6635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (gDemanglerFn == NULL) { 6735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return NULL; 6835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 6935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return (*gDemanglerFn)(symbol, NULL, NULL, NULL); 7035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 7135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 7235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstruct stack_crawl_state_t { 7335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes uintptr_t* frames; 7435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes size_t frame_count; 7535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes size_t max_depth; 7635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes bool have_skipped_self; 7735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 7835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes stack_crawl_state_t(uintptr_t* frames, size_t max_depth) 7935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes : frames(frames), frame_count(0), max_depth(max_depth), have_skipped_self(false) { 8035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 8135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes}; 8235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 831e980b6bc8315d00a07312b25486531247abd98cElliott Hughesstatic _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) { 841e980b6bc8315d00a07312b25486531247abd98cElliott Hughes stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg); 8535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 8635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes uintptr_t ip = _Unwind_GetIP(context); 8735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 8835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes // The first stack frame is get_backtrace itself. Skip it. 8935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (ip != 0 && !state->have_skipped_self) { 9035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes state->have_skipped_self = true; 9135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return _URC_NO_REASON; 921e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 9335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 9452171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng#ifdef __arm__ 9552171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng /* 9652171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * The instruction pointer is pointing at the instruction after the bl(x), and 9752171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB 9852171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * in PC). So we need to do a quick check here to find out if the previous 9952171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise 4 from PC. 10052171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng */ 10152171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng if (ip != 0) { 10252171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng short* ptr = reinterpret_cast<short*>(ip); 10352171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng // Thumb BLX(2) 10463dd03ccedc316724c40e140067e612932e4420eBen Cheng if ((*(ptr-1) & 0xff80) == 0x4780) { 10552171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng ip -= 2; 10652171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } else { 10752171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng ip -= 4; 10852171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } 10952171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } 11052171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng#endif 11152171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng 11235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes state->frames[state->frame_count++] = ip; 11335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return (state->frame_count >= state->max_depth) ? _URC_END_OF_STACK : _URC_NO_REASON; 1141e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 1151e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 11635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ int get_backtrace(uintptr_t* frames, size_t max_depth) { 11735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes stack_crawl_state_t state(frames, max_depth); 1181e980b6bc8315d00a07312b25486531247abd98cElliott Hughes _Unwind_Backtrace(trace_function, &state); 11935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return state.frame_count; 1201e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 1211e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 12235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void log_backtrace(uintptr_t* frames, size_t frame_count) { 123239e7a0756fddf3698bf72cab10d7f382421090bElliott Hughes uintptr_t self_bt[16]; 12435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (frames == NULL) { 12535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes frame_count = get_backtrace(self_bt, 16); 12635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes frames = self_bt; 1271e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1281e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 1291e980b6bc8315d00a07312b25486531247abd98cElliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", 1301e980b6bc8315d00a07312b25486531247abd98cElliott Hughes "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 1311e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 13235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes for (size_t i = 0 ; i < frame_count; ++i) { 1331e980b6bc8315d00a07312b25486531247abd98cElliott Hughes void* offset = 0; 1341e980b6bc8315d00a07312b25486531247abd98cElliott Hughes const char* symbol = NULL; 1351e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 1361e980b6bc8315d00a07312b25486531247abd98cElliott Hughes Dl_info info; 13735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (dladdr((void*) frames[i], &info) != 0) { 1381e980b6bc8315d00a07312b25486531247abd98cElliott Hughes offset = info.dli_saddr; 1391e980b6bc8315d00a07312b25486531247abd98cElliott Hughes symbol = info.dli_sname; 1401e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1411e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 14235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes uintptr_t rel_pc; 14335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes const mapinfo_t* mi = (gMapInfo != NULL) ? mapinfo_find(gMapInfo, frames[i], &rel_pc) : NULL; 14435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes const char* soname = (mi != NULL) ? mi->name : info.dli_fname; 14535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (soname == NULL) { 14635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes soname = "<unknown>"; 14735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 14835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (symbol != NULL) { 14935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes // TODO: we might need a flag to say whether it's safe to allocate (demangling allocates). 15035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes char* demangled_symbol = demangle(symbol); 15135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes const char* best_name = (demangled_symbol != NULL) ? demangled_symbol : symbol; 15235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 15335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", " #%02d pc %08x %s (%s+0x%x)", 15435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes i, rel_pc, soname, best_name, frames[i] - (uintptr_t) offset); 15535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 15635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes free(demangled_symbol); 15735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } else { 15835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", " #%02d pc %08x %s", 15935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes i, rel_pc, soname); 1601e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1611e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1621e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 163