tor-browser

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

elfhack.cpp (57225B)


      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 <assert.h>
      7 #include <cstring>
      8 #include <cstdlib>
      9 #include <cstdio>
     10 #include <memory>
     11 
     12 #include "elfxx.h"
     13 #include "mozilla/CheckedInt.h"
     14 
     15 #define ver "1"
     16 #define elfhack_data ".elfhack.data.v" ver
     17 #define elfhack_text ".elfhack.text.v" ver
     18 
     19 #ifndef R_ARM_V4BX
     20 #  define R_ARM_V4BX 0x28
     21 #endif
     22 #ifndef R_ARM_CALL
     23 #  define R_ARM_CALL 0x1c
     24 #endif
     25 #ifndef R_ARM_JUMP24
     26 #  define R_ARM_JUMP24 0x1d
     27 #endif
     28 #ifndef R_ARM_THM_JUMP24
     29 #  define R_ARM_THM_JUMP24 0x1e
     30 #endif
     31 
     32 char* rundir = nullptr;
     33 
     34 template <typename T>
     35 struct wrapped {
     36  T value;
     37 };
     38 
     39 class Elf_Addr_Traits {
     40 public:
     41  typedef wrapped<Elf32_Addr> Type32;
     42  typedef wrapped<Elf64_Addr> Type64;
     43 
     44  template <class endian, typename R, typename T>
     45  static inline void swap(T& t, R& r) {
     46    r.value = endian::swap(t.value);
     47  }
     48 };
     49 
     50 typedef serializable<Elf_Addr_Traits> Elf_Addr;
     51 
     52 class ElfRelHack_Section : public ElfSection {
     53 public:
     54  ElfRelHack_Section(Elf_Shdr& s)
     55      : ElfSection(s, nullptr, nullptr),
     56        block_size((8 * s.sh_entsize - 1) * s.sh_entsize) {
     57    name = elfhack_data;
     58  };
     59 
     60  void serialize(std::ofstream& file, unsigned char ei_class,
     61                 unsigned char ei_data) {
     62    if (bitmap) {
     63      relr.push_back((bitmap << 1) | 1);
     64    }
     65    for (std::vector<Elf64_Addr>::iterator i = relr.begin(); i != relr.end();
     66         ++i) {
     67      Elf_Addr out;
     68      out.value = *i;
     69      out.serialize(file, ei_class, ei_data);
     70    }
     71  }
     72 
     73  bool isRelocatable() { return true; }
     74 
     75  void push_back(Elf64_Addr offset) {
     76    // The format used for the packed relocations is SHT_RELR, described in
     77    // https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/Jnz1lgLJAgAJ
     78    // The gist of it is that an address is recorded, and the following words,
     79    // if their LSB is 1, represent a bitmap of word-size-spaced relocations
     80    // at the addresses that follow. There can be multiple such bitmaps, such
     81    // that very long streaks of (possibly spaced) relocations can be recorded
     82    // in a very compact way.
     83    for (;;) {
     84      // [block_start; block_start + block_size] represents the range of offsets
     85      // the current bitmap can record. If the offset doesn't fall in that
     86      // range, or if doesn't align properly to be recorded, we record the
     87      // bitmap, and slide the block corresponding to a new bitmap. If the
     88      // offset doesn't fall in the range for the new bitmap, or if there wasn't
     89      // an active bitmap in the first place, we record the offset and start a
     90      // new bitmap for the block that follows it.
     91      if (!block_start || offset < block_start ||
     92          offset >= block_start + block_size ||
     93          (offset - block_start) % shdr.sh_entsize) {
     94        if (bitmap) {
     95          relr.push_back((bitmap << 1) | 1);
     96          block_start += block_size;
     97          bitmap = 0;
     98          continue;
     99        }
    100        relr.push_back(offset);
    101        block_start = offset + shdr.sh_entsize;
    102        break;
    103      }
    104      bitmap |= 1ULL << ((offset - block_start) / shdr.sh_entsize);
    105      break;
    106    }
    107    shdr.sh_size = (relr.size() + (bitmap ? 1 : 0)) * shdr.sh_entsize;
    108  }
    109 
    110 private:
    111  std::vector<Elf64_Addr> relr;
    112  size_t block_size;
    113  Elf64_Addr block_start = 0;
    114  Elf64_Addr bitmap = 0;
    115 };
    116 
    117 class ElfRelHackCode_Section : public ElfSection {
    118 public:
    119  ElfRelHackCode_Section(Elf_Shdr& s, Elf& e,
    120                         ElfRelHack_Section& relhack_section, unsigned int init,
    121                         unsigned int mprotect_cb, unsigned int sysconf_cb)
    122      : ElfSection(s, nullptr, nullptr),
    123        parent(e),
    124        relhack_section(relhack_section),
    125        init(init),
    126        init_trampoline(nullptr),
    127        mprotect_cb(mprotect_cb),
    128        sysconf_cb(sysconf_cb) {
    129    std::string file(rundir);
    130    file += "/inject/";
    131    switch (parent.getMachine()) {
    132      case EM_386:
    133        file += "x86";
    134        break;
    135      case EM_X86_64:
    136        file += "x86_64";
    137        break;
    138      case EM_ARM:
    139        file += "arm";
    140        break;
    141      case EM_AARCH64:
    142        file += "aarch64";
    143        break;
    144      default:
    145        throw std::runtime_error("unsupported architecture");
    146    }
    147    file += ".o";
    148    std::ifstream inject(file.c_str(), std::ios::in | std::ios::binary);
    149    elf = new Elf(inject);
    150    if (elf->getType() != ET_REL)
    151      throw std::runtime_error("object for injected code is not ET_REL");
    152    if (elf->getMachine() != parent.getMachine())
    153      throw std::runtime_error(
    154          "architecture of object for injected code doesn't match");
    155 
    156    ElfSymtab_Section* symtab = nullptr;
    157 
    158    // Find the symbol table.
    159    for (ElfSection* section = elf->getSection(1); section != nullptr;
    160         section = section->getNext()) {
    161      if (section->getType() == SHT_SYMTAB)
    162        symtab = (ElfSymtab_Section*)section;
    163    }
    164    if (symtab == nullptr)
    165      throw std::runtime_error(
    166          "Couldn't find a symbol table for the injected code");
    167 
    168    relro = parent.getSegmentByType(PT_GNU_RELRO);
    169 
    170    // Find the init symbol
    171    entry_point = -1;
    172    std::string symbol = "init";
    173    if (!init) symbol += "_noinit";
    174    if (relro) symbol += "_relro";
    175    Elf_SymValue* sym = symtab->lookup(symbol.c_str());
    176    if (!sym)
    177      throw std::runtime_error(
    178          "Couldn't find an 'init' symbol in the injected code");
    179 
    180    entry_point = sym->value.getValue();
    181 
    182    // Get all relevant sections from the injected code object.
    183    add_code_section(sym->value.getSection());
    184 
    185    // If the original init function is located too far away, we're going to
    186    // need to use a trampoline. See comment in inject.c.
    187    // Theoretically, we should check for (init - instr) > boundary, where
    188    // boundary is the platform-dependent limit, and instr is the virtual
    189    // address of the instruction that calls the original init, but we don't
    190    // have it at this point, so punt to just init.
    191    if ((init > 0xffffff && parent.getMachine() == EM_ARM) ||
    192        (init > 0x07ffffff && parent.getMachine() == EM_AARCH64)) {
    193      Elf_SymValue* trampoline = symtab->lookup("init_trampoline");
    194      if (!trampoline) {
    195        throw std::runtime_error(
    196            "Couldn't find an 'init_trampoline' symbol in the injected code");
    197      }
    198 
    199      init_trampoline = trampoline->value.getSection();
    200      add_code_section(init_trampoline);
    201    }
    202 
    203    // Adjust code sections offsets according to their size
    204    std::vector<ElfSection*>::iterator c = code.begin();
    205    (*c)->getShdr().sh_addr = 0;
    206    for (ElfSection* last = *(c++); c != code.end(); ++c) {
    207      unsigned int addr = last->getShdr().sh_addr + last->getSize();
    208      if (addr & ((*c)->getAddrAlign() - 1))
    209        addr = (addr | ((*c)->getAddrAlign() - 1)) + 1;
    210      (*c)->getShdr().sh_addr = addr;
    211      // We need to align this section depending on the greater
    212      // alignment required by code sections.
    213      if (shdr.sh_addralign < (*c)->getAddrAlign())
    214        shdr.sh_addralign = (*c)->getAddrAlign();
    215      last = *c;
    216    }
    217    shdr.sh_size = code.back()->getAddr() + code.back()->getSize();
    218    data = static_cast<char*>(malloc(shdr.sh_size));
    219    if (!data) {
    220      throw std::runtime_error("Could not malloc ElfSection data");
    221    }
    222    char* buf = data;
    223    for (c = code.begin(); c != code.end(); ++c) {
    224      memcpy(buf, (*c)->getData(), (*c)->getSize());
    225      buf += (*c)->getSize();
    226    }
    227    name = elfhack_text;
    228  }
    229 
    230  ~ElfRelHackCode_Section() { delete elf; }
    231 
    232  void serialize(std::ofstream& file, unsigned char ei_class,
    233                 unsigned char ei_data) override {
    234    // Readjust code offsets
    235    for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end();
    236         ++c)
    237      (*c)->getShdr().sh_addr += getAddr();
    238 
    239    // Apply relocations
    240    for (std::vector<ElfSection*>::iterator c = code.begin(); c != code.end();
    241         ++c) {
    242      for (ElfSection* rel = elf->getSection(1); rel != nullptr;
    243           rel = rel->getNext())
    244        if (((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) &&
    245            (rel->getInfo().section == *c)) {
    246          if (rel->getType() == SHT_REL)
    247            apply_relocations((ElfRel_Section<Elf_Rel>*)rel, *c);
    248          else
    249            apply_relocations((ElfRel_Section<Elf_Rela>*)rel, *c);
    250        }
    251    }
    252 
    253    ElfSection::serialize(file, ei_class, ei_data);
    254  }
    255 
    256  bool isRelocatable() override { return false; }
    257 
    258  unsigned int getEntryPoint() { return entry_point; }
    259 
    260  void insertBefore(ElfSection* section, bool dirty = true) override {
    261    // Adjust the address so that this section is adjacent to the one it's
    262    // being inserted before. This avoids creating holes which subsequently
    263    // might lead the PHDR-adjusting code to create unnecessary additional
    264    // PT_LOADs.
    265    shdr.sh_addr =
    266        (section->getAddr() - shdr.sh_size) & ~(shdr.sh_addralign - 1);
    267    ElfSection::insertBefore(section, dirty);
    268  }
    269 
    270 private:
    271  void add_code_section(ElfSection* section) {
    272    if (section) {
    273      /* Don't add section if it's already been added in the past */
    274      for (auto s = code.begin(); s != code.end(); ++s) {
    275        if (section == *s) return;
    276      }
    277      code.push_back(section);
    278      find_code(section);
    279    }
    280  }
    281 
    282  /* Look at the relocations associated to the given section to find other
    283   * sections that it requires */
    284  void find_code(ElfSection* section) {
    285    for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
    286      if (((s->getType() == SHT_REL) || (s->getType() == SHT_RELA)) &&
    287          (s->getInfo().section == section)) {
    288        if (s->getType() == SHT_REL)
    289          scan_relocs_for_code((ElfRel_Section<Elf_Rel>*)s);
    290        else
    291          scan_relocs_for_code((ElfRel_Section<Elf_Rela>*)s);
    292      }
    293    }
    294  }
    295 
    296  template <typename Rel_Type>
    297  void scan_relocs_for_code(ElfRel_Section<Rel_Type>* rel) {
    298    ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink();
    299    for (auto r = rel->rels.begin(); r != rel->rels.end(); ++r) {
    300      ElfSection* section =
    301          symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection();
    302      add_code_section(section);
    303    }
    304  }
    305 
    306  // TODO: sort out which non-aarch64 relocation types should be using
    307  //  `value` (even though in practice it's either 0 or the same as addend)
    308  class pc32_relocation {
    309   public:
    310    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    311                          Elf64_Sxword addend, unsigned int addr,
    312                          Elf64_Word value) {
    313      return addr + addend - offset - base_addr;
    314    }
    315  };
    316 
    317  class arm_plt32_relocation {
    318   public:
    319    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    320                          Elf64_Sxword addend, unsigned int addr,
    321                          Elf64_Word value) {
    322      // We don't care about sign_extend because the only case where this is
    323      // going to be used only jumps forward.
    324      Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr) >> 2;
    325      tmp = (addend + tmp) & 0x00ffffff;
    326      return (addend & 0xff000000) | tmp;
    327    }
    328  };
    329 
    330  class arm_thm_jump24_relocation {
    331   public:
    332    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    333                          Elf64_Sxword addend, unsigned int addr,
    334                          Elf64_Word value) {
    335      /* Follows description of b.w and bl instructions as per
    336         ARM Architecture Reference Manual ARM® v7-A and ARM® v7-R edition,
    337         A8.6.16 We limit ourselves to Encoding T4 of b.w and Encoding T1 of bl.
    338         We don't care about sign_extend because the only case where this is
    339         going to be used only jumps forward. */
    340      Elf32_Addr tmp = (Elf32_Addr)(addr - offset - base_addr);
    341      unsigned int word0 = addend & 0xffff, word1 = addend >> 16;
    342 
    343      /* Encoding T4 of B.W is 10x1 ; Encoding T1 of BL is 11x1. */
    344      unsigned int type = (word1 & 0xd000) >> 12;
    345      if (((word0 & 0xf800) != 0xf000) || ((type & 0x9) != 0x9))
    346        throw std::runtime_error(
    347            "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for B.W "
    348            "<label> and BL <label>");
    349 
    350      /* When the target address points to ARM code, switch a BL to a
    351       * BLX. This however can't be done with a B.W without adding a
    352       * trampoline, which is not supported as of now. */
    353      if ((addr & 0x1) == 0) {
    354        if (type == 0x9)
    355          throw std::runtime_error(
    356              "R_ARM_THM_JUMP24/R_ARM_THM_CALL relocation only supported for "
    357              "BL <label> when label points to ARM code");
    358        /* The address of the target is always relative to a 4-bytes
    359         * aligned address, so if the address of the BL instruction is
    360         * not 4-bytes aligned, adjust for it. */
    361        if ((base_addr + offset) & 0x2) tmp += 2;
    362        /* Encoding T2 of BLX is 11x0. */
    363        type = 0xc;
    364      }
    365 
    366      unsigned int s = (word0 & (1 << 10)) >> 10;
    367      unsigned int j1 = (word1 & (1 << 13)) >> 13;
    368      unsigned int j2 = (word1 & (1 << 11)) >> 11;
    369      unsigned int i1 = j1 ^ s ? 0 : 1;
    370      unsigned int i2 = j2 ^ s ? 0 : 1;
    371 
    372      tmp += ((s << 24) | (i1 << 23) | (i2 << 22) | ((word0 & 0x3ff) << 12) |
    373              ((word1 & 0x7ff) << 1));
    374 
    375      s = (tmp & (1 << 24)) >> 24;
    376      j1 = ((tmp & (1 << 23)) >> 23) ^ !s;
    377      j2 = ((tmp & (1 << 22)) >> 22) ^ !s;
    378 
    379      return 0xf000 | (s << 10) | ((tmp & (0x3ff << 12)) >> 12) | (type << 28) |
    380             (j1 << 29) | (j2 << 27) | ((tmp & 0xffe) << 15);
    381    }
    382  };
    383 
    384  class gotoff_relocation {
    385   public:
    386    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    387                          Elf64_Sxword addend, unsigned int addr,
    388                          Elf64_Word value) {
    389      return addr + addend;
    390    }
    391  };
    392 
    393  template <int start, int end>
    394  class abs_lo12_nc_relocation {
    395   public:
    396    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    397                          Elf64_Sxword addend, unsigned int addr,
    398                          Elf64_Word value) {
    399      // Fill the bits [end:start] of the immediate value in an ADD, LDR or STR
    400      // instruction, at bits [21:10].
    401      // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
    402      // profile C5.6.4, C5.6.83 or C5.6.178 and ELF for the ARM® 64-bit
    403      // Architecture (AArch64) 4.6.6, Table 4-9.
    404      Elf64_Word mask = (1 << (end + 1)) - 1;
    405      return value | (((((addr + addend) & mask) >> start) & 0xfff) << 10);
    406    }
    407  };
    408 
    409  class adr_prel_pg_hi21_relocation {
    410   public:
    411    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    412                          Elf64_Sxword addend, unsigned int addr,
    413                          Elf64_Word value) {
    414      // Fill the bits [32:12] of the immediate value in a ADRP instruction,
    415      // at bits [23:5]+[30:29].
    416      // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
    417      // profile C5.6.10 and ELF for the ARM® 64-bit Architecture
    418      // (AArch64) 4.6.6, Table 4-9.
    419      Elf64_Word imm = ((addr + addend) >> 12) - ((base_addr + offset) >> 12);
    420      Elf64_Word immLo = (imm & 0x3) << 29;
    421      Elf64_Word immHi = (imm & 0x1ffffc) << 3;
    422      return value & 0x9f00001f | immLo | immHi;
    423    }
    424  };
    425 
    426  class call26_relocation {
    427   public:
    428    Elf32_Addr operator()(unsigned int base_addr, Elf64_Off offset,
    429                          Elf64_Sxword addend, unsigned int addr,
    430                          Elf64_Word value) {
    431      // Fill the bits [27:2] of the immediate value in a BL instruction,
    432      // at bits [25:0].
    433      // per ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture
    434      // profile C5.6.26 and ELF for the ARM® 64-bit Architecture
    435      // (AArch64) 4.6.6, Table 4-10.
    436      return value | (((addr + addend - offset - base_addr) & 0x0ffffffc) >> 2);
    437    }
    438  };
    439 
    440  template <class relocation_type>
    441  void apply_relocation(ElfSection* the_code, char* base, Elf_Rel* r,
    442                        unsigned int addr) {
    443    relocation_type relocation;
    444    Elf32_Addr value;
    445    memcpy(&value, base + r->r_offset, 4);
    446    value = relocation(the_code->getAddr(), r->r_offset, value, addr, value);
    447    memcpy(base + r->r_offset, &value, 4);
    448  }
    449 
    450  template <class relocation_type>
    451  void apply_relocation(ElfSection* the_code, char* base, Elf_Rela* r,
    452                        unsigned int addr) {
    453    relocation_type relocation;
    454    Elf64_Word value;
    455    memcpy(&value, base + r->r_offset, 4);
    456    Elf32_Addr new_value =
    457        relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr, value);
    458    memcpy(base + r->r_offset, &new_value, 4);
    459  }
    460 
    461  template <typename Rel_Type>
    462  void apply_relocations(ElfRel_Section<Rel_Type>* rel, ElfSection* the_code) {
    463    assert(rel->getType() == Rel_Type::sh_type);
    464    char* buf = data + (the_code->getAddr() - code.front()->getAddr());
    465    // TODO: various checks on the sections
    466    ElfSymtab_Section* symtab = (ElfSymtab_Section*)rel->getLink();
    467    for (typename std::vector<Rel_Type>::iterator r = rel->rels.begin();
    468         r != rel->rels.end(); ++r) {
    469      // TODO: various checks on the symbol
    470      const char* name = symtab->syms[ELF64_R_SYM(r->r_info)].name;
    471      unsigned int addr;
    472      if (symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection() == nullptr) {
    473        if (strcmp(name, "relhack") == 0) {
    474          addr = relhack_section.getAddr();
    475        } else if (strcmp(name, "relhack_end") == 0) {
    476          addr = relhack_section.getAddr() + relhack_section.getSize();
    477        } else if (strcmp(name, "__ehdr_start") == 0) {
    478          // TODO: change this ugly hack to something better
    479          ElfSection* ehdr = parent.getSection(1)->getPrevious()->getPrevious();
    480          addr = ehdr->getAddr();
    481        } else if (strcmp(name, "original_init") == 0) {
    482          if (init_trampoline) {
    483            addr = init_trampoline->getAddr();
    484          } else {
    485            addr = init;
    486          }
    487        } else if (strcmp(name, "real_original_init") == 0) {
    488          addr = init;
    489        } else if (relro && strcmp(name, "mprotect_cb") == 0) {
    490          addr = mprotect_cb;
    491        } else if (relro && strcmp(name, "sysconf_cb") == 0) {
    492          addr = sysconf_cb;
    493        } else if (relro && strcmp(name, "relro_start") == 0) {
    494          addr = relro->getAddr();
    495        } else if (relro && strcmp(name, "relro_end") == 0) {
    496          addr = (relro->getAddr() + relro->getMemSize());
    497        } else if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0) {
    498          // We actually don't need a GOT, but need it as a reference for
    499          // GOTOFF relocations. We'll just use the start of the ELF file
    500          addr = 0;
    501        } else if (strcmp(name, "") == 0) {
    502          // This is for R_ARM_V4BX, until we find something better
    503          addr = -1;
    504        } else {
    505          throw std::runtime_error("Unsupported symbol in relocation");
    506        }
    507      } else {
    508        ElfSection* section =
    509            symtab->syms[ELF64_R_SYM(r->r_info)].value.getSection();
    510        assert((section->getType() == SHT_PROGBITS) &&
    511               (section->getFlags() & SHF_EXECINSTR));
    512        addr = symtab->syms[ELF64_R_SYM(r->r_info)].value.getValue();
    513      }
    514      // Do the relocation
    515 #define REL(machine, type) (EM_##machine | (R_##machine##_##type << 8))
    516      switch (elf->getMachine() | (ELF64_R_TYPE(r->r_info) << 8)) {
    517        case REL(X86_64, PC32):
    518        case REL(X86_64, PLT32):
    519        case REL(386, PC32):
    520        case REL(386, GOTPC):
    521        case REL(ARM, GOTPC):
    522        case REL(ARM, REL32):
    523        case REL(AARCH64, PREL32):
    524        case REL(AARCH64,
    525                 PREL64):  // In theory PREL64 should have its own relocation
    526                           // function, but in practice it doesn't matter.
    527          apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
    528          break;
    529        case REL(ARM, CALL):
    530        case REL(ARM, JUMP24):
    531        case REL(ARM, PLT32):
    532          apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
    533          break;
    534        case REL(ARM, THM_PC22 /* THM_CALL */):
    535        case REL(ARM, THM_JUMP24):
    536          apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr);
    537          break;
    538        case REL(386, GOTOFF):
    539        case REL(ARM, GOTOFF):
    540          apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
    541          break;
    542        case REL(AARCH64, ADD_ABS_LO12_NC):
    543          apply_relocation<abs_lo12_nc_relocation<0, 11>>(the_code, buf, &*r,
    544                                                          addr);
    545          break;
    546        case REL(AARCH64, ADR_PREL_PG_HI21):
    547          apply_relocation<adr_prel_pg_hi21_relocation>(the_code, buf, &*r,
    548                                                        addr);
    549          break;
    550        case REL(AARCH64, LDST32_ABS_LO12_NC):
    551          apply_relocation<abs_lo12_nc_relocation<2, 11>>(the_code, buf, &*r,
    552                                                          addr);
    553          break;
    554        case REL(AARCH64, LDST64_ABS_LO12_NC):
    555          apply_relocation<abs_lo12_nc_relocation<3, 11>>(the_code, buf, &*r,
    556                                                          addr);
    557          break;
    558        case REL(AARCH64, CALL26):
    559          apply_relocation<call26_relocation>(the_code, buf, &*r, addr);
    560          break;
    561        case REL(ARM, V4BX):
    562          // Ignore R_ARM_V4BX relocations
    563          break;
    564        default:
    565          throw std::runtime_error("Unsupported relocation type");
    566      }
    567    }
    568  }
    569 
    570  Elf *elf, &parent;
    571  ElfRelHack_Section& relhack_section;
    572  std::vector<ElfSection*> code;
    573  unsigned int init;
    574  ElfSection* init_trampoline;
    575  unsigned int mprotect_cb;
    576  unsigned int sysconf_cb;
    577  int entry_point;
    578  ElfSegment* relro;
    579 };
    580 
    581 unsigned int get_addend(Elf_Rel* rel, Elf* elf) {
    582  ElfLocation loc(rel->r_offset, elf);
    583  Elf_Addr addr(loc.getBuffer(), Elf_Addr::size(elf->getClass()),
    584                elf->getClass(), elf->getData());
    585  return addr.value;
    586 }
    587 
    588 unsigned int get_addend(Elf_Rela* rel, Elf* elf) { return rel->r_addend; }
    589 
    590 void set_relative_reloc(Elf_Rel* rel, Elf* elf, unsigned int value) {
    591  ElfLocation loc(rel->r_offset, elf);
    592  Elf_Addr addr;
    593  addr.value = value;
    594  addr.serialize(const_cast<char*>(loc.getBuffer()),
    595                 Elf_Addr::size(elf->getClass()), elf->getClass(),
    596                 elf->getData());
    597 }
    598 
    599 void set_relative_reloc(Elf_Rela* rel, Elf* elf, unsigned int value) {
    600  // ld puts the value of relocated relocations both in the addend and
    601  // at r_offset. For consistency, keep it that way.
    602  set_relative_reloc((Elf_Rel*)rel, elf, value);
    603  rel->r_addend = value;
    604 }
    605 
    606 void maybe_split_segment(Elf* elf, ElfSegment* segment) {
    607  std::list<ElfSection*>::iterator it = segment->begin();
    608  for (ElfSection* last = *(it++); it != segment->end(); last = *(it++)) {
    609    // When two consecutive non-SHT_NOBITS sections are apart by more
    610    // than the alignment of the section, the second can be moved closer
    611    // to the first, but this requires the segment to be split.
    612    if (((*it)->getType() != SHT_NOBITS) && (last->getType() != SHT_NOBITS) &&
    613        ((*it)->getOffset() - last->getOffset() - last->getSize() >
    614         segment->getAlign())) {
    615      // Probably very wrong.
    616      Elf_Phdr phdr;
    617      phdr.p_type = PT_LOAD;
    618      phdr.p_vaddr = 0;
    619      phdr.p_paddr = phdr.p_vaddr + segment->getVPDiff();
    620      phdr.p_flags = segment->getFlags();
    621      phdr.p_align = segment->getAlign();
    622      phdr.p_filesz = (Elf64_Xword)-1LL;
    623      phdr.p_memsz = (Elf64_Xword)-1LL;
    624      ElfSegment* newSegment = new ElfSegment(&phdr);
    625      elf->insertSegmentAfter(segment, newSegment);
    626      for (; it != segment->end(); ++it) {
    627        newSegment->addSection(*it);
    628      }
    629      for (it = newSegment->begin(); it != newSegment->end(); ++it) {
    630        segment->removeSection(*it);
    631      }
    632      break;
    633    }
    634  }
    635 }
    636 
    637 // EH_FRAME constants
    638 static const unsigned char DW_EH_PE_absptr = 0x00;
    639 static const unsigned char DW_EH_PE_omit = 0xff;
    640 
    641 // Data size
    642 static const unsigned char DW_EH_PE_LEB128 = 0x01;
    643 static const unsigned char DW_EH_PE_data2 = 0x02;
    644 static const unsigned char DW_EH_PE_data4 = 0x03;
    645 static const unsigned char DW_EH_PE_data8 = 0x04;
    646 
    647 // Data signedness
    648 static const unsigned char DW_EH_PE_signed = 0x08;
    649 
    650 // Modifiers
    651 static const unsigned char DW_EH_PE_pcrel = 0x10;
    652 
    653 // Return the data size part of the encoding value
    654 static unsigned char encoding_data_size(unsigned char encoding) {
    655  return encoding & 0x07;
    656 }
    657 
    658 // Advance `step` bytes in the buffer at `data` with size `size`, returning
    659 // the advanced buffer pointer and remaining size.
    660 // Returns true if step <= size.
    661 static bool advance_buffer(char** data, size_t* size, size_t step) {
    662  if (step > *size) return false;
    663 
    664  *data += step;
    665  *size -= step;
    666  return true;
    667 }
    668 
    669 // Advance in the given buffer, skipping the full length of the variable-length
    670 // encoded LEB128 type in CIE/FDE data.
    671 static bool skip_LEB128(char** data, size_t* size) {
    672  if (!*size) return false;
    673 
    674  while (*size && (*(*data)++ & (char)0x80)) {
    675    (*size)--;
    676  }
    677  return true;
    678 }
    679 
    680 // Advance in the given buffer, skipping the full length of a pointer encoded
    681 // with the given encoding.
    682 static bool skip_eh_frame_pointer(char** data, size_t* size,
    683                                  unsigned char encoding) {
    684  switch (encoding_data_size(encoding)) {
    685    case DW_EH_PE_data2:
    686      return advance_buffer(data, size, 2);
    687    case DW_EH_PE_data4:
    688      return advance_buffer(data, size, 4);
    689    case DW_EH_PE_data8:
    690      return advance_buffer(data, size, 8);
    691    case DW_EH_PE_LEB128:
    692      return skip_LEB128(data, size);
    693  }
    694  throw std::runtime_error("unreachable");
    695 }
    696 
    697 // Specialized implementations for adjust_eh_frame_pointer().
    698 template <typename T>
    699 static bool adjust_eh_frame_sized_pointer(char** data, size_t* size,
    700                                          ElfSection* eh_frame,
    701                                          unsigned int origAddr, Elf* elf) {
    702  if (*size < sizeof(T)) return false;
    703 
    704  serializable<FixedSizeData<T>> pointer(*data, *size, elf->getClass(),
    705                                         elf->getData());
    706  mozilla::CheckedInt<T> value = pointer.value;
    707  if (origAddr < eh_frame->getAddr()) {
    708    unsigned int diff = eh_frame->getAddr() - origAddr;
    709    value -= diff;
    710  } else {
    711    unsigned int diff = origAddr - eh_frame->getAddr();
    712    value += diff;
    713  }
    714  if (!value.isValid())
    715    throw std::runtime_error("Overflow while adjusting eh_frame");
    716  pointer.value = value.value();
    717  pointer.serialize(*data, *size, elf->getClass(), elf->getData());
    718  return advance_buffer(data, size, sizeof(T));
    719 }
    720 
    721 // In the given eh_frame section, adjust the pointer with the given encoding,
    722 // pointed to by the given buffer (`data`, `size`), considering the eh_frame
    723 // section was originally at `origAddr`. Also advances in the buffer.
    724 static bool adjust_eh_frame_pointer(char** data, size_t* size,
    725                                    unsigned char encoding,
    726                                    ElfSection* eh_frame, unsigned int origAddr,
    727                                    Elf* elf) {
    728  if ((encoding & 0x70) != DW_EH_PE_pcrel)
    729    return skip_eh_frame_pointer(data, size, encoding);
    730 
    731  if (encoding & DW_EH_PE_signed) {
    732    switch (encoding_data_size(encoding)) {
    733      case DW_EH_PE_data2:
    734        return adjust_eh_frame_sized_pointer<int16_t>(data, size, eh_frame,
    735                                                      origAddr, elf);
    736      case DW_EH_PE_data4:
    737        return adjust_eh_frame_sized_pointer<int32_t>(data, size, eh_frame,
    738                                                      origAddr, elf);
    739      case DW_EH_PE_data8:
    740        return adjust_eh_frame_sized_pointer<int64_t>(data, size, eh_frame,
    741                                                      origAddr, elf);
    742    }
    743  } else {
    744    switch (encoding_data_size(encoding)) {
    745      case DW_EH_PE_data2:
    746        return adjust_eh_frame_sized_pointer<uint16_t>(data, size, eh_frame,
    747                                                       origAddr, elf);
    748      case DW_EH_PE_data4:
    749        return adjust_eh_frame_sized_pointer<uint32_t>(data, size, eh_frame,
    750                                                       origAddr, elf);
    751      case DW_EH_PE_data8:
    752        return adjust_eh_frame_sized_pointer<uint64_t>(data, size, eh_frame,
    753                                                       origAddr, elf);
    754    }
    755  }
    756 
    757  throw std::runtime_error("Unsupported eh_frame pointer encoding");
    758 }
    759 
    760 // The eh_frame section may contain "PC"-relative pointers. If we move the
    761 // section, those need to be adjusted. Other type of pointers are relative to
    762 // sections we don't touch.
    763 static void adjust_eh_frame(ElfSection* eh_frame, unsigned int origAddr,
    764                            Elf* elf) {
    765  if (eh_frame->getAddr() == origAddr)  // nothing to do;
    766    return;
    767 
    768  char* data = const_cast<char*>(eh_frame->getData());
    769  size_t size = eh_frame->getSize();
    770  unsigned char LSDAencoding = DW_EH_PE_omit;
    771  unsigned char FDEencoding = DW_EH_PE_absptr;
    772  bool hasZ = false;
    773 
    774  // Decoding of eh_frame based on https://www.airs.com/blog/archives/460
    775  while (size) {
    776    if (size < sizeof(uint32_t)) goto malformed;
    777 
    778    serializable<FixedSizeData<uint32_t>> entryLength(
    779        data, size, elf->getClass(), elf->getData());
    780    if (!advance_buffer(&data, &size, sizeof(uint32_t))) goto malformed;
    781 
    782    char* cursor = data;
    783    size_t length = entryLength.value;
    784 
    785    if (length == 0) {
    786      continue;
    787    }
    788 
    789    if (size < sizeof(uint32_t)) goto malformed;
    790 
    791    serializable<FixedSizeData<uint32_t>> id(data, size, elf->getClass(),
    792                                             elf->getData());
    793    if (!advance_buffer(&cursor, &length, sizeof(uint32_t))) goto malformed;
    794 
    795    if (id.value == 0) {
    796      // This is a Common Information Entry
    797      if (length < 2) goto malformed;
    798      // Reset LSDA and FDE encodings, and hasZ for subsequent FDEs.
    799      LSDAencoding = DW_EH_PE_omit;
    800      FDEencoding = DW_EH_PE_absptr;
    801      hasZ = false;
    802      // CIE version. Should only be 1 or 3.
    803      char version = *cursor++;
    804      length--;
    805      if (version != 1 && version != 3) {
    806        throw std::runtime_error("Unsupported eh_frame version");
    807      }
    808      // NUL terminated string.
    809      const char* augmentationString = cursor;
    810      size_t l = strnlen(augmentationString, length - 1);
    811      if (l == length - 1) goto malformed;
    812      if (!advance_buffer(&cursor, &length, l + 1)) goto malformed;
    813      // Skip code alignment factor (LEB128)
    814      if (!skip_LEB128(&cursor, &length)) goto malformed;
    815      // Skip data alignment factor (LEB128)
    816      if (!skip_LEB128(&cursor, &length)) goto malformed;
    817      // Skip return address register (single byte in CIE version 1, LEB128
    818      // in CIE version 3)
    819      if (version == 1) {
    820        if (!advance_buffer(&cursor, &length, 1)) goto malformed;
    821      } else {
    822        if (!skip_LEB128(&cursor, &length)) goto malformed;
    823      }
    824      // Past this, it's data driven by the contents of the augmentation string.
    825      for (size_t i = 0; i < l; i++) {
    826        if (!length) goto malformed;
    827        switch (augmentationString[i]) {
    828          case 'z':
    829            if (!skip_LEB128(&cursor, &length)) goto malformed;
    830            hasZ = true;
    831            break;
    832          case 'L':
    833            LSDAencoding = *cursor++;
    834            length--;
    835            break;
    836          case 'R':
    837            FDEencoding = *cursor++;
    838            length--;
    839            break;
    840          case 'P': {
    841            unsigned char encoding = (unsigned char)*cursor++;
    842            length--;
    843            if (!adjust_eh_frame_pointer(&cursor, &length, encoding, eh_frame,
    844                                         origAddr, elf))
    845              goto malformed;
    846          } break;
    847          default:
    848            goto malformed;
    849        }
    850      }
    851    } else {
    852      // This is a Frame Description Entry
    853      // Starting address
    854      if (!adjust_eh_frame_pointer(&cursor, &length, FDEencoding, eh_frame,
    855                                   origAddr, elf))
    856        goto malformed;
    857 
    858      if (LSDAencoding != DW_EH_PE_omit) {
    859        // Skip number of bytes, same size as the starting address.
    860        if (!skip_eh_frame_pointer(&cursor, &length, FDEencoding))
    861          goto malformed;
    862        if (hasZ) {
    863          if (!skip_LEB128(&cursor, &length)) goto malformed;
    864        }
    865        // pointer to the LSDA.
    866        if (!adjust_eh_frame_pointer(&cursor, &length, LSDAencoding, eh_frame,
    867                                     origAddr, elf))
    868          goto malformed;
    869      }
    870    }
    871 
    872    data += entryLength.value;
    873    size -= entryLength.value;
    874  }
    875  return;
    876 
    877 malformed:
    878  throw std::runtime_error("malformed .eh_frame");
    879 }
    880 
    881 template <typename Rel_Type>
    882 int do_relocation_section(Elf* elf, unsigned int rel_type,
    883                          unsigned int rel_type2, bool force) {
    884  ElfDynamic_Section* dyn = elf->getDynSection();
    885  if (dyn == nullptr) {
    886    fprintf(stderr, "Couldn't find SHT_DYNAMIC section\n");
    887    return -1;
    888  }
    889 
    890  ElfRel_Section<Rel_Type>* section =
    891      (ElfRel_Section<Rel_Type>*)dyn->getSectionForType(Rel_Type::d_tag);
    892  if (section == nullptr) {
    893    fprintf(stderr, "No relocations\n");
    894    return -1;
    895  }
    896  assert(section->getType() == Rel_Type::sh_type);
    897 
    898  Elf64_Shdr relhack64_section = {0,
    899                                  SHT_PROGBITS,
    900                                  SHF_ALLOC,
    901                                  0,
    902                                  (Elf64_Off)-1LL,
    903                                  0,
    904                                  SHN_UNDEF,
    905                                  0,
    906                                  Elf_Addr::size(elf->getClass()),
    907                                  Elf_Addr::size(elf->getClass())};
    908  Elf64_Shdr relhackcode64_section = {0,
    909                                      SHT_PROGBITS,
    910                                      SHF_ALLOC | SHF_EXECINSTR,
    911                                      0,
    912                                      (Elf64_Off)-1LL,
    913                                      0,
    914                                      SHN_UNDEF,
    915                                      0,
    916                                      1,
    917                                      0};
    918 
    919  unsigned int entry_sz = Elf_Addr::size(elf->getClass());
    920 
    921  // The injected code needs to be executed before any init code in the
    922  // binary. There are three possible cases:
    923  // - The binary has no init code at all. In this case, we will add a
    924  //   DT_INIT entry pointing to the injected code.
    925  // - The binary has a DT_INIT entry. In this case, we will interpose:
    926  //   we change DT_INIT to point to the injected code, and have the
    927  //   injected code call the original DT_INIT entry point.
    928  // - The binary has no DT_INIT entry, but has a DT_INIT_ARRAY. In this
    929  //   case, we interpose as well, by replacing the first entry in the
    930  //   array to point to the injected code, and have the injected code
    931  //   call the original first entry.
    932  // The binary may have .ctors instead of DT_INIT_ARRAY, for its init
    933  // functions, but this falls into the second case above, since .ctors
    934  // are actually run by DT_INIT code.
    935  ElfValue* value = dyn->getValueForType(DT_INIT);
    936  unsigned int original_init = value ? value->getValue() : 0;
    937  ElfSection* init_array = nullptr;
    938  if (!value || !value->getValue()) {
    939    value = dyn->getValueForType(DT_INIT_ARRAYSZ);
    940    if (value && value->getValue() >= entry_sz)
    941      init_array = dyn->getSectionForType(DT_INIT_ARRAY);
    942  }
    943 
    944  Elf_Shdr relhack_section(relhack64_section);
    945  Elf_Shdr relhackcode_section(relhackcode64_section);
    946  auto relhack_ptr = std::make_unique<ElfRelHack_Section>(relhack_section);
    947  auto relhack = relhack_ptr.get();
    948 
    949  ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink();
    950  Elf_SymValue* sym = symtab->lookup("__cxa_pure_virtual");
    951 
    952  std::vector<Rel_Type> new_rels;
    953  std::vector<Rel_Type> init_array_relocs;
    954  size_t init_array_insert = 0;
    955  for (typename std::vector<Rel_Type>::iterator i = section->rels.begin();
    956       i != section->rels.end(); ++i) {
    957    // We don't need to keep R_*_NONE relocations
    958    if (!ELF64_R_TYPE(i->r_info)) continue;
    959    ElfLocation loc(i->r_offset, elf);
    960    // __cxa_pure_virtual is a function used in vtables to point at pure
    961    // virtual methods. The __cxa_pure_virtual function usually abort()s.
    962    // These functions are however normally never called. In the case
    963    // where they would, jumping to the null address instead of calling
    964    // __cxa_pure_virtual is going to work just as well. So we can remove
    965    // relocations for the __cxa_pure_virtual symbol and null out the
    966    // content at the offset pointed by the relocation.
    967    if (sym) {
    968      if (sym->defined) {
    969        // If we are statically linked to libstdc++, the
    970        // __cxa_pure_virtual symbol is defined in our lib, and we
    971        // have relative relocations (rel_type) for it.
    972        if (ELF64_R_TYPE(i->r_info) == rel_type) {
    973          Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(),
    974                        elf->getData());
    975          if (addr.value == sym->value.getValue()) {
    976            memset((char*)loc.getBuffer(), 0, entry_sz);
    977            continue;
    978          }
    979        }
    980      } else {
    981        // If we are dynamically linked to libstdc++, the
    982        // __cxa_pure_virtual symbol is undefined in our lib, and we
    983        // have absolute relocations (rel_type2) for it.
    984        if ((ELF64_R_TYPE(i->r_info) == rel_type2) &&
    985            (sym == &symtab->syms[ELF64_R_SYM(i->r_info)])) {
    986          memset((char*)loc.getBuffer(), 0, entry_sz);
    987          continue;
    988        }
    989      }
    990    }
    991    // Keep track of the relocations associated with the init_array section.
    992    if (init_array && i->r_offset >= init_array->getAddr() &&
    993        i->r_offset < init_array->getAddr() + init_array->getSize()) {
    994      init_array_relocs.push_back(*i);
    995      init_array_insert = new_rels.size();
    996    } else if (!(loc.getSection()->getFlags() & SHF_WRITE) ||
    997               (ELF64_R_TYPE(i->r_info) != rel_type)) {
    998      // Don't pack relocations happening in non writable sections.
    999      // Our injected code is likely not to be allowed to write there.
   1000      new_rels.push_back(*i);
   1001    } else if (i->r_offset & 1) {
   1002      // RELR packing doesn't support relocations at an odd address, but
   1003      // there shouldn't be any.
   1004      new_rels.push_back(*i);
   1005    } else {
   1006      // With Elf_Rel, the value pointed by the relocation offset is the addend.
   1007      // With Elf_Rela, the addend is in the relocation entry, but the elfhacked
   1008      // relocation info doesn't contain it. Elfhack relies on the value pointed
   1009      // by the relocation offset to also contain the addend. Which is true with
   1010      // BFD ld and gold, but not lld, which leaves that nulled out. So if that
   1011      // value is nulled out, we update it to the addend.
   1012      Elf_Addr addr(loc.getBuffer(), entry_sz, elf->getClass(), elf->getData());
   1013      unsigned int addend = get_addend(&*i, elf);
   1014      if (addr.value == 0) {
   1015        addr.value = addend;
   1016        addr.serialize(const_cast<char*>(loc.getBuffer()), entry_sz,
   1017                       elf->getClass(), elf->getData());
   1018      } else if (addr.value != addend) {
   1019        fprintf(stderr,
   1020                "Relocation addend inconsistent with content. Skipping\n");
   1021        return -1;
   1022      }
   1023      relhack->push_back(i->r_offset);
   1024    }
   1025  }
   1026 
   1027  if (init_array) {
   1028    // Some linkers create a DT_INIT_ARRAY section that, for all purposes,
   1029    // is empty: it only contains 0x0 or 0xffffffff pointers with no
   1030    // relocations. In some other cases, there can be null pointers with no
   1031    // relocations in the middle of the section. Example: crtend_so.o in the
   1032    // Android NDK contains a sized .init_array with a null pointer and no
   1033    // relocation, which ends up in all Android libraries, and in some cases it
   1034    // ends up in the middle of the final .init_array section. If we have such a
   1035    // reusable slot at the beginning of .init_array, we just use it. It we have
   1036    // one in the middle of .init_array, we slide its content to move the "hole"
   1037    // at the beginning and use it there (we need our injected code to run
   1038    // before any other). Otherwise, replace the first entry and keep the
   1039    // original pointer.
   1040    std::sort(init_array_relocs.begin(), init_array_relocs.end(),
   1041              [](Rel_Type& a, Rel_Type& b) { return a.r_offset < b.r_offset; });
   1042    size_t expected = init_array->getAddr();
   1043    const size_t zero = 0;
   1044    const size_t all = SIZE_MAX;
   1045    const char* data = init_array->getData();
   1046    size_t length = Elf_Addr::size(elf->getClass());
   1047    size_t off = 0;
   1048    for (; off < init_array_relocs.size(); off++) {
   1049      auto& r = init_array_relocs[off];
   1050      if (r.r_offset >= expected + length &&
   1051          (memcmp(data + off * length, &zero, length) == 0 ||
   1052           memcmp(data + off * length, &all, length) == 0)) {
   1053        // We found a hole, move the preceding entries.
   1054        while (off) {
   1055          auto& p = init_array_relocs[--off];
   1056          if (ELF64_R_TYPE(p.r_info) == rel_type) {
   1057            unsigned int addend = get_addend(&p, elf);
   1058            p.r_offset += length;
   1059            set_relative_reloc(&p, elf, addend);
   1060          } else {
   1061            fprintf(stderr,
   1062                    "Unsupported relocation type in DT_INIT_ARRAY. Skipping\n");
   1063            return -1;
   1064          }
   1065        }
   1066        break;
   1067      }
   1068      expected = r.r_offset + length;
   1069    }
   1070 
   1071    if (off == 0) {
   1072      // We either found a hole above, and can now use the first entry,
   1073      // or the init_array section is effectively empty (see further above)
   1074      // and we also can use the first entry.
   1075      // Either way, code further below will take care of actually setting
   1076      // the right r_info and r_added for the relocation.
   1077      Rel_Type rel;
   1078      rel.r_offset = init_array->getAddr();
   1079      init_array_relocs.insert(init_array_relocs.begin(), rel);
   1080    } else {
   1081      // Use relocated value of DT_INIT_ARRAY's first entry for the
   1082      // function to be called by the injected code.
   1083      auto& rel = init_array_relocs[0];
   1084      unsigned int addend = get_addend(&rel, elf);
   1085      if (ELF64_R_TYPE(rel.r_info) == rel_type) {
   1086        original_init = addend;
   1087      } else if (ELF64_R_TYPE(rel.r_info) == rel_type2) {
   1088        ElfSymtab_Section* symtab = (ElfSymtab_Section*)section->getLink();
   1089        original_init =
   1090            symtab->syms[ELF64_R_SYM(rel.r_info)].value.getValue() + addend;
   1091      } else {
   1092        fprintf(stderr,
   1093                "Unsupported relocation type for DT_INIT_ARRAY's first entry. "
   1094                "Skipping\n");
   1095        return -1;
   1096      }
   1097    }
   1098 
   1099    new_rels.insert(std::next(new_rels.begin(), init_array_insert),
   1100                    init_array_relocs.begin(), init_array_relocs.end());
   1101  }
   1102 
   1103  unsigned int mprotect_cb = 0;
   1104  unsigned int sysconf_cb = 0;
   1105  // If there is a relro segment, our injected code will run after the linker
   1106  // sets the corresponding pages read-only. We need to make our code change
   1107  // that to read-write before applying relocations, which means it needs to
   1108  // call mprotect. To do that, we need to find a reference to the mprotect
   1109  // symbol. In case the library already has one, we use that, but otherwise, we
   1110  // add the symbol. Then the injected code needs to be able to call the
   1111  // corresponding function, which means it needs access to a pointer to it. We
   1112  // get such a pointer by making the linker apply a relocation for the symbol
   1113  // at an address our code can read. The problem here is that there is not much
   1114  // relocated space where we can put such a pointer, so we abuse the bss
   1115  // section temporarily (it will be restored to a null value before any code
   1116  // can actually use it)
   1117  if (elf->getSegmentByType(PT_GNU_RELRO)) {
   1118    ElfSection* gnu_versym = dyn->getSectionForType(DT_VERSYM);
   1119    auto ensure_symbol = [&symtab, &gnu_versym](const char* symbol) {
   1120      Elf_SymValue* sym_value = symtab->lookup(symbol, STT(FUNC));
   1121      if (!sym_value) {
   1122        symtab->syms.emplace_back();
   1123        sym_value = &symtab->syms.back();
   1124        symtab->grow(symtab->syms.size() * symtab->getEntSize());
   1125        sym_value->name =
   1126            ((ElfStrtab_Section*)symtab->getLink())->getStr(symbol);
   1127        sym_value->info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC);
   1128        sym_value->other = STV_DEFAULT;
   1129        new (&sym_value->value) ElfLocation(nullptr, 0, ElfLocation::ABSOLUTE);
   1130        sym_value->size = 0;
   1131        sym_value->defined = false;
   1132 
   1133        // The DT_VERSYM data (in the .gnu.version section) has the same number
   1134        // of entries as the symbols table. Since we added one entry there, we
   1135        // need to add one entry here. Zeroes in the extra data means no version
   1136        // for that symbol, which is the simplest thing to do.
   1137        if (gnu_versym) {
   1138          gnu_versym->grow(gnu_versym->getSize() + gnu_versym->getEntSize());
   1139        }
   1140      }
   1141    };
   1142    // ensure_symbol may trigger a symbol table vector resize, so only lookup
   1143    // the symbols after we're done touching the symbol table.
   1144    ensure_symbol("mprotect");
   1145    ensure_symbol("sysconf");
   1146    Elf_SymValue* mprotect = symtab->lookup("mprotect", STT(FUNC));
   1147    Elf_SymValue* sysconf = symtab->lookup("sysconf", STT(FUNC));
   1148 
   1149    // Add relocations for the mprotect and sysconf symbols.
   1150    auto add_relocation_to = [&new_rels, &symtab, rel_type2](
   1151                                 Elf_SymValue* symbol, unsigned int location) {
   1152      new_rels.emplace_back();
   1153      Rel_Type& rel = new_rels.back();
   1154      memset(&rel, 0, sizeof(rel));
   1155      rel.r_info = ELF64_R_INFO(
   1156          std::distance(symtab->syms.begin(),
   1157                        std::vector<Elf_SymValue>::iterator(symbol)),
   1158          rel_type2);
   1159      rel.r_offset = location;
   1160      return location;
   1161    };
   1162 
   1163    // Find the beginning of the bss section, and use an aligned location in
   1164    // there for the relocation.
   1165    for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
   1166      if (s->getType() != SHT_NOBITS ||
   1167          (s->getFlags() & (SHF_TLS | SHF_WRITE)) != SHF_WRITE) {
   1168        continue;
   1169      }
   1170      size_t ptr_size = Elf_Addr::size(elf->getClass());
   1171      size_t usable_start = (s->getAddr() + ptr_size - 1) & ~(ptr_size - 1);
   1172      size_t usable_end = (s->getAddr() + s->getSize()) & ~(ptr_size - 1);
   1173      if (usable_end - usable_start >= 2 * ptr_size) {
   1174        mprotect_cb = add_relocation_to(mprotect, usable_start);
   1175        sysconf_cb = add_relocation_to(sysconf, usable_start + ptr_size);
   1176        break;
   1177      }
   1178    }
   1179 
   1180    if (mprotect_cb == 0 || sysconf_cb == 0) {
   1181      fprintf(stderr, "Couldn't find .bss. Skipping\n");
   1182      return -1;
   1183    }
   1184  }
   1185 
   1186  size_t old_size = section->getSize();
   1187 
   1188  section->rels.assign(new_rels.begin(), new_rels.end());
   1189  section->shrink(new_rels.size() * section->getEntSize());
   1190 
   1191  auto relhackcode_ptr = std::make_unique<ElfRelHackCode_Section>(
   1192      relhackcode_section, *elf, *relhack, original_init, mprotect_cb,
   1193      sysconf_cb);
   1194  auto relhackcode = relhackcode_ptr.get();
   1195  // Find the first executable section, and insert the relhack code before
   1196  // that. The relhack data is inserted between .rel.dyn and .rel.plt.
   1197  ElfSection* first_executable = nullptr;
   1198  for (ElfSection* s = elf->getSection(1); s != nullptr; s = s->getNext()) {
   1199    if (s->getFlags() & SHF_EXECINSTR) {
   1200      first_executable = s;
   1201      break;
   1202    }
   1203  }
   1204 
   1205  if (!first_executable) {
   1206    fprintf(stderr, "Couldn't find executable section. Skipping\n");
   1207    return -1;
   1208  }
   1209 
   1210  // Once the pointers for relhack, relhackcode, and init are inserted,
   1211  // their ownership is transferred to the Elf object, which will free
   1212  // them when itself is freed. Hence the .release() calls here (and
   1213  // the init.release() call later on). Please note that the raw
   1214  // pointers will continue to be used after .release(), which is why
   1215  // we are caching them (since .release() will end up setting the
   1216  // smart pointer's internal raw pointer to nullptr).
   1217 
   1218  relhack->insertBefore(section);
   1219  relhack_ptr.release();
   1220 
   1221  relhackcode->insertBefore(first_executable);
   1222  relhackcode_ptr.release();
   1223 
   1224  // Don't try further if we can't gain from the relocation section size change.
   1225  // We account for the fact we're going to split the PT_LOAD before the
   1226  // injected code section, so the overhead of the page alignment for section
   1227  // needs to be accounted for.
   1228  size_t align = first_executable->getSegmentByType(PT_LOAD)->getAlign();
   1229  size_t new_size = relhack->getSize() + section->getSize() +
   1230                    relhackcode->getSize() +
   1231                    (relhackcode->getAddr() & (align - 1));
   1232  if (!force && (new_size >= old_size || old_size - new_size < align)) {
   1233    fprintf(stderr, "No gain. Skipping\n");
   1234    return -1;
   1235  }
   1236 
   1237  // .eh_frame/.eh_frame_hdr may be between the relocation sections and the
   1238  // executable sections. When that happens, we may end up creating a separate
   1239  // PT_LOAD for just both of them because they are not considered relocatable.
   1240  // But they are, in fact, kind of relocatable, albeit with some manual work.
   1241  // Which we'll do here.
   1242  ElfSegment* eh_frame_segment = elf->getSegmentByType(PT_GNU_EH_FRAME);
   1243  ElfSection* eh_frame_hdr =
   1244      eh_frame_segment ? eh_frame_segment->getFirstSection() : nullptr;
   1245  // The .eh_frame section usually follows the eh_frame_hdr section.
   1246  ElfSection* eh_frame = eh_frame_hdr ? eh_frame_hdr->getNext() : nullptr;
   1247  ElfSection* first = eh_frame_hdr;
   1248  ElfSection* second = eh_frame;
   1249  if (eh_frame && strcmp(eh_frame->getName(), ".eh_frame")) {
   1250    // But sometimes it appears *before* the eh_frame_hdr section.
   1251    eh_frame = eh_frame_hdr->getPrevious();
   1252    first = eh_frame;
   1253    second = eh_frame_hdr;
   1254  }
   1255  if (eh_frame_hdr && (!eh_frame || strcmp(eh_frame->getName(), ".eh_frame"))) {
   1256    throw std::runtime_error(
   1257        "Expected to find an .eh_frame section adjacent to .eh_frame_hdr");
   1258  }
   1259  if (eh_frame && first->getAddr() > relhack->getAddr() &&
   1260      second->getAddr() < first_executable->getAddr()) {
   1261    // The distance between both sections needs to be preserved because
   1262    // eh_frame_hdr contains relative offsets to eh_frame. Well, they could be
   1263    // relocated too, but it's not worth the effort for the few number of bytes
   1264    // this would save.
   1265    Elf64_Off distance = second->getAddr() - first->getAddr();
   1266    Elf64_Addr origAddr = eh_frame->getAddr();
   1267    ElfSection* previous = first->getPrevious();
   1268    first->getShdr().sh_addr = (previous->getAddr() + previous->getSize() +
   1269                                first->getAddrAlign() - 1) &
   1270                               ~(first->getAddrAlign() - 1);
   1271    second->getShdr().sh_addr =
   1272        (first->getAddr() + std::min(first->getSize(), distance) +
   1273         second->getAddrAlign() - 1) &
   1274        ~(second->getAddrAlign() - 1);
   1275    // Re-adjust to keep the original distance.
   1276    // If the first section has a smaller alignment requirement than the second,
   1277    // the second will be farther away, so we need to adjust the first.
   1278    // If the second section has a smaller alignment requirement than the first,
   1279    // it will already be at the right distance.
   1280    first->getShdr().sh_addr = second->getAddr() - distance;
   1281    assert(distance == second->getAddr() - first->getAddr());
   1282    first->markDirty();
   1283    adjust_eh_frame(eh_frame, origAddr, elf);
   1284  }
   1285 
   1286  // Adjust PT_LOAD segments
   1287  for (ElfSegment* segment = elf->getSegmentByType(PT_LOAD); segment;
   1288       segment = elf->getSegmentByType(PT_LOAD, segment)) {
   1289    maybe_split_segment(elf, segment);
   1290  }
   1291 
   1292  // Ensure Elf sections will be at their final location.
   1293  elf->normalize();
   1294  auto init =
   1295      std::make_unique<ElfLocation>(relhackcode, relhackcode->getEntryPoint());
   1296  if (init_array) {
   1297    // Adjust the first DT_INIT_ARRAY entry to point at the injected code
   1298    // by transforming its relocation into a relative one pointing to the
   1299    // address of the injected code.
   1300    Rel_Type* rel = &section->rels[init_array_insert];
   1301    rel->r_info = ELF64_R_INFO(0, rel_type);  // Set as a relative relocation
   1302    set_relative_reloc(rel, elf, init->getValue());
   1303  } else {
   1304    if (dyn->setValueForType(DT_INIT, init.get())) {
   1305      init.release();
   1306    } else {
   1307      fprintf(stderr, "Can't grow .dynamic section to set DT_INIT. Skipping\n");
   1308      return -1;
   1309    }
   1310  }
   1311 
   1312  // TODO: adjust the value according to the remaining number of relative
   1313  // relocations
   1314  if (dyn->getValueForType(Rel_Type::d_tag_count))
   1315    dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));
   1316 
   1317  return 0;
   1318 }
   1319 
   1320 static inline int backup_file(const char* name) {
   1321  std::string fname(name);
   1322  fname += ".bak";
   1323  return rename(name, fname.c_str());
   1324 }
   1325 
   1326 void do_file(const char* name, bool backup = false, bool force = false) {
   1327  std::ifstream file(name, std::ios::in | std::ios::binary);
   1328  Elf elf(file);
   1329  unsigned int size = elf.getSize();
   1330  fprintf(stderr, "%s: ", name);
   1331  if (elf.getType() != ET_DYN) {
   1332    fprintf(stderr, "Not a shared object. Skipping\n");
   1333    return;
   1334  }
   1335 
   1336  for (ElfSection* section = elf.getSection(1); section != nullptr;
   1337       section = section->getNext()) {
   1338    if (section->getName() &&
   1339        (strncmp(section->getName(), ".elfhack.", 9) == 0)) {
   1340      fprintf(stderr, "Already elfhacked. Skipping\n");
   1341      return;
   1342    }
   1343  }
   1344 
   1345  int exit = -1;
   1346  switch (elf.getMachine()) {
   1347    case EM_386:
   1348      exit =
   1349          do_relocation_section<Elf_Rel>(&elf, R_386_RELATIVE, R_386_32, force);
   1350      break;
   1351    case EM_X86_64:
   1352      exit = do_relocation_section<Elf_Rela>(&elf, R_X86_64_RELATIVE,
   1353                                             R_X86_64_64, force);
   1354      break;
   1355    case EM_ARM:
   1356      exit = do_relocation_section<Elf_Rel>(&elf, R_ARM_RELATIVE, R_ARM_ABS32,
   1357                                            force);
   1358      break;
   1359    case EM_AARCH64:
   1360      exit = do_relocation_section<Elf_Rela>(&elf, R_AARCH64_RELATIVE,
   1361                                             R_AARCH64_ABS64, force);
   1362      break;
   1363    default:
   1364      throw std::runtime_error("unsupported architecture");
   1365  }
   1366  if (exit == 0) {
   1367    if (!force && (elf.getSize() >= size)) {
   1368      fprintf(stderr, "No gain. Skipping\n");
   1369    } else if (backup && backup_file(name) != 0) {
   1370      fprintf(stderr, "Couln't create backup file\n");
   1371    } else {
   1372      std::ofstream ofile(name,
   1373                          std::ios::out | std::ios::binary | std::ios::trunc);
   1374      elf.write(ofile);
   1375      fprintf(stderr, "Reduced by %d bytes\n", size - elf.getSize());
   1376    }
   1377  }
   1378 }
   1379 
   1380 void undo_file(const char* name, bool backup = false) {
   1381  std::ifstream file(name, std::ios::in | std::ios::binary);
   1382  Elf elf(file);
   1383  unsigned int size = elf.getSize();
   1384  fprintf(stderr, "%s: ", name);
   1385  if (elf.getType() != ET_DYN) {
   1386    fprintf(stderr, "Not a shared object. Skipping\n");
   1387    return;
   1388  }
   1389 
   1390  ElfSection *data = nullptr, *text = nullptr;
   1391  for (ElfSection* section = elf.getSection(1); section != nullptr;
   1392       section = section->getNext()) {
   1393    if (section->getName() && (strcmp(section->getName(), elfhack_data) == 0))
   1394      data = section;
   1395    if (section->getName() && (strcmp(section->getName(), elfhack_text) == 0))
   1396      text = section;
   1397  }
   1398 
   1399  if (!data || !text) {
   1400    fprintf(stderr, "Not elfhacked. Skipping\n");
   1401    return;
   1402  }
   1403 
   1404  // When both elfhack sections are in the same segment, try to merge
   1405  // the segment that contains them both and the following segment.
   1406  // When the elfhack sections are in separate segments, try to merge
   1407  // those segments.
   1408  ElfSegment* first = data->getSegmentByType(PT_LOAD);
   1409  ElfSegment* second = text->getSegmentByType(PT_LOAD);
   1410  if (first == second) {
   1411    second = elf.getSegmentByType(PT_LOAD, first);
   1412  }
   1413 
   1414  // Only merge the segments when their flags match.
   1415  if (second->getFlags() != first->getFlags()) {
   1416    fprintf(stderr, "Couldn't merge PT_LOAD segments. Skipping\n");
   1417    return;
   1418  }
   1419  // Move sections from the second PT_LOAD to the first, and remove the
   1420  // second PT_LOAD segment.
   1421  for (std::list<ElfSection*>::iterator section = second->begin();
   1422       section != second->end(); ++section)
   1423    first->addSection(*section);
   1424 
   1425  elf.removeSegment(second);
   1426  elf.normalize();
   1427 
   1428  if (backup && backup_file(name) != 0) {
   1429    fprintf(stderr, "Couln't create backup file\n");
   1430  } else {
   1431    std::ofstream ofile(name,
   1432                        std::ios::out | std::ios::binary | std::ios::trunc);
   1433    elf.write(ofile);
   1434    fprintf(stderr, "Grown by %d bytes\n", elf.getSize() - size);
   1435  }
   1436 }
   1437 
   1438 int main(int argc, char* argv[]) {
   1439  int arg;
   1440  bool backup = false;
   1441  bool force = false;
   1442  bool revert = false;
   1443  char* lastSlash = rindex(argv[0], '/');
   1444  if (lastSlash != nullptr) rundir = strndup(argv[0], lastSlash - argv[0]);
   1445  for (arg = 1; arg < argc; arg++) {
   1446    if (strcmp(argv[arg], "-f") == 0)
   1447      force = true;
   1448    else if (strcmp(argv[arg], "-b") == 0)
   1449      backup = true;
   1450    else if (strcmp(argv[arg], "-r") == 0)
   1451      revert = true;
   1452    else if (revert) {
   1453      undo_file(argv[arg], backup);
   1454    } else
   1455      do_file(argv[arg], backup, force);
   1456  }
   1457 
   1458  free(rundir);
   1459  return 0;
   1460 }