PageRenderTime 33ms CodeModel.GetById 14ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/thirdparty/breakpad/common/linux/synth_elf.cc

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