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> 32c7c5f85ead6a58eadd511c728a9020a493bc128fElliott Hughes#include <inttypes.h> 331e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <unistd.h> 341e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <unwind.h> 351e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include <sys/types.h> 361e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 371e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#include "debug_mapinfo.h" 38c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris#include "malloc_debug_disable.h" 39eb847bc8666842a3cfc9c06e8458ad1abebebaf0Elliott Hughes#include "private/libc_logging.h" 401e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 41ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes#if defined(__LP64__) 42ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes#define PAD_PTR "016" PRIxPTR 43ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes#else 44ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes#define PAD_PTR "08" PRIxPTR 45ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes#endif 46ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes 471e980b6bc8315d00a07312b25486531247abd98cElliott Hughes/* depends how the system includes define this */ 481e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#ifdef HAVE_UNWIND_CONTEXT_STRUCT 491e980b6bc8315d00a07312b25486531247abd98cElliott Hughestypedef struct _Unwind_Context __unwind_context; 501e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#else 511e980b6bc8315d00a07312b25486531247abd98cElliott Hughestypedef _Unwind_Context __unwind_context; 521e980b6bc8315d00a07312b25486531247abd98cElliott Hughes#endif 531e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 541728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic mapinfo_t* g_map_info = NULL; 551728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic void* g_demangler; 5635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughestypedef char* (*DemanglerFn)(const char*, char*, size_t*, int*); 571728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic DemanglerFn g_demangler_fn = NULL; 5835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 5935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void backtrace_startup() { 60c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris ScopedDisableDebugCalls disable; 61c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris 621728b2396591853345507a063ed6075dfd251706Elliott Hughes g_map_info = mapinfo_create(getpid()); 631728b2396591853345507a063ed6075dfd251706Elliott Hughes g_demangler = dlopen("libgccdemangle.so", RTLD_NOW); 641728b2396591853345507a063ed6075dfd251706Elliott Hughes if (g_demangler != NULL) { 651728b2396591853345507a063ed6075dfd251706Elliott Hughes void* sym = dlsym(g_demangler, "__cxa_demangle"); 661728b2396591853345507a063ed6075dfd251706Elliott Hughes g_demangler_fn = reinterpret_cast<DemanglerFn>(sym); 6735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 6835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 6935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 7035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void backtrace_shutdown() { 71c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris ScopedDisableDebugCalls disable; 72c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris 731728b2396591853345507a063ed6075dfd251706Elliott Hughes mapinfo_destroy(g_map_info); 741728b2396591853345507a063ed6075dfd251706Elliott Hughes dlclose(g_demangler); 7535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 7635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 7735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstatic char* demangle(const char* symbol) { 781728b2396591853345507a063ed6075dfd251706Elliott Hughes if (g_demangler_fn == NULL) { 7935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return NULL; 8035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 811728b2396591853345507a063ed6075dfd251706Elliott Hughes return (*g_demangler_fn)(symbol, NULL, NULL, NULL); 8235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes} 8335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 8435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughesstruct stack_crawl_state_t { 8535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes uintptr_t* frames; 8635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes size_t frame_count; 8735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes size_t max_depth; 8835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes bool have_skipped_self; 8935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 9035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes stack_crawl_state_t(uintptr_t* frames, size_t max_depth) 9135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes : frames(frames), frame_count(0), max_depth(max_depth), have_skipped_self(false) { 9235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 9335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes}; 9435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 951e980b6bc8315d00a07312b25486531247abd98cElliott Hughesstatic _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) { 961e980b6bc8315d00a07312b25486531247abd98cElliott Hughes stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg); 9735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 9835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes uintptr_t ip = _Unwind_GetIP(context); 9935b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 10035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes // The first stack frame is get_backtrace itself. Skip it. 10135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (ip != 0 && !state->have_skipped_self) { 10235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes state->have_skipped_self = true; 10335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return _URC_NO_REASON; 1041e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 10535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 106c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris#if defined(__arm__) 10752171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng /* 10852171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * The instruction pointer is pointing at the instruction after the bl(x), and 10952171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * the _Unwind_Backtrace routine already masks the Thumb mode indicator (LSB 11052171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * in PC). So we need to do a quick check here to find out if the previous 11152171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng * instruction is a Thumb-mode BLX(2). If so subtract 2 otherwise 4 from PC. 11252171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng */ 11352171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng if (ip != 0) { 11452171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng short* ptr = reinterpret_cast<short*>(ip); 11552171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng // Thumb BLX(2) 11663dd03ccedc316724c40e140067e612932e4420eBen Cheng if ((*(ptr-1) & 0xff80) == 0x4780) { 11752171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng ip -= 2; 11852171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } else { 11952171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng ip -= 4; 12052171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } 12152171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng } 12252171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng#endif 12352171b9bdcb2aa1efe9c4deab37c029699fe763dBen Cheng 12435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes state->frames[state->frame_count++] = ip; 12535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return (state->frame_count >= state->max_depth) ? _URC_END_OF_STACK : _URC_NO_REASON; 1261e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 1271e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 12835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ int get_backtrace(uintptr_t* frames, size_t max_depth) { 129c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris ScopedDisableDebugCalls disable; 130c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris 13135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes stack_crawl_state_t state(frames, max_depth); 1321e980b6bc8315d00a07312b25486531247abd98cElliott Hughes _Unwind_Backtrace(trace_function, &state); 13335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes return state.frame_count; 1341e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 1351e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 13635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes__LIBC_HIDDEN__ void log_backtrace(uintptr_t* frames, size_t frame_count) { 137c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris ScopedDisableDebugCalls disable; 138c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris 139239e7a0756fddf3698bf72cab10d7f382421090bElliott Hughes uintptr_t self_bt[16]; 14035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (frames == NULL) { 14135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes frame_count = get_backtrace(self_bt, 16); 14235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes frames = self_bt; 1431e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1441e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 1451e980b6bc8315d00a07312b25486531247abd98cElliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", 1461e980b6bc8315d00a07312b25486531247abd98cElliott Hughes "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 1471e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 14835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes for (size_t i = 0 ; i < frame_count; ++i) { 149c7c5f85ead6a58eadd511c728a9020a493bc128fElliott Hughes uintptr_t offset = 0; 1501e980b6bc8315d00a07312b25486531247abd98cElliott Hughes const char* symbol = NULL; 1511e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 1521e980b6bc8315d00a07312b25486531247abd98cElliott Hughes Dl_info info; 15335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (dladdr((void*) frames[i], &info) != 0) { 154c7c5f85ead6a58eadd511c728a9020a493bc128fElliott Hughes offset = reinterpret_cast<uintptr_t>(info.dli_saddr); 1551e980b6bc8315d00a07312b25486531247abd98cElliott Hughes symbol = info.dli_sname; 1561e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1571e980b6bc8315d00a07312b25486531247abd98cElliott Hughes 158c701e5b3357b6484572d46f29c5d1e51063dfcbbChristopher Ferris uintptr_t rel_pc = offset; 1591728b2396591853345507a063ed6075dfd251706Elliott Hughes const mapinfo_t* mi = (g_map_info != NULL) ? mapinfo_find(g_map_info, frames[i], &rel_pc) : NULL; 16035b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes const char* soname = (mi != NULL) ? mi->name : info.dli_fname; 16135b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (soname == NULL) { 16235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes soname = "<unknown>"; 16335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } 16435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes if (symbol != NULL) { 16535b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes // TODO: we might need a flag to say whether it's safe to allocate (demangling allocates). 16635b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes char* demangled_symbol = demangle(symbol); 16735b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes const char* best_name = (demangled_symbol != NULL) ? demangled_symbol : symbol; 16835b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 169c7c5f85ead6a58eadd511c728a9020a493bc128fElliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", 170ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes " #%02zd pc %" PAD_PTR " %s (%s+%" PRIuPTR ")", 171ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes i, rel_pc, soname, best_name, frames[i] - offset); 17235b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes 17335b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes free(demangled_symbol); 17435b621c5f4c79959cd36fec0153c2c9c43ebe5f0Elliott Hughes } else { 175c7c5f85ead6a58eadd511c728a9020a493bc128fElliott Hughes __libc_format_log(ANDROID_LOG_ERROR, "libc", 176ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes " #%02zd pc %" PAD_PTR " %s", 177ba76572789740ec1a04da30dd89121ef5cb0bf44Elliott Hughes i, rel_pc, soname); 1781e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1791e980b6bc8315d00a07312b25486531247abd98cElliott Hughes } 1801e980b6bc8315d00a07312b25486531247abd98cElliott Hughes} 181