Home | History | Annotate | Download | only in malloc_debug
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <dlfcn.h>
     30 #include <errno.h>
     31 #include <inttypes.h>
     32 #include <malloc.h>
     33 #include <pthread.h>
     34 #include <string.h>
     35 #include <sys/types.h>
     36 #include <unistd.h>
     37 #include <unwind.h>
     38 
     39 #include "backtrace.h"
     40 #include "debug_log.h"
     41 #include "MapData.h"
     42 
     43 #if defined(__LP64__)
     44 #define PAD_PTR "016" PRIxPTR
     45 #else
     46 #define PAD_PTR "08" PRIxPTR
     47 #endif
     48 
     49 typedef struct _Unwind_Context __unwind_context;
     50 
     51 extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
     52 
     53 static MapData g_map_data;
     54 static const MapEntry* g_current_code_map = nullptr;
     55 
     56 static _Unwind_Reason_Code find_current_map(__unwind_context* context, void*) {
     57   uintptr_t ip = _Unwind_GetIP(context);
     58 
     59   if (ip == 0) {
     60     return _URC_END_OF_STACK;
     61   }
     62   g_current_code_map = g_map_data.find(ip);
     63   return _URC_END_OF_STACK;
     64 }
     65 
     66 void backtrace_startup() {
     67   _Unwind_Backtrace(find_current_map, nullptr);
     68 }
     69 
     70 void backtrace_shutdown() {
     71 }
     72 
     73 struct stack_crawl_state_t {
     74   uintptr_t* frames;
     75   size_t frame_count;
     76   size_t cur_frame = 0;
     77 
     78   stack_crawl_state_t(uintptr_t* frames, size_t frame_count)
     79       : frames(frames), frame_count(frame_count) {}
     80 };
     81 
     82 static _Unwind_Reason_Code trace_function(__unwind_context* context, void* arg) {
     83   stack_crawl_state_t* state = static_cast<stack_crawl_state_t*>(arg);
     84 
     85   uintptr_t ip = _Unwind_GetIP(context);
     86 
     87   // The instruction pointer is pointing at the instruction after the return
     88   // call on all architectures.
     89   // Modify the pc to point at the real function.
     90   if (ip != 0) {
     91 #if defined(__arm__)
     92     // If the ip is suspiciously low, do nothing to avoid a segfault trying
     93     // to access this memory.
     94     if (ip >= 4096) {
     95       // Check bits [15:11] of the first halfword assuming the instruction
     96       // is 32 bits long. If the bits are any of these values, then our
     97       // assumption was correct:
     98       //  b11101
     99       //  b11110
    100       //  b11111
    101       // Otherwise, this is a 16 bit instruction.
    102       uint16_t value = (*reinterpret_cast<uint16_t*>(ip - 2)) >> 11;
    103       if (value == 0x1f || value == 0x1e || value == 0x1d) {
    104         ip -= 4;
    105       } else {
    106         ip -= 2;
    107       }
    108     }
    109 #elif defined(__aarch64__)
    110     // All instructions are 4 bytes long, skip back one instruction.
    111     ip -= 4;
    112 #elif defined(__i386__) || defined(__x86_64__)
    113     // It's difficult to decode exactly where the previous instruction is,
    114     // so subtract 1 to estimate where the instruction lives.
    115     ip--;
    116 #endif
    117 
    118     // Do not record the frames that fall in our own shared library.
    119     if (g_current_code_map && (ip >= g_current_code_map->start) && ip < g_current_code_map->end) {
    120       return _URC_NO_REASON;
    121     }
    122   }
    123 
    124   state->frames[state->cur_frame++] = ip;
    125   return (state->cur_frame >= state->frame_count) ? _URC_END_OF_STACK : _URC_NO_REASON;
    126 }
    127 
    128 size_t backtrace_get(uintptr_t* frames, size_t frame_count) {
    129   stack_crawl_state_t state(frames, frame_count);
    130   _Unwind_Backtrace(trace_function, &state);
    131   return state.cur_frame;
    132 }
    133 
    134 std::string backtrace_string(const uintptr_t* frames, size_t frame_count) {
    135   std::string str;
    136 
    137   for (size_t frame_num = 0; frame_num < frame_count; frame_num++) {
    138     uintptr_t offset = 0;
    139     const char* symbol = nullptr;
    140 
    141     Dl_info info;
    142     if (dladdr(reinterpret_cast<void*>(frames[frame_num]), &info) != 0) {
    143       offset = reinterpret_cast<uintptr_t>(info.dli_saddr);
    144       symbol = info.dli_sname;
    145     }
    146 
    147     uintptr_t rel_pc = offset;
    148     const MapEntry* entry = g_map_data.find(frames[frame_num], &rel_pc);
    149 
    150     const char* soname = (entry != nullptr) ? entry->name.c_str() : info.dli_fname;
    151     if (soname == nullptr) {
    152       soname = "<unknown>";
    153     }
    154     char buf[1024];
    155     if (symbol != nullptr) {
    156       char* demangled_symbol = __cxa_demangle(symbol, nullptr, nullptr, nullptr);
    157       const char* best_name = (demangled_symbol != nullptr) ? demangled_symbol : symbol;
    158 
    159       __libc_format_buffer(buf, sizeof(buf),
    160           "          #%02zd  pc %" PAD_PTR "  %s (%s+%" PRIuPTR ")\n", frame_num,
    161           rel_pc, soname, best_name, frames[frame_num] - offset);
    162       free(demangled_symbol);
    163     } else {
    164       __libc_format_buffer(buf, sizeof(buf),
    165           "          #%02zd  pc %" PAD_PTR "  %s\n", frame_num, rel_pc, soname);
    166     }
    167     str += buf;
    168   }
    169 
    170   return str;
    171 }
    172 
    173 void backtrace_log(const uintptr_t* frames, size_t frame_count) {
    174   error_log_string(backtrace_string(frames, frame_count).c_str());
    175 }
    176