1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // The University of Illinois/NCSA
4 // Open Source License (NCSA)
5 //
6 // Copyright (c) 2014-2016, Advanced Micro Devices, Inc. All rights reserved.
7 //
8 // Developed by:
9 //
10 //                 AMD Research and AMD HSA Software Development
11 //
12 //                 Advanced Micro Devices, Inc.
13 //
14 //                 www.amd.com
15 //
16 // Permission is hereby granted, free of charge, to any person obtaining a copy
17 // of this software and associated documentation files (the "Software"), to
18 // deal with the Software without restriction, including without limitation
19 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
20 // and/or sell copies of the Software, and to permit persons to whom the
21 // Software is furnished to do so, subject to the following conditions:
22 //
23 //  - Redistributions of source code must retain the above copyright notice,
24 //    this list of conditions and the following disclaimers.
25 //  - Redistributions in binary form must reproduce the above copyright
26 //    notice, this list of conditions and the following disclaimers in
27 //    the documentation and/or other materials provided with the distribution.
28 //  - Neither the names of Advanced Micro Devices, Inc,
29 //    nor the names of its contributors may be used to endorse or promote
30 //    products derived from this Software without specific prior written
31 //    permission.
32 //
33 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
36 // THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
37 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
39 // DEALINGS WITH THE SOFTWARE.
40 //
41 ////////////////////////////////////////////////////////////////////////////////
42 
43 #include "amd_elf_image.hpp"
44 #include "amd_hsa_code_util.hpp"
45 #include <gelf.h>
46 #include <errno.h>
47 #include <cstring>
48 #include <cerrno>
49 #include <fstream>
50 #include <memory>
51 #include <cassert>
52 #include <cstdlib>
53 #include <algorithm>
54 #ifdef _WIN32
55 #include <Windows.h>
56 #define alignof __alignof
57 #endif // _WIN32
58 #include <libelf.h>
59 
60 #ifndef _WIN32
61 #define _open open
62 #define _close close
63 #define _tempnam tempnam
64 #include <fcntl.h>
65 #include <unistd.h>
66 #endif
67 
68 #if defined(USE_MEMFILE)
69 
70 #include "memfile.h"
71 #define OpenTemp(f)           mem_open(NULL, 0, 0)
72 #define CloseTemp(f)          mem_close(f)
73 #define _read(f, b, l)        mem_read((f), (b), (l))
74 #define _write(f, b, l)       mem_write((f), (b), (l))
75 #define _lseek(f, l, w)       mem_lseek((f), (l), (w))
76 #define _ftruncate(f, l)      mem_ftruncate((f), (size_t)(l))
77 #define sendfile(o, i, p, s)  mem_sendfile((o), (i), (p), (s))
78 
79 #else // USE_MEMFILE
80 
81 #define OpenTemp(f) amd::hsa::OpenTempFile(f);
82 #define CloseTemp(f) amd::hsa::CloseTempFile(f);
83 
84 #ifndef _WIN32
85 #define _read read
86 #define _write write
87 #define _lseek lseek
88 #define _ftruncate ftruncate
89 #if defined(__FreeBSD__) || defined(__DragonFly__)
90 #include <sys/types.h>
91 #include <sys/socket.h>
92 #include <sys/uio.h>
93 #ifndef SF_SYNC
94 #define SF_SYNC 0
95 #endif
96 #else
97 #include <sys/sendfile.h>
98 #endif
99 #else
100 #define _ftruncate _chsize
101 #endif // !_WIN32
102 
103 #endif // !USE_MEMFILE
104 
105 #if !defined(BSD_LIBELF)
106   #define elf_setshstrndx elfx_update_shstrndx
107 #endif
108 
109 #define NOTE_RECORD_ALIGNMENT 4
110 
111 using amd::hsa::alignUp;
112 
113 namespace amd {
114   namespace elf {
115 
116     class FileImage {
117     public:
118       FileImage();
119       ~FileImage();
120       bool create();
121       bool readFrom(const std::string& filename);
122       bool copyFrom(const void* data, size_t size);
123       bool writeTo(const std::string& filename);
124       bool copyTo(void** buffer, size_t* size = 0);
125       bool copyTo(void* buffer, size_t size);
126       size_t getSize();
127 
output()128       std::string output() { return out.str(); }
129 
fd()130       int fd() { return d; }
131 
132     private:
133       int d;
134       std::ostringstream out;
135 
136       bool error(const char* msg);
137       bool perror(const char *msg);
138       std::string werror();
139     };
140 
FileImage()141     FileImage::FileImage()
142       : d(-1)
143     {
144     }
145 
~FileImage()146     FileImage::~FileImage()
147     {
148       if (d != -1) { CloseTemp(d); }
149     }
150 
error(const char * msg)151     bool FileImage::error(const char* msg)
152     {
153       out << "Error: " << msg << std::endl;
154       return false;
155     }
156 
perror(const char * msg)157     bool FileImage::perror(const char* msg)
158     {
159       out << "Error: " << msg << ": " << strerror(errno) << std::endl;
160       return false;
161     }
162 
163 #ifdef _WIN32
werror()164     std::string FileImage::werror()
165     {
166       LPVOID lpMsgBuf;
167       DWORD dw = GetLastError();
168 
169       FormatMessage(
170         FORMAT_MESSAGE_ALLOCATE_BUFFER |
171         FORMAT_MESSAGE_FROM_SYSTEM |
172         FORMAT_MESSAGE_IGNORE_INSERTS,
173         NULL,
174         dw,
175         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
176         (LPTSTR)&lpMsgBuf,
177         0, NULL);
178       std::string result((LPTSTR)lpMsgBuf);
179       LocalFree(lpMsgBuf);
180       return result;
181     }
182 #endif // _WIN32
183 
create()184     bool FileImage::create()
185     {
186       d = OpenTemp("amdelf");
187       if (d == -1) { return error("Failed to open temporary file for elf image"); }
188       return true;
189     }
190 
readFrom(const std::string & filename)191     bool FileImage::readFrom(const std::string& filename)
192     {
193 #ifdef _WIN32
194       std::unique_ptr<char> buffer(new char[32 * 1024 * 1024]);
195       HANDLE in = CreateFile(filename.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
196       if (in == INVALID_HANDLE_VALUE) { out << "Failed to open " << filename << ": " << werror() << std::endl; return false; }
197       DWORD read;
198       unsigned write;
199       int written;
200       do {
201         if (!ReadFile(in, buffer.get(), sizeof(buffer), &read, NULL)) {
202           out << "Failed to read " << filename << ": " << werror() << std::endl;
203           CloseHandle(in);
204           return false;
205         }
206         if (read > 0) {
207           write = read;
208           do {
209             written = _write(d, buffer.get(), write);
210             if (written < 0) {
211               out << "Failed to write image file: " << werror() << std::endl;
212               CloseHandle(in);
213             }
214             write -= written;
215           } while (write > 0);
216         }
217       } while (read > 0);
218       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek(0) failed"); }
219       CloseHandle(in);
220       return true;
221 #else // _WIN32
222       int in = _open(filename.c_str(), O_RDONLY);
223       if (in < 0) { return perror("open failed"); }
224       if (_lseek(in, 0L, SEEK_END) < 0) { return perror("lseek failed"); }
225       off_t size;
226       if ((size = _lseek(in, 0L, SEEK_CUR)) < 0) { return perror("lseek(2) failed"); }
227       if (_lseek(in, 0L, SEEK_SET) < 0) { return perror("lseek(3) failed"); }
228       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek(3) failed"); }
229       ssize_t written;
230       do {
231 #if defined(__FreeBSD__) || defined(__DragonFly__)
232         int err = sendfile(in, d, size, 0, NULL, &written, SF_SYNC);
233 #else
234         written = sendfile(d, in, NULL, size);
235 #endif
236         if (written < 0) {
237           _close(in);
238           return perror("sendfile failed");
239         }
240         size -= written;
241       } while (size > 0);
242       _close(in);
243       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek(0) failed"); }
244       return true;
245 #endif // _WIN32
246     }
247 
copyFrom(const void * data,size_t size)248     bool FileImage::copyFrom(const void* data, size_t size)
249     {
250       assert(d != -1);
251       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek failed"); }
252       if (_ftruncate(d, 0) < 0) { return perror("ftruncate failed"); }
253       int written, offset = 0;
254       while (size > 0) {
255         written = _write(d, (const char*) data + offset, size);
256         if (written < 0) {
257           return perror("write failed");
258         }
259         size -= written;
260         offset += written;
261       }
262       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek failed"); }
263       return true;
264     }
265 
getSize()266     size_t FileImage::getSize()
267     {
268       assert(d != -1);
269       if (_lseek(d, 0L, SEEK_END) < 0) { return perror("lseek failed"); }
270       long seek = 0;
271       if ((seek = _lseek(d, 0L, SEEK_CUR)) < 0) { return perror("lseek(2) failed"); }
272       if (_lseek(d, 0L, SEEK_SET) < 0) { return perror("lseek(3) failed"); }
273       return seek;
274     }
275 
copyTo(void ** buffer,size_t * size)276     bool FileImage::copyTo(void** buffer, size_t* size)
277     {
278       size_t size1 = getSize();
279       void* buffer1 = malloc(size1);
280       if (_read(d, buffer1, size1) < 0) { free(buffer1); return perror("read failed"); }
281       *buffer = buffer1;
282       if (size) { *size = size1; }
283       return true;
284     }
285 
copyTo(void * buffer,size_t size)286     bool FileImage::copyTo(void* buffer, size_t size)
287     {
288       size_t size1 = getSize();
289       if (size < size1) { return error("Buffer size is not enough"); }
290       if (_read(d, buffer, size1) < 0) { return perror("read failed"); }
291       return true;
292     }
293 
writeTo(const std::string & filename)294     bool FileImage::writeTo(const std::string& filename)
295     {
296       bool res = false;
297       size_t size = 0;
298       void *buffer = nullptr;
299       if (copyTo(&buffer, &size)) {
300         res = true;
301         std::ofstream out(filename.c_str(), std::ios::binary);
302         out.write((char*)buffer, size);
303       }
304       free(buffer);
305       return res;
306     }
307 
308     class Buffer {
309     public:
310       typedef unsigned char byte_type;
311       typedef size_t size_type;
312 
313       Buffer();
314       Buffer(const byte_type *src, size_type size, size_type align = 0);
315       virtual ~Buffer();
316 
raw() const317       const byte_type* raw() const
318         { return this->isConst() ? ptr_ : data_.data(); }
align() const319       size_type align() const
320         { return align_; }
size() const321       size_type size() const
322         { return this->isConst() ? size_ : data_.size(); }
isConst() const323       bool isConst() const
324         { return 0 != size_; }
isEmpty()325       bool isEmpty()
326         { return size() == 0; }
hasRaw(const byte_type * src) const327       bool hasRaw(const byte_type *src) const
328         { return (src >= this->raw()) && (src < this->raw() + this->size()); }
329       template<typename T>
has(const T * src) const330       bool has(const T *src) const
331         { return this->hasRaw((const byte_type*)src); }
has(size_type offset) const332       bool has(size_type offset) const
333         { return offset < this->size(); }
334 
335       template<typename T>
getOffset(const T * src) const336       size_type getOffset(const T *src) const
337         { return this->getRawOffset((const byte_type*)src); }
338       template<typename T>
get(size_type offset) const339       T get(size_type offset) const
340         { return (T)this->getRaw(offset); }
341       size_type addString(const std::string &str, size_type align = 0);
342       size_type addStringLength(const std::string &str, size_type align = 0);
nextOffset(size_type align) const343       size_type nextOffset(size_type align) const { return alignUp(this->size(), align); }
344       template<typename T>
add(const T * src,size_type size,size_type align)345       size_type add(const T *src, size_type size, size_type align)
346         { return this->addRaw((const byte_type*)src, size, align); }
347       template<typename T>
add(const T & src,size_type align=0)348       size_type add(const T &src, size_type align = 0)
349         { return this->addRaw((const byte_type*)&src, sizeof(T), align == 0 ? alignof(T) : align); }
350       size_type align(size_type align);
351 
352       template<typename T>
reserve()353       size_type reserve()
354       {
355         Buffer::size_type offset = this->align(alignof(T));
356         data_.insert(data_.end(), sizeof(T), 0x0);
357         return offset;
358       }
359 
360     private:
361       size_type getRawOffset(const byte_type *src) const;
362       const byte_type* getRaw(size_type offset) const;
363       size_type addRaw(const byte_type *src, size_type size, size_type align);
364 
365       std::vector<byte_type> data_;
366       const byte_type *ptr_;
367       size_type size_;
368       size_type align_;
369     };
370 
Buffer()371     Buffer::Buffer()
372       : ptr_(nullptr)
373       , size_(0)
374       , align_(0)
375     {
376     }
377 
Buffer(const Buffer::byte_type * src,Buffer::size_type size,Buffer::size_type align)378     Buffer::Buffer(const Buffer::byte_type *src, Buffer::size_type size, Buffer::size_type align)
379       : ptr_(src)
380       , size_(size)
381       , align_(align)
382     {
383     }
384 
~Buffer()385     Buffer::~Buffer()
386     {
387     }
388 
getRawOffset(const Buffer::byte_type * src) const389     Buffer::size_type Buffer::getRawOffset(const Buffer::byte_type *src) const
390     {
391       assert(this->has(src));
392       return src - this->raw();
393     }
394 
getRaw(Buffer::size_type offset) const395     const Buffer::byte_type* Buffer::getRaw(Buffer::size_type offset) const
396     {
397       assert(this->has(offset));
398       return this->raw() + offset;
399     }
400 
addRaw(const Buffer::byte_type * src,Buffer::size_type size,Buffer::size_type align)401     Buffer::size_type Buffer::addRaw(const Buffer::byte_type *src, Buffer::size_type size, Buffer::size_type align)
402     {
403       assert(!this->isConst());
404       assert(nullptr != src);
405       assert(0 != size);
406       assert(0 != align);
407       Buffer::size_type offset = this->align(align);
408       data_.insert(data_.end(), src, src + size);
409       return offset;
410     }
411 
addString(const std::string & str,size_type align)412     Buffer::size_type Buffer::addString(const std::string &str, size_type align)
413     {
414       return this->add(str.c_str(), str.length() + 1, align == 0 ? alignof(char) : align);
415     }
416 
addStringLength(const std::string & str,size_type align)417     Buffer::size_type Buffer::addStringLength(const std::string &str, size_type align)
418     {
419       return this->add((uint32_t)(str.length() + 1), align == 0 ? alignof(uint32_t) : align);
420     }
421 
align(Buffer::size_type align)422     Buffer::size_type Buffer::align(Buffer::size_type align)
423     {
424       assert(!this->isConst());
425       assert(0 != align);
426       Buffer::size_type offset = alignUp(this->size(), align);
427       align_ = (std::max)(align_, align);
428       data_.insert(data_.end(), offset - this->size(), 0x0);
429       return offset;
430     }
431 
432     class GElfImage;
433     class GElfSegment;
434 
435     class GElfSection : public virtual Section {
436     public:
437       GElfSection(GElfImage* elf);
438 
439       bool push(const char* name, uint32_t shtype, uint64_t shflags, uint16_t shlink, uint32_t info, uint32_t align, uint64_t entsize = 0);
440       bool pull0();
441       bool pull(uint16_t ndx);
pullData()442       virtual bool pullData() { return true; }
443       bool push();
444       uint16_t getSectionIndex() const override;
type() const445       uint32_t type() const override { return hdr.sh_type; }
446       std::string Name() const override;
offset() const447       uint64_t offset() const override { return hdr.sh_offset; }
addr() const448       uint64_t addr() const override { return hdr.sh_addr; }
449       bool updateAddr(uint64_t addr) override;
addralign() const450       uint64_t addralign() const override { return data0.size() == 0 ? data.align() : data0.align(); }
flags() const451       uint64_t flags() const override { return hdr.sh_flags; }
size() const452       uint64_t size() const override { return data0.size() == 0 ? data.size() : data0.size(); }
453       uint64_t nextDataOffset(uint64_t align) const override;
454       uint64_t addData(const void *src, uint64_t size, uint64_t align) override;
455       bool getData(uint64_t offset, void* dest, uint64_t size) override;
hasRelocationSection() const456       bool hasRelocationSection() const override { return reloc_sec != 0; }
457       RelocationSection* relocationSection(SymbolTable* symtab = 0) override;
segment()458       Segment* segment() override { return seg; }
asRelocationSection()459       RelocationSection* asRelocationSection() override { return 0; }
setMemSize(uint64_t s)460       bool setMemSize(uint64_t s) override { memsize_ = s; return true; }
memSize() const461       uint64_t memSize() const override { return memsize_ ? memsize_ : size(); }
setAlign(uint64_t a)462       bool setAlign(uint64_t a) override { align_ = a; return true; }
memAlign() const463       uint64_t memAlign() const override { return align_ ? align_ : addralign(); }
464 
465     protected:
466       GElfImage* elf;
467       Segment* seg;
468       GElf_Shdr hdr;
469       Buffer data0, data;
470       uint64_t memsize_;
471       uint64_t align_;
472       RelocationSection *reloc_sec;
473 
474       size_t ndxscn;
475 
476       friend class GElfSymbol;
477       friend class GElfSegment;
478       friend class GElfImage;
479     };
480 
481     class GElfSegment : public Segment {
482     public:
483       GElfSegment(GElfImage* elf, uint16_t index);
484       GElfSegment(GElfImage* elf, uint16_t index, uint32_t type, uint32_t flags, uint64_t paddr = 0);
485       bool push(uint64_t vaddr);
486       bool pull();
type() const487       uint64_t type() const override { return phdr.p_type; }
memSize() const488       uint64_t memSize() const override { return phdr.p_memsz; }
align() const489       uint64_t align() const override { return phdr.p_align; }
imageSize() const490       uint64_t imageSize() const override { return phdr.p_filesz; }
vaddr() const491       uint64_t vaddr() const override { return phdr.p_vaddr; }
flags() const492       uint64_t flags() const override { return phdr.p_flags; }
offset() const493       uint64_t offset() const override { return phdr.p_offset; }
494       const char* data() const override;
495       uint16_t getSegmentIndex() override;
496       bool updateAddSection(Section *section) override;
497 
498     private:
499       GElfImage* elf;
500       uint16_t index;
501       GElf_Phdr phdr;
502       std::vector<Section*> sections;
503     };
504 
505     class GElfStringTable : public GElfSection, public StringTable {
506     public:
507       GElfStringTable(GElfImage* elf);
508       bool push(const char* name, uint32_t shtype, uint64_t shflags);
509       bool pullData() override;
510       const char* addString(const std::string& s) override;
511       size_t addString1(const std::string& s) override;
512       const char* getString(size_t ndx) override;
513       size_t getStringIndex(const char* name) override;
514 
getSectionIndex() const515       uint16_t getSectionIndex() const override { return GElfSection::getSectionIndex(); }
type() const516       uint32_t type() const override { return GElfSection::type(); }
Name() const517       std::string Name() const override { return GElfSection::Name(); }
addr() const518       uint64_t addr() const override { return GElfSection::addr(); }
offset() const519       uint64_t offset() const override { return GElfSection::offset(); }
updateAddr(uint64_t addr)520       bool updateAddr(uint64_t addr) override { return GElfSection::updateAddr(addr); }
addralign() const521       uint64_t addralign() const override { return GElfSection::addralign(); }
flags() const522       uint64_t flags() const override { return GElfSection::flags(); }
size() const523       uint64_t size() const override { return GElfSection::size(); }
segment()524       Segment* segment() override { return GElfSection::segment(); }
nextDataOffset(uint64_t align) const525       uint64_t nextDataOffset(uint64_t align) const override { return GElfSection::nextDataOffset(align); }
addData(const void * src,uint64_t size,uint64_t align)526       uint64_t addData(const void *src, uint64_t size, uint64_t align) override { return GElfSection::addData(src, size, align); }
getData(uint64_t offset,void * dest,uint64_t size)527       bool getData(uint64_t offset, void* dest, uint64_t size) override { return GElfSection::getData(offset, dest, size); }
hasRelocationSection() const528       bool hasRelocationSection() const override { return GElfSection::hasRelocationSection(); }
relocationSection(SymbolTable * symtab)529       RelocationSection* relocationSection(SymbolTable* symtab) override { return GElfSection::relocationSection(); }
asRelocationSection()530       RelocationSection* asRelocationSection() override { return 0; }
memSize() const531       uint64_t memSize() const override { return GElfSection::memSize(); }
setMemSize(uint64_t s)532       bool setMemSize(uint64_t s) override { return GElfSection::setMemSize(s); }
memAlign() const533       uint64_t memAlign() const override { return GElfSection::memAlign(); }
setAlign(uint64_t a)534       bool setAlign(uint64_t a) override { return GElfSection::setAlign(a); }
535     };
536 
537     class GElfSymbolTable;
538 
539     class GElfSymbol : public Symbol {
540     public:
541       GElfSymbol(GElfSymbolTable* symtab, Buffer &data, size_t index);
542 
543       bool push(const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, uint16_t shndx, unsigned char other);
544 
index()545       uint32_t index() override { return eindex / sizeof(GElf_Rela); }
type()546       uint32_t type() override { return GELF_ST_TYPE(Sym()->st_info); }
binding()547       uint32_t binding() override { return GELF_ST_BIND(Sym()->st_info); }
size()548       uint64_t size() override { return Sym()->st_size; }
value()549       uint64_t value() override { return Sym()->st_value; }
other()550       unsigned char other() override { return Sym()->st_other; }
551       std::string name() override;
552       Section* section() override;
553 
setValue(uint64_t value)554       void setValue(uint64_t value) override { Sym()->st_value = value; }
setSize(uint64_t size)555       void setSize(uint64_t size) override { Sym()->st_size = size; }
556 
557     private:
Sym()558       GElf_Sym* Sym() { return edata.get<GElf_Sym*>(eindex); }
559       GElfSymbolTable* symtab;
560       Buffer &edata;
561       size_t eindex;
562       friend class GElfSymbolTable;
563     };
564 
565     class GElfSymbolTable : public GElfSection, public SymbolTable {
566     private:
567       Symbol* addSymbolInternal(Section* section, const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, unsigned char other = 0);
568 
569       GElfStringTable* strtab;
570       std::vector<std::unique_ptr<GElfSymbol>> symbols;
571       friend class GElfSymbol;
572 
573     public:
574       GElfSymbolTable(GElfImage* elf);
575       bool push(const char* name, GElfStringTable* strtab);
576       bool pullData() override;
getSectionIndex() const577       uint16_t getSectionIndex() const override { return GElfSection::getSectionIndex(); }
type() const578       uint32_t type() const override { return GElfSection::type(); }
Name() const579       std::string Name() const override { return GElfSection::Name(); }
offset() const580       uint64_t offset() const override { return GElfSection::offset(); }
addr() const581       uint64_t addr() const override { return GElfSection::addr(); }
updateAddr(uint64_t addr)582       bool updateAddr(uint64_t addr) override { return GElfSection::updateAddr(addr); }
addralign() const583       uint64_t addralign() const override { return GElfSection::addralign(); }
flags() const584       uint64_t flags() const override { return GElfSection::flags(); }
size() const585       uint64_t size() const override { return GElfSection::size(); }
segment()586       Segment* segment() override { return GElfSection::segment(); }
nextDataOffset(uint64_t align) const587       uint64_t nextDataOffset(uint64_t align) const override { return GElfSection::nextDataOffset(align); }
addData(const void * src,uint64_t size,uint64_t align)588       uint64_t addData(const void *src, uint64_t size, uint64_t align) override { return GElfSection::addData(src, size, align); }
getData(uint64_t offset,void * dest,uint64_t size)589       bool getData(uint64_t offset, void* dest, uint64_t size) override { return GElfSection::getData(offset, dest, size); }
hasRelocationSection() const590       bool hasRelocationSection() const override { return GElfSection::hasRelocationSection(); }
relocationSection(SymbolTable * symtab)591       RelocationSection* relocationSection(SymbolTable* symtab) override { return GElfSection::relocationSection(); }
592       Symbol* addSymbol(Section* section, const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, unsigned char other = 0) override;
593       size_t symbolCount() override;
594       Symbol* symbol(size_t i) override;
asRelocationSection()595       RelocationSection* asRelocationSection() override { return 0; }
memSize() const596       uint64_t memSize() const override { return GElfSection::memSize(); }
setMemSize(uint64_t s)597       bool setMemSize(uint64_t s) override { return GElfSection::setMemSize(s); }
memAlign() const598       uint64_t memAlign() const override { return GElfSection::memAlign(); }
setAlign(uint64_t a)599       bool setAlign(uint64_t a) override { return GElfSection::setAlign(a); }
600     };
601 
602     class GElfNoteSection : public GElfSection, public NoteSection {
603     public:
604       GElfNoteSection(GElfImage* elf);
605       bool push(const std::string& name);
getSectionIndex() const606       uint16_t getSectionIndex() const override { return GElfSection::getSectionIndex(); }
type() const607       uint32_t type() const override { return GElfSection::type(); }
Name() const608       std::string Name() const override { return GElfSection::Name(); }
addr() const609       uint64_t addr() const override { return GElfSection::addr(); }
updateAddr(uint64_t addr)610       bool updateAddr(uint64_t addr) override { return GElfSection::updateAddr(addr); }
offset() const611       uint64_t offset() const override { return GElfSection::offset(); }
addralign() const612       uint64_t addralign() const override { return GElfSection::addralign(); }
flags() const613       uint64_t flags() const override { return GElfSection::flags(); }
size() const614       uint64_t size() const override { return GElfSection::size(); }
segment()615       Segment* segment() override { return GElfSection::segment(); }
nextDataOffset(uint64_t align) const616       uint64_t nextDataOffset(uint64_t align) const override { return GElfSection::nextDataOffset(align); }
addData(const void * src,uint64_t size,uint64_t align)617       uint64_t addData(const void *src, uint64_t size, uint64_t align) override { return GElfSection::addData(src, size, align); }
getData(uint64_t offset,void * dest,uint64_t size)618       bool getData(uint64_t offset, void* dest, uint64_t size) override { return GElfSection::getData(offset, dest, size); }
hasRelocationSection() const619       bool hasRelocationSection() const override { return GElfSection::hasRelocationSection(); }
relocationSection(SymbolTable * symtab)620       RelocationSection* relocationSection(SymbolTable* symtab) override { return GElfSection::relocationSection(); }
621       bool addNote(const std::string& name, uint32_t type, const void* desc, uint32_t desc_size) override;
622       bool getNote(const std::string& name, uint32_t type, void** desc, uint32_t* desc_size) override;
asRelocationSection()623       RelocationSection* asRelocationSection() override { return 0; }
memSize() const624       uint64_t memSize() const override { return GElfSection::memSize(); }
setMemSize(uint64_t s)625       bool setMemSize(uint64_t s) override { return GElfSection::setMemSize(s); }
memAlign() const626       uint64_t memAlign() const override { return GElfSection::memAlign(); }
setAlign(uint64_t a)627       bool setAlign(uint64_t a) override { return GElfSection::setAlign(a); }
628     };
629 
630     class GElfRelocationSection;
631 
632     class GElfRelocation : public Relocation {
633     private:
Rela()634       GElf_Rela *Rela() { return edata.get<GElf_Rela*>(eindex); }
635 
636       GElfRelocationSection* rsection;
637       Buffer &edata;
638       size_t eindex;
639 
640     public:
GElfRelocation(GElfRelocationSection * rsection_,Buffer & edata_,size_t eindex_)641       GElfRelocation(GElfRelocationSection* rsection_, Buffer &edata_, size_t eindex_)
642         : rsection(rsection_),
643           edata(edata_), eindex(eindex_)
644       {
645       }
646 
647       bool push(uint32_t type, Symbol* symbol, uint64_t offset, int64_t addend);
648 
649       RelocationSection* section() override;
type()650       uint32_t type() override { return GELF_R_TYPE(Rela()->r_info); }
symbolIndex()651       uint32_t symbolIndex() override { return GELF_R_SYM(Rela()->r_info); }
652       Symbol* symbol() override;
offset()653       uint64_t offset() override { return Rela()->r_offset; }
addend()654       int64_t addend() override { return Rela()->r_addend; }
655     };
656 
657     class GElfRelocationSection : public GElfSection, public RelocationSection {
658     private:
659       Section* section;
660       GElfSymbolTable* symtab;
661       std::vector<std::unique_ptr<GElfRelocation>> relocations;
662 
663     public:
664       GElfRelocationSection(GElfImage* elf, Section* targetSection = 0, GElfSymbolTable* symtab_ = 0);
665       bool push(const std::string& name);
666       bool pullData() override;
getSectionIndex() const667       uint16_t getSectionIndex() const override { return GElfSection::getSectionIndex(); }
type() const668       uint32_t type() const override { return GElfSection::type(); }
Name() const669       std::string Name() const override { return GElfSection::Name(); }
addr() const670       uint64_t addr() const override { return GElfSection::addr(); }
offset() const671       uint64_t offset() const override { return GElfSection::offset(); }
updateAddr(uint64_t addr)672       bool updateAddr(uint64_t addr) override { return GElfSection::updateAddr(addr); }
addralign() const673       uint64_t addralign() const override { return GElfSection::addralign(); }
flags() const674       uint64_t flags() const override { return GElfSection::flags(); }
size() const675       uint64_t size() const override { return GElfSection::size(); }
segment()676       Segment* segment() override { return GElfSection::segment(); }
nextDataOffset(uint64_t align) const677       uint64_t nextDataOffset(uint64_t align) const override { return GElfSection::nextDataOffset(align); }
addData(const void * src,uint64_t size,uint64_t align)678       uint64_t addData(const void *src, uint64_t size, uint64_t align) override { return GElfSection::addData(src, size, align); }
getData(uint64_t offset,void * dest,uint64_t size)679       bool getData(uint64_t offset, void* dest, uint64_t size) override { return GElfSection::getData(offset, dest, size); }
hasRelocationSection() const680       bool hasRelocationSection() const override { return GElfSection::hasRelocationSection(); }
relocationSection(SymbolTable * symtab)681       RelocationSection* relocationSection(SymbolTable* symtab) override { return GElfSection::relocationSection(); }
asRelocationSection()682       RelocationSection* asRelocationSection() override { return this; }
683 
relocationCount() const684       size_t relocationCount() const override { return relocations.size(); }
relocation(size_t i)685       Relocation* relocation(size_t i) override { return relocations[i].get(); }
686       Relocation* addRelocation(uint32_t type, Symbol* symbol, uint64_t offset, int64_t addend) override;
targetSection()687       Section* targetSection() override { return section; }
memSize() const688       uint64_t memSize() const override { return GElfSection::memSize(); }
setMemSize(uint64_t s)689       bool setMemSize(uint64_t s) override { return GElfSection::setMemSize(s); }
memAlign() const690       uint64_t memAlign() const override { return GElfSection::memAlign(); }
setAlign(uint64_t a)691       bool setAlign(uint64_t a) override { return GElfSection::setAlign(a); }
692       friend class GElfRelocation;
693     };
694 
695     class GElfImage : public Image {
696     public:
697       GElfImage(int elfclass);
698       ~GElfImage();
699       bool initNew(uint16_t machine, uint16_t type, uint8_t os_abi = 0, uint8_t abi_version = 0, uint32_t e_flags = 0) override;
700       bool loadFromFile(const std::string& filename) override;
701       bool saveToFile(const std::string& filename) override;
702       bool initFromBuffer(const void* buffer, size_t size) override;
703       bool initAsBuffer(const void* buffer, size_t size) override;
704       bool close();
705       bool writeTo(const std::string& filename) override;
706       bool copyToBuffer(void** buf, size_t* size = 0) override;
707       bool copyToBuffer(void* buf, size_t size) override;
708 
data()709       const char* data() override { assert(buffer); return buffer; }
710       uint64_t size() override;
711 
712       bool push();
713 
714       bool Freeze() override;
715       bool Validate() override;
716 
Machine()717       uint16_t Machine() override { return ehdr.e_machine; }
Type()718       uint16_t Type() override { return ehdr.e_type; }
EFlags()719       uint32_t EFlags() override{ return ehdr.e_flags; }
720 
721       GElfStringTable* shstrtab() override;
722       GElfStringTable* strtab() override;
getSymtab(uint16_t index)723       GElfSymbolTable* getSymtab(uint16_t index) override
724       {
725         return static_cast<GElfSymbolTable*>(section(index));
726       }
727 
728       GElfStringTable* addStringTable(const std::string& name) override;
729       GElfStringTable* getStringTable(uint16_t index) override;
730 
731       GElfSymbolTable* addSymbolTable(const std::string& name, StringTable* stab = 0) override;
732       GElfSymbolTable* symtab() override;
733 
segment(size_t i)734       GElfSegment* segment(size_t i) override { return segments[i].get(); }
735       Segment* segmentByVAddr(uint64_t vaddr) override;
sectionCount()736       size_t sectionCount() override { return sections.size(); }
section(size_t i)737       GElfSection* section(size_t i) override { return sections[i].get(); }
738       Section* sectionByVAddr(uint64_t vaddr) override;
739       uint16_t machine() const;
740       uint16_t etype() const;
eclass() const741       int eclass() const { return elfclass; }
742       bool elfError(const char* msg);
743 
744       GElfNoteSection* note() override;
745       GElfNoteSection* addNoteSection(const std::string& name) override;
746 
segmentCount()747       size_t segmentCount() override { return segments.size(); }
748       Segment* initSegment(uint32_t type, uint32_t flags, uint64_t paddr = 0) override;
749       bool addSegments() override;
750 
751       Section* addSection(const std::string &name,
752                           uint32_t type,
753                           uint64_t flags = 0,
754                           uint64_t entsize = 0,
755                           Segment* segment = 0) override;
756 
757       RelocationSection* addRelocationSection(Section* sec, SymbolTable* symtab);
758       RelocationSection* relocationSection(Section* sec, SymbolTable* symtab = 0) override;
759 
760     private:
761       bool frozen;
762       int elfclass;
763       FileImage img;
764       const char* buffer;
765       size_t bufferSize;
766       Elf* e;
767       GElf_Ehdr ehdr;
768       GElfStringTable* shstrtabSection;
769       GElfStringTable* strtabSection;
770       GElfSymbolTable* symtabSection;
771       GElfNoteSection* noteSection;
772       std::vector<std::unique_ptr<GElfSegment>> segments;
773       std::vector<std::unique_ptr<GElfSection>> sections;
774 
775       bool imgError();
776       const char *elfError();
777       bool elfBegin(Elf_Cmd cmd);
778       bool elfEnd();
779       bool push0();
780       bool pullElf();
781 
782       friend class GElfSection;
783       friend class GElfSymbolTable;
784       friend class GElfNoteSection;
785       friend class GElfRelocationSection;
786       friend class GElfSegment;
787       friend class GElfSymbol;
788     };
789 
GElfSegment(GElfImage * elf_,uint16_t index_)790     GElfSegment::GElfSegment(GElfImage* elf_, uint16_t index_)
791       : elf(elf_),
792         index(index_)
793     {
794       memset(&phdr, 0, sizeof(phdr));
795     }
796 
GElfSegment(GElfImage * elf_,uint16_t index_,uint32_t type,uint32_t flags,uint64_t paddr)797     GElfSegment::GElfSegment(GElfImage* elf_, uint16_t index_,
798       uint32_t type, uint32_t flags, uint64_t paddr)
799       : elf(elf_),
800         index(index_)
801     {
802       memset(&phdr, 0, sizeof(phdr));
803       phdr.p_type = type;
804       phdr.p_flags = flags;
805       phdr.p_paddr = paddr;
806     }
807 
data() const808     const char* GElfSegment::data() const
809     {
810       return (const char*) elf->data() + phdr.p_offset;
811     }
812 
Freeze()813     bool GElfImage::Freeze()
814     {
815       assert(!frozen);
816       if (!push()) { return false; }
817       frozen = true;
818       return true;
819     }
820 
Validate()821     bool GElfImage::Validate()
822     {
823       if (ELFMAG0 != ehdr.e_ident[EI_MAG0] ||
824           ELFMAG1 != ehdr.e_ident[EI_MAG1] ||
825           ELFMAG2 != ehdr.e_ident[EI_MAG2] ||
826           ELFMAG3 != ehdr.e_ident[EI_MAG3]) {
827         out << "Invalid ELF magic" << std::endl;
828         return false;
829       }
830       if (EV_CURRENT != ehdr.e_version) {
831         out << "Invalid ELF version" << std::endl;
832         return false;
833       }
834       return true;
835     }
836 
push(uint64_t vaddr)837     bool GElfSegment::push(uint64_t vaddr)
838     {
839       phdr.p_align = 0;
840       phdr.p_offset = 0;
841       if (!sections.empty()) {
842         phdr.p_offset = sections[0]->offset();
843       }
844       for (Section* section : sections) {
845         phdr.p_align = (std::max)(phdr.p_align, section->memAlign());
846       }
847       phdr.p_vaddr = alignUp(vaddr, (std::max)(phdr.p_align, (uint64_t) 1));
848       phdr.p_filesz = 0;
849       phdr.p_memsz = 0;
850       for (Section* section : sections) {
851         phdr.p_memsz = alignUp(phdr.p_memsz, (std::max)(section->memAlign(), (uint64_t) 1));
852         phdr.p_filesz = alignUp(phdr.p_filesz, (std::max)(section->memAlign(), (uint64_t) 1));
853         if (!section->updateAddr(phdr.p_vaddr + phdr.p_memsz)) { return false; }
854         phdr.p_filesz += (section->type() == SHT_NOBITS) ? 0 : section->size();
855         phdr.p_memsz += section->memSize();
856       }
857       if (!gelf_update_phdr(elf->e, index, &phdr)) { return elf->elfError("gelf_update_phdr failed"); }
858       return true;
859     }
860 
pull()861     bool GElfSegment::pull()
862     {
863       if (!gelf_getphdr(elf->e, index, &phdr)) { return elf->elfError("gelf_getphdr failed"); }
864       return true;
865     }
866 
getSegmentIndex()867     uint16_t GElfSegment::getSegmentIndex()
868     {
869       return index;
870     }
871 
updateAddSection(Section * section)872     bool GElfSegment::updateAddSection(Section *section)
873     {
874       sections.push_back(section);
875       return true;
876     }
877 
GElfSection(GElfImage * elf_)878     GElfSection::GElfSection(GElfImage* elf_)
879       : elf(elf_),
880         memsize_(0),
881         align_(0),
882         reloc_sec(nullptr),
883         ndxscn(0)
884     {
885     }
886 
getSectionIndex() const887     uint16_t GElfSection::getSectionIndex() const
888     {
889       return (uint16_t)ndxscn;
890     }
891 
Name() const892     std::string GElfSection::Name() const
893     {
894       return std::string(elf->shstrtab()->getString(hdr.sh_name));
895     }
896 
updateAddr(uint64_t addr)897     bool GElfSection::updateAddr(uint64_t addr)
898     {
899       Elf_Scn *scn = elf_getscn(elf->e, ndxscn);
900       assert(scn);
901       if (!gelf_getshdr(scn, &hdr)) { return elf->elfError("gelf_get_shdr failed"); }
902       hdr.sh_addr = addr;
903       if (!gelf_update_shdr(scn, &hdr)) { return elf->elfError("gelf_update_shdr failed"); }
904       return true;
905     }
906 
push(const char * name,uint32_t shtype,uint64_t shflags,uint16_t shlink,uint32_t info,uint32_t align,uint64_t entsize)907     bool GElfSection::push(const char* name, uint32_t shtype, uint64_t shflags, uint16_t shlink, uint32_t info, uint32_t align, uint64_t entsize)
908     {
909       Elf_Scn *scn = elf_newscn(elf->e);
910       if (!scn) { return false; }
911       ndxscn = elf_ndxscn(scn);
912       if (!gelf_getshdr(scn, &hdr)) { return elf->elfError("gelf_get_shdr failed"); }
913       align = (std::max)(align, (uint32_t) 8);
914       hdr.sh_name = elf->shstrtab()->addString1(name);
915       hdr.sh_type = shtype;
916       hdr.sh_flags = shflags;
917       hdr.sh_link = shlink;
918       hdr.sh_addr = 0;
919       hdr.sh_info = info;
920       hdr.sh_addralign = align;
921       hdr.sh_entsize = entsize;
922       if (!gelf_update_shdr(scn, &hdr)) { return elf->elfError("gelf_update_shdr failed"); }
923       return true;
924     }
925 
pull0()926     bool GElfSection::pull0()
927     {
928       Elf_Scn *scn = elf_getscn(elf->e, ndxscn);
929       if (!scn) { return false; }
930       if (!gelf_getshdr(scn, &hdr)) { return elf->elfError("gelf_get_shdr failed"); }
931       return true;
932     }
933 
pull(uint16_t ndx)934     bool GElfSection::pull(uint16_t ndx)
935     {
936       ndxscn = (size_t) ndx;
937       if (!pull0()) { return false; }
938       Elf_Scn *scn = elf_getscn(elf->e, ndx);
939       if (!scn) { return false; }
940       Elf_Data *edata0 = elf_getdata(scn, NULL);
941       if (edata0) {
942         data0 = Buffer((const Buffer::byte_type*)edata0->d_buf, edata0->d_size, edata0->d_align);
943       }
944       seg = elf->segmentByVAddr(hdr.sh_addr);
945       return true;
946     }
947 
push()948     bool GElfSection::push()
949     {
950       Elf_Scn *scn = elf_getscn(elf->e, ndxscn);
951       assert(scn);
952       Elf_Data *edata = nullptr;
953       edata = elf_newdata(scn);
954       if (!edata) { return elf->elfError("elf_newdata failed"); }
955       if (hdr.sh_type == SHT_NOBITS) {
956         edata->d_buf = 0;
957         edata->d_size = memsize_;
958         if (align_ != 0) {
959           edata->d_align = align_;
960         }
961       } else {
962         edata->d_buf = (void*)data.raw();
963         edata->d_size = data.size();
964         if (data.align() != 0) {
965           edata->d_align = data.align();
966         }
967       }
968       edata->d_align = (std::max)(edata->d_align, (uint64_t) 8);
969       switch (hdr.sh_type) {
970       case SHT_RELA:
971         edata->d_type = ELF_T_RELA;
972         break;
973       case SHT_SYMTAB:
974         edata->d_type = ELF_T_SYM;
975         break;
976       default:
977         edata->d_type = ELF_T_BYTE;
978         break;
979       }
980       edata->d_version = EV_CURRENT;
981       if (!gelf_getshdr(scn, &hdr)) { return elf->elfError("gelf_get_shdr failed"); }
982       hdr.sh_size = edata->d_size;
983       hdr.sh_addralign = edata->d_align;
984       if (!gelf_update_shdr(scn, &hdr)) { return elf->elfError("gelf_update_shdr failed"); }
985       return true;
986     }
987 
nextDataOffset(uint64_t align) const988     uint64_t GElfSection::nextDataOffset(uint64_t align) const
989     {
990       return data.nextOffset(align);
991     }
992 
addData(const void * src,uint64_t size,uint64_t align)993     uint64_t GElfSection::addData(const void *src, uint64_t size, uint64_t align)
994     {
995       return data.add(src, size, align);
996     }
997 
getData(uint64_t offset,void * dest,uint64_t size)998     bool GElfSection::getData(uint64_t offset, void* dest, uint64_t size)
999     {
1000       Elf_Data* edata = 0;
1001       uint64_t coffset = 0;
1002       uint64_t csize = 0;
1003       Elf_Scn *scn = elf_getscn(elf->e, ndxscn);
1004       assert(scn);
1005       if ((edata = elf_getdata(scn, edata)) != 0) {
1006         if (coffset <= offset && offset <= coffset + edata->d_size) {
1007           csize = (std::min)(size, edata->d_size - offset);
1008           memcpy(dest, (const char*) edata->d_buf + offset - coffset, csize);
1009           coffset += csize;
1010           dest = (char*) dest + csize;
1011           size -= csize;
1012           if (!size) { return true; }
1013         }
1014       }
1015       return false;
1016     }
1017 
relocationSection(SymbolTable * symtab)1018     RelocationSection* GElfSection::relocationSection(SymbolTable* symtab)
1019     {
1020       if (!reloc_sec) {
1021         reloc_sec = elf->addRelocationSection(this, symtab);
1022       }
1023       return reloc_sec;
1024     }
1025 
GElfStringTable(GElfImage * elf)1026     GElfStringTable::GElfStringTable(GElfImage* elf)
1027       : GElfSection(elf)
1028     {
1029     }
1030 
push(const char * name,uint32_t shtype,uint64_t shflags)1031     bool GElfStringTable::push(const char* name, uint32_t shtype, uint64_t shflags)
1032     {
1033       if (!GElfSection::push(name, shtype, shflags, SHN_UNDEF, 0, 0)) { return false; }
1034       return true;
1035     }
1036 
pullData()1037     bool GElfStringTable::pullData()
1038     {
1039       return true;
1040     }
1041 
addString(const std::string & s)1042     const char* GElfStringTable::addString(const std::string& s)
1043     {
1044       if (data0.size() == 0 && data.size() == 0) {
1045         data.add('\0');
1046       }
1047       return data.get<const char*>(data.addString(s));
1048     }
1049 
addString1(const std::string & s)1050     size_t GElfStringTable::addString1(const std::string& s)
1051     {
1052       if (data0.size() == 0 && data.size() == 0) {
1053         data.add('\0');
1054       }
1055       return data.addString(s);
1056     }
1057 
getString(size_t ndx)1058     const char* GElfStringTable::getString(size_t ndx)
1059     {
1060       if (data0.has(ndx)) { return data0.get<const char*>(ndx); }
1061       else if (data.has(ndx)) { return data.get<const char*>(ndx); }
1062       return nullptr;
1063     }
1064 
getStringIndex(const char * s)1065     size_t GElfStringTable::getStringIndex(const char* s)
1066     {
1067       if (data0.has(s)) {
1068         return data0.getOffset(s);
1069       } else if (data.has(s)) {
1070         return data.getOffset(s);
1071       } else {
1072         assert(false);
1073         return 0;
1074       }
1075     }
1076 
GElfSymbol(GElfSymbolTable * symtab_,Buffer & data_,size_t index_)1077     GElfSymbol::GElfSymbol(GElfSymbolTable* symtab_, Buffer &data_, size_t index_)
1078       : symtab(symtab_),
1079         edata(data_),
1080         eindex(index_)
1081     {
1082     }
1083 
section()1084     Section* GElfSymbol::section()
1085     {
1086       if (Sym()->st_shndx != SHN_UNDEF) {
1087         return symtab->elf->section(Sym()->st_shndx);
1088       }
1089       return 0;
1090     }
1091 
push(const std::string & name,uint64_t value,uint64_t size,unsigned char type,unsigned char binding,uint16_t shndx,unsigned char other)1092     bool GElfSymbol::push(const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, uint16_t shndx, unsigned char other)
1093     {
1094       Sym()->st_name = symtab->strtab->addString1(name.c_str());
1095       Sym()->st_value = value;
1096       Sym()->st_size = size;
1097       Sym()->st_info = GELF_ST_INFO(binding, type);
1098       Sym()->st_shndx = shndx;
1099       Sym()->st_other = other;
1100       return true;
1101     }
1102 
name()1103     std::string GElfSymbol::name()
1104     {
1105       return symtab->strtab->getString(Sym()->st_name);
1106     }
1107 
GElfSymbolTable(GElfImage * elf)1108     GElfSymbolTable::GElfSymbolTable(GElfImage* elf)
1109       : GElfSection(elf),
1110         strtab(0)
1111     {
1112     }
1113 
push(const char * name,GElfStringTable * strtab)1114     bool GElfSymbolTable::push(const char* name, GElfStringTable* strtab)
1115     {
1116       if (!strtab) { strtab = elf->strtab(); }
1117       this->strtab = strtab;
1118       if (!GElfSection::push(name, SHT_SYMTAB, 0, strtab->getSectionIndex(), 0, 0, sizeof(Elf64_Sym))) { return false;  }
1119       return true;
1120     }
1121 
pullData()1122     bool GElfSymbolTable::pullData()
1123     {
1124       strtab = elf->getStringTable(hdr.sh_link);
1125       for (size_t i = 0; i < data0.size() / sizeof(GElf_Sym); ++i) {
1126         symbols.push_back(std::unique_ptr<GElfSymbol>(new GElfSymbol(this, data0, i * sizeof(GElf_Sym))));
1127       }
1128       return true;
1129     }
1130 
addSymbolInternal(Section * section,const std::string & name,uint64_t value,uint64_t size,unsigned char type,unsigned char binding,unsigned char other)1131     Symbol* GElfSymbolTable::addSymbolInternal(Section* section, const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, unsigned char other)
1132     {
1133       GElfSymbol *sym = new (std::nothrow) GElfSymbol(this, data, data.reserve<GElf_Sym>());
1134       uint16_t shndx = section ? section->getSectionIndex() : (uint16_t) SHN_UNDEF;
1135       if (!sym->push(name, value, size, type, binding, shndx, other)) {
1136         delete sym;
1137         return nullptr;
1138       }
1139       symbols.push_back(std::unique_ptr<GElfSymbol>(sym));
1140       return sym;
1141     }
1142 
addSymbol(Section * section,const std::string & name,uint64_t value,uint64_t size,unsigned char type,unsigned char binding,unsigned char other)1143     Symbol* GElfSymbolTable::addSymbol(Section* section, const std::string& name, uint64_t value, uint64_t size, unsigned char type, unsigned char binding, unsigned char other)
1144     {
1145       if (symbols.size() == 0) {
1146         this->addSymbolInternal(nullptr, "", 0, 0, 0, 0, 0);
1147       }
1148       return this->addSymbolInternal(section, name, value, size, type, binding, other);
1149     }
1150 
symbolCount()1151     size_t GElfSymbolTable::symbolCount()
1152     {
1153       return symbols.size();
1154     }
1155 
symbol(size_t i)1156     Symbol* GElfSymbolTable::symbol(size_t i)
1157     {
1158       return symbols[i].get();
1159     }
1160 
GElfNoteSection(GElfImage * elf)1161     GElfNoteSection::GElfNoteSection(GElfImage* elf)
1162       : GElfSection(elf)
1163     {
1164     }
1165 
push(const std::string & name)1166     bool GElfNoteSection::push(const std::string& name)
1167     {
1168       return GElfSection::push(name.c_str(), SHT_NOTE, 0, 0, 0, 8);
1169     }
1170 
addNote(const std::string & name,uint32_t type,const void * desc,uint32_t desc_size)1171     bool GElfNoteSection::addNote(const std::string& name, uint32_t type, const void* desc, uint32_t desc_size)
1172     {
1173       data.addStringLength(name, NOTE_RECORD_ALIGNMENT);
1174       data.add(desc_size, NOTE_RECORD_ALIGNMENT);
1175       data.add(type, NOTE_RECORD_ALIGNMENT);
1176       data.addString(name, NOTE_RECORD_ALIGNMENT);
1177       data.align(NOTE_RECORD_ALIGNMENT);
1178       if (desc_size > 0) {
1179         assert(desc);
1180         data.add(desc, desc_size, NOTE_RECORD_ALIGNMENT);
1181         data.align(NOTE_RECORD_ALIGNMENT);
1182       }
1183       return true;
1184     }
1185 
getNote(const std::string & name,uint32_t type,void ** desc,uint32_t * desc_size)1186     bool GElfNoteSection::getNote(const std::string& name, uint32_t type, void** desc, uint32_t* desc_size)
1187     {
1188       Elf_Data* data = 0;
1189       Elf_Scn *scn = elf_getscn(elf->e, ndxscn);
1190       assert(scn);
1191       while ((data = elf_getdata(scn, data)) != 0) {
1192         uint32_t note_offset = 0;
1193         while (note_offset < data->d_size) {
1194           char* notec = (char *) data->d_buf + note_offset;
1195           Elf64_Nhdr* note = (Elf64_Nhdr*) notec;
1196           if (type == note->n_type) {
1197             std::string note_name = GetNoteString(note->n_namesz, notec + sizeof(Elf64_Nhdr));
1198             if (name == note_name) {
1199               *desc = notec + sizeof(Elf64_Nhdr) + alignUp(note->n_namesz, 4);
1200               *desc_size = note->n_descsz;
1201               return true;
1202             }
1203           }
1204           note_offset += sizeof(Elf64_Nhdr) + alignUp(note->n_namesz, 4) + alignUp(note->n_descsz, 4);
1205         }
1206       }
1207       return false;
1208     }
1209 
push(uint32_t type,Symbol * symbol,uint64_t offset,int64_t addend)1210     bool GElfRelocation::push(uint32_t type, Symbol* symbol, uint64_t offset, int64_t addend)
1211     {
1212       Rela()->r_info = GELF_R_INFO((uint64_t) symbol->index(), type);
1213       Rela()->r_offset = offset;
1214       Rela()->r_addend = addend;
1215       return true;
1216     }
1217 
section()1218     RelocationSection* GElfRelocation::section()
1219     {
1220       return rsection;
1221     }
1222 
symbol()1223     Symbol* GElfRelocation::symbol()
1224     {
1225       return rsection->symtab->symbol(symbolIndex());
1226     }
1227 
GElfRelocationSection(GElfImage * elf,Section * section_,GElfSymbolTable * symtab_)1228     GElfRelocationSection::GElfRelocationSection(GElfImage* elf, Section* section_, GElfSymbolTable* symtab_)
1229       : GElfSection(elf),
1230         section(section_),
1231         symtab(symtab_)
1232     {
1233     }
1234 
push(const std::string & name)1235     bool GElfRelocationSection::push(const std::string& name)
1236     {
1237       return GElfSection::push(name.c_str(), SHT_RELA, 0, symtab->getSectionIndex(), section->getSectionIndex(), 0, sizeof(Elf64_Rela));
1238     }
1239 
addRelocation(uint32_t type,Symbol * symbol,uint64_t offset,int64_t addend)1240     Relocation* GElfRelocationSection::addRelocation(uint32_t type, Symbol* symbol, uint64_t offset, int64_t addend)
1241     {
1242       GElfRelocation *rela = new (std::nothrow) GElfRelocation(this, data, data.reserve<GElf_Rela>());
1243       if (!rela || !rela->push(type, symbol, offset, addend)) {
1244         delete rela;
1245         return nullptr;
1246       }
1247       relocations.push_back(std::unique_ptr<GElfRelocation>(rela));
1248       return rela;
1249     }
1250 
pullData()1251     bool GElfRelocationSection::pullData()
1252     {
1253       section = elf->section(hdr.sh_info);
1254       symtab = elf->getSymtab(hdr.sh_link);
1255       Elf_Scn *lScn = elf_getscn(elf->e, ndxscn);
1256       assert(lScn);
1257       Elf_Data *lData = elf_getdata(lScn, nullptr);
1258       assert(lData);
1259       data0 = Buffer((const Buffer::byte_type*)lData->d_buf, lData->d_size, lData->d_align);
1260       for (size_t i = 0; i < data0.size() / sizeof(GElf_Rela); ++i) {
1261         relocations.push_back(std::unique_ptr<GElfRelocation>(new GElfRelocation(this, data0, i * sizeof(GElf_Rela))));
1262       }
1263       return true;
1264     }
1265 
GElfImage(int elfclass_)1266     GElfImage::GElfImage(int elfclass_)
1267       : frozen(true),
1268         elfclass(elfclass_),
1269         buffer(0), bufferSize(0),
1270         e(0),
1271         shstrtabSection(0), strtabSection(0),
1272         symtabSection(0),
1273         noteSection(0)
1274     {
1275       if (EV_NONE == elf_version(EV_CURRENT)) {
1276         assert(false);
1277       }
1278     }
1279 
~GElfImage()1280     GElfImage::~GElfImage()
1281     {
1282       elf_end(e);
1283     }
1284 
imgError()1285     bool GElfImage::imgError()
1286     {
1287       out << img.output();
1288       return false;
1289     }
1290 
elfError()1291     const char *GElfImage::elfError()
1292     {
1293       return elf_errmsg(-1);
1294     }
1295 
elfBegin(Elf_Cmd cmd)1296     bool GElfImage::elfBegin(Elf_Cmd cmd)
1297     {
1298       if ((e = elf_begin(img.fd(), cmd, NULL
1299 #ifdef AMD_LIBELF
1300                        , NULL
1301 #endif
1302         )) == NULL) {
1303         out << "elf_begin failed: " << elfError() << std::endl;
1304         return false;
1305       }
1306       return true;
1307     }
1308 
initNew(uint16_t machine,uint16_t type,uint8_t os_abi,uint8_t abi_version,uint32_t e_flags)1309     bool GElfImage::initNew(uint16_t machine, uint16_t type, uint8_t os_abi, uint8_t abi_version, uint32_t e_flags)
1310     {
1311       if (!img.create()) { return imgError(); }
1312       if (!elfBegin(ELF_C_WRITE)) { return false; }
1313       if (!gelf_newehdr(e, elfclass)) { return elfError("gelf_newehdr failed"); }
1314       if (!gelf_getehdr(e, &ehdr)) { return elfError("gelf_getehdr failed"); }
1315       ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1316       ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1317       ehdr.e_ident[EI_OSABI] = os_abi;
1318       ehdr.e_ident[EI_ABIVERSION] = abi_version;
1319       ehdr.e_machine = machine;
1320       ehdr.e_type = type;
1321       ehdr.e_version = EV_CURRENT;
1322       ehdr.e_flags = e_flags;
1323       if (!gelf_update_ehdr(e, &ehdr)) { return elfError("gelf_updateehdr failed"); }
1324       sections.push_back(std::unique_ptr<GElfSection>());
1325       if (!shstrtab()->push(".shstrtab", SHT_STRTAB, SHF_STRINGS)) { return elfError("Failed to create shstrtab"); }
1326       ehdr.e_shstrndx = shstrtab()->getSectionIndex();
1327       if (!gelf_update_ehdr(e, &ehdr)) { return elfError("gelf_updateehdr failed"); }
1328       if (!strtab()->push(".strtab", SHT_STRTAB, SHF_STRINGS)) { return elfError("Failed to create strtab"); }
1329       frozen = false;
1330       return true;
1331     }
1332 
loadFromFile(const std::string & filename)1333     bool GElfImage::loadFromFile(const std::string& filename)
1334     {
1335       if (!img.create()) { return imgError(); }
1336       if (!img.readFrom(filename)) { return imgError(); }
1337       if (!elfBegin(ELF_C_RDWR)) { return false; }
1338       return pullElf();
1339     }
1340 
saveToFile(const std::string & filename)1341     bool GElfImage::saveToFile(const std::string& filename)
1342     {
1343       if (buffer) {
1344         std::ofstream out(filename.c_str(), std::ios::binary);
1345         if (out.fail()) { return false; }
1346         out.write(buffer, bufferSize);
1347         return !out.fail();
1348       } else {
1349         if (!push()) { return false; }
1350         return img.writeTo(filename);
1351       }
1352     }
1353 
initFromBuffer(const void * buffer,size_t size)1354     bool GElfImage::initFromBuffer(const void* buffer, size_t size)
1355     {
1356       if (size == 0) { size = ElfSize(buffer); }
1357       if (!img.create()) { return imgError(); }
1358       if (!img.copyFrom(buffer, size)) { return imgError(); }
1359       if (!elfBegin(ELF_C_RDWR)) { return false; }
1360       return pullElf();
1361     }
1362 
initAsBuffer(const void * buffer,size_t size)1363     bool GElfImage::initAsBuffer(const void* buffer, size_t size)
1364     {
1365       if (size == 0) { size = ElfSize(buffer); }
1366       if ((e = elf_memory(reinterpret_cast<char*>(const_cast<void*>(buffer)), size
1367 #ifdef AMD_LIBELF
1368                        , NULL
1369 #endif
1370         )) == NULL) {
1371         out << "elf_begin(buffer) failed: " << elfError() << std::endl;
1372         return false;
1373       }
1374       this->buffer = reinterpret_cast<const char*>(buffer);
1375       this->bufferSize = size;
1376       return pullElf();
1377     }
1378 
pullElf()1379     bool GElfImage::pullElf()
1380     {
1381       if (!gelf_getehdr(e, &ehdr)) { return elfError("gelf_getehdr failed"); }
1382       segments.reserve(ehdr.e_phnum);
1383       for (size_t i = 0; i < ehdr.e_phnum; ++i) {
1384         GElfSegment* segment = new GElfSegment(this, i);
1385         segment->pull();
1386         segments.push_back(std::unique_ptr<GElfSegment>(segment));
1387       }
1388 
1389       shstrtabSection = new GElfStringTable(this);
1390       if (!shstrtabSection->pull(ehdr.e_shstrndx)) { return false; }
1391       Elf_Scn* scn = 0;
1392       for (unsigned n = 0; n < ehdr.e_shnum; ++n) {
1393         scn = elf_getscn(e, n);
1394         if (n == ehdr.e_shstrndx) {
1395           sections.push_back(std::unique_ptr<GElfSection>(shstrtabSection));
1396           continue;
1397         }
1398         GElf_Shdr shdr;
1399         if (!gelf_getshdr(scn, &shdr)) { return elfError("Failed to get shdr"); }
1400         GElfSection* section = 0;
1401         if (shdr.sh_type == SHT_NOTE) {
1402           section = new GElfNoteSection(this);
1403         } else if (shdr.sh_type == SHT_RELA) {
1404           section = new GElfRelocationSection(this);
1405         } else if (shdr.sh_type == SHT_STRTAB) {
1406           section = new GElfStringTable(this);
1407         } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
1408           section = new GElfSymbolTable(this);
1409         } else if (shdr.sh_type == SHT_NULL) {
1410           section = 0;
1411           sections.push_back(std::unique_ptr<GElfSection>());
1412         } else {
1413           section = new GElfSection(this);
1414         }
1415         if (section) {
1416           sections.push_back(std::unique_ptr<GElfSection>(section));
1417           if (!section->pull(n)) { return false; }
1418         }
1419       }
1420 
1421       for (size_t n = 1; n < sections.size(); ++n) {
1422         GElfSection* section = sections[n].get();
1423         if (section->type() == SHT_STRTAB) {
1424           if (!section->pullData()) { return false; }
1425         }
1426       }
1427 
1428       for (size_t n = 1; n < sections.size(); ++n) {
1429         GElfSection* section = sections[n].get();
1430         if (section->type() == SHT_SYMTAB || section->type() == SHT_DYNSYM) {
1431           if (!section->pullData()) { return false; }
1432         }
1433       }
1434 
1435       for (size_t n = 1; n < sections.size(); ++n) {
1436         GElfSection* section = sections[n].get();
1437         if (section->type() != SHT_STRTAB && section->type() != SHT_SYMTAB && section->type() != SHT_DYNSYM) {
1438           if (!section->pullData()) { return false; }
1439         }
1440       }
1441 
1442       for (size_t i = 1; i < sections.size(); ++i) {
1443         if (i == ehdr.e_shstrndx || i == ehdr.e_shstrndx) { continue; }
1444         std::unique_ptr<GElfSection>& section = sections[i];
1445         if (section->Name() == ".strtab") { strtabSection = static_cast<GElfStringTable*>(section.get()); }
1446         if (section->Name() == ".symtab") { symtabSection = static_cast<GElfSymbolTable*>(section.get()); }
1447         if (section->Name() == ".note") { noteSection = static_cast<GElfNoteSection*>(section.get()); }
1448       }
1449 
1450       size_t phnum;
1451       if (elf_getphdrnum(e, &phnum) < 0) { return elfError("elf_getphdrnum failed"); }
1452       for (size_t i = 0; i < phnum; ++i) {
1453         segments.push_back(std::unique_ptr<GElfSegment>(new GElfSegment(this, i)));
1454         if (!segments[i]->pull()) { return false; }
1455       }
1456 
1457       return true;
1458     }
1459 
elfError(const char * msg)1460     bool GElfImage::elfError(const char* msg)
1461     {
1462       out << "Error: " << msg << ": " << elfError() << std::endl;
1463       return false;
1464     }
1465 
size()1466     uint64_t GElfImage::size()
1467     {
1468       if (buffer) {
1469         return ElfSize(buffer);
1470       } else {
1471         return img.getSize();
1472       }
1473     }
1474 
push0()1475     bool GElfImage::push0()
1476     {
1477       assert(e);
1478       for (std::unique_ptr<GElfSection>& section : sections) {
1479         if (section && !section->push()) { return false; }
1480       }
1481 
1482       for (std::unique_ptr<GElfSection>& section : sections) {
1483         if (section && !section->pull0()) { return false; }
1484       }
1485 
1486       if (!segments.empty()) {
1487         if (!gelf_newphdr(e, segments.size())) { return elfError("gelf_newphdr failed"); }
1488       }
1489       if (elf_update(e, ELF_C_NULL) < 0) { return elfError("elf_update (1.1) failed"); }
1490       if (!segments.empty()) {
1491         for (std::unique_ptr<GElfSection>& section : sections) {
1492           // Update section offsets.
1493           if (section && !section->pull0()) { return false; }
1494         }
1495         uint64_t vaddr = 0;
1496         for (std::unique_ptr<GElfSegment>& segment : segments) {
1497           if (!segment->push(vaddr)) { return false; }
1498           vaddr = segment->vaddr() + segment->memSize();
1499         }
1500       }
1501       return true;
1502     }
1503 
push()1504     bool GElfImage::push()
1505     {
1506       if (!push0()) { return false; }
1507       if (elf_update(e, ELF_C_WRITE) < 0) { return elfError("elf_update (2) failed"); }
1508       return true;
1509     }
1510 
segmentByVAddr(uint64_t vaddr)1511     Segment* GElfImage::segmentByVAddr(uint64_t vaddr)
1512     {
1513       for (std::unique_ptr<GElfSegment>& seg : segments) {
1514         if (seg->vaddr() <= vaddr && vaddr < seg->vaddr() + seg->memSize()) {
1515           return seg.get();
1516         }
1517       }
1518       return 0;
1519     }
1520 
sectionByVAddr(uint64_t vaddr)1521     Section* GElfImage::sectionByVAddr(uint64_t vaddr)
1522     {
1523       for (size_t n = 1; n < sections.size(); ++n) {
1524         if (sections[n]->addr() <= vaddr && vaddr < sections[n]->addr() + sections[n]->size()) {
1525           return sections[n].get();
1526         }
1527       }
1528       return nullptr;
1529     }
1530 
elfEnd()1531     bool GElfImage::elfEnd()
1532     {
1533       return false;
1534     }
1535 
writeTo(const std::string & filename)1536     bool GElfImage::writeTo(const std::string& filename)
1537     {
1538       if (!img.writeTo(filename)) { return imgError(); }
1539       return true;
1540     }
1541 
copyToBuffer(void ** buf,size_t * size)1542     bool GElfImage::copyToBuffer(void** buf, size_t* size)
1543     {
1544       if (buffer) {
1545         *buf = malloc(bufferSize);
1546         memcpy(*buf, buffer, bufferSize);
1547         if (size) { *size = bufferSize; }
1548         return true;
1549       } else {
1550         return img.copyTo(buf, size);
1551       }
1552     }
1553 
copyToBuffer(void * buf,size_t size)1554     bool GElfImage::copyToBuffer(void* buf, size_t size)
1555     {
1556       if (buffer) {
1557         if (size < bufferSize) { return false; }
1558         memcpy(buf, buffer, bufferSize);
1559         return true;
1560       } else {
1561         return img.copyTo(buf, size);
1562       }
1563     }
1564 
addStringTable(const std::string & name)1565     GElfStringTable* GElfImage::addStringTable(const std::string& name)
1566     {
1567       GElfStringTable* stab = new GElfStringTable(this);
1568       sections.push_back(std::unique_ptr<GElfStringTable>(stab));
1569       return stab;
1570     }
1571 
getStringTable(uint16_t index)1572     GElfStringTable* GElfImage::getStringTable(uint16_t index)
1573     {
1574       return static_cast<GElfStringTable*>(sections[index].get());
1575     }
1576 
addSymbolTable(const std::string & name,StringTable * stab)1577     GElfSymbolTable* GElfImage::addSymbolTable(const std::string& name, StringTable* stab)
1578     {
1579       if (!stab) { stab = strtab(); }
1580       const char* name0 = shstrtab()->addString(name);
1581       GElfSymbolTable* symtab = new GElfSymbolTable(this);
1582       symtab->push(name0, static_cast<GElfStringTable*>(stab));
1583       sections.push_back(std::unique_ptr<GElfSection>(symtab));
1584       return symtab;
1585     }
1586 
shstrtab()1587     GElfStringTable* GElfImage::shstrtab() {
1588       if (!shstrtabSection) {
1589         shstrtabSection = addStringTable(".shstrtab");
1590       }
1591       return shstrtabSection;
1592     }
1593 
strtab()1594     GElfStringTable* GElfImage::strtab() {
1595       if (!strtabSection) {
1596         strtabSection = addStringTable(".shstrtab");
1597       }
1598       return strtabSection;
1599     }
1600 
symtab()1601     GElfSymbolTable* GElfImage::symtab()
1602     {
1603       if (!symtabSection) {
1604         symtabSection = addSymbolTable(".symtab", strtab());
1605       }
1606       return symtabSection;
1607     }
1608 
1609 
note()1610     GElfNoteSection* GElfImage::note()
1611     {
1612       if (!noteSection) { noteSection = addNoteSection(".note"); }
1613       return noteSection;
1614     }
1615 
addNoteSection(const std::string & name)1616     GElfNoteSection* GElfImage::addNoteSection(const std::string& name)
1617     {
1618       GElfNoteSection* note = new GElfNoteSection(this);
1619       note->push(name);
1620       sections.push_back(std::unique_ptr<GElfSection>(note));
1621       return note;
1622     }
1623 
initSegment(uint32_t type,uint32_t flags,uint64_t paddr)1624     Segment* GElfImage::initSegment(uint32_t type, uint32_t flags, uint64_t paddr)
1625     {
1626       GElfSegment *seg = new (std::nothrow) GElfSegment(this, segments.size(), type, flags, paddr);
1627       segments.push_back(std::unique_ptr<GElfSegment>(seg));
1628       return seg;
1629     }
1630 
addSegments()1631     bool GElfImage::addSegments()
1632     {
1633       return true;
1634     }
1635 
addSection(const std::string & name,uint32_t type,uint64_t flags,uint64_t entsize,Segment * segment)1636     Section* GElfImage::addSection(const std::string &name,
1637                                    uint32_t type,
1638                                    uint64_t flags,
1639                                    uint64_t entsize, Segment* segment)
1640     {
1641       GElfSection *section = new (std::nothrow) GElfSection(this);
1642       if (!section || !section->push(name.c_str(), type, flags, 0, 0, 0, entsize)) {
1643         delete section;
1644         return nullptr;
1645       }
1646       if (segment) {
1647         if (!segment->updateAddSection(section)) {
1648           delete section;
1649           return nullptr;
1650         }
1651       }
1652       sections.push_back(std::unique_ptr<GElfSection>(section));
1653       return section;
1654     }
1655 
addRelocationSection(Section * sec,SymbolTable * symtab)1656     RelocationSection* GElfImage::addRelocationSection(Section* sec, SymbolTable* symtab)
1657     {
1658       std::string section_name = ".rela" + sec->Name();
1659       if (!symtab) { symtab = this->symtab(); }
1660       GElfRelocationSection *rsec = new GElfRelocationSection(this, sec, (GElfSymbolTable*) symtab);
1661       if (!rsec || !rsec->push(section_name)) {
1662         delete rsec;
1663         return nullptr;
1664       }
1665       sections.push_back(std::unique_ptr<GElfRelocationSection>(rsec));
1666       return rsec;
1667     }
1668 
relocationSection(Section * sec,SymbolTable * symtab)1669     RelocationSection* GElfImage::relocationSection(Section* sec, SymbolTable* symtab)
1670     {
1671       return sec->relocationSection(symtab);
1672     }
1673 
machine() const1674     uint16_t GElfImage::machine() const
1675     {
1676       return ehdr.e_machine;
1677     }
1678 
etype() const1679     uint16_t GElfImage::etype() const
1680     {
1681       return ehdr.e_type;
1682     }
1683 
NewElf32Image()1684     Image* NewElf32Image() { return new GElfImage(ELFCLASS32); }
NewElf64Image()1685     Image* NewElf64Image() { return new GElfImage(ELFCLASS64); }
1686 
ElfSize(const void * emi)1687     uint64_t ElfSize(const void* emi)
1688     {
1689       const Elf64_Ehdr *ehdr = (const Elf64_Ehdr*) emi;
1690       if (NULL == ehdr || EV_CURRENT != ehdr->e_version) {
1691         return false;
1692       }
1693 
1694       const Elf64_Shdr *shdr = (const Elf64_Shdr*)((char*)emi + ehdr->e_shoff);
1695       if (NULL == shdr) {
1696         return false;
1697       }
1698 
1699       uint64_t max_offset = ehdr->e_shoff;
1700       uint64_t total_size = max_offset + ehdr->e_shentsize * ehdr->e_shnum;
1701 
1702       for (uint16_t i = 0; i < ehdr->e_shnum; ++i) {
1703         uint64_t cur_offset = static_cast<uint64_t>(shdr[i].sh_offset);
1704         if (max_offset < cur_offset) {
1705           max_offset = cur_offset;
1706           total_size = max_offset;
1707           if (SHT_NOBITS != shdr[i].sh_type) {
1708             total_size += static_cast<uint64_t>(shdr[i].sh_size);
1709           }
1710         }
1711       }
1712 
1713       return total_size;
1714     }
1715 
GetNoteString(uint32_t s_size,const char * s)1716     std::string GetNoteString(uint32_t s_size, const char* s)
1717     {
1718       if (!s_size) { return ""; }
1719       if (s[s_size-1] == '\0') {
1720         return std::string(s, s_size-1);
1721       } else {
1722         return std::string(s, s_size);
1723       }
1724     }
1725 
1726   }
1727 }
1728