elf.cpp (31926B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #undef NDEBUG 6 #include <cstring> 7 #include <assert.h> 8 #include "elfxx.h" 9 10 template <class endian, typename R, typename T> 11 void Elf_Ehdr_Traits::swap(T& t, R& r) { 12 memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident)); 13 r.e_type = endian::swap(t.e_type); 14 r.e_machine = endian::swap(t.e_machine); 15 r.e_version = endian::swap(t.e_version); 16 r.e_entry = endian::swap(t.e_entry); 17 r.e_phoff = endian::swap(t.e_phoff); 18 r.e_shoff = endian::swap(t.e_shoff); 19 r.e_flags = endian::swap(t.e_flags); 20 r.e_ehsize = endian::swap(t.e_ehsize); 21 r.e_phentsize = endian::swap(t.e_phentsize); 22 r.e_phnum = endian::swap(t.e_phnum); 23 r.e_shentsize = endian::swap(t.e_shentsize); 24 r.e_shnum = endian::swap(t.e_shnum); 25 r.e_shstrndx = endian::swap(t.e_shstrndx); 26 } 27 28 template <class endian, typename R, typename T> 29 void Elf_Phdr_Traits::swap(T& t, R& r) { 30 r.p_type = endian::swap(t.p_type); 31 r.p_offset = endian::swap(t.p_offset); 32 r.p_vaddr = endian::swap(t.p_vaddr); 33 r.p_paddr = endian::swap(t.p_paddr); 34 r.p_filesz = endian::swap(t.p_filesz); 35 r.p_memsz = endian::swap(t.p_memsz); 36 r.p_flags = endian::swap(t.p_flags); 37 r.p_align = endian::swap(t.p_align); 38 } 39 40 template <class endian, typename R, typename T> 41 void Elf_Shdr_Traits::swap(T& t, R& r) { 42 r.sh_name = endian::swap(t.sh_name); 43 r.sh_type = endian::swap(t.sh_type); 44 r.sh_flags = endian::swap(t.sh_flags); 45 r.sh_addr = endian::swap(t.sh_addr); 46 r.sh_offset = endian::swap(t.sh_offset); 47 r.sh_size = endian::swap(t.sh_size); 48 r.sh_link = endian::swap(t.sh_link); 49 r.sh_info = endian::swap(t.sh_info); 50 r.sh_addralign = endian::swap(t.sh_addralign); 51 r.sh_entsize = endian::swap(t.sh_entsize); 52 } 53 54 template <class endian, typename R, typename T> 55 void Elf_Dyn_Traits::swap(T& t, R& r) { 56 r.d_tag = endian::swap(t.d_tag); 57 r.d_un.d_val = endian::swap(t.d_un.d_val); 58 } 59 60 template <class endian, typename R, typename T> 61 void Elf_Sym_Traits::swap(T& t, R& r) { 62 r.st_name = endian::swap(t.st_name); 63 r.st_value = endian::swap(t.st_value); 64 r.st_size = endian::swap(t.st_size); 65 r.st_info = t.st_info; 66 r.st_other = t.st_other; 67 r.st_shndx = endian::swap(t.st_shndx); 68 } 69 70 template <class endian> 71 struct _Rel_info { 72 static inline void swap(Elf32_Word& t, Elf32_Word& r) { r = endian::swap(t); } 73 static inline void swap(Elf64_Xword& t, Elf64_Xword& r) { 74 r = endian::swap(t); 75 } 76 static inline void swap(Elf64_Xword& t, Elf32_Word& r) { 77 r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t))); 78 } 79 static inline void swap(Elf32_Word& t, Elf64_Xword& r) { 80 r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t))); 81 } 82 }; 83 84 template <class endian, typename R, typename T> 85 void Elf_Rel_Traits::swap(T& t, R& r) { 86 r.r_offset = endian::swap(t.r_offset); 87 _Rel_info<endian>::swap(t.r_info, r.r_info); 88 } 89 90 template <class endian, typename R, typename T> 91 void Elf_Rela_Traits::swap(T& t, R& r) { 92 r.r_offset = endian::swap(t.r_offset); 93 _Rel_info<endian>::swap(t.r_info, r.r_info); 94 r.r_addend = endian::swap(t.r_addend); 95 } 96 97 static const Elf64_Shdr null64_section = {0, SHT_NULL, 0, 0, 0, 98 0, SHN_UNDEF, 0, 0, 0}; 99 100 Elf_Shdr null_section(null64_section); 101 102 Elf_Ehdr::Elf_Ehdr(std::ifstream& file, unsigned char ei_class, 103 unsigned char ei_data) 104 : serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data), 105 ElfSection(null_section, nullptr, nullptr) { 106 shdr.sh_size = Elf_Ehdr::size(ei_class); 107 } 108 109 Elf::Elf(std::ifstream& file) { 110 if (!file.is_open()) throw std::runtime_error("Error opening file"); 111 112 file.exceptions(std::ifstream::eofbit | std::ifstream::failbit | 113 std::ifstream::badbit); 114 // Read ELF magic number and identification information 115 unsigned char e_ident[EI_VERSION]; 116 file.seekg(0); 117 file.read((char*)e_ident, sizeof(e_ident)); 118 file.seekg(0); 119 ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); 120 121 // ELFOSABI_LINUX is kept unsupported because I haven't looked whether 122 // STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing. 123 if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) && 124 (ehdr->e_ident[EI_ABIVERSION] != 0)) 125 throw std::runtime_error("unsupported ELF ABI"); 126 127 if (ehdr->e_version != 1) throw std::runtime_error("unsupported ELF version"); 128 129 // Sanity checks 130 if (ehdr->e_shnum == 0) 131 throw std::runtime_error("sstripped ELF files aren't supported"); 132 133 if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS])) 134 throw std::runtime_error( 135 "unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)"); 136 137 if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS])) 138 throw std::runtime_error( 139 "unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)"); 140 141 if (ehdr->e_phnum == 0) { 142 if (ehdr->e_phoff != 0) 143 throw std::runtime_error( 144 "unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0"); 145 if (ehdr->e_phentsize != 0) 146 throw std::runtime_error( 147 "unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0"); 148 } else if (ehdr->e_phoff != ehdr->e_ehsize) 149 throw std::runtime_error( 150 "unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize"); 151 else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS])) 152 throw std::runtime_error( 153 "unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)"); 154 155 // Read section headers 156 Elf_Shdr** shdr = new Elf_Shdr*[ehdr->e_shnum]; 157 file.seekg(ehdr->e_shoff); 158 for (int i = 0; i < ehdr->e_shnum; i++) 159 shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); 160 161 // Sanity check in section header for index 0 162 if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) || 163 (shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) || 164 (shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) || 165 (shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) || 166 (shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0)) 167 throw std::runtime_error( 168 "Section header for index 0 contains unsupported values"); 169 170 if ((shdr[ehdr->e_shstrndx]->sh_link != 0) || 171 (shdr[ehdr->e_shstrndx]->sh_info != 0)) 172 throw std::runtime_error( 173 "unsupported ELF content: string table with sh_link != 0 || sh_info != " 174 "0"); 175 176 // Store these temporarily 177 tmp_shdr = shdr; 178 tmp_file = &file; 179 180 // Fill sections list 181 sections = new ElfSection*[ehdr->e_shnum]; 182 for (int i = 0; i < ehdr->e_shnum; i++) sections[i] = nullptr; 183 for (int i = 1; i < ehdr->e_shnum; i++) { 184 // The .dynamic section is going to have references to other sections, 185 // so it's better to start with that one and recursively initialize those 186 // other sections first, to avoid possible infinite recursion (bug 1606739). 187 if (tmp_shdr[i]->sh_type == SHT_DYNAMIC) { 188 getSection(i); 189 } 190 } 191 for (int i = 1; i < ehdr->e_shnum; i++) { 192 if (sections[i] != nullptr) continue; 193 getSection(i); 194 } 195 Elf_Shdr s; 196 s.sh_name = 0; 197 s.sh_type = SHT_NULL; 198 s.sh_flags = 0; 199 s.sh_addr = 0; 200 s.sh_offset = ehdr->e_shoff; 201 s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]); 202 s.sh_size = s.sh_entsize * ehdr->e_shnum; 203 s.sh_link = 0; 204 s.sh_info = 0; 205 s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8; 206 shdr_section = new ElfSection(s, nullptr, nullptr); 207 208 // Fake section for program headers 209 s.sh_offset = ehdr->e_phoff; 210 s.sh_addr = ehdr->e_phoff; 211 s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]); 212 s.sh_size = s.sh_entsize * ehdr->e_phnum; 213 phdr_section = new ElfSection(s, nullptr, nullptr); 214 215 phdr_section->insertAfter(ehdr, false); 216 217 sections[1]->insertAfter(phdr_section, false); 218 for (int i = 2; i < ehdr->e_shnum; i++) { 219 // TODO: this should be done in a better way 220 if ((shdr_section->getPrevious() == nullptr) && 221 (shdr[i]->sh_offset > ehdr->e_shoff)) { 222 shdr_section->insertAfter(sections[i - 1], false); 223 sections[i]->insertAfter(shdr_section, false); 224 } else 225 sections[i]->insertAfter(sections[i - 1], false); 226 } 227 if (shdr_section->getPrevious() == nullptr) 228 shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false); 229 230 tmp_file = nullptr; 231 tmp_shdr = nullptr; 232 for (int i = 0; i < ehdr->e_shnum; i++) delete shdr[i]; 233 delete[] shdr; 234 235 eh_shstrndx = (ElfStrtab_Section*)sections[ehdr->e_shstrndx]; 236 237 // Skip reading program headers if there aren't any 238 if (ehdr->e_phnum == 0) return; 239 240 bool adjusted_phdr_section = false; 241 // Read program headers 242 file.seekg(ehdr->e_phoff); 243 for (int i = 0; i < ehdr->e_phnum; i++) { 244 Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]); 245 if (phdr.p_type == PT_LOAD) { 246 // Default alignment for PT_LOAD on x86-64 prevents elfhack from 247 // doing anything useful. However, the system doesn't actually 248 // require such a big alignment, so in order for elfhack to work 249 // efficiently, reduce alignment when it's originally the default 250 // one. 251 if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000)) 252 phdr.p_align = 0x1000; 253 } 254 ElfSegment* segment = new ElfSegment(&phdr); 255 // Some segments aren't entirely filled (if at all) by sections 256 // For those, we use fake sections 257 if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) { 258 // Use a fake section for ehdr and phdr 259 ehdr->getShdr().sh_addr = phdr.p_vaddr; 260 if (!adjusted_phdr_section) { 261 phdr_section->getShdr().sh_addr += phdr.p_vaddr; 262 adjusted_phdr_section = true; 263 } 264 segment->addSection(ehdr); 265 segment->addSection(phdr_section); 266 } 267 if (phdr.p_type == PT_PHDR) { 268 if (!adjusted_phdr_section) { 269 phdr_section->getShdr().sh_addr = phdr.p_vaddr; 270 adjusted_phdr_section = true; 271 } 272 segment->addSection(phdr_section); 273 } 274 for (int j = 1; j < ehdr->e_shnum; j++) 275 if (phdr.contains(sections[j])) segment->addSection(sections[j]); 276 // Make sure that our view of segments corresponds to the original 277 // ELF file. 278 // GNU gold likes to start some segments before the first section 279 // they contain. https://sourceware.org/bugzilla/show_bug.cgi?id=19392 280 unsigned int gold_adjustment = segment->getAddr() - phdr.p_vaddr; 281 assert(segment->getFileSize() == phdr.p_filesz - gold_adjustment); 282 // gold makes TLS segments end on an aligned virtual address, even 283 // when the underlying section ends before that, while bfd ld 284 // doesn't. It's fine if we don't keep that alignment. 285 unsigned int memsize = segment->getMemSize(); 286 if (phdr.p_type == PT_TLS && memsize != phdr.p_memsz) { 287 unsigned int align = segment->getAlign(); 288 memsize = (memsize + align - 1) & ~(align - 1); 289 } 290 assert(memsize == phdr.p_memsz - gold_adjustment); 291 segments.push_back(segment); 292 } 293 294 new (&eh_entry) ElfLocation(ehdr->e_entry, this); 295 } 296 297 Elf::~Elf() { 298 for (std::vector<ElfSegment*>::iterator seg = segments.begin(); 299 seg != segments.end(); seg++) 300 delete *seg; 301 delete[] sections; 302 ElfSection* section = ehdr; 303 while (section != nullptr) { 304 ElfSection* next = section->getNext(); 305 delete section; 306 section = next; 307 } 308 } 309 310 // TODO: This shouldn't fail after inserting sections 311 ElfSection* Elf::getSection(int index) { 312 if ((index < -1) || (index >= ehdr->e_shnum)) 313 throw std::runtime_error("Section index out of bounds"); 314 if (index == -1) 315 index = ehdr->e_shstrndx; // TODO: should be fixed to use the actual 316 // current number 317 // Special case: the section at index 0 is void 318 if (index == 0) return nullptr; 319 // Infinite recursion guard 320 if (sections[index] == (ElfSection*)this) return nullptr; 321 if (sections[index] == nullptr) { 322 sections[index] = (ElfSection*)this; 323 switch (tmp_shdr[index]->sh_type) { 324 case SHT_DYNAMIC: 325 sections[index] = 326 new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this); 327 break; 328 case SHT_REL: 329 sections[index] = 330 new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this); 331 break; 332 case SHT_RELA: 333 sections[index] = 334 new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this); 335 break; 336 case SHT_DYNSYM: 337 case SHT_SYMTAB: 338 sections[index] = 339 new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this); 340 break; 341 case SHT_STRTAB: 342 sections[index] = 343 new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this); 344 break; 345 default: 346 sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this); 347 } 348 } 349 return sections[index]; 350 } 351 352 ElfSection* Elf::getSectionAt(Elf64_Off offset) { 353 for (int i = 1; i < ehdr->e_shnum; i++) { 354 ElfSection* section = getSection(i); 355 if ((section != nullptr) && (section->getFlags() & SHF_ALLOC) && 356 !(section->getFlags() & SHF_TLS) && (offset >= section->getAddr()) && 357 (offset < section->getAddr() + section->getSize())) 358 return section; 359 } 360 return nullptr; 361 } 362 363 ElfSegment* Elf::getSegmentByType(unsigned int type, ElfSegment* last) { 364 std::vector<ElfSegment*>::iterator seg; 365 if (last) { 366 seg = std::find(segments.begin(), segments.end(), last); 367 ++seg; 368 } else 369 seg = segments.begin(); 370 for (; seg != segments.end(); seg++) 371 if ((*seg)->getType() == type) return *seg; 372 return nullptr; 373 } 374 375 void Elf::removeSegment(ElfSegment* segment) { 376 if (!segment) return; 377 std::vector<ElfSegment*>::iterator seg; 378 seg = std::find(segments.begin(), segments.end(), segment); 379 if (seg == segments.end()) return; 380 segment->clear(); 381 segments.erase(seg); 382 } 383 384 ElfDynamic_Section* Elf::getDynSection() { 385 for (std::vector<ElfSegment*>::iterator seg = segments.begin(); 386 seg != segments.end(); seg++) 387 if (((*seg)->getType() == PT_DYNAMIC) && 388 ((*seg)->getFirstSection() != nullptr) && 389 (*seg)->getFirstSection()->getType() == SHT_DYNAMIC) 390 return (ElfDynamic_Section*)(*seg)->getFirstSection(); 391 392 return nullptr; 393 } 394 395 void Elf::normalize() { 396 // fixup section headers sh_name; TODO: that should be done by sections 397 // themselves 398 for (ElfSection* section = ehdr; section != nullptr; 399 section = section->getNext()) { 400 if (section->getIndex() == 0) 401 continue; 402 else 403 ehdr->e_shnum = section->getIndex() + 1; 404 section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName()); 405 } 406 ehdr->markDirty(); 407 // Check segments consistency 408 int i = 0; 409 for (std::vector<ElfSegment*>::iterator seg = segments.begin(); 410 seg != segments.end(); seg++, i++) { 411 std::list<ElfSection*>::iterator it = (*seg)->begin(); 412 for (ElfSection* last = *(it++); it != (*seg)->end(); last = *(it++)) { 413 if (((*it)->getType() != SHT_NOBITS) && 414 ((*it)->getAddr() - last->getAddr()) != 415 ((*it)->getOffset() - last->getOffset())) { 416 throw std::runtime_error("Segments inconsistency"); 417 } 418 } 419 } 420 421 ElfSegment* prevLoad = nullptr; 422 for (auto& it : segments) { 423 if (it->getType() == PT_LOAD) { 424 if (prevLoad) { 425 size_t alignedPrevEnd = (prevLoad->getAddr() + prevLoad->getMemSize() + 426 prevLoad->getAlign() - 1) & 427 ~(prevLoad->getAlign() - 1); 428 size_t alignedStart = it->getAddr() & ~(it->getAlign() - 1); 429 if (alignedPrevEnd > alignedStart) { 430 throw std::runtime_error("Segments overlap"); 431 } 432 } 433 prevLoad = it; 434 } 435 } 436 437 // fixup ehdr before writing 438 if (ehdr->e_phnum != segments.size()) { 439 ehdr->e_phnum = segments.size(); 440 phdr_section->getShdr().sh_size = 441 segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]); 442 phdr_section->getNext()->markDirty(); 443 } 444 // fixup shdr before writing 445 if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize()) 446 shdr_section->getShdr().sh_size = 447 ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]); 448 ehdr->e_shoff = shdr_section->getOffset(); 449 ehdr->e_entry = eh_entry.getValue(); 450 ehdr->e_shstrndx = eh_shstrndx->getIndex(); 451 452 // Check sections consistency 453 unsigned int minOffset = 0; 454 for (ElfSection* section = ehdr; section != nullptr; 455 section = section->getNext()) { 456 unsigned int offset = section->getOffset(); 457 if (offset < minOffset) { 458 throw std::runtime_error("Sections overlap"); 459 } 460 if (section->getType() != SHT_NOBITS) { 461 minOffset = offset + section->getSize(); 462 } 463 } 464 } 465 466 void Elf::write(std::ofstream& file) { 467 normalize(); 468 for (ElfSection* section = ehdr; section != nullptr; 469 section = section->getNext()) { 470 file.seekp(section->getOffset()); 471 if (section == phdr_section) { 472 for (std::vector<ElfSegment*>::iterator seg = segments.begin(); 473 seg != segments.end(); seg++) { 474 Elf_Phdr phdr; 475 phdr.p_type = (*seg)->getType(); 476 phdr.p_flags = (*seg)->getFlags(); 477 phdr.p_offset = (*seg)->getOffset(); 478 phdr.p_vaddr = (*seg)->getAddr(); 479 phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff(); 480 phdr.p_filesz = (*seg)->getFileSize(); 481 phdr.p_memsz = (*seg)->getMemSize(); 482 phdr.p_align = (*seg)->getAlign(); 483 phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]); 484 } 485 } else if (section == shdr_section) { 486 null_section.serialize(file, ehdr->e_ident[EI_CLASS], 487 ehdr->e_ident[EI_DATA]); 488 for (ElfSection* sec = ehdr; sec != nullptr; sec = sec->getNext()) { 489 if (sec->getType() != SHT_NULL) 490 sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS], 491 ehdr->e_ident[EI_DATA]); 492 } 493 } else 494 section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]); 495 } 496 } 497 498 ElfSection::ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent) 499 : shdr(s), 500 link(shdr.sh_link == SHN_UNDEF ? nullptr 501 : parent->getSection(shdr.sh_link)), 502 next(nullptr), 503 previous(nullptr), 504 index(-1) { 505 if ((file == nullptr) || (shdr.sh_type == SHT_NULL) || 506 (shdr.sh_type == SHT_NOBITS)) 507 data = nullptr; 508 else { 509 data = static_cast<char*>(malloc(shdr.sh_size)); 510 if (!data) { 511 throw std::runtime_error("Could not malloc ElfSection data"); 512 } 513 auto pos = file->tellg(); 514 file->seekg(shdr.sh_offset); 515 file->read(data, shdr.sh_size); 516 file->seekg(pos); 517 } 518 if (shdr.sh_name == 0) 519 name = nullptr; 520 else { 521 ElfStrtab_Section* strtab = (ElfStrtab_Section*)parent->getSection(-1); 522 // Special case (see elfgeneric.cpp): if strtab is nullptr, the 523 // section being created is the strtab. 524 if (strtab == nullptr) 525 name = &data[shdr.sh_name]; 526 else 527 name = strtab->getStr(shdr.sh_name); 528 } 529 // Only SHT_REL/SHT_RELA sections use sh_info to store a section 530 // number. 531 if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA)) 532 info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : nullptr; 533 else 534 info.index = shdr.sh_info; 535 } 536 537 Elf64_Addr ElfSection::getAddr() { 538 if (shdr.sh_addr != (Elf64_Addr)-1) return shdr.sh_addr; 539 540 // It should be safe to adjust sh_addr for all allocated sections that 541 // are neither SHT_NOBITS nor SHT_PROGBITS 542 if ((previous != nullptr) && isRelocatable()) { 543 unsigned int addr = previous->getAddr(); 544 if (previous->getType() != SHT_NOBITS) addr += previous->getSize(); 545 546 if (addr & (getAddrAlign() - 1)) addr = (addr | (getAddrAlign() - 1)) + 1; 547 548 return (shdr.sh_addr = addr); 549 } 550 return shdr.sh_addr; 551 } 552 553 Elf64_Off ElfSection::getOffset() { 554 if (shdr.sh_offset != (Elf64_Off)-1) return shdr.sh_offset; 555 556 if (previous == nullptr) return (shdr.sh_offset = 0); 557 558 Elf64_Off offset = previous->getOffset(); 559 560 ElfSegment* ptload = getSegmentByType(PT_LOAD); 561 ElfSegment* prev_ptload = previous->getSegmentByType(PT_LOAD); 562 563 if (ptload && (ptload == prev_ptload)) { 564 offset += getAddr() - previous->getAddr(); 565 return (shdr.sh_offset = offset); 566 } 567 568 if (previous->getType() != SHT_NOBITS) offset += previous->getSize(); 569 570 Elf32_Word align = 0x1000; 571 for (std::vector<ElfSegment*>::iterator seg = segments.begin(); 572 seg != segments.end(); seg++) 573 align = std::max(align, (*seg)->getAlign()); 574 575 Elf32_Word mask = align - 1; 576 // SHF_TLS is used for .tbss which is some kind of special case. 577 if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && 578 (getFlags() & SHF_ALLOC)) { 579 if ((getAddr() & mask) < (offset & mask)) 580 offset = (offset | mask) + (getAddr() & mask) + 1; 581 else 582 offset = (offset & ~mask) + (getAddr() & mask); 583 } 584 if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1))) 585 offset = (offset | (getAddrAlign() - 1)) + 1; 586 587 return (shdr.sh_offset = offset); 588 } 589 590 int ElfSection::getIndex() { 591 if (index != -1) return index; 592 if (getType() == SHT_NULL) return (index = 0); 593 ElfSection* reference; 594 for (reference = previous; 595 (reference != nullptr) && (reference->getType() == SHT_NULL); 596 reference = reference->getPrevious()); 597 if (reference == nullptr) return (index = 1); 598 return (index = reference->getIndex() + 1); 599 } 600 601 Elf_Shdr& ElfSection::getShdr() { 602 getOffset(); 603 if (shdr.sh_link == (Elf64_Word)-1) 604 shdr.sh_link = getLink() ? getLink()->getIndex() : 0; 605 if (shdr.sh_info == (Elf64_Word)-1) 606 shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) 607 ? (getInfo().section ? getInfo().section->getIndex() : 0) 608 : getInfo().index; 609 610 return shdr; 611 } 612 613 ElfSegment::ElfSegment(Elf_Phdr* phdr) 614 : type(phdr->p_type), 615 v_p_diff(phdr->p_paddr - phdr->p_vaddr), 616 flags(phdr->p_flags), 617 align(phdr->p_align), 618 vaddr(phdr->p_vaddr), 619 filesz(phdr->p_filesz), 620 memsz(phdr->p_memsz) {} 621 622 void ElfSegment::addSection(ElfSection* section) { 623 // Make sure all sections in PT_GNU_RELRO won't be moved by elfhack 624 assert(!((type == PT_GNU_RELRO) && (section->isRelocatable()))); 625 626 // TODO: Check overlapping sections 627 std::list<ElfSection*>::iterator i; 628 for (i = sections.begin(); i != sections.end(); ++i) 629 if ((*i)->getAddr() > section->getAddr()) break; 630 sections.insert(i, section); 631 section->addToSegment(this); 632 } 633 634 void ElfSegment::removeSection(ElfSection* section) { 635 sections.remove(section); 636 section->removeFromSegment(this); 637 } 638 639 unsigned int ElfSegment::getFileSize() { 640 if (type == PT_GNU_RELRO) return filesz; 641 642 if (sections.empty()) return 0; 643 // Search the last section that is not SHT_NOBITS 644 std::list<ElfSection*>::reverse_iterator i; 645 for (i = sections.rbegin(); 646 (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i); 647 // All sections are SHT_NOBITS 648 if (i == sections.rend()) return 0; 649 650 unsigned int end = (*i)->getAddr() + (*i)->getSize(); 651 652 return end - sections.front()->getAddr(); 653 } 654 655 unsigned int ElfSegment::getMemSize() { 656 if (type == PT_GNU_RELRO) return memsz; 657 658 if (sections.empty()) return 0; 659 660 unsigned int end = sections.back()->getAddr() + sections.back()->getSize(); 661 662 return end - sections.front()->getAddr(); 663 } 664 665 unsigned int ElfSegment::getOffset() { 666 if ((type == PT_GNU_RELRO) && !sections.empty() && 667 (sections.front()->getAddr() != vaddr)) 668 throw std::runtime_error( 669 "PT_GNU_RELRO segment doesn't start on a section start"); 670 671 return sections.empty() ? 0 : sections.front()->getOffset(); 672 } 673 674 unsigned int ElfSegment::getAddr() { 675 if ((type == PT_GNU_RELRO) && !sections.empty() && 676 (sections.front()->getAddr() != vaddr)) 677 throw std::runtime_error( 678 "PT_GNU_RELRO segment doesn't start on a section start"); 679 680 return sections.empty() ? 0 : sections.front()->getAddr(); 681 } 682 683 void ElfSegment::clear() { 684 for (std::list<ElfSection*>::iterator i = sections.begin(); 685 i != sections.end(); ++i) 686 (*i)->removeFromSegment(this); 687 sections.clear(); 688 } 689 690 ElfValue* ElfDynamic_Section::getValueForType(unsigned int tag) { 691 for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) 692 if (dyns[i].tag == tag) return dyns[i].value; 693 694 return nullptr; 695 } 696 697 ElfSection* ElfDynamic_Section::getSectionForType(unsigned int tag) { 698 ElfValue* value = getValueForType(tag); 699 return value ? value->getSection() : nullptr; 700 } 701 702 bool ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue* val) { 703 unsigned int i; 704 unsigned int shnum = shdr.sh_size / shdr.sh_entsize; 705 for (i = 0; (i < shnum) && (dyns[i].tag != DT_NULL); i++) 706 if (dyns[i].tag == tag) { 707 delete dyns[i].value; 708 dyns[i].value = val; 709 return true; 710 } 711 // If we get here, this means we didn't match for the given tag 712 // Most of the time, there are a few DT_NULL entries, that we can 713 // use to add our value, but if we are on the last entry, we can't. 714 if (i >= shnum - 1) return false; 715 716 dyns[i].tag = tag; 717 dyns[i].value = val; 718 return true; 719 } 720 721 ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file, 722 Elf* parent) 723 : ElfSection(s, file, parent) { 724 auto pos = file->tellg(); 725 dyns.resize(s.sh_size / s.sh_entsize); 726 file->seekg(shdr.sh_offset); 727 // Here we assume tags refer to only one section (e.g. DT_RELSZ accounts 728 // for .rel.dyn size) 729 for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) { 730 Elf_Dyn dyn(*file, parent->getClass(), parent->getData()); 731 dyns[i].tag = dyn.d_tag; 732 switch (dyn.d_tag) { 733 case DT_NULL: 734 case DT_SYMBOLIC: 735 case DT_TEXTREL: 736 case DT_BIND_NOW: 737 dyns[i].value = new ElfValue(); 738 break; 739 case DT_NEEDED: 740 case DT_SONAME: 741 case DT_RPATH: 742 case DT_PLTREL: 743 case DT_RUNPATH: 744 case DT_FLAGS: 745 case DT_RELACOUNT: 746 case DT_RELCOUNT: 747 case DT_VERDEFNUM: 748 case DT_VERNEEDNUM: 749 dyns[i].value = new ElfPlainValue(dyn.d_un.d_val); 750 break; 751 case DT_PLTGOT: 752 case DT_HASH: 753 case DT_STRTAB: 754 case DT_SYMTAB: 755 case DT_RELA: 756 case DT_INIT: 757 case DT_FINI: 758 case DT_REL: 759 case DT_JMPREL: 760 case DT_INIT_ARRAY: 761 case DT_FINI_ARRAY: 762 case DT_GNU_HASH: 763 case DT_VERSYM: 764 case DT_VERNEED: 765 case DT_VERDEF: 766 dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent); 767 break; 768 default: 769 dyns[i].value = nullptr; 770 } 771 } 772 // Another loop to get the section sizes 773 for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) 774 switch (dyns[i].tag) { 775 case DT_PLTRELSZ: 776 dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL)); 777 break; 778 case DT_RELASZ: 779 dyns[i].value = new ElfSize(getSectionForType(DT_RELA)); 780 break; 781 case DT_STRSZ: 782 dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB)); 783 break; 784 case DT_RELSZ: 785 dyns[i].value = new ElfSize(getSectionForType(DT_REL)); 786 break; 787 case DT_INIT_ARRAYSZ: 788 dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY)); 789 break; 790 case DT_FINI_ARRAYSZ: 791 dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY)); 792 break; 793 case DT_RELAENT: 794 dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA)); 795 break; 796 case DT_SYMENT: 797 dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB)); 798 break; 799 case DT_RELENT: 800 dyns[i].value = new ElfEntSize(getSectionForType(DT_REL)); 801 break; 802 } 803 804 file->seekg(pos); 805 } 806 807 ElfDynamic_Section::~ElfDynamic_Section() { 808 for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) 809 delete dyns[i].value; 810 } 811 812 void ElfDynamic_Section::serialize(std::ofstream& file, unsigned char ei_class, 813 unsigned char ei_data) { 814 for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { 815 Elf_Dyn dyn; 816 dyn.d_tag = dyns[i].tag; 817 dyn.d_un.d_val = (dyns[i].value != nullptr) ? dyns[i].value->getValue() : 0; 818 dyn.serialize(file, ei_class, ei_data); 819 } 820 } 821 822 ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file, 823 Elf* parent) 824 : ElfSection(s, file, parent) { 825 auto pos = file->tellg(); 826 syms.resize(s.sh_size / s.sh_entsize); 827 ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink(); 828 file->seekg(shdr.sh_offset); 829 for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { 830 Elf_Sym sym(*file, parent->getClass(), parent->getData()); 831 syms[i].name = strtab->getStr(sym.st_name); 832 syms[i].info = sym.st_info; 833 syms[i].other = sym.st_other; 834 ElfSection* section = 835 (sym.st_shndx == SHN_ABS) ? nullptr : parent->getSection(sym.st_shndx); 836 new (&syms[i].value) 837 ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE); 838 syms[i].size = sym.st_size; 839 syms[i].defined = (sym.st_shndx != SHN_UNDEF); 840 } 841 file->seekg(pos); 842 } 843 844 void ElfSymtab_Section::serialize(std::ofstream& file, unsigned char ei_class, 845 unsigned char ei_data) { 846 ElfStrtab_Section* strtab = (ElfStrtab_Section*)getLink(); 847 for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) { 848 Elf_Sym sym; 849 sym.st_name = strtab->getStrIndex(syms[i].name); 850 sym.st_info = syms[i].info; 851 sym.st_other = syms[i].other; 852 sym.st_value = syms[i].value.getValue(); 853 ElfSection* section = syms[i].value.getSection(); 854 if (syms[i].defined) 855 sym.st_shndx = section ? section->getIndex() : SHN_ABS; 856 else 857 sym.st_shndx = SHN_UNDEF; 858 sym.st_size = syms[i].size; 859 sym.serialize(file, ei_class, ei_data); 860 } 861 } 862 863 Elf_SymValue* ElfSymtab_Section::lookup(const char* name, 864 unsigned int type_filter) { 865 for (std::vector<Elf_SymValue>::iterator sym = syms.begin(); 866 sym != syms.end(); sym++) { 867 if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) && 868 (strcmp(sym->name, name) == 0)) { 869 return &*sym; 870 } 871 } 872 return nullptr; 873 } 874 875 const char* ElfStrtab_Section::getStr(unsigned int index) { 876 for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); 877 t++) { 878 if (index < t->used) return t->buf + index; 879 index -= t->used; 880 } 881 assert(1 == 0); 882 return nullptr; 883 } 884 885 const char* ElfStrtab_Section::getStr(const char* string) { 886 if (string == nullptr) return nullptr; 887 888 // If the given string is within the section, return it 889 for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); 890 t++) 891 if ((string >= t->buf) && (string < t->buf + t->used)) return string; 892 893 // TODO: should scan in the section to find an existing string 894 895 // If not, we need to allocate the string in the section 896 size_t len = strlen(string) + 1; 897 898 if (table.back().size - table.back().used < len) 899 table.resize(table.size() + 1); 900 901 char* alloc_str = table.back().buf + table.back().used; 902 memcpy(alloc_str, string, len); 903 table.back().used += len; 904 905 shdr.sh_size += len; 906 markDirty(); 907 908 return alloc_str; 909 } 910 911 unsigned int ElfStrtab_Section::getStrIndex(const char* string) { 912 if (string == nullptr) return 0; 913 914 unsigned int index = 0; 915 string = getStr(string); 916 for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); 917 t++) { 918 if ((string >= t->buf) && (string < t->buf + t->used)) 919 return index + (string - t->buf); 920 index += t->used; 921 } 922 923 assert(1 == 0); 924 return 0; 925 } 926 927 void ElfStrtab_Section::serialize(std::ofstream& file, unsigned char ei_class, 928 unsigned char ei_data) { 929 file.seekp(getOffset()); 930 for (std::vector<table_storage>::iterator t = table.begin(); t != table.end(); 931 t++) 932 file.write(t->buf, t->used); 933 }