tor-browser

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

elfxx.h (19403B)


      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 #include <stdexcept>
      6 #include <list>
      7 #include <vector>
      8 #include <cstring>
      9 #include <fstream>
     10 #include <algorithm>
     11 #include <elf.h>
     12 #include <asm/byteorder.h>
     13 
     14 // Technically, __*_to_cpu and __cpu_to* function are equivalent,
     15 // so swap can use either of both.
     16 #define def_swap(endian, type, bits)                    \
     17  static inline type##bits##_t swap(type##bits##_t i) { \
     18    return __##endian##bits##_to_cpu(i);                \
     19  }
     20 
     21 class little_endian {
     22 public:
     23  def_swap(le, uint, 16);
     24  def_swap(le, uint, 32);
     25  def_swap(le, uint, 64);
     26  def_swap(le, int, 16);
     27  def_swap(le, int, 32);
     28  def_swap(le, int, 64);
     29 };
     30 
     31 class big_endian {
     32 public:
     33  def_swap(be, uint, 16);
     34  def_swap(be, uint, 32);
     35  def_swap(be, uint, 64);
     36  def_swap(be, int, 16);
     37  def_swap(be, int, 32);
     38  def_swap(be, int, 64);
     39 };
     40 
     41 // forward declaration
     42 class ElfSection;
     43 class ElfSegment;
     44 // TODO: Rename Elf_* types
     45 class Elf_Ehdr;
     46 class Elf_Phdr;
     47 class Elf;
     48 class ElfDynamic_Section;
     49 class ElfStrtab_Section;
     50 
     51 template <typename X>
     52 class FixedSizeData {
     53 public:
     54  struct Wrapper {
     55    X value;
     56  };
     57  typedef Wrapper Type32;
     58  typedef Wrapper Type64;
     59 
     60  template <class endian, typename R, typename T>
     61  static void swap(T& t, R& r) {
     62    r.value = endian::swap(t.value);
     63  }
     64 };
     65 
     66 class Elf_Ehdr_Traits {
     67 public:
     68  typedef Elf32_Ehdr Type32;
     69  typedef Elf64_Ehdr Type64;
     70 
     71  template <class endian, typename R, typename T>
     72  static void swap(T& t, R& r);
     73 };
     74 
     75 class Elf_Phdr_Traits {
     76 public:
     77  typedef Elf32_Phdr Type32;
     78  typedef Elf64_Phdr Type64;
     79 
     80  template <class endian, typename R, typename T>
     81  static void swap(T& t, R& r);
     82 };
     83 
     84 class Elf_Shdr_Traits {
     85 public:
     86  typedef Elf32_Shdr Type32;
     87  typedef Elf64_Shdr Type64;
     88 
     89  template <class endian, typename R, typename T>
     90  static void swap(T& t, R& r);
     91 };
     92 
     93 class Elf_Dyn_Traits {
     94 public:
     95  typedef Elf32_Dyn Type32;
     96  typedef Elf64_Dyn Type64;
     97 
     98  template <class endian, typename R, typename T>
     99  static void swap(T& t, R& r);
    100 };
    101 
    102 class Elf_Sym_Traits {
    103 public:
    104  typedef Elf32_Sym Type32;
    105  typedef Elf64_Sym Type64;
    106 
    107  template <class endian, typename R, typename T>
    108  static void swap(T& t, R& r);
    109 };
    110 
    111 class Elf_Rel_Traits {
    112 public:
    113  typedef Elf32_Rel Type32;
    114  typedef Elf64_Rel Type64;
    115 
    116  template <class endian, typename R, typename T>
    117  static void swap(T& t, R& r);
    118 };
    119 
    120 class Elf_Rela_Traits {
    121 public:
    122  typedef Elf32_Rela Type32;
    123  typedef Elf64_Rela Type64;
    124 
    125  template <class endian, typename R, typename T>
    126  static void swap(T& t, R& r);
    127 };
    128 
    129 class ElfValue {
    130 public:
    131  virtual unsigned int getValue() { return 0; }
    132  virtual ElfSection* getSection() { return nullptr; }
    133 };
    134 
    135 class ElfPlainValue : public ElfValue {
    136  unsigned int value;
    137 
    138 public:
    139  ElfPlainValue(unsigned int val) : value(val) {};
    140  unsigned int getValue() { return value; }
    141 };
    142 
    143 class ElfLocation : public ElfValue {
    144  ElfSection* section;
    145  unsigned int offset;
    146 
    147 public:
    148  enum position { ABSOLUTE, RELATIVE };
    149  ElfLocation() : section(nullptr), offset(0) {};
    150  ElfLocation(ElfSection* section, unsigned int off,
    151              enum position pos = RELATIVE);
    152  ElfLocation(unsigned int location, Elf* elf);
    153  unsigned int getValue();
    154  ElfSection* getSection() { return section; }
    155  const char* getBuffer();
    156 };
    157 
    158 class ElfSize : public ElfValue {
    159  ElfSection* section;
    160 
    161 public:
    162  ElfSize(ElfSection* s) : section(s) {};
    163  unsigned int getValue();
    164  ElfSection* getSection() { return section; }
    165 };
    166 
    167 class ElfEntSize : public ElfValue {
    168  ElfSection* section;
    169 
    170 public:
    171  ElfEntSize(ElfSection* s) : section(s) {};
    172  unsigned int getValue();
    173  ElfSection* getSection() { return section; }
    174 };
    175 
    176 template <typename T>
    177 class serializable : public T::Type64 {
    178 public:
    179  serializable() {};
    180  serializable(const typename T::Type64& p) : T::Type64(p) {};
    181 
    182 private:
    183  template <typename R>
    184  void init(const char* buf, size_t len, unsigned char ei_data) {
    185    R e;
    186    assert(len >= sizeof(e));
    187    memcpy(&e, buf, sizeof(e));
    188    if (ei_data == ELFDATA2LSB) {
    189      T::template swap<little_endian>(e, *this);
    190      return;
    191    } else if (ei_data == ELFDATA2MSB) {
    192      T::template swap<big_endian>(e, *this);
    193      return;
    194    }
    195    throw std::runtime_error("Unsupported ELF data encoding");
    196  }
    197 
    198  template <typename R>
    199  void serialize(const char* buf, size_t len, unsigned char ei_data) {
    200    assert(len >= sizeof(R));
    201    if (ei_data == ELFDATA2LSB) {
    202      T::template swap<little_endian>(*this, *(R*)buf);
    203      return;
    204    } else if (ei_data == ELFDATA2MSB) {
    205      T::template swap<big_endian>(*this, *(R*)buf);
    206      return;
    207    }
    208    throw std::runtime_error("Unsupported ELF data encoding");
    209  }
    210 
    211 public:
    212  serializable(const char* buf, size_t len, unsigned char ei_class,
    213               unsigned char ei_data) {
    214    if (ei_class == ELFCLASS32) {
    215      init<typename T::Type32>(buf, len, ei_data);
    216      return;
    217    } else if (ei_class == ELFCLASS64) {
    218      init<typename T::Type64>(buf, len, ei_data);
    219      return;
    220    }
    221    throw std::runtime_error("Unsupported ELF class");
    222  }
    223 
    224  serializable(std::ifstream& file, unsigned char ei_class,
    225               unsigned char ei_data) {
    226    if (ei_class == ELFCLASS32) {
    227      typename T::Type32 e;
    228      file.read((char*)&e, sizeof(e));
    229      init<typename T::Type32>((char*)&e, sizeof(e), ei_data);
    230      return;
    231    } else if (ei_class == ELFCLASS64) {
    232      typename T::Type64 e;
    233      file.read((char*)&e, sizeof(e));
    234      init<typename T::Type64>((char*)&e, sizeof(e), ei_data);
    235      return;
    236    }
    237    throw std::runtime_error("Unsupported ELF class or data encoding");
    238  }
    239 
    240  void serialize(std::ofstream& file, unsigned char ei_class,
    241                 unsigned char ei_data) {
    242    if (ei_class == ELFCLASS32) {
    243      typename T::Type32 e;
    244      serialize<typename T::Type32>((char*)&e, sizeof(e), ei_data);
    245      file.write((char*)&e, sizeof(e));
    246      return;
    247    } else if (ei_class == ELFCLASS64) {
    248      typename T::Type64 e;
    249      serialize<typename T::Type64>((char*)&e, sizeof(e), ei_data);
    250      file.write((char*)&e, sizeof(e));
    251      return;
    252    }
    253    throw std::runtime_error("Unsupported ELF class or data encoding");
    254  }
    255 
    256  void serialize(char* buf, size_t len, unsigned char ei_class,
    257                 unsigned char ei_data) {
    258    if (ei_class == ELFCLASS32) {
    259      serialize<typename T::Type32>(buf, len, ei_data);
    260      return;
    261    } else if (ei_class == ELFCLASS64) {
    262      serialize<typename T::Type64>(buf, len, ei_data);
    263      return;
    264    }
    265    throw std::runtime_error("Unsupported ELF class");
    266  }
    267 
    268  static inline unsigned int size(unsigned char ei_class) {
    269    if (ei_class == ELFCLASS32)
    270      return sizeof(typename T::Type32);
    271    else if (ei_class == ELFCLASS64)
    272      return sizeof(typename T::Type64);
    273    return 0;
    274  }
    275 };
    276 
    277 typedef serializable<Elf_Shdr_Traits> Elf_Shdr;
    278 
    279 class Elf {
    280 public:
    281  Elf(std::ifstream& file);
    282  ~Elf();
    283 
    284  /* index == -1 is treated as index == ehdr.e_shstrndx */
    285  ElfSection* getSection(int index);
    286 
    287  ElfSection* getSectionAt(Elf64_Off offset);
    288 
    289  ElfSegment* getSegmentByType(unsigned int type, ElfSegment* last = nullptr);
    290 
    291  ElfDynamic_Section* getDynSection();
    292 
    293  void normalize();
    294  void write(std::ofstream& file);
    295 
    296  unsigned char getClass();
    297  unsigned char getData();
    298  unsigned char getType();
    299  unsigned char getMachine();
    300  unsigned int getSize();
    301 
    302  void insertSegmentAfter(ElfSegment* previous, ElfSegment* segment) {
    303    std::vector<ElfSegment*>::iterator prev =
    304        std::find(segments.begin(), segments.end(), previous);
    305    segments.insert(prev + 1, segment);
    306  }
    307 
    308  void removeSegment(ElfSegment* segment);
    309 
    310 private:
    311  Elf_Ehdr* ehdr;
    312  ElfLocation eh_entry;
    313  ElfStrtab_Section* eh_shstrndx;
    314  ElfSection** sections;
    315  std::vector<ElfSegment*> segments;
    316  ElfSection *shdr_section, *phdr_section;
    317  /* Values used only during initialization */
    318  Elf_Shdr** tmp_shdr;
    319  std::ifstream* tmp_file;
    320 };
    321 
    322 class ElfSection {
    323 public:
    324  typedef union {
    325    ElfSection* section;
    326    int index;
    327  } SectionInfo;
    328 
    329  ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent);
    330 
    331  virtual ~ElfSection() { free(data); }
    332 
    333  const char* getName() { return name; }
    334  unsigned int getType() { return shdr.sh_type; }
    335  unsigned int getFlags() { return shdr.sh_flags; }
    336  Elf64_Addr getAddr();
    337  Elf64_Off getSize() { return shdr.sh_size; }
    338  unsigned int getAddrAlign() { return shdr.sh_addralign; }
    339  unsigned int getEntSize() { return shdr.sh_entsize; }
    340  const char* getData() { return data; }
    341  ElfSection* getLink() { return link; }
    342  SectionInfo getInfo() { return info; }
    343 
    344  void shrink(unsigned int newsize) {
    345    if (newsize < shdr.sh_size) {
    346      shdr.sh_size = newsize;
    347      markDirty();
    348    }
    349  }
    350 
    351  void grow(unsigned int newsize) {
    352    if (newsize > shdr.sh_size) {
    353      data = static_cast<char*>(realloc(data, newsize));
    354      memset(data + shdr.sh_size, 0, newsize - shdr.sh_size);
    355      shdr.sh_size = newsize;
    356      markDirty();
    357    }
    358  }
    359 
    360  Elf64_Off getOffset();
    361  int getIndex();
    362  Elf_Shdr& getShdr();
    363 
    364  ElfSection* getNext() { return next; }
    365  ElfSection* getPrevious() { return previous; }
    366 
    367  virtual bool isRelocatable() {
    368    return ((getType() == SHT_SYMTAB) || (getType() == SHT_STRTAB) ||
    369            (getType() == SHT_RELA) || (getType() == SHT_HASH) ||
    370            (getType() == SHT_NOTE) || (getType() == SHT_REL) ||
    371            (getType() == SHT_DYNSYM) || (getType() == SHT_GNU_HASH) ||
    372            (getType() == SHT_GNU_verdef) || (getType() == SHT_GNU_verneed) ||
    373            (getType() == SHT_GNU_versym) || getSegmentByType(PT_INTERP)) &&
    374           (getFlags() & SHF_ALLOC);
    375  }
    376 
    377  void insertAfter(ElfSection* section, bool dirty = true) {
    378    if (previous != nullptr) previous->next = next;
    379    if (next != nullptr) next->previous = previous;
    380    previous = section;
    381    if (section != nullptr) {
    382      next = section->next;
    383      section->next = this;
    384    } else
    385      next = nullptr;
    386    if (next != nullptr) next->previous = this;
    387    if (dirty) markDirty();
    388    insertInSegments(section->segments);
    389  }
    390 
    391  virtual void insertBefore(ElfSection* section, bool dirty = true) {
    392    if (previous != nullptr) previous->next = next;
    393    if (next != nullptr) next->previous = previous;
    394    next = section;
    395    if (section != nullptr) {
    396      previous = section->previous;
    397      section->previous = this;
    398    } else
    399      previous = nullptr;
    400    if (previous != nullptr) previous->next = this;
    401    if (dirty) markDirty();
    402    insertInSegments(section->segments);
    403  }
    404 
    405  void markDirty() {
    406    if (link != nullptr) shdr.sh_link = -1;
    407    if (info.index) shdr.sh_info = -1;
    408    shdr.sh_offset = -1;
    409    if (isRelocatable()) shdr.sh_addr = -1;
    410    if (next) next->markDirty();
    411  }
    412 
    413  virtual void serialize(std::ofstream& file, unsigned char ei_class,
    414                         unsigned char ei_data) {
    415    if (getType() == SHT_NOBITS) return;
    416    file.seekp(getOffset());
    417    file.write(data, getSize());
    418  }
    419 
    420  ElfSegment* getSegmentByType(unsigned int type);
    421 
    422 private:
    423  friend class ElfSegment;
    424 
    425  void addToSegment(ElfSegment* segment) { segments.push_back(segment); }
    426 
    427  void removeFromSegment(ElfSegment* segment) {
    428    std::vector<ElfSegment*>::iterator i =
    429        std::find(segments.begin(), segments.end(), segment);
    430    segments.erase(i, i + 1);
    431  }
    432 
    433  void insertInSegments(std::vector<ElfSegment*>& segs);
    434 
    435 protected:
    436  Elf_Shdr shdr;
    437  char* data;
    438  const char* name;
    439 
    440 private:
    441  ElfSection* link;
    442  SectionInfo info;
    443  ElfSection *next, *previous;
    444  int index;
    445  std::vector<ElfSegment*> segments;
    446 };
    447 
    448 class ElfSegment {
    449 public:
    450  ElfSegment(Elf_Phdr* phdr);
    451 
    452  unsigned int getType() { return type; }
    453  unsigned int getFlags() { return flags; }
    454  unsigned int getAlign() { return align; }
    455 
    456  ElfSection* getFirstSection() {
    457    return sections.empty() ? nullptr : sections.front();
    458  }
    459  int getVPDiff() { return v_p_diff; }
    460  unsigned int getFileSize();
    461  unsigned int getMemSize();
    462  unsigned int getOffset();
    463  unsigned int getAddr();
    464 
    465  void addSection(ElfSection* section);
    466  void removeSection(ElfSection* section);
    467 
    468  std::list<ElfSection*>::iterator begin() { return sections.begin(); }
    469  std::list<ElfSection*>::iterator end() { return sections.end(); }
    470 
    471  void clear();
    472 
    473 private:
    474  unsigned int type;
    475  int v_p_diff;  // Difference between physical and virtual address
    476  unsigned int flags;
    477  unsigned int align;
    478  std::list<ElfSection*> sections;
    479  // The following are only really used for PT_GNU_RELRO until something
    480  // better is found.
    481  unsigned int vaddr;
    482  unsigned int filesz, memsz;
    483 };
    484 
    485 class Elf_Ehdr : public serializable<Elf_Ehdr_Traits>, public ElfSection {
    486 public:
    487  Elf_Ehdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data);
    488  void serialize(std::ofstream& file, unsigned char ei_class,
    489                 unsigned char ei_data) {
    490    serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data);
    491  }
    492 };
    493 
    494 class Elf_Phdr : public serializable<Elf_Phdr_Traits> {
    495 public:
    496  Elf_Phdr() {};
    497  Elf_Phdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
    498      : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data) {};
    499  bool contains(ElfSection* section) {
    500    unsigned int size = section->getSize();
    501    unsigned int addr = section->getAddr();
    502    // This may be biased, but should work in most cases
    503    if ((section->getFlags() & SHF_ALLOC) == 0) return false;
    504    // Special case for PT_DYNAMIC. Eventually, this should
    505    // be better handled than special cases
    506    if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC))
    507      return false;
    508    // Special case for PT_TLS.
    509    if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS)) return false;
    510    return (addr >= p_vaddr) && (addr + size <= p_vaddr + p_memsz);
    511  }
    512 };
    513 
    514 typedef serializable<Elf_Dyn_Traits> Elf_Dyn;
    515 
    516 struct Elf_DynValue {
    517  unsigned int tag;
    518  ElfValue* value;
    519 };
    520 
    521 class ElfDynamic_Section : public ElfSection {
    522 public:
    523  ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent);
    524  ~ElfDynamic_Section();
    525 
    526  void serialize(std::ofstream& file, unsigned char ei_class,
    527                 unsigned char ei_data);
    528 
    529  ElfValue* getValueForType(unsigned int tag);
    530  ElfSection* getSectionForType(unsigned int tag);
    531  bool setValueForType(unsigned int tag, ElfValue* val);
    532 
    533 private:
    534  std::vector<Elf_DynValue> dyns;
    535 };
    536 
    537 typedef serializable<Elf_Sym_Traits> Elf_Sym;
    538 
    539 struct Elf_SymValue {
    540  const char* name;
    541  unsigned char info;
    542  unsigned char other;
    543  ElfLocation value;
    544  unsigned int size;
    545  bool defined;
    546 };
    547 
    548 #define STT(type) (1 << STT_##type)
    549 
    550 class ElfSymtab_Section : public ElfSection {
    551 public:
    552  ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent);
    553 
    554  void serialize(std::ofstream& file, unsigned char ei_class,
    555                 unsigned char ei_data);
    556 
    557  Elf_SymValue* lookup(const char* name,
    558                       unsigned int type_filter = STT(OBJECT) | STT(FUNC));
    559 
    560  // private: // Until we have a real API
    561  std::vector<Elf_SymValue> syms;
    562 };
    563 
    564 class Elf_Rel : public serializable<Elf_Rel_Traits> {
    565 public:
    566  Elf_Rel() : serializable<Elf_Rel_Traits>() {};
    567 
    568  Elf_Rel(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
    569      : serializable<Elf_Rel_Traits>(file, ei_class, ei_data) {};
    570 
    571  static const unsigned int sh_type = SHT_REL;
    572  static const unsigned int d_tag = DT_REL;
    573  static const unsigned int d_tag_count = DT_RELCOUNT;
    574 };
    575 
    576 class Elf_Rela : public serializable<Elf_Rela_Traits> {
    577 public:
    578  Elf_Rela() : serializable<Elf_Rela_Traits>() {};
    579 
    580  Elf_Rela(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
    581      : serializable<Elf_Rela_Traits>(file, ei_class, ei_data) {};
    582 
    583  static const unsigned int sh_type = SHT_RELA;
    584  static const unsigned int d_tag = DT_RELA;
    585  static const unsigned int d_tag_count = DT_RELACOUNT;
    586 };
    587 
    588 template <class Rel>
    589 class ElfRel_Section : public ElfSection {
    590 public:
    591  ElfRel_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent)
    592      : ElfSection(s, file, parent) {
    593    auto pos = file->tellg();
    594    file->seekg(shdr.sh_offset);
    595    for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
    596      Rel r(*file, parent->getClass(), parent->getData());
    597      rels.push_back(r);
    598    }
    599    file->seekg(pos);
    600  }
    601 
    602  void serialize(std::ofstream& file, unsigned char ei_class,
    603                 unsigned char ei_data) {
    604    for (typename std::vector<Rel>::iterator i = rels.begin(); i != rels.end();
    605         ++i)
    606      (*i).serialize(file, ei_class, ei_data);
    607  }
    608  // private: // Until we have a real API
    609  std::vector<Rel> rels;
    610 };
    611 
    612 class ElfStrtab_Section : public ElfSection {
    613 public:
    614  ElfStrtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent)
    615      : ElfSection(s, file, parent) {
    616    table.push_back(table_storage(data, shdr.sh_size));
    617  }
    618 
    619  ~ElfStrtab_Section() {
    620    for (std::vector<table_storage>::iterator t = table.begin() + 1;
    621         t != table.end(); ++t)
    622      delete[] t->buf;
    623  }
    624 
    625  const char* getStr(unsigned int index);
    626 
    627  const char* getStr(const char* string);
    628 
    629  unsigned int getStrIndex(const char* string);
    630 
    631  void serialize(std::ofstream& file, unsigned char ei_class,
    632                 unsigned char ei_data);
    633 
    634 private:
    635  struct table_storage {
    636    unsigned int size, used;
    637    char* buf;
    638 
    639    table_storage() : size(4096), used(0), buf(new char[4096]) {}
    640    table_storage(const char* data, unsigned int sz)
    641        : size(sz), used(sz), buf(const_cast<char*>(data)) {}
    642  };
    643  std::vector<table_storage> table;
    644 };
    645 
    646 inline unsigned char Elf::getClass() { return ehdr->e_ident[EI_CLASS]; }
    647 
    648 inline unsigned char Elf::getData() { return ehdr->e_ident[EI_DATA]; }
    649 
    650 inline unsigned char Elf::getType() { return ehdr->e_type; }
    651 
    652 inline unsigned char Elf::getMachine() { return ehdr->e_machine; }
    653 
    654 inline unsigned int Elf::getSize() {
    655  ElfSection* section;
    656  for (section = shdr_section /* It's usually not far from the end */;
    657       section->getNext() != nullptr; section = section->getNext());
    658  return section->getOffset() + section->getSize();
    659 }
    660 
    661 inline ElfSegment* ElfSection::getSegmentByType(unsigned int type) {
    662  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
    663       seg != segments.end(); ++seg)
    664    if ((*seg)->getType() == type) return *seg;
    665  return nullptr;
    666 }
    667 
    668 inline void ElfSection::insertInSegments(std::vector<ElfSegment*>& segs) {
    669  for (std::vector<ElfSegment*>::iterator it = segs.begin(); it != segs.end();
    670       ++it) {
    671    (*it)->addSection(this);
    672  }
    673 }
    674 
    675 inline ElfLocation::ElfLocation(ElfSection* section, unsigned int off,
    676                                enum position pos)
    677    : section(section) {
    678  if ((pos == ABSOLUTE) && section)
    679    offset = off - section->getAddr();
    680  else
    681    offset = off;
    682 }
    683 
    684 inline ElfLocation::ElfLocation(unsigned int location, Elf* elf) {
    685  section = elf->getSectionAt(location);
    686  offset = location - (section ? section->getAddr() : 0);
    687 }
    688 
    689 inline unsigned int ElfLocation::getValue() {
    690  return (section ? section->getAddr() : 0) + offset;
    691 }
    692 
    693 inline const char* ElfLocation::getBuffer() {
    694  return section ? section->getData() + offset : nullptr;
    695 }
    696 
    697 inline unsigned int ElfSize::getValue() { return section->getSize(); }
    698 
    699 inline unsigned int ElfEntSize::getValue() { return section->getEntSize(); }