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