1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,264 @@ 1.4 +#include "common/linux/synth_elf.h" 1.5 + 1.6 +#include <assert.h> 1.7 +#include <elf.h> 1.8 +#include <stdio.h> 1.9 +#include <string.h> 1.10 + 1.11 +#include "common/using_std_string.h" 1.12 + 1.13 +namespace google_breakpad { 1.14 +namespace synth_elf { 1.15 + 1.16 +#ifndef NT_GNU_BUILD_ID 1.17 +#define NT_GNU_BUILD_ID 3 1.18 +#endif 1.19 + 1.20 +ELF::ELF(uint16_t machine, 1.21 + uint8_t file_class, 1.22 + Endianness endianness) 1.23 + : Section(endianness), 1.24 + addr_size_(file_class == ELFCLASS64 ? 8 : 4), 1.25 + program_count_(0), 1.26 + program_header_table_(endianness), 1.27 + section_count_(0), 1.28 + section_header_table_(endianness), 1.29 + section_header_strings_(endianness) { 1.30 + // Could add support for more machine types here if needed. 1.31 + assert(machine == EM_386 || 1.32 + machine == EM_X86_64 || 1.33 + machine == EM_ARM); 1.34 + assert(file_class == ELFCLASS32 || file_class == ELFCLASS64); 1.35 + 1.36 + start() = 0; 1.37 + // Add ELF header 1.38 + // e_ident 1.39 + // EI_MAG0...EI_MAG3 1.40 + D8(ELFMAG0); 1.41 + D8(ELFMAG1); 1.42 + D8(ELFMAG2); 1.43 + D8(ELFMAG3); 1.44 + // EI_CLASS 1.45 + D8(file_class); 1.46 + // EI_DATA 1.47 + D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB); 1.48 + // EI_VERSION 1.49 + D8(EV_CURRENT); 1.50 + // EI_OSABI 1.51 + D8(ELFOSABI_SYSV); 1.52 + // EI_ABIVERSION 1.53 + D8(0); 1.54 + // EI_PAD 1.55 + Append(7, 0); 1.56 + assert(Size() == EI_NIDENT); 1.57 + 1.58 + // e_type 1.59 + D16(ET_EXEC); //TODO: allow passing ET_DYN? 1.60 + // e_machine 1.61 + D16(machine); 1.62 + // e_version 1.63 + D32(EV_CURRENT); 1.64 + // e_entry 1.65 + Append(endianness, addr_size_, 0); 1.66 + // e_phoff 1.67 + Append(endianness, addr_size_, program_header_label_); 1.68 + // e_shoff 1.69 + Append(endianness, addr_size_, section_header_label_); 1.70 + // e_flags 1.71 + D32(0); 1.72 + // e_ehsize 1.73 + D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); 1.74 + // e_phentsize 1.75 + D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr)); 1.76 + // e_phnum 1.77 + D16(program_count_label_); 1.78 + // e_shentsize 1.79 + D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr)); 1.80 + // e_shnum 1.81 + D16(section_count_label_); 1.82 + // e_shstrndx 1.83 + D16(section_header_string_index_); 1.84 + 1.85 + // Add an empty section for SHN_UNDEF. 1.86 + Section shn_undef; 1.87 + AddSection("", shn_undef, SHT_NULL); 1.88 +} 1.89 + 1.90 +int ELF::AddSection(const string& name, const Section& section, 1.91 + uint32_t type, uint32_t flags, uint64_t addr, 1.92 + uint32_t link, uint64_t entsize, uint64_t offset) { 1.93 + Label offset_label; 1.94 + Label string_label(section_header_strings_.Add(name)); 1.95 + size_t size = section.Size(); 1.96 + 1.97 + int index = section_count_; 1.98 + ++section_count_; 1.99 + 1.100 + section_header_table_ 1.101 + // sh_name 1.102 + .D32(string_label) 1.103 + // sh_type 1.104 + .D32(type) 1.105 + // sh_flags 1.106 + .Append(endianness(), addr_size_, flags) 1.107 + // sh_addr 1.108 + .Append(endianness(), addr_size_, addr) 1.109 + // sh_offset 1.110 + .Append(endianness(), addr_size_, offset_label) 1.111 + // sh_size 1.112 + .Append(endianness(), addr_size_, size) 1.113 + // sh_link 1.114 + .D32(link) 1.115 + // sh_info 1.116 + .D32(0) 1.117 + // sh_addralign 1.118 + .Append(endianness(), addr_size_, 0) 1.119 + // sh_entsize 1.120 + .Append(endianness(), addr_size_, entsize); 1.121 + 1.122 + sections_.push_back(ElfSection(section, type, addr, offset, offset_label, 1.123 + size)); 1.124 + return index; 1.125 +} 1.126 + 1.127 +void ELF::AppendSection(ElfSection §ion) { 1.128 + // NULL and NOBITS sections have no content, so they 1.129 + // don't need to be written to the file. 1.130 + if (section.type_ == SHT_NULL) { 1.131 + section.offset_label_ = 0; 1.132 + } else if (section.type_ == SHT_NOBITS) { 1.133 + section.offset_label_ = section.offset_; 1.134 + } else { 1.135 + Mark(§ion.offset_label_); 1.136 + Append(section); 1.137 + Align(4); 1.138 + } 1.139 +} 1.140 + 1.141 +void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) { 1.142 + assert(start > 0); 1.143 + assert(size_t(start) < sections_.size()); 1.144 + assert(end > 0); 1.145 + assert(size_t(end) < sections_.size()); 1.146 + ++program_count_; 1.147 + 1.148 + // p_type 1.149 + program_header_table_.D32(type); 1.150 + 1.151 + if (addr_size_ == 8) { 1.152 + // p_flags 1.153 + program_header_table_.D32(flags); 1.154 + } 1.155 + 1.156 + size_t filesz = 0; 1.157 + size_t memsz = 0; 1.158 + bool prev_was_nobits = false; 1.159 + for (int i = start; i <= end; ++i) { 1.160 + size_t size = sections_[i].size_; 1.161 + if (sections_[i].type_ != SHT_NOBITS) { 1.162 + assert(!prev_was_nobits); 1.163 + // non SHT_NOBITS sections are 4-byte aligned (see AddSection) 1.164 + size = (size + 3) & ~3; 1.165 + filesz += size; 1.166 + } else { 1.167 + prev_was_nobits = true; 1.168 + } 1.169 + memsz += size; 1.170 + } 1.171 + 1.172 + program_header_table_ 1.173 + // p_offset 1.174 + .Append(endianness(), addr_size_, sections_[start].offset_label_) 1.175 + // p_vaddr 1.176 + .Append(endianness(), addr_size_, sections_[start].addr_) 1.177 + // p_paddr 1.178 + .Append(endianness(), addr_size_, sections_[start].addr_) 1.179 + // p_filesz 1.180 + .Append(endianness(), addr_size_, filesz) 1.181 + // p_memsz 1.182 + .Append(endianness(), addr_size_, memsz); 1.183 + 1.184 + if (addr_size_ == 4) { 1.185 + // p_flags 1.186 + program_header_table_.D32(flags); 1.187 + } 1.188 + 1.189 + // p_align 1.190 + program_header_table_.Append(endianness(), addr_size_, 0); 1.191 +} 1.192 + 1.193 +void ELF::Finish() { 1.194 + // Add the section header string table at the end. 1.195 + section_header_string_index_ = section_count_; 1.196 + //printf(".shstrtab size: %ld\n", section_header_strings_.Size()); 1.197 + AddSection(".shstrtab", section_header_strings_, SHT_STRTAB); 1.198 + //printf("section_count_: %ld, sections_.size(): %ld\n", 1.199 + // section_count_, sections_.size()); 1.200 + if (program_count_) { 1.201 + Mark(&program_header_label_); 1.202 + Append(program_header_table_); 1.203 + } else { 1.204 + program_header_label_ = 0; 1.205 + } 1.206 + 1.207 + for (vector<ElfSection>::iterator it = sections_.begin(); 1.208 + it < sections_.end(); ++it) { 1.209 + AppendSection(*it); 1.210 + } 1.211 + section_count_label_ = section_count_; 1.212 + program_count_label_ = program_count_; 1.213 + 1.214 + // Section header table starts here. 1.215 + Mark(§ion_header_label_); 1.216 + Append(section_header_table_); 1.217 +} 1.218 + 1.219 +SymbolTable::SymbolTable(Endianness endianness, 1.220 + size_t addr_size, 1.221 + StringTable& table) : Section(endianness), 1.222 + addr_size_(addr_size), 1.223 + table_(table) { 1.224 + assert(addr_size_ == 4 || addr_size_ == 8); 1.225 +} 1.226 + 1.227 +void SymbolTable::AddSymbol(const string& name, uint32_t value, 1.228 + uint32_t size, unsigned info, uint16_t shndx) { 1.229 + assert(addr_size_ == 4); 1.230 + D32(table_.Add(name)); 1.231 + D32(value); 1.232 + D32(size); 1.233 + D8(info); 1.234 + D8(0); // other 1.235 + D16(shndx); 1.236 +} 1.237 + 1.238 +void SymbolTable::AddSymbol(const string& name, uint64_t value, 1.239 + uint64_t size, unsigned info, uint16_t shndx) { 1.240 + assert(addr_size_ == 8); 1.241 + D32(table_.Add(name)); 1.242 + D8(info); 1.243 + D8(0); // other 1.244 + D16(shndx); 1.245 + D64(value); 1.246 + D64(size); 1.247 +} 1.248 + 1.249 +void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes, 1.250 + size_t desc_size) { 1.251 + // Elf32_Nhdr and Elf64_Nhdr are exactly the same. 1.252 + Elf32_Nhdr note_header; 1.253 + memset(¬e_header, 0, sizeof(note_header)); 1.254 + note_header.n_namesz = name.length() + 1; 1.255 + note_header.n_descsz = desc_size; 1.256 + note_header.n_type = type; 1.257 + 1.258 + Append(reinterpret_cast<const uint8_t*>(¬e_header), 1.259 + sizeof(note_header)); 1.260 + AppendCString(name); 1.261 + Align(4); 1.262 + Append(desc_bytes, desc_size); 1.263 + Align(4); 1.264 +} 1.265 + 1.266 +} // namespace synth_elf 1.267 +} // namespace google_breakpad