Home | History | Annotate | Download | only in symbolize
      1 // Copyright (c) 2006, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      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
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 //
     30 // Author: Satoru Takabayashi
     31 //
     32 // This library provides Symbolize() function that symbolizes program
     33 // counters to their corresponding symbol names on linux platforms.
     34 // This library has a minimal implementation of an ELF symbol table
     35 // reader (i.e. it doesn't depend on libelf, etc.).
     36 //
     37 // The algorithm used in Symbolize() is as follows.
     38 //
     39 //   1. Go through a list of maps in /proc/self/maps and find the map
     40 //   containing the program counter.
     41 //
     42 //   2. Open the mapped file and find a regular symbol table inside.
     43 //   Iterate over symbols in the symbol table and look for the symbol
     44 //   containing the program counter.  If such a symbol is found,
     45 //   obtain the symbol name, and demangle the symbol if possible.
     46 //   If the symbol isn't found in the regular symbol table (binary is
     47 //   stripped), try the same thing with a dynamic symbol table.
     48 //
     49 // Note that Symbolize() is originally implemented to be used in
     50 // FailureSignalHandler() in base/google.cc.  Hence it doesn't use
     51 // malloc() and other unsafe operations.  It should be both
     52 // thread-safe and async-signal-safe.
     53 
     54 #ifndef BASE_SYMBOLIZE_H_
     55 #define BASE_SYMBOLIZE_H_
     56 
     57 #include "utilities.h"
     58 #include "config.h"
     59 #include "glog/logging.h"
     60 
     61 #ifdef HAVE_SYMBOLIZE
     62 
     63 #if defined(__ELF__)  // defined by gcc
     64 #if defined(__OpenBSD__)
     65 #include <sys/exec_elf.h>
     66 #else
     67 #include <elf.h>
     68 #endif
     69 
     70 #if !defined(ANDROID)
     71 #include <link.h>  // For ElfW() macro.
     72 #endif
     73 
     74 // For systems where SIZEOF_VOID_P is not defined, determine it
     75 // based on __LP64__ (defined by gcc on 64-bit systems)
     76 #if !defined(SIZEOF_VOID_P)
     77 # if defined(__LP64__)
     78 #  define SIZEOF_VOID_P 8
     79 # else
     80 #  define SIZEOF_VOID_P 4
     81 # endif
     82 #endif
     83 
     84 // If there is no ElfW macro, let's define it by ourself.
     85 #ifndef ElfW
     86 # if SIZEOF_VOID_P == 4
     87 #  define ElfW(type) Elf32_##type
     88 # elif SIZEOF_VOID_P == 8
     89 #  define ElfW(type) Elf64_##type
     90 # else
     91 #  error "Unknown sizeof(void *)"
     92 # endif
     93 #endif
     94 
     95 _START_GOOGLE_NAMESPACE_
     96 
     97 // Gets the section header for the given name, if it exists. Returns true on
     98 // success. Otherwise, returns false.
     99 bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
    100                             ElfW(Shdr) *out);
    101 
    102 _END_GOOGLE_NAMESPACE_
    103 
    104 #endif  /* __ELF__ */
    105 
    106 _START_GOOGLE_NAMESPACE_
    107 
    108 // Restrictions on the callbacks that follow:
    109 //  - The callbacks must not use heaps but only use stacks.
    110 //  - The callbacks must be async-signal-safe.
    111 
    112 // Installs a callback function, which will be called right before a symbol name
    113 // is printed. The callback is intended to be used for showing a file name and a
    114 // line number preceding a symbol name.
    115 // "fd" is a file descriptor of the object file containing the program
    116 // counter "pc". The callback function should write output to "out"
    117 // and return the size of the output written. On error, the callback
    118 // function should return -1.
    119 typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size,
    120                                  uint64 relocation);
    121 void InstallSymbolizeCallback(SymbolizeCallback callback);
    122 
    123 // Installs a callback function, which will be called instead of
    124 // OpenObjectFileContainingPcAndGetStartAddress.  The callback is expected
    125 // to searches for the object file (from /proc/self/maps) that contains
    126 // the specified pc.  If found, sets |start_address| to the start address
    127 // of where this object file is mapped in memory, sets the module base
    128 // address into |base_address|, copies the object file name into
    129 // |out_file_name|, and attempts to open the object file.  If the object
    130 // file is opened successfully, returns the file descriptor.  Otherwise,
    131 // returns -1.  |out_file_name_size| is the size of the file name buffer
    132 // (including the null-terminator).
    133 typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
    134                                                uint64_t &start_address,
    135                                                uint64_t &base_address,
    136                                                char *out_file_name,
    137                                                int out_file_name_size);
    138 void InstallSymbolizeOpenObjectFileCallback(
    139     SymbolizeOpenObjectFileCallback callback);
    140 
    141 _END_GOOGLE_NAMESPACE_
    142 
    143 #endif
    144 
    145 _START_GOOGLE_NAMESPACE_
    146 
    147 // Symbolizes a program counter.  On success, returns true and write the
    148 // symbol name to "out".  The symbol name is demangled if possible
    149 // (supports symbols generated by GCC 3.x or newer).  Otherwise,
    150 // returns false.
    151 bool Symbolize(void *pc, char *out, int out_size);
    152 
    153 _END_GOOGLE_NAMESPACE_
    154 
    155 #endif  // BASE_SYMBOLIZE_H_
    156