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