synth_elf.cc revision 3ca4a120de8ec3f35e972e4b23f527bb8f65c479
1#include "common/linux/synth_elf.h" 2 3#include <assert.h> 4#include <elf.h> 5#include <stdio.h> 6 7namespace google_breakpad { 8namespace synth_elf { 9 10ELF::ELF(uint16_t machine, 11 uint8_t file_class, 12 Endianness endianness) 13 : Section(endianness), 14 addr_size_(file_class == ELFCLASS64 ? 8 : 4), 15 program_count_(0), 16 section_count_(0), 17 section_header_table_(endianness), 18 section_header_strings_(endianness) { 19 // Could add support for more machine types here if needed. 20 assert(machine == EM_386 || 21 machine == EM_X86_64 || 22 machine == EM_ARM); 23 assert(file_class == ELFCLASS32 || file_class == ELFCLASS64); 24 25 start() = 0; 26 // Add ELF header 27 // e_ident 28 // EI_MAG0...EI_MAG3 29 D8(ELFMAG0); 30 D8(ELFMAG1); 31 D8(ELFMAG2); 32 D8(ELFMAG3); 33 // EI_CLASS 34 D8(file_class); 35 // EI_DATA 36 D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB); 37 // EI_VERSION 38 D8(EV_CURRENT); 39 // EI_OSABI 40 D8(ELFOSABI_SYSV); 41 // EI_ABIVERSION 42 D8(0); 43 // EI_PAD 44 Append(7, 0); 45 assert(Size() == EI_NIDENT); 46 47 // e_type 48 D16(ET_EXEC); //TODO: allow passing ET_DYN? 49 // e_machine 50 D16(machine); 51 // e_version 52 D32(EV_CURRENT); 53 // e_entry 54 Append(endianness, addr_size_, 0); 55 // e_phoff 56 Append(endianness, addr_size_, program_header_label_); 57 // e_shoff 58 Append(endianness, addr_size_, section_header_label_); 59 // e_flags 60 D32(0); 61 // e_ehsize 62 D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); 63 // e_phentsize 64 D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr)); 65 // e_phnum 66 D16(program_count_label_); 67 // e_shentsize 68 D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr)); 69 // e_shnum 70 D16(section_count_label_); 71 // e_shstrndx 72 D16(section_header_string_index_); 73 74 // Add an empty section for SHN_UNDEF. 75 Section shn_undef; 76 AddSection("", shn_undef, SHT_NULL); 77} 78 79int ELF::AddSection(const string& name, const Section& section, 80 uint32_t type, uint32_t flags, uint64_t addr, 81 uint32_t link, uint64_t entsize, uint64_t offset) { 82 Label offset_label; 83 Label string_label(section_header_strings_.Add(name)); 84 size_t size = section.Size(); 85 86 int index = section_count_; 87 ++section_count_; 88 89 section_header_table_ 90 // sh_name 91 .D32(string_label) 92 // sh_type 93 .D32(type) 94 // sh_flags 95 .Append(endianness(), addr_size_, flags) 96 // sh_addr 97 .Append(endianness(), addr_size_, addr) 98 // sh_offset 99 .Append(endianness(), addr_size_, offset_label) 100 // sh_size 101 .Append(endianness(), addr_size_, size) 102 // sh_link 103 .D32(link) 104 // sh_info 105 .D32(0) 106 // sh_addralign 107 .Append(endianness(), addr_size_, 0) 108 // sh_entsize 109 .Append(endianness(), addr_size_, entsize); 110 111 // NULL and NOBITS sections have no content, so they 112 // don't need to be written to the file. 113 if (type == SHT_NULL) { 114 offset_label = 0; 115 } else if (type == SHT_NOBITS) { 116 offset_label = offset; 117 } else { 118 Mark(&offset_label); 119 Append(section); 120 Align(4); 121 } 122 return index; 123} 124 125void ELF::Finish() { 126 // Add the section header string table at the end. 127 section_header_string_index_ = section_count_; 128 //printf(".shstrtab size: %ld\n", section_header_strings_.Size()); 129 AddSection(".shstrtab", section_header_strings_, SHT_STRTAB); 130 //printf("section_count_: %ld, sections_.size(): %ld\n", 131 // section_count_, sections_.size()); 132 section_count_label_ = section_count_; 133 program_count_label_ = program_count_; 134 // TODO: allow adding entries to program header table 135 program_header_label_ = 0; 136 137 // Section header table starts here. 138 Mark(§ion_header_label_); 139 Append(section_header_table_); 140} 141 142SymbolTable::SymbolTable(Endianness endianness, 143 size_t addr_size, 144 StringTable& table) : Section(endianness), 145 addr_size_(addr_size), 146 table_(table) { 147 assert(addr_size_ == 4 || addr_size_ == 8); 148} 149 150void SymbolTable::AddSymbol(const string& name, uint32_t value, 151 uint32_t size, unsigned info, uint16_t shndx) { 152 assert(addr_size_ == 4); 153 D32(table_.Add(name)); 154 D32(value); 155 D32(size); 156 D8(info); 157 D8(0); // other 158 D16(shndx); 159} 160 161void SymbolTable::AddSymbol(const string& name, uint64_t value, 162 uint64_t size, unsigned info, uint16_t shndx) { 163 assert(addr_size_ == 8); 164 D32(table_.Add(name)); 165 D8(info); 166 D8(0); // other 167 D16(shndx); 168 D64(value); 169 D64(size); 170} 171 172} // namespace synth_elf 173} // namespace google_breakpad 174 175