15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Satoru Takabayashi
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This library provides Symbolize() function that symbolizes program
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// counters to their corresponding symbol names on linux platforms.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This library has a minimal implementation of an ELF symbol table
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reader (i.e. it doesn't depend on libelf, etc.).
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The algorithm used in Symbolize() is as follows.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   1. Go through a list of maps in /proc/self/maps and find the map
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   containing the program counter.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   2. Open the mapped file and find a regular symbol table inside.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   Iterate over symbols in the symbol table and look for the symbol
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   containing the program counter.  If such a symbol is found,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   obtain the symbol name, and demangle the symbol if possible.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   If the symbol isn't found in the regular symbol table (binary is
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   stripped), try the same thing with a dynamic symbol table.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that Symbolize() is originally implemented to be used in
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FailureSignalHandler() in base/google.cc.  Hence it doesn't use
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// malloc() and other unsafe operations.  It should be both
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread-safe and async-signal-safe.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_SYMBOLIZE_H_
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_SYMBOLIZE_H_
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "utilities.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "glog/logging.h"
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYMBOLIZE
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__ELF__)  // defined by gcc
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__OpenBSD__)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/exec_elf.h>
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <elf.h>
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(ANDROID)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <link.h>  // For ElfW() macro.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For systems where SIZEOF_VOID_P is not defined, determine it
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// based on __LP64__ (defined by gcc on 64-bit systems)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(SIZEOF_VOID_P)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if defined(__LP64__)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define SIZEOF_VOID_P 8
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define SIZEOF_VOID_P 4
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is no ElfW macro, let's define it by ourself.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef ElfW
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if SIZEOF_VOID_P == 4
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define ElfW(type) Elf32_##type
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# elif SIZEOF_VOID_P == 8
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  define ElfW(type) Elf64_##type
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# else
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#  error "Unknown sizeof(void *)"
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_START_GOOGLE_NAMESPACE_
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the section header for the given name, if it exists. Returns true on
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// success. Otherwise, returns false.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ElfW(Shdr) *out);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_END_GOOGLE_NAMESPACE_
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  /* __ELF__ */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_START_GOOGLE_NAMESPACE_
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Restrictions on the callbacks that follow:
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//  - The callbacks must not use heaps but only use stacks.
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//  - The callbacks must be async-signal-safe.
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Installs a callback function, which will be called right before a symbol name
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is printed. The callback is intended to be used for showing a file name and a
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// line number preceding a symbol name.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "fd" is a file descriptor of the object file containing the program
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// counter "pc". The callback function should write output to "out"
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and return the size of the output written. On error, the callback
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function should return -1.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 uint64 relocation);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InstallSymbolizeCallback(SymbolizeCallback callback);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Installs a callback function, which will be called instead of
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// OpenObjectFileContainingPcAndGetStartAddress.  The callback is expected
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// to searches for the object file (from /proc/self/maps) that contains
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// the specified pc.  If found, sets |start_address| to the start address
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// of where this object file is mapped in memory, sets the module base
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// address into |base_address|, copies the object file name into
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |out_file_name|, and attempts to open the object file.  If the object
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// file is opened successfully, returns the file descriptor.  Otherwise,
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// returns -1.  |out_file_name_size| is the size of the file name buffer
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// (including the null-terminator).
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               uint64_t &start_address,
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               uint64_t &base_address,
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               char *out_file_name,
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               int out_file_name_size);
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void InstallSymbolizeOpenObjectFileCallback(
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SymbolizeOpenObjectFileCallback callback);
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_END_GOOGLE_NAMESPACE_
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_START_GOOGLE_NAMESPACE_
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Symbolizes a program counter.  On success, returns true and write the
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// symbol name to "out".  The symbol name is demangled if possible
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (supports symbols generated by GCC 3.x or newer).  Otherwise,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns false.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Symbolize(void *pc, char *out, int out_size);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_END_GOOGLE_NAMESPACE_
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_SYMBOLIZE_H_
156