tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

elf.cpp (31926B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #undef NDEBUG
      6 #include <cstring>
      7 #include <assert.h>
      8 #include "elfxx.h"
      9 
     10 template <class endian, typename R, typename T>
     11 void Elf_Ehdr_Traits::swap(T& t, R& r) {
     12  memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident));
     13  r.e_type = endian::swap(t.e_type);
     14  r.e_machine = endian::swap(t.e_machine);
     15  r.e_version = endian::swap(t.e_version);
     16  r.e_entry = endian::swap(t.e_entry);
     17  r.e_phoff = endian::swap(t.e_phoff);
     18  r.e_shoff = endian::swap(t.e_shoff);
     19  r.e_flags = endian::swap(t.e_flags);
     20  r.e_ehsize = endian::swap(t.e_ehsize);
     21  r.e_phentsize = endian::swap(t.e_phentsize);
     22  r.e_phnum = endian::swap(t.e_phnum);
     23  r.e_shentsize = endian::swap(t.e_shentsize);
     24  r.e_shnum = endian::swap(t.e_shnum);
     25  r.e_shstrndx = endian::swap(t.e_shstrndx);
     26 }
     27 
     28 template <class endian, typename R, typename T>
     29 void Elf_Phdr_Traits::swap(T& t, R& r) {
     30  r.p_type = endian::swap(t.p_type);
     31  r.p_offset = endian::swap(t.p_offset);
     32  r.p_vaddr = endian::swap(t.p_vaddr);
     33  r.p_paddr = endian::swap(t.p_paddr);
     34  r.p_filesz = endian::swap(t.p_filesz);
     35  r.p_memsz = endian::swap(t.p_memsz);
     36  r.p_flags = endian::swap(t.p_flags);
     37  r.p_align = endian::swap(t.p_align);
     38 }
     39 
     40 template <class endian, typename R, typename T>
     41 void Elf_Shdr_Traits::swap(T& t, R& r) {
     42  r.sh_name = endian::swap(t.sh_name);
     43  r.sh_type = endian::swap(t.sh_type);
     44  r.sh_flags = endian::swap(t.sh_flags);
     45  r.sh_addr = endian::swap(t.sh_addr);
     46  r.sh_offset = endian::swap(t.sh_offset);
     47  r.sh_size = endian::swap(t.sh_size);
     48  r.sh_link = endian::swap(t.sh_link);
     49  r.sh_info = endian::swap(t.sh_info);
     50  r.sh_addralign = endian::swap(t.sh_addralign);
     51  r.sh_entsize = endian::swap(t.sh_entsize);
     52 }
     53 
     54 template <class endian, typename R, typename T>
     55 void Elf_Dyn_Traits::swap(T& t, R& r) {
     56  r.d_tag = endian::swap(t.d_tag);
     57  r.d_un.d_val = endian::swap(t.d_un.d_val);
     58 }
     59 
     60 template <class endian, typename R, typename T>
     61 void Elf_Sym_Traits::swap(T& t, R& r) {
     62  r.st_name = endian::swap(t.st_name);
     63  r.st_value = endian::swap(t.st_value);
     64  r.st_size = endian::swap(t.st_size);
     65  r.st_info = t.st_info;
     66  r.st_other = t.st_other;
     67  r.st_shndx = endian::swap(t.st_shndx);
     68 }
     69 
     70 template <class endian>
     71 struct _Rel_info {
     72  static inline void swap(Elf32_Word& t, Elf32_Word& r) { r = endian::swap(t); }
     73  static inline void swap(Elf64_Xword& t, Elf64_Xword& r) {
     74    r = endian::swap(t);
     75  }
     76  static inline void swap(Elf64_Xword& t, Elf32_Word& r) {
     77    r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t)));
     78  }
     79  static inline void swap(Elf32_Word& t, Elf64_Xword& r) {
     80    r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t)));
     81  }
     82 };
     83 
     84 template <class endian, typename R, typename T>
     85 void Elf_Rel_Traits::swap(T& t, R& r) {
     86  r.r_offset = endian::swap(t.r_offset);
     87  _Rel_info<endian>::swap(t.r_info, r.r_info);
     88 }
     89 
     90 template <class endian, typename R, typename T>
     91 void Elf_Rela_Traits::swap(T& t, R& r) {
     92  r.r_offset = endian::swap(t.r_offset);
     93  _Rel_info<endian>::swap(t.r_info, r.r_info);
     94  r.r_addend = endian::swap(t.r_addend);
     95 }
     96 
     97 static const Elf64_Shdr null64_section = {0, SHT_NULL,  0, 0, 0,
     98                                          0, SHN_UNDEF, 0, 0, 0};
     99 
    100 Elf_Shdr null_section(null64_section);
    101 
    102 Elf_Ehdr::Elf_Ehdr(std::ifstream& file, unsigned char ei_class,
    103                   unsigned char ei_data)
    104    : serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data),
    105      ElfSection(null_section, nullptr, nullptr) {
    106  shdr.sh_size = Elf_Ehdr::size(ei_class);
    107 }
    108 
    109 Elf::Elf(std::ifstream& file) {
    110  if (!file.is_open()) throw std::runtime_error("Error opening file");
    111 
    112  file.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
    113                  std::ifstream::badbit);
    114  // Read ELF magic number and identification information
    115  unsigned char e_ident[EI_VERSION];
    116  file.seekg(0);
    117  file.read((char*)e_ident, sizeof(e_ident));
    118  file.seekg(0);
    119  ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
    120 
    121  // ELFOSABI_LINUX is kept unsupported because I haven't looked whether
    122  // STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing.
    123  if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) &&
    124      (ehdr->e_ident[EI_ABIVERSION] != 0))
    125    throw std::runtime_error("unsupported ELF ABI");
    126 
    127  if (ehdr->e_version != 1) throw std::runtime_error("unsupported ELF version");
    128 
    129  // Sanity checks
    130  if (ehdr->e_shnum == 0)
    131    throw std::runtime_error("sstripped ELF files aren't supported");
    132 
    133  if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS]))
    134    throw std::runtime_error(
    135        "unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)");
    136 
    137  if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS]))
    138    throw std::runtime_error(
    139        "unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)");
    140 
    141  if (ehdr->e_phnum == 0) {
    142    if (ehdr->e_phoff != 0)
    143      throw std::runtime_error(
    144          "unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0");
    145    if (ehdr->e_phentsize != 0)
    146      throw std::runtime_error(
    147          "unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0");
    148  } else if (ehdr->e_phoff != ehdr->e_ehsize)
    149    throw std::runtime_error(
    150        "unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize");
    151  else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS]))
    152    throw std::runtime_error(
    153        "unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)");
    154 
    155  // Read section headers
    156  Elf_Shdr** shdr = new Elf_Shdr*[ehdr->e_shnum];
    157  file.seekg(ehdr->e_shoff);
    158  for (int i = 0; i < ehdr->e_shnum; i++)
    159    shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
    160 
    161  // Sanity check in section header for index 0
    162  if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) ||
    163      (shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) ||
    164      (shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) ||
    165      (shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) ||
    166      (shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0))
    167    throw std::runtime_error(
    168        "Section header for index 0 contains unsupported values");
    169 
    170  if ((shdr[ehdr->e_shstrndx]->sh_link != 0) ||
    171      (shdr[ehdr->e_shstrndx]->sh_info != 0))
    172    throw std::runtime_error(
    173        "unsupported ELF content: string table with sh_link != 0 || sh_info != "
    174        "0");
    175 
    176  // Store these temporarily
    177  tmp_shdr = shdr;
    178  tmp_file = &file;
    179 
    180  // Fill sections list
    181  sections = new ElfSection*[ehdr->e_shnum];
    182  for (int i = 0; i < ehdr->e_shnum; i++) sections[i] = nullptr;
    183  for (int i = 1; i < ehdr->e_shnum; i++) {
    184    // The .dynamic section is going to have references to other sections,
    185    // so it's better to start with that one and recursively initialize those
    186    // other sections first, to avoid possible infinite recursion (bug 1606739).
    187    if (tmp_shdr[i]->sh_type == SHT_DYNAMIC) {
    188      getSection(i);
    189    }
    190  }
    191  for (int i = 1; i < ehdr->e_shnum; i++) {
    192    if (sections[i] != nullptr) continue;
    193    getSection(i);
    194  }
    195  Elf_Shdr s;
    196  s.sh_name = 0;
    197  s.sh_type = SHT_NULL;
    198  s.sh_flags = 0;
    199  s.sh_addr = 0;
    200  s.sh_offset = ehdr->e_shoff;
    201  s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]);
    202  s.sh_size = s.sh_entsize * ehdr->e_shnum;
    203  s.sh_link = 0;
    204  s.sh_info = 0;
    205  s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
    206  shdr_section = new ElfSection(s, nullptr, nullptr);
    207 
    208  // Fake section for program headers
    209  s.sh_offset = ehdr->e_phoff;
    210  s.sh_addr = ehdr->e_phoff;
    211  s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]);
    212  s.sh_size = s.sh_entsize * ehdr->e_phnum;
    213  phdr_section = new ElfSection(s, nullptr, nullptr);
    214 
    215  phdr_section->insertAfter(ehdr, false);
    216 
    217  sections[1]->insertAfter(phdr_section, false);
    218  for (int i = 2; i < ehdr->e_shnum; i++) {
    219    // TODO: this should be done in a better way
    220    if ((shdr_section->getPrevious() == nullptr) &&
    221        (shdr[i]->sh_offset > ehdr->e_shoff)) {
    222      shdr_section->insertAfter(sections[i - 1], false);
    223      sections[i]->insertAfter(shdr_section, false);
    224    } else
    225      sections[i]->insertAfter(sections[i - 1], false);
    226  }
    227  if (shdr_section->getPrevious() == nullptr)
    228    shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false);
    229 
    230  tmp_file = nullptr;
    231  tmp_shdr = nullptr;
    232  for (int i = 0; i < ehdr->e_shnum; i++) delete shdr[i];
    233  delete[] shdr;
    234 
    235  eh_shstrndx = (ElfStrtab_Section*)sections[ehdr->e_shstrndx];
    236 
    237  // Skip reading program headers if there aren't any
    238  if (ehdr->e_phnum == 0) return;
    239 
    240  bool adjusted_phdr_section = false;
    241  // Read program headers
    242  file.seekg(ehdr->e_phoff);
    243  for (int i = 0; i < ehdr->e_phnum; i++) {
    244    Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
    245    if (phdr.p_type == PT_LOAD) {
    246      // Default alignment for PT_LOAD on x86-64 prevents elfhack from
    247      // doing anything useful. However, the system doesn't actually
    248      // require such a big alignment, so in order for elfhack to work
    249      // efficiently, reduce alignment when it's originally the default
    250      // one.
    251      if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000))
    252        phdr.p_align = 0x1000;
    253    }
    254    ElfSegment* segment = new ElfSegment(&phdr);
    255    // Some segments aren't entirely filled (if at all) by sections
    256    // For those, we use fake sections
    257    if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) {
    258      // Use a fake section for ehdr and phdr
    259      ehdr->getShdr().sh_addr = phdr.p_vaddr;
    260      if (!adjusted_phdr_section) {
    261        phdr_section->getShdr().sh_addr += phdr.p_vaddr;
    262        adjusted_phdr_section = true;
    263      }
    264      segment->addSection(ehdr);
    265      segment->addSection(phdr_section);
    266    }
    267    if (phdr.p_type == PT_PHDR) {
    268      if (!adjusted_phdr_section) {
    269        phdr_section->getShdr().sh_addr = phdr.p_vaddr;
    270        adjusted_phdr_section = true;
    271      }
    272      segment->addSection(phdr_section);
    273    }
    274    for (int j = 1; j < ehdr->e_shnum; j++)
    275      if (phdr.contains(sections[j])) segment->addSection(sections[j]);
    276    // Make sure that our view of segments corresponds to the original
    277    // ELF file.
    278    // GNU gold likes to start some segments before the first section
    279    // they contain. https://sourceware.org/bugzilla/show_bug.cgi?id=19392
    280    unsigned int gold_adjustment = segment->getAddr() - phdr.p_vaddr;
    281    assert(segment->getFileSize() == phdr.p_filesz - gold_adjustment);
    282    // gold makes TLS segments end on an aligned virtual address, even
    283    // when the underlying section ends before that, while bfd ld
    284    // doesn't. It's fine if we don't keep that alignment.
    285    unsigned int memsize = segment->getMemSize();
    286    if (phdr.p_type == PT_TLS && memsize != phdr.p_memsz) {
    287      unsigned int align = segment->getAlign();
    288      memsize = (memsize + align - 1) & ~(align - 1);
    289    }
    290    assert(memsize == phdr.p_memsz - gold_adjustment);
    291    segments.push_back(segment);
    292  }
    293 
    294  new (&eh_entry) ElfLocation(ehdr->e_entry, this);
    295 }
    296 
    297 Elf::~Elf() {
    298  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    299       seg != segments.end(); seg++)
    300    delete *seg;
    301  delete[] sections;
    302  ElfSection* section = ehdr;
    303  while (section != nullptr) {
    304    ElfSection* next = section->getNext();
    305    delete section;
    306    section = next;
    307  }
    308 }
    309 
    310 // TODO: This shouldn't fail after inserting sections
    311 ElfSection* Elf::getSection(int index) {
    312  if ((index < -1) || (index >= ehdr->e_shnum))
    313    throw std::runtime_error("Section index out of bounds");
    314  if (index == -1)
    315    index = ehdr->e_shstrndx;  // TODO: should be fixed to use the actual
    316                               // current number
    317  // Special case: the section at index 0 is void
    318  if (index == 0) return nullptr;
    319  // Infinite recursion guard
    320  if (sections[index] == (ElfSection*)this) return nullptr;
    321  if (sections[index] == nullptr) {
    322    sections[index] = (ElfSection*)this;
    323    switch (tmp_shdr[index]->sh_type) {
    324      case SHT_DYNAMIC:
    325        sections[index] =
    326            new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this);
    327        break;
    328      case SHT_REL:
    329        sections[index] =
    330            new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this);
    331        break;
    332      case SHT_RELA:
    333        sections[index] =
    334            new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this);
    335        break;
    336      case SHT_DYNSYM:
    337      case SHT_SYMTAB:
    338        sections[index] =
    339            new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this);
    340        break;
    341      case SHT_STRTAB:
    342        sections[index] =
    343            new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this);
    344        break;
    345      default:
    346        sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
    347    }
    348  }
    349  return sections[index];
    350 }
    351 
    352 ElfSection* Elf::getSectionAt(Elf64_Off offset) {
    353  for (int i = 1; i < ehdr->e_shnum; i++) {
    354    ElfSection* section = getSection(i);
    355    if ((section != nullptr) && (section->getFlags() & SHF_ALLOC) &&
    356        !(section->getFlags() & SHF_TLS) && (offset >= section->getAddr()) &&
    357        (offset < section->getAddr() + section->getSize()))
    358      return section;
    359  }
    360  return nullptr;
    361 }
    362 
    363 ElfSegment* Elf::getSegmentByType(unsigned int type, ElfSegment* last) {
    364  std::vector<ElfSegment*>::iterator seg;
    365  if (last) {
    366    seg = std::find(segments.begin(), segments.end(), last);
    367    ++seg;
    368  } else
    369    seg = segments.begin();
    370  for (; seg != segments.end(); seg++)
    371    if ((*seg)->getType() == type) return *seg;
    372  return nullptr;
    373 }
    374 
    375 void Elf::removeSegment(ElfSegment* segment) {
    376  if (!segment) return;
    377  std::vector<ElfSegment*>::iterator seg;
    378  seg = std::find(segments.begin(), segments.end(), segment);
    379  if (seg == segments.end()) return;
    380  segment->clear();
    381  segments.erase(seg);
    382 }
    383 
    384 ElfDynamic_Section* Elf::getDynSection() {
    385  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    386       seg != segments.end(); seg++)
    387    if (((*seg)->getType() == PT_DYNAMIC) &&
    388        ((*seg)->getFirstSection() != nullptr) &&
    389        (*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
    390      return (ElfDynamic_Section*)(*seg)->getFirstSection();
    391 
    392  return nullptr;
    393 }
    394 
    395 void Elf::normalize() {
    396  // fixup section headers sh_name; TODO: that should be done by sections
    397  // themselves
    398  for (ElfSection* section = ehdr; section != nullptr;
    399       section = section->getNext()) {
    400    if (section->getIndex() == 0)
    401      continue;
    402    else
    403      ehdr->e_shnum = section->getIndex() + 1;
    404    section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
    405  }
    406  ehdr->markDirty();
    407  // Check segments consistency
    408  int i = 0;
    409  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    410       seg != segments.end(); seg++, i++) {
    411    std::list<ElfSection*>::iterator it = (*seg)->begin();
    412    for (ElfSection* last = *(it++); it != (*seg)->end(); last = *(it++)) {
    413      if (((*it)->getType() != SHT_NOBITS) &&
    414          ((*it)->getAddr() - last->getAddr()) !=
    415              ((*it)->getOffset() - last->getOffset())) {
    416        throw std::runtime_error("Segments inconsistency");
    417      }
    418    }
    419  }
    420 
    421  ElfSegment* prevLoad = nullptr;
    422  for (auto& it : segments) {
    423    if (it->getType() == PT_LOAD) {
    424      if (prevLoad) {
    425        size_t alignedPrevEnd = (prevLoad->getAddr() + prevLoad->getMemSize() +
    426                                 prevLoad->getAlign() - 1) &
    427                                ~(prevLoad->getAlign() - 1);
    428        size_t alignedStart = it->getAddr() & ~(it->getAlign() - 1);
    429        if (alignedPrevEnd > alignedStart) {
    430          throw std::runtime_error("Segments overlap");
    431        }
    432      }
    433      prevLoad = it;
    434    }
    435  }
    436 
    437  // fixup ehdr before writing
    438  if (ehdr->e_phnum != segments.size()) {
    439    ehdr->e_phnum = segments.size();
    440    phdr_section->getShdr().sh_size =
    441        segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
    442    phdr_section->getNext()->markDirty();
    443  }
    444  // fixup shdr before writing
    445  if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize())
    446    shdr_section->getShdr().sh_size =
    447        ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]);
    448  ehdr->e_shoff = shdr_section->getOffset();
    449  ehdr->e_entry = eh_entry.getValue();
    450  ehdr->e_shstrndx = eh_shstrndx->getIndex();
    451 
    452  // Check sections consistency
    453  unsigned int minOffset = 0;
    454  for (ElfSection* section = ehdr; section != nullptr;
    455       section = section->getNext()) {
    456    unsigned int offset = section->getOffset();
    457    if (offset < minOffset) {
    458      throw std::runtime_error("Sections overlap");
    459    }
    460    if (section->getType() != SHT_NOBITS) {
    461      minOffset = offset + section->getSize();
    462    }
    463  }
    464 }
    465 
    466 void Elf::write(std::ofstream& file) {
    467  normalize();
    468  for (ElfSection* section = ehdr; section != nullptr;
    469       section = section->getNext()) {
    470    file.seekp(section->getOffset());
    471    if (section == phdr_section) {
    472      for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    473           seg != segments.end(); seg++) {
    474        Elf_Phdr phdr;
    475        phdr.p_type = (*seg)->getType();
    476        phdr.p_flags = (*seg)->getFlags();
    477        phdr.p_offset = (*seg)->getOffset();
    478        phdr.p_vaddr = (*seg)->getAddr();
    479        phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff();
    480        phdr.p_filesz = (*seg)->getFileSize();
    481        phdr.p_memsz = (*seg)->getMemSize();
    482        phdr.p_align = (*seg)->getAlign();
    483        phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
    484      }
    485    } else if (section == shdr_section) {
    486      null_section.serialize(file, ehdr->e_ident[EI_CLASS],
    487                             ehdr->e_ident[EI_DATA]);
    488      for (ElfSection* sec = ehdr; sec != nullptr; sec = sec->getNext()) {
    489        if (sec->getType() != SHT_NULL)
    490          sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS],
    491                                   ehdr->e_ident[EI_DATA]);
    492      }
    493    } else
    494      section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
    495  }
    496 }
    497 
    498 ElfSection::ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent)
    499    : shdr(s),
    500      link(shdr.sh_link == SHN_UNDEF ? nullptr
    501                                     : parent->getSection(shdr.sh_link)),
    502      next(nullptr),
    503      previous(nullptr),
    504      index(-1) {
    505  if ((file == nullptr) || (shdr.sh_type == SHT_NULL) ||
    506      (shdr.sh_type == SHT_NOBITS))
    507    data = nullptr;
    508  else {
    509    data = static_cast<char*>(malloc(shdr.sh_size));
    510    if (!data) {
    511      throw std::runtime_error("Could not malloc ElfSection data");
    512    }
    513    auto pos = file->tellg();
    514    file->seekg(shdr.sh_offset);
    515    file->read(data, shdr.sh_size);
    516    file->seekg(pos);
    517  }
    518  if (shdr.sh_name == 0)
    519    name = nullptr;
    520  else {
    521    ElfStrtab_Section* strtab = (ElfStrtab_Section*)parent->getSection(-1);
    522    // Special case (see elfgeneric.cpp): if strtab is nullptr, the
    523    // section being created is the strtab.
    524    if (strtab == nullptr)
    525      name = &data[shdr.sh_name];
    526    else
    527      name = strtab->getStr(shdr.sh_name);
    528  }
    529  // Only SHT_REL/SHT_RELA sections use sh_info to store a section
    530  // number.
    531  if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
    532    info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : nullptr;
    533  else
    534    info.index = shdr.sh_info;
    535 }
    536 
    537 Elf64_Addr ElfSection::getAddr() {
    538  if (shdr.sh_addr != (Elf64_Addr)-1) return shdr.sh_addr;
    539 
    540  // It should be safe to adjust sh_addr for all allocated sections that
    541  // are neither SHT_NOBITS nor SHT_PROGBITS
    542  if ((previous != nullptr) && isRelocatable()) {
    543    unsigned int addr = previous->getAddr();
    544    if (previous->getType() != SHT_NOBITS) addr += previous->getSize();
    545 
    546    if (addr & (getAddrAlign() - 1)) addr = (addr | (getAddrAlign() - 1)) + 1;
    547 
    548    return (shdr.sh_addr = addr);
    549  }
    550  return shdr.sh_addr;
    551 }
    552 
    553 Elf64_Off ElfSection::getOffset() {
    554  if (shdr.sh_offset != (Elf64_Off)-1) return shdr.sh_offset;
    555 
    556  if (previous == nullptr) return (shdr.sh_offset = 0);
    557 
    558  Elf64_Off offset = previous->getOffset();
    559 
    560  ElfSegment* ptload = getSegmentByType(PT_LOAD);
    561  ElfSegment* prev_ptload = previous->getSegmentByType(PT_LOAD);
    562 
    563  if (ptload && (ptload == prev_ptload)) {
    564    offset += getAddr() - previous->getAddr();
    565    return (shdr.sh_offset = offset);
    566  }
    567 
    568  if (previous->getType() != SHT_NOBITS) offset += previous->getSize();
    569 
    570  Elf32_Word align = 0x1000;
    571  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    572       seg != segments.end(); seg++)
    573    align = std::max(align, (*seg)->getAlign());
    574 
    575  Elf32_Word mask = align - 1;
    576  // SHF_TLS is used for .tbss which is some kind of special case.
    577  if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) &&
    578      (getFlags() & SHF_ALLOC)) {
    579    if ((getAddr() & mask) < (offset & mask))
    580      offset = (offset | mask) + (getAddr() & mask) + 1;
    581    else
    582      offset = (offset & ~mask) + (getAddr() & mask);
    583  }
    584  if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
    585    offset = (offset | (getAddrAlign() - 1)) + 1;
    586 
    587  return (shdr.sh_offset = offset);
    588 }
    589 
    590 int ElfSection::getIndex() {
    591  if (index != -1) return index;
    592  if (getType() == SHT_NULL) return (index = 0);
    593  ElfSection* reference;
    594  for (reference = previous;
    595       (reference != nullptr) && (reference->getType() == SHT_NULL);
    596       reference = reference->getPrevious());
    597  if (reference == nullptr) return (index = 1);
    598  return (index = reference->getIndex() + 1);
    599 }
    600 
    601 Elf_Shdr& ElfSection::getShdr() {
    602  getOffset();
    603  if (shdr.sh_link == (Elf64_Word)-1)
    604    shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
    605  if (shdr.sh_info == (Elf64_Word)-1)
    606    shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA))
    607                       ? (getInfo().section ? getInfo().section->getIndex() : 0)
    608                       : getInfo().index;
    609 
    610  return shdr;
    611 }
    612 
    613 ElfSegment::ElfSegment(Elf_Phdr* phdr)
    614    : type(phdr->p_type),
    615      v_p_diff(phdr->p_paddr - phdr->p_vaddr),
    616      flags(phdr->p_flags),
    617      align(phdr->p_align),
    618      vaddr(phdr->p_vaddr),
    619      filesz(phdr->p_filesz),
    620      memsz(phdr->p_memsz) {}
    621 
    622 void ElfSegment::addSection(ElfSection* section) {
    623  // Make sure all sections in PT_GNU_RELRO won't be moved by elfhack
    624  assert(!((type == PT_GNU_RELRO) && (section->isRelocatable())));
    625 
    626  // TODO: Check overlapping sections
    627  std::list<ElfSection*>::iterator i;
    628  for (i = sections.begin(); i != sections.end(); ++i)
    629    if ((*i)->getAddr() > section->getAddr()) break;
    630  sections.insert(i, section);
    631  section->addToSegment(this);
    632 }
    633 
    634 void ElfSegment::removeSection(ElfSection* section) {
    635  sections.remove(section);
    636  section->removeFromSegment(this);
    637 }
    638 
    639 unsigned int ElfSegment::getFileSize() {
    640  if (type == PT_GNU_RELRO) return filesz;
    641 
    642  if (sections.empty()) return 0;
    643  // Search the last section that is not SHT_NOBITS
    644  std::list<ElfSection*>::reverse_iterator i;
    645  for (i = sections.rbegin();
    646       (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i);
    647  // All sections are SHT_NOBITS
    648  if (i == sections.rend()) return 0;
    649 
    650  unsigned int end = (*i)->getAddr() + (*i)->getSize();
    651 
    652  return end - sections.front()->getAddr();
    653 }
    654 
    655 unsigned int ElfSegment::getMemSize() {
    656  if (type == PT_GNU_RELRO) return memsz;
    657 
    658  if (sections.empty()) return 0;
    659 
    660  unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
    661 
    662  return end - sections.front()->getAddr();
    663 }
    664 
    665 unsigned int ElfSegment::getOffset() {
    666  if ((type == PT_GNU_RELRO) && !sections.empty() &&
    667      (sections.front()->getAddr() != vaddr))
    668    throw std::runtime_error(
    669        "PT_GNU_RELRO segment doesn't start on a section start");
    670 
    671  return sections.empty() ? 0 : sections.front()->getOffset();
    672 }
    673 
    674 unsigned int ElfSegment::getAddr() {
    675  if ((type == PT_GNU_RELRO) && !sections.empty() &&
    676      (sections.front()->getAddr() != vaddr))
    677    throw std::runtime_error(
    678        "PT_GNU_RELRO segment doesn't start on a section start");
    679 
    680  return sections.empty() ? 0 : sections.front()->getAddr();
    681 }
    682 
    683 void ElfSegment::clear() {
    684  for (std::list<ElfSection*>::iterator i = sections.begin();
    685       i != sections.end(); ++i)
    686    (*i)->removeFromSegment(this);
    687  sections.clear();
    688 }
    689 
    690 ElfValue* ElfDynamic_Section::getValueForType(unsigned int tag) {
    691  for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
    692    if (dyns[i].tag == tag) return dyns[i].value;
    693 
    694  return nullptr;
    695 }
    696 
    697 ElfSection* ElfDynamic_Section::getSectionForType(unsigned int tag) {
    698  ElfValue* value = getValueForType(tag);
    699  return value ? value->getSection() : nullptr;
    700 }
    701 
    702 bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue* val) {
    703  unsigned int i;
    704  unsigned int shnum = shdr.sh_size / shdr.sh_entsize;
    705  for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++)
    706    if (dyns[i].tag == tag) {
    707      delete dyns[i].value;
    708      dyns[i].value = val;
    709      return true;
    710    }
    711  // If we get here, this means we didn't match for the given tag
    712  // Most of the time, there are a few DT_NULL entries, that we can
    713  // use to add our value, but if we are on the last entry, we can't.
    714  if (i >= shnum - 1) return false;
    715 
    716  dyns[i].tag = tag;
    717  dyns[i].value = val;
    718  return true;
    719 }
    720 
    721 ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file,
    722                                       Elf* parent)
    723    : ElfSection(s, file, parent) {
    724  auto pos = file->tellg();
    725  dyns.resize(s.sh_size / s.sh_entsize);
    726  file->seekg(shdr.sh_offset);
    727  // Here we assume tags refer to only one section (e.g. DT_RELSZ accounts
    728  // for .rel.dyn size)
    729  for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
    730    Elf_Dyn dyn(*file, parent->getClass(), parent->getData());
    731    dyns[i].tag = dyn.d_tag;
    732    switch (dyn.d_tag) {
    733      case DT_NULL:
    734      case DT_SYMBOLIC:
    735      case DT_TEXTREL:
    736      case DT_BIND_NOW:
    737        dyns[i].value = new ElfValue();
    738        break;
    739      case DT_NEEDED:
    740      case DT_SONAME:
    741      case DT_RPATH:
    742      case DT_PLTREL:
    743      case DT_RUNPATH:
    744      case DT_FLAGS:
    745      case DT_RELACOUNT:
    746      case DT_RELCOUNT:
    747      case DT_VERDEFNUM:
    748      case DT_VERNEEDNUM:
    749        dyns[i].value = new ElfPlainValue(dyn.d_un.d_val);
    750        break;
    751      case DT_PLTGOT:
    752      case DT_HASH:
    753      case DT_STRTAB:
    754      case DT_SYMTAB:
    755      case DT_RELA:
    756      case DT_INIT:
    757      case DT_FINI:
    758      case DT_REL:
    759      case DT_JMPREL:
    760      case DT_INIT_ARRAY:
    761      case DT_FINI_ARRAY:
    762      case DT_GNU_HASH:
    763      case DT_VERSYM:
    764      case DT_VERNEED:
    765      case DT_VERDEF:
    766        dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent);
    767        break;
    768      default:
    769        dyns[i].value = nullptr;
    770    }
    771  }
    772  // Another loop to get the section sizes
    773  for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++)
    774    switch (dyns[i].tag) {
    775      case DT_PLTRELSZ:
    776        dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL));
    777        break;
    778      case DT_RELASZ:
    779        dyns[i].value = new ElfSize(getSectionForType(DT_RELA));
    780        break;
    781      case DT_STRSZ:
    782        dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB));
    783        break;
    784      case DT_RELSZ:
    785        dyns[i].value = new ElfSize(getSectionForType(DT_REL));
    786        break;
    787      case DT_INIT_ARRAYSZ:
    788        dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY));
    789        break;
    790      case DT_FINI_ARRAYSZ:
    791        dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY));
    792        break;
    793      case DT_RELAENT:
    794        dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA));
    795        break;
    796      case DT_SYMENT:
    797        dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB));
    798        break;
    799      case DT_RELENT:
    800        dyns[i].value = new ElfEntSize(getSectionForType(DT_REL));
    801        break;
    802    }
    803 
    804  file->seekg(pos);
    805 }
    806 
    807 ElfDynamic_Section::~ElfDynamic_Section() {
    808  for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
    809    delete dyns[i].value;
    810 }
    811 
    812 void ElfDynamic_Section::serialize(std::ofstream& file, unsigned char ei_class,
    813                                   unsigned char ei_data) {
    814  for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
    815    Elf_Dyn dyn;
    816    dyn.d_tag = dyns[i].tag;
    817    dyn.d_un.d_val = (dyns[i].value != nullptr) ? dyns[i].value->getValue() : 0;
    818    dyn.serialize(file, ei_class, ei_data);
    819  }
    820 }
    821 
    822 ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file,
    823                                     Elf* parent)
    824    : ElfSection(s, file, parent) {
    825  auto pos = file->tellg();
    826  syms.resize(s.sh_size / s.sh_entsize);
    827  ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink();
    828  file->seekg(shdr.sh_offset);
    829  for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
    830    Elf_Sym sym(*file, parent->getClass(), parent->getData());
    831    syms[i].name = strtab->getStr(sym.st_name);
    832    syms[i].info = sym.st_info;
    833    syms[i].other = sym.st_other;
    834    ElfSection* section =
    835        (sym.st_shndx == SHN_ABS) ? nullptr : parent->getSection(sym.st_shndx);
    836    new (&syms[i].value)
    837        ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
    838    syms[i].size = sym.st_size;
    839    syms[i].defined = (sym.st_shndx != SHN_UNDEF);
    840  }
    841  file->seekg(pos);
    842 }
    843 
    844 void ElfSymtab_Section::serialize(std::ofstream& file, unsigned char ei_class,
    845                                  unsigned char ei_data) {
    846  ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink();
    847  for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
    848    Elf_Sym sym;
    849    sym.st_name = strtab->getStrIndex(syms[i].name);
    850    sym.st_info = syms[i].info;
    851    sym.st_other = syms[i].other;
    852    sym.st_value = syms[i].value.getValue();
    853    ElfSection* section = syms[i].value.getSection();
    854    if (syms[i].defined)
    855      sym.st_shndx = section ? section->getIndex() : SHN_ABS;
    856    else
    857      sym.st_shndx = SHN_UNDEF;
    858    sym.st_size = syms[i].size;
    859    sym.serialize(file, ei_class, ei_data);
    860  }
    861 }
    862 
    863 Elf_SymValue* ElfSymtab_Section::lookup(const char* name,
    864                                        unsigned int type_filter) {
    865  for (std::vector<Elf_SymValue>::iterator sym = syms.begin();
    866       sym != syms.end(); sym++) {
    867    if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) &&
    868        (strcmp(sym->name, name) == 0)) {
    869      return &*sym;
    870    }
    871  }
    872  return nullptr;
    873 }
    874 
    875 const char* ElfStrtab_Section::getStr(unsigned int index) {
    876  for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
    877       t++) {
    878    if (index < t->used) return t->buf + index;
    879    index -= t->used;
    880  }
    881  assert(1 == 0);
    882  return nullptr;
    883 }
    884 
    885 const char* ElfStrtab_Section::getStr(const char* string) {
    886  if (string == nullptr) return nullptr;
    887 
    888  // If the given string is within the section, return it
    889  for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
    890       t++)
    891    if ((string >= t->buf) && (string < t->buf + t->used)) return string;
    892 
    893  // TODO: should scan in the section to find an existing string
    894 
    895  // If not, we need to allocate the string in the section
    896  size_t len = strlen(string) + 1;
    897 
    898  if (table.back().size - table.back().used < len)
    899    table.resize(table.size() + 1);
    900 
    901  char* alloc_str = table.back().buf + table.back().used;
    902  memcpy(alloc_str, string, len);
    903  table.back().used += len;
    904 
    905  shdr.sh_size += len;
    906  markDirty();
    907 
    908  return alloc_str;
    909 }
    910 
    911 unsigned int ElfStrtab_Section::getStrIndex(const char* string) {
    912  if (string == nullptr) return 0;
    913 
    914  unsigned int index = 0;
    915  string = getStr(string);
    916  for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
    917       t++) {
    918    if ((string >= t->buf) && (string < t->buf + t->used))
    919      return index + (string - t->buf);
    920    index += t->used;
    921  }
    922 
    923  assert(1 == 0);
    924  return 0;
    925 }
    926 
    927 void ElfStrtab_Section::serialize(std::ofstream& file, unsigned char ei_class,
    928                                  unsigned char ei_data) {
    929  file.seekp(getOffset());
    930  for (std::vector<table_storage>::iterator t = table.begin(); t != table.end();
    931       t++)
    932    file.write(t->buf, t->used);
    933 }