toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 #include "common/linux/synth_elf.h"
     3 #include <assert.h>
     4 #include <elf.h>
     5 #include <stdio.h>
     6 #include <string.h>
     8 #include "common/using_std_string.h"
    10 namespace google_breakpad {
    11 namespace synth_elf {
    13 #ifndef NT_GNU_BUILD_ID
    14 #define NT_GNU_BUILD_ID 3
    15 #endif
    17 ELF::ELF(uint16_t machine,
    18          uint8_t file_class,
    19          Endianness endianness)
    20   : Section(endianness),
    21     addr_size_(file_class == ELFCLASS64 ? 8 : 4),
    22     program_count_(0),
    23     program_header_table_(endianness),
    24     section_count_(0),
    25     section_header_table_(endianness),
    26     section_header_strings_(endianness) {
    27   // Could add support for more machine types here if needed.
    28   assert(machine == EM_386 ||
    29          machine == EM_X86_64 ||
    30          machine == EM_ARM);
    31   assert(file_class == ELFCLASS32 || file_class == ELFCLASS64);
    33   start() = 0;
    34   // Add ELF header
    35   // e_ident
    36   // EI_MAG0...EI_MAG3
    37   D8(ELFMAG0);
    38   D8(ELFMAG1);
    39   D8(ELFMAG2);
    40   D8(ELFMAG3);
    41   // EI_CLASS
    42   D8(file_class);
    43   // EI_DATA
    44   D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB);
    45   // EI_VERSION
    46   D8(EV_CURRENT);
    47   // EI_OSABI
    48   D8(ELFOSABI_SYSV);
    49   // EI_ABIVERSION
    50   D8(0);
    51   // EI_PAD
    52   Append(7, 0);
    53   assert(Size() == EI_NIDENT);
    55   // e_type
    56   D16(ET_EXEC);  //TODO: allow passing ET_DYN?
    57   // e_machine
    58   D16(machine);
    59   // e_version
    60   D32(EV_CURRENT);
    61   // e_entry
    62   Append(endianness, addr_size_, 0);
    63   // e_phoff
    64   Append(endianness, addr_size_, program_header_label_);
    65   // e_shoff
    66   Append(endianness, addr_size_, section_header_label_);
    67   // e_flags
    68   D32(0);
    69   // e_ehsize
    70   D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr));
    71   // e_phentsize
    72   D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr));
    73   // e_phnum
    74   D16(program_count_label_);
    75   // e_shentsize
    76   D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr));
    77   // e_shnum
    78   D16(section_count_label_);
    79   // e_shstrndx
    80   D16(section_header_string_index_);
    82   // Add an empty section for SHN_UNDEF.
    83   Section shn_undef;
    84   AddSection("", shn_undef, SHT_NULL);
    85 }
    87 int ELF::AddSection(const string& name, const Section& section,
    88                     uint32_t type, uint32_t flags, uint64_t addr,
    89                     uint32_t link, uint64_t entsize, uint64_t offset) {
    90   Label offset_label;
    91   Label string_label(section_header_strings_.Add(name));
    92   size_t size = section.Size();
    94   int index = section_count_;
    95   ++section_count_;
    97   section_header_table_
    98     // sh_name
    99     .D32(string_label)
   100     // sh_type
   101     .D32(type)
   102     // sh_flags
   103     .Append(endianness(), addr_size_, flags)
   104     // sh_addr
   105     .Append(endianness(), addr_size_, addr)
   106     // sh_offset
   107     .Append(endianness(), addr_size_, offset_label)
   108     // sh_size
   109     .Append(endianness(), addr_size_, size)
   110     // sh_link
   111     .D32(link)
   112     // sh_info
   113     .D32(0)
   114     // sh_addralign
   115     .Append(endianness(), addr_size_, 0)
   116     // sh_entsize
   117     .Append(endianness(), addr_size_, entsize);
   119   sections_.push_back(ElfSection(section, type, addr, offset, offset_label,
   120                                  size));
   121   return index;
   122 }
   124 void ELF::AppendSection(ElfSection &section) {
   125   // NULL and NOBITS sections have no content, so they
   126   // don't need to be written to the file.
   127   if (section.type_ == SHT_NULL) {
   128     section.offset_label_ = 0;
   129   } else if (section.type_ == SHT_NOBITS) {
   130     section.offset_label_ = section.offset_;
   131   } else {
   132     Mark(&section.offset_label_);
   133     Append(section);
   134     Align(4);
   135   }
   136 }
   138 void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) {
   139   assert(start > 0);
   140   assert(size_t(start) < sections_.size());
   141   assert(end > 0);
   142   assert(size_t(end) < sections_.size());
   143   ++program_count_;
   145   // p_type
   146   program_header_table_.D32(type);
   148   if (addr_size_ == 8) {
   149     // p_flags
   150     program_header_table_.D32(flags);
   151   }
   153   size_t filesz = 0;
   154   size_t memsz = 0;
   155   bool prev_was_nobits = false;
   156   for (int i = start; i <= end; ++i) {
   157     size_t size = sections_[i].size_;
   158     if (sections_[i].type_ != SHT_NOBITS) {
   159       assert(!prev_was_nobits);
   160       // non SHT_NOBITS sections are 4-byte aligned (see AddSection)
   161       size = (size + 3) & ~3;
   162       filesz += size;
   163     } else {
   164       prev_was_nobits = true;
   165     }
   166     memsz += size;
   167   }
   169   program_header_table_
   170     // p_offset
   171     .Append(endianness(), addr_size_, sections_[start].offset_label_)
   172     // p_vaddr
   173     .Append(endianness(), addr_size_, sections_[start].addr_)
   174     // p_paddr
   175     .Append(endianness(), addr_size_, sections_[start].addr_)
   176     // p_filesz
   177     .Append(endianness(), addr_size_, filesz)
   178     // p_memsz
   179     .Append(endianness(), addr_size_, memsz);
   181   if (addr_size_ == 4) {
   182     // p_flags
   183     program_header_table_.D32(flags);
   184   }
   186   // p_align
   187   program_header_table_.Append(endianness(), addr_size_, 0);
   188 }
   190 void ELF::Finish() {
   191   // Add the section header string table at the end.
   192   section_header_string_index_ = section_count_;
   193   //printf(".shstrtab size: %ld\n", section_header_strings_.Size());
   194   AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
   195   //printf("section_count_: %ld, sections_.size(): %ld\n",
   196   //     section_count_, sections_.size());
   197   if (program_count_) {
   198     Mark(&program_header_label_);
   199     Append(program_header_table_);
   200   } else {
   201     program_header_label_ = 0;
   202   }
   204   for (vector<ElfSection>::iterator it = sections_.begin();
   205        it < sections_.end(); ++it) {
   206     AppendSection(*it);
   207   }
   208   section_count_label_ = section_count_;
   209   program_count_label_ = program_count_;
   211   // Section header table starts here.
   212   Mark(&section_header_label_);
   213   Append(section_header_table_);
   214 }
   216 SymbolTable::SymbolTable(Endianness endianness,
   217                          size_t addr_size,
   218                          StringTable& table) : Section(endianness),
   219                                                addr_size_(addr_size),
   220                                                table_(table) {
   221   assert(addr_size_ == 4 || addr_size_ == 8);
   222 }
   224 void SymbolTable::AddSymbol(const string& name, uint32_t value,
   225                             uint32_t size, unsigned info, uint16_t shndx) {
   226   assert(addr_size_ == 4);
   227   D32(table_.Add(name));
   228   D32(value);
   229   D32(size);
   230   D8(info);
   231   D8(0); // other
   232   D16(shndx);
   233 }
   235 void SymbolTable::AddSymbol(const string& name, uint64_t value,
   236                             uint64_t size, unsigned info, uint16_t shndx) {
   237   assert(addr_size_ == 8);
   238   D32(table_.Add(name));
   239   D8(info);
   240   D8(0); // other
   241   D16(shndx);
   242   D64(value);
   243   D64(size);
   244 }
   246 void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes,
   247                     size_t desc_size) {
   248   // Elf32_Nhdr and Elf64_Nhdr are exactly the same.
   249   Elf32_Nhdr note_header;
   250   memset(&note_header, 0, sizeof(note_header));
   251   note_header.n_namesz = name.length() + 1;
   252   note_header.n_descsz = desc_size;
   253   note_header.n_type = type;
   255   Append(reinterpret_cast<const uint8_t*>(&note_header),
   256          sizeof(note_header));
   257   AppendCString(name);
   258   Align(4);
   259   Append(desc_bytes, desc_size);
   260   Align(4);
   261 }
   263 }  // namespace synth_elf
   264 }  // namespace google_breakpad

mercurial