1// -*- mode: C++ -*- 2 3// Copyright (c) 2011, Google Inc. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: 9// 10// * Redistributions of source code must retain the above copyright 11// notice, this list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above 13// copyright notice, this list of conditions and the following disclaimer 14// in the documentation and/or other materials provided with the 15// distribution. 16// * Neither the name of Google Inc. nor the names of its 17// contributors may be used to endorse or promote products derived from 18// this software without specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> 33 34// synth_elf.h: Interface to synth_elf::ELF: fake ELF generator. 35 36#ifndef COMMON_LINUX_SYNTH_ELF_H_ 37#define COMMON_LINUX_SYNTH_ELF_H_ 38 39#include "common/test_assembler.h" 40 41#include <list> 42#include <vector> 43#include <map> 44#include <string> 45#include <utility> 46 47#include "common/using_std_string.h" 48 49namespace google_breakpad { 50namespace synth_elf { 51 52using std::list; 53using std::vector; 54using std::map; 55using std::pair; 56using test_assembler::Endianness; 57using test_assembler::kLittleEndian; 58using test_assembler::kUnsetEndian; 59using test_assembler::Label; 60using test_assembler::Section; 61 62// String tables are common in ELF headers, so subclass Section 63// to make them easy to generate. 64class StringTable : public Section { 65public: 66 StringTable(Endianness endianness = kUnsetEndian) 67 : Section(endianness) { 68 start() = 0; 69 empty_string = Add(""); 70 } 71 72 // Add the string s to the string table, and return 73 // a label containing the offset into the string table 74 // at which it was added. 75 Label Add(const string& s) { 76 if (strings_.find(s) != strings_.end()) 77 return strings_[s]; 78 79 Label string_label(Here()); 80 AppendCString(s); 81 strings_[s] = string_label; 82 return string_label; 83 } 84 85 // All StringTables contain an empty string as their first 86 // entry. 87 Label empty_string; 88 89 // Avoid inserting duplicate strings. 90 map<string,Label> strings_; 91}; 92 93// A Section representing an entire ELF file. 94class ELF : public Section { 95 public: 96 ELF(uint16_t machine, // EM_386, etc 97 uint8_t file_class, // ELFCLASS{32,64} 98 Endianness endianness = kLittleEndian); 99 100 // Add the Section section to the section header table and append it 101 // to the file. Returns the index of the section in the section 102 // header table. 103 int AddSection(const string& name, const Section& section, 104 uint32_t type, uint32_t flags = 0, uint64_t addr = 0, 105 uint32_t link = 0, uint64_t entsize = 0, uint64_t offset = 0); 106 107 // Add a segment containing from section index start to section index end. 108 // The indexes must have been gotten from AddSection. 109 void AddSegment(int start, int end, uint32_t type, uint32_t flags = 0); 110 111 // Write out all data. GetContents may be used after this. 112 void Finish(); 113 114 private: 115 // Size of an address, in bytes. 116 const size_t addr_size_; 117 118 // Offset to the program header table. 119 Label program_header_label_; 120 // Number of entries in the program header table. 121 int program_count_; 122 Label program_count_label_; 123 // The program header table itself. 124 Section program_header_table_; 125 126 // Offset to the section header table. 127 Label section_header_label_; 128 // Number of entries in the section header table. 129 int section_count_; 130 Label section_count_label_; 131 // The section header table itself. 132 Section section_header_table_; 133 134 // Index of the section header string table in the section 135 // header table. 136 Label section_header_string_index_; 137 // Section containing the names of section header table entries. 138 StringTable section_header_strings_; 139 140 // Record of an added section 141 struct ElfSection : public Section { 142 ElfSection(const Section& section, uint32_t type, uint32_t addr, 143 uint32_t offset, Label offset_label, uint32_t size) 144 : Section(section), type_(type), addr_(addr), offset_(offset) 145 , offset_label_(offset_label), size_(size) { 146 } 147 148 uint32_t type_; 149 uint32_t addr_; 150 uint32_t offset_; 151 Label offset_label_; 152 uint32_t size_; 153 }; 154 155 vector<ElfSection> sections_; 156 157 void AppendSection(ElfSection §ion); 158}; 159 160// A class to build .symtab or .dynsym sections. 161class SymbolTable : public Section { 162 public: 163 // table is the StringTable that contains symbol names. The caller 164 // must ensure that it remains alive for the life of the 165 // SymbolTable. 166 SymbolTable(Endianness endianness, size_t addr_size, StringTable& table); 167 168 // Add an Elf32_Sym. 169 void AddSymbol(const string& name, uint32_t value, 170 uint32_t size, unsigned info, uint16_t shndx); 171 // Add an Elf64_Sym. 172 void AddSymbol(const string& name, uint64_t value, 173 uint64_t size, unsigned info, uint16_t shndx); 174 175 private: 176 size_t addr_size_; 177 StringTable& table_; 178}; 179 180// A class for note sections 181class Notes : public Section { 182public: 183 Notes(Endianness endianness) 184 : Section(endianness) { 185 } 186 187 // Add a note. 188 void AddNote(int type, const string &name, const uint8_t* desc_bytes, 189 size_t desc_size); 190}; 191 192} // namespace synth_elf 193} // namespace google_breakpad 194 195#endif // COMMON_LINUX_SYNTH_ELF_H_ 196