dump_symbols_unittest.cc revision 7867fcbc885065ceb6afee36b824da9d0dd47fe8
1// Copyright (c) 2011 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// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> 31 32// dump_symbols_unittest.cc: 33// Unittests for google_breakpad::DumpSymbols 34 35#include <elf.h> 36#include <link.h> 37#include <stdio.h> 38 39#include <sstream> 40#include <string> 41#include <vector> 42 43#include "breakpad_googletest_includes.h" 44#include "common/linux/synth_elf.h" 45#include "common/using_std_string.h" 46 47namespace google_breakpad { 48bool WriteSymbolFileInternal(const uint8_t* obj_file, 49 const string &obj_filename, 50 const string &debug_dir, 51 bool cfi, 52 std::ostream &sym_stream); 53} 54 55using google_breakpad::synth_elf::ELF; 56using google_breakpad::synth_elf::StringTable; 57using google_breakpad::synth_elf::SymbolTable; 58using google_breakpad::test_assembler::kLittleEndian; 59using google_breakpad::test_assembler::Section; 60using google_breakpad::WriteSymbolFileInternal; 61using std::stringstream; 62using std::vector; 63using ::testing::Test; 64 65class DumpSymbols : public Test { 66 public: 67 void GetElfContents(ELF& elf) { 68 string contents; 69 ASSERT_TRUE(elf.GetContents(&contents)); 70 ASSERT_LT(0, contents.size()); 71 72 elfdata_v.clear(); 73 elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end()); 74 elfdata = &elfdata_v[0]; 75 } 76 77 vector<uint8_t> elfdata_v; 78 uint8_t* elfdata; 79}; 80 81TEST_F(DumpSymbols, Invalid) { 82 Elf32_Ehdr header; 83 memset(&header, 0, sizeof(header)); 84 stringstream s; 85 EXPECT_FALSE(WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(&header), 86 "foo", 87 "", 88 true, 89 s)); 90} 91 92TEST_F(DumpSymbols, SimplePublic32) { 93 ELF elf(EM_386, ELFCLASS32, kLittleEndian); 94 // Zero out text section for simplicity. 95 Section text(kLittleEndian); 96 text.Append(4096, 0); 97 elf.AddSection(".text", text, SHT_PROGBITS); 98 99 // Add a public symbol. 100 StringTable table(kLittleEndian); 101 SymbolTable syms(kLittleEndian, 4, table); 102 syms.AddSymbol("superfunc", (uint32_t)0x1000, (uint32_t)0x10, 103 ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), 104 SHN_UNDEF + 1); 105 int index = elf.AddSection(".dynstr", table, SHT_STRTAB); 106 elf.AddSection(".dynsym", syms, 107 SHT_DYNSYM, // type 108 SHF_ALLOC, // flags 109 0, // addr 110 index, // link 111 sizeof(Elf32_Sym)); // entsize 112 113 elf.Finish(); 114 GetElfContents(elf); 115 116 stringstream s; 117 ASSERT_TRUE(WriteSymbolFileInternal(elfdata, 118 "foo", 119 "", 120 true, 121 s)); 122 EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n" 123 "PUBLIC 1000 0 superfunc\n", 124 s.str()); 125} 126 127TEST_F(DumpSymbols, SimplePublic64) { 128 ELF elf(EM_X86_64, ELFCLASS64, kLittleEndian); 129 // Zero out text section for simplicity. 130 Section text(kLittleEndian); 131 text.Append(4096, 0); 132 elf.AddSection(".text", text, SHT_PROGBITS); 133 134 // Add a public symbol. 135 StringTable table(kLittleEndian); 136 SymbolTable syms(kLittleEndian, 8, table); 137 syms.AddSymbol("superfunc", (uint64_t)0x1000, (uint64_t)0x10, 138 ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), 139 SHN_UNDEF + 1); 140 int index = elf.AddSection(".dynstr", table, SHT_STRTAB); 141 elf.AddSection(".dynsym", syms, 142 SHT_DYNSYM, // type 143 SHF_ALLOC, // flags 144 0, // addr 145 index, // link 146 sizeof(Elf64_Sym)); // entsize 147 148 elf.Finish(); 149 GetElfContents(elf); 150 151 stringstream s; 152 ASSERT_TRUE(WriteSymbolFileInternal(elfdata, 153 "foo", 154 "", 155 true, 156 s)); 157 EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n" 158 "PUBLIC 1000 0 superfunc\n", 159 s.str()); 160} 161