183e085b7a331c96237cf8e814f97b3ef4c36a70fjimblandy// Copyright (c) 2010 Google Inc. 268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// All rights reserved. 368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Redistribution and use in source and binary forms, with or without 568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// modification, are permitted provided that the following conditions are 668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// met: 768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// * Redistributions of source code must retain the above copyright 968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// notice, this list of conditions and the following disclaimer. 1068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// * Redistributions in binary form must reproduce the above 1168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// copyright notice, this list of conditions and the following disclaimer 1268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// in the documentation and/or other materials provided with the 1368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// distribution. 1468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// * Neither the name of Google Inc. nor the names of its 1568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// contributors may be used to endorse or promote products derived from 1668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// this software without specific prior written permission. 1768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 1868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 3068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Author: Alfred Peng 3168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 3268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <demangle.h> 3368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <fcntl.h> 3468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <gelf.h> 3568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <link.h> 3668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <sys/mman.h> 3768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <stab.h> 3868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <sys/stat.h> 3968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <sys/types.h> 4068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <unistd.h> 4168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 4268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <functional> 43dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#include <map> 4468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include <vector> 4568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 462cc15ba4327831f917ff55b87e6d5fc3c7750085ted.mielczarek@gmail.com#include "common/scoped_ptr.h" 4768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include "common/solaris/dump_symbols.h" 4868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include "common/solaris/file_id.h" 4968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai#include "common/solaris/guid_creator.h" 5068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 5168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// This namespace contains helper functions. 5268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovainamespace { 5368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 54dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekusing std::make_pair; 55dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 56dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#if defined(_LP64) 57dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarektypedef Elf64_Sym Elf_Sym; 58dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#else 59dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarektypedef Elf32_Sym Elf_Sym; 60dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek#endif 61dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 62dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Symbol table entry from stabs. Sun CC specific. 6368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistruct slist { 6468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // String table index. 6568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai unsigned int n_strx; 6668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Stab type. 6768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai unsigned char n_type; 6868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai char n_other; 6968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai short n_desc; 7068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai unsigned long n_value; 7168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 7268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 73dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Symbol table entry 74dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekstruct SymbolEntry { 75dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Offset from the start of the file. 76dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek GElf_Addr offset; 77dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Function size. 78dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek GElf_Word size; 79dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}; 80dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 8168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Infomation of a line. 8268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistruct LineInfo { 8368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Offset from start of the function. 8468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Load from stab symbol. 8568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Off rva_to_func; 8668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Offset from base of the loading binary. 8768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Off rva_to_base; 8868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Size of the line. 8968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // The first line: equals to rva_to_func. 9068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // The other lines: the difference of rva_to_func of the line and 9168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // rva_to_func of the previous N_SLINE. 9268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai uint32_t size; 9368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Line number. 9468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai uint32_t line_num; 9568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 9668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 9768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Information of a function. 9868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistruct FuncInfo { 9968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Name of the function. 10068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const char *name; 10168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Offset from the base of the loading address. 10268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Off rva_to_base; 10368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Virtual address of the function. 10468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Load from stab symbol. 10568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Addr addr; 10668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Size of the function. 10768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Equal to rva_to_func of the last function line. 10868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai uint32_t size; 10968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Total size of stack parameters. 11068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai uint32_t stack_param_size; 11168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Line information array. 11268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::vector<struct LineInfo> line_info; 11368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 11468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 11568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Information of a source file. 11668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistruct SourceFileInfo { 11768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Name of the source file. 11868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const char *name; 11968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Starting address of the source file. 12068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Addr addr; 12168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Id of the source file. 12268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int source_id; 12368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Functions information. 12468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::vector<struct FuncInfo> func_info; 12568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 12668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 127dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekstruct CompareString { 128dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek bool operator()(const char *s1, const char *s2) const { 129dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return strcmp(s1, s2) < 0; 130dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 131dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek}; 132dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 133dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarektypedef std::map<const char *, struct SymbolEntry *, CompareString> SymbolMap; 134dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 13568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Information of a symbol table. 13668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// This is the root of all types of symbol. 13768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistruct SymbolInfo { 13868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::vector<struct SourceFileInfo> source_file_info; 139dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Symbols information. 140dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek SymbolMap symbol_entries; 14168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 14268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 14368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Stab section name. 14468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiconst char *kStabName = ".stab"; 14568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 14668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Stab str section name. 14768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiconst char *kStabStrName = ".stabstr"; 14868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 149dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Symtab section name. 150dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekconst char *kSymtabName = ".symtab"; 151dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 152dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Strtab section name. 153dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekconst char *kStrtabName = ".strtab"; 154dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 15568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Default buffer lenght for demangle. 156dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekconst int demangleLen = 20000; 157dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 158dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Offset to the string table. 1596162aed3c3fcfc53373c963ac375d39a5dfa5a25ted.mielczarek@gmail.comuint64_t stringOffset = 0; 160dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 161dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// Update the offset to the start of the string index of the next 162dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek// object module for every N_ENDM stabs. 163dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekinline void RecalculateOffset(struct slist* cur_list, char *stabstr) { 164dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek while ((--cur_list)->n_strx == 0) ; 165dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek stringOffset += cur_list->n_strx; 166dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 167dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek char *temp = stabstr + stringOffset; 168dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek while (*temp != '\0') { 169dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ++stringOffset; 170dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ++temp; 171dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 172dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Skip the extra '\0' 173dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ++stringOffset; 174dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek} 17568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 17668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Demangle using demangle library on Solaris. 17768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistd::string Demangle(const char *mangled) { 17868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int status = 0; 1794af5fe0b593f5d79aee8c54f6bc1542b1deed87enealsid std::string str(mangled); 18068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai char *demangled = (char *)malloc(demangleLen); 1814af5fe0b593f5d79aee8c54f6bc1542b1deed87enealsid 18268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!demangled) { 18368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "no enough memory.\n"); 18468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai goto out; 18568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 18668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 18768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if ((status = cplus_demangle(mangled, demangled, demangleLen)) == 18868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai DEMANGLE_ESPACE) { 18968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "incorrect demangle.\n"); 19068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai goto out; 19168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 19268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 1934af5fe0b593f5d79aee8c54f6bc1542b1deed87enealsid str = demangled; 19468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai free(demangled); 19568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 19668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiout: 1974af5fe0b593f5d79aee8c54f6bc1542b1deed87enealsid return str; 19868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 19968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 20068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool WriteFormat(int fd, const char *fmt, ...) { 20168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai va_list list; 20268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai char buffer[4096]; 20368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ssize_t expected, written; 20468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai va_start(list, fmt); 20568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai vsnprintf(buffer, sizeof(buffer), fmt, list); 20668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai expected = strlen(buffer); 20768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai written = write(fd, buffer, strlen(buffer)); 20868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai va_end(list); 20968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return expected == written; 21068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 21168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 21268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool IsValidElf(const GElf_Ehdr *elf_header) { 21368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return memcmp(elf_header, ELFMAG, SELFMAG) == 0; 21468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 21568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 21668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaistatic bool FindSectionByName(Elf *elf, const char *name, 21768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int shstrndx, 21868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Shdr *shdr) { 21968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai assert(name != NULL); 22068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 22168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (strlen(name) == 0) 22268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 22368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 22468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai Elf_Scn *scn = NULL; 22568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 22668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while ((scn = elf_nextscn(elf, scn)) != NULL) { 22768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (gelf_getshdr(scn, shdr) == (GElf_Shdr *)0) { 22868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0)); 22968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 23068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 23168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 23268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const char *section_name = elf_strptr(elf, shstrndx, shdr->sh_name); 23368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!section_name) { 23468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1)); 23568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai continue; 23668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 23768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 23868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (strcmp(section_name, name) == 0) 23968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 24068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 24168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 24268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 24368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 24468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 24568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// The parameter size is used for FPO-optimized code, and 24668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// this is all tied up with the debugging data for Windows x86. 24768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Set it to 0 on Solaris. 24868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiint LoadStackParamSize(struct slist *list, 24968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *list_end, 25068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct FuncInfo *func_info) { 25168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *cur_list = list; 25268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int step = 1; 25368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list < list_end && cur_list->n_type == N_PSYM) { 25468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 25568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++step; 25668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 25768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 25868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_info->stack_param_size = 0; 25968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return step; 26068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 26168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 26268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiint LoadLineInfo(struct slist *list, 26368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *list_end, 26468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct FuncInfo *func_info) { 26568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *cur_list = list; 26668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai do { 26768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Skip non line information. 26868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list < list_end && cur_list->n_type != N_SLINE) { 269dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Only exit when got another function, or source file, or end stab. 270dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO || 271dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek cur_list->n_type == N_ENDM) { 27268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return cur_list - list; 273dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 27468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 27568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 27668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct LineInfo line; 27768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list < list_end && cur_list->n_type == N_SLINE) { 27868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai line.rva_to_func = cur_list->n_value; 27968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // n_desc is a signed short 28068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai line.line_num = (unsigned short)cur_list->n_desc; 28168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_info->line_info.push_back(line); 28268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 28368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 28468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (cur_list == list_end && cur_list->n_type == N_ENDM) 28568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai break; 28668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } while (list < list_end); 28768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 28868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return cur_list - list; 28968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 29068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 29168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiint LoadFuncSymbols(struct slist *list, 29268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *list_end, 293dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek char *stabstr, 29468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Word base, 29568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct SourceFileInfo *source_file_info) { 29668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *cur_list = list; 29768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai assert(cur_list->n_type == N_SO); 29868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 29968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 30068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_file_info->func_info.clear(); 30168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list < list_end) { 30268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Go until the function symbol. 30368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list < list_end && cur_list->n_type != N_FUN) { 30468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (cur_list->n_type == N_SO) { 30568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return cur_list - list; 30668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 30768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 308dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (cur_list->n_type == N_ENDM) 309dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek RecalculateOffset(cur_list, stabstr); 31068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai continue; 31168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 31268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai while (cur_list->n_type == N_FUN) { 31368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct FuncInfo func_info; 31468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai memset(&func_info, 0, sizeof(func_info)); 315dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_info.name = stabstr + cur_list->n_strx + stringOffset; 31668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // The n_value field is always 0 from stab generated by Sun CC. 31768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // TODO(Alfred): Find the correct value. 31868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_info.addr = cur_list->n_value; 31968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ++cur_list; 320dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (cur_list->n_type == N_ENDM) 321dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek RecalculateOffset(cur_list, stabstr); 32268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM && 32368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai cur_list->n_type != N_FUN) { 32468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Stack parameter size. 32568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai cur_list += LoadStackParamSize(cur_list, list_end, &func_info); 32668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Line info. 32768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai cur_list += LoadLineInfo(cur_list, list_end, &func_info); 32868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 329dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (cur_list < list_end && cur_list->n_type == N_ENDM) 330dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek RecalculateOffset(cur_list, stabstr); 33168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Functions in this module should have address bigger than the module 33268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // starting address. 33368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // 33468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // These two values are always 0 with Sun CC. 33568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // TODO(Alfred): Get the correct value or remove the condition statement. 33668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (func_info.addr >= source_file_info->addr) { 33768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_file_info->func_info.push_back(func_info); 33868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 33968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 34068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 34168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return cur_list - list; 34268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 34368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 34468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Compute size and rva information based on symbols loaded from stab section. 345dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarekbool ComputeSizeAndRVA(struct SymbolInfo *symbols) { 34668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::vector<struct SourceFileInfo> *sorted_files = 34768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai &(symbols->source_file_info); 348dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek SymbolMap *symbol_entries = &(symbols->symbol_entries); 34968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t i = 0; i < sorted_files->size(); ++i) { 35068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct SourceFileInfo &source_file = (*sorted_files)[i]; 35168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::vector<struct FuncInfo> *sorted_functions = &(source_file.func_info); 352dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek int func_size = sorted_functions->size(); 353dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 354dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek for (size_t j = 0; j < func_size; ++j) { 35568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct FuncInfo &func_info = (*sorted_functions)[j]; 35668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int line_count = func_info.line_info.size(); 357dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 358dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Discard the ending part of the name. 359dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek std::string func_name(func_info.name); 360dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek std::string::size_type last_colon = func_name.find_first_of(':'); 361dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (last_colon != std::string::npos) 362dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_name = func_name.substr(0, last_colon); 363dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 364dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek // Fine the symbol offset from the loading address and size by name. 365dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek SymbolMap::const_iterator it = symbol_entries->find(func_name.c_str()); 366dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (it->second) { 367dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_info.rva_to_base = it->second->offset; 368dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_info.size = (line_count == 0) ? 0 : it->second->size; 369dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } else { 370dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_info.rva_to_base = 0; 371dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek func_info.size = 0; 372dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 373dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 37468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Compute function and line size. 37568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t k = 0; k < line_count; ++k) { 37668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct LineInfo &line_info = func_info.line_info[k]; 377dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 378dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base; 379dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (k == line_count - 1) { 380dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek line_info.size = func_info.size - line_info.rva_to_func; 38168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } else { 382dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek struct LineInfo &next_line = func_info.line_info[k + 1]; 383dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek line_info.size = next_line.rva_to_func - line_info.rva_to_func; 38468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 38568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } // for each line. 38668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } // for each function. 38768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } // for each source file. 388dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek for (SymbolMap::iterator it = symbol_entries->begin(); 389dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek it != symbol_entries->end(); ++it) { 390dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek free(it->second); 391dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 39268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 39368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 39468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 39568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool LoadAllSymbols(const GElf_Shdr *stab_section, 39668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const GElf_Shdr *stabstr_section, 39768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Word base, 39868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct SymbolInfo *symbols) { 39968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (stab_section == NULL || stabstr_section == NULL) 40068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 40168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 402dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek char *stabstr = 403dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek reinterpret_cast<char *>(stabstr_section->sh_offset + base); 40468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *lists = 40568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai reinterpret_cast<struct slist *>(stab_section->sh_offset + base); 40668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int nstab = stab_section->sh_size / sizeof(struct slist); 40768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int source_id = 0; 408dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 40968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // First pass, load all symbols from the object file. 41068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (int i = 0; i < nstab; ) { 41168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int step = 1; 41268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct slist *cur_list = lists + i; 41368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (cur_list->n_type == N_SO) { 41468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // FUNC <address> <size> <param_stack_size> <function> 41568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct SourceFileInfo source_file_info; 416dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek source_file_info.name = stabstr + cur_list->n_strx + stringOffset; 41768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // The n_value field is always 0 from stab generated by Sun CC. 41868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // TODO(Alfred): Find the correct value. 41968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_file_info.addr = cur_list->n_value; 42068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (strchr(source_file_info.name, '.')) 42168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_file_info.source_id = source_id++; 42268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai else 42368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_file_info.source_id = -1; 424dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek step = LoadFuncSymbols(cur_list, lists + nstab - 1, stabstr, 425dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek base, &source_file_info); 42668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai symbols->source_file_info.push_back(source_file_info); 42768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 42868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai i += step; 42968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 43068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Second pass, compute the size of functions and lines. 431dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return ComputeSizeAndRVA(symbols); 43268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 43368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 43468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols, 43568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai void *obj_base) { 43668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Word base = reinterpret_cast<GElf_Word>(obj_base); 43768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 43868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const GElf_Shdr *sections = 43968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai reinterpret_cast<GElf_Shdr *>(elf_header->e_shoff + base); 44068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Shdr stab_section; 44168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx, 44268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai &stab_section)) { 44368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "Stab section not found.\n"); 44468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 44568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 44668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Shdr stabstr_section; 44768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx, 44868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai &stabstr_section)) { 44968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "Stabstr section not found.\n"); 45068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 45168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 452dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek GElf_Shdr symtab_section; 453dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (!FindSectionByName(elf, kSymtabName, elf_header->e_shstrndx, 454dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek &symtab_section)) { 455dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek fprintf(stderr, "Symtab section not found.\n"); 456dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return false; 457dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 458dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek GElf_Shdr strtab_section; 459dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (!FindSectionByName(elf, kStrtabName, elf_header->e_shstrndx, 460dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek &strtab_section)) { 461dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek fprintf(stderr, "Strtab section not found.\n"); 462dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return false; 463dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 464dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 465dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek Elf_Sym *symbol = (Elf_Sym *)((char *)base + symtab_section.sh_offset); 466dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek for (int i = 0; i < symtab_section.sh_size/symtab_section.sh_entsize; ++i) { 467dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek struct SymbolEntry *symbol_entry = 468dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek (struct SymbolEntry *)malloc(sizeof(struct SymbolEntry)); 469dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek const char *name = reinterpret_cast<char *>( 470dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek strtab_section.sh_offset + (GElf_Word)base + symbol->st_name); 471dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek symbol_entry->offset = symbol->st_value; 472dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek symbol_entry->size = symbol->st_size; 473dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek symbols->symbol_entries.insert(make_pair(name, symbol_entry)); 474dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek ++symbol; 475dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 476dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek 47768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 47868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Load symbols. 479dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return LoadAllSymbols(&stab_section, &stabstr_section, base, symbols); 48068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 48168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 48268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) { 48368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const char *arch_name = NULL; 48468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (arch == EM_386) 48568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai arch_name = "x86"; 48668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai else if (arch == EM_X86_64) 48768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai arch_name = "x86_64"; 488dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek else if (arch == EM_SPARC32PLUS) 489dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek arch_name = "SPARC_32+"; 490dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek else { 491dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek printf("Please add more ARCH support\n"); 49268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 493dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek } 49468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 49568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai unsigned char identifier[16]; 49668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai google_breakpad::FileID file_id(obj_file.c_str()); 49768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (file_id.ElfFileIdentifier(identifier)) { 49868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai char identifier_str[40]; 49968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai file_id.ConvertIdentifierToString(identifier, 50068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai identifier_str, sizeof(identifier_str)); 50168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::string filename = obj_file; 50268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai size_t slash_pos = obj_file.find_last_of("/"); 50368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (slash_pos != std::string::npos) 50468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai filename = obj_file.substr(slash_pos + 1); 50568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name, 50668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai identifier_str, filename.c_str()); 50768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 50868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 50968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 51068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 51168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) { 51268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { 51368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (symbols.source_file_info[i].source_id != -1) { 51468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const char *name = symbols.source_file_info[i].name; 51568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!WriteFormat(fd, "FILE %d %s\n", 51668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai symbols.source_file_info[i].source_id, name)) 51768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 51868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 51968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 52068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 52168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 52268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 52368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool WriteOneFunction(int fd, int source_id, 52468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const struct FuncInfo &func_info){ 52568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Discard the ending part of the name. 52668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::string func_name(func_info.name); 52768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai std::string::size_type last_colon = func_name.find_last_of(':'); 52868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (last_colon != std::string::npos) 52968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_name = func_name.substr(0, last_colon); 53068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_name = Demangle(func_name.c_str()); 53168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 532dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (func_info.size <= 0) 53368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 53468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 53568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit). 536dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (WriteFormat(fd, "FUNC %llx %x %d %s\n", 53768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai (long long)func_info.rva_to_base, 53868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_info.size, 53968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_info.stack_param_size, 54068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai func_name.c_str())) { 54168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t i = 0; i < func_info.line_info.size(); ++i) { 54268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const struct LineInfo &line_info = func_info.line_info[i]; 543dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (line_info.line_num == 0) 544dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek return true; 545dd2ff4a21c57672170eb14ccc5142efd7d92f3f1ted.mielczarek if (!WriteFormat(fd, "%llx %x %d %d\n", 54668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai (long long)line_info.rva_to_base, 54768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai line_info.size, 54868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai line_info.line_num, 54968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai source_id)) 55068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 55168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 55268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 55368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 55468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 55568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 55668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 55768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) { 55868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t i = 0; i < symbols.source_file_info.size(); ++i) { 55968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const struct SourceFileInfo &file_info = symbols.source_file_info[i]; 56068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai for (size_t j = 0; j < file_info.func_info.size(); ++j) { 56168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai const struct FuncInfo &func_info = file_info.func_info[j]; 56268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!WriteOneFunction(fd, file_info.source_id, func_info)) 56368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 56468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 56568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 56668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 56768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 56868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 56968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) { 57068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return WriteSourceFileInfo(fd, symbols) && 57168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai WriteFunctionInfo(fd, symbols); 57268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 57368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 57468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 57568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// FDWrapper 57668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 57768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Wrapper class to make sure opened file is closed. 57868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 57968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiclass FDWrapper { 58068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai public: 58168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai explicit FDWrapper(int fd) : 58268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fd_(fd) { 58368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 58468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ~FDWrapper() { 58568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (fd_ != -1) 58668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai close(fd_); 58768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 58868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int get() { 58968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return fd_; 59068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 59168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int release() { 59268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int fd = fd_; 59368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fd_ = -1; 59468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return fd; 59568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 59668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai private: 59768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int fd_; 59868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 59968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 60068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 60168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// MmapWrapper 60268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 60368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// Wrapper class to make sure mapped regions are unmapped. 60468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai// 60568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiclass MmapWrapper { 60668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai public: 60768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai MmapWrapper(void *mapped_address, size_t mapped_size) : 60868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai base_(mapped_address), size_(mapped_size) { 60968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 61068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ~MmapWrapper() { 61168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (base_ != NULL) { 61268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai assert(size_ > 0); 61368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai munmap((char *)base_, size_); 61468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 61568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 61668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai void release() { 61768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai base_ = NULL; 61868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai size_ = 0; 61968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 62068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 62168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai private: 62268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai void *base_; 62368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai size_t size_; 62468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 62568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 62668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} // namespace 62768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 62868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovainamespace google_breakpad { 62968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 63068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaiclass AutoElfEnder { 63168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai public: 63268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai AutoElfEnder(Elf *elf) : elf_(elf) {} 63368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai ~AutoElfEnder() { if (elf_) elf_end(elf_); } 63468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai private: 63568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai Elf *elf_; 63668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai}; 63768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 63868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 63968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovaibool DumpSymbols::WriteSymbolFile(const std::string &obj_file, int sym_fd) { 64068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (elf_version(EV_CURRENT) == EV_NONE) { 64168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0)); 64268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 64368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 64468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 64568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai int obj_fd = open(obj_file.c_str(), O_RDONLY); 64668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (obj_fd < 0) 64768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 64868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai FDWrapper obj_fd_wrapper(obj_fd); 64968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct stat st; 65068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) 65168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 65268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai void *obj_base = mmap(NULL, st.st_size, 65368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai PROT_READ, MAP_PRIVATE, obj_fd, 0); 654718478d95dad2d0e95ba7ad347e3074f99d28e3dnealsid if (obj_base == MAP_FAILED) 65568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 65668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai MmapWrapper map_wrapper(obj_base, st.st_size); 65768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai GElf_Ehdr elf_header; 65868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL); 65968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai AutoElfEnder elfEnder(elf); 66068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 66168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) { 66268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1)); 66368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 66468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 66568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 66668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!IsValidElf(&elf_header)) { 66768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai fprintf(stderr, "header magic doesn't match\n"); 66868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 66968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai } 67068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai struct SymbolInfo symbols; 67168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (!LoadSymbols(elf, &elf_header, &symbols, obj_base)) 67268004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 67368004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai // Write to symbol file. 67468004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) && 67568004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai DumpStabSymbols(sym_fd, symbols)) 67668004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return true; 67768004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 67868004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai return false; 67968004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} 68068004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai 68168004c84d6b852cfd4096cd211d2f8d3ff1d9f48mmentovai} // namespace google_breakpad 682