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