1// elfcpp_file.h -- file access for elfcpp -*- C++ -*- 2 3// Copyright 2006, 2007, Free Software Foundation, Inc. 4// Written by Ian Lance Taylor <iant@google.com>. 5 6// This file is part of elfcpp. 7 8// This program is free software; you can redistribute it and/or 9// modify it under the terms of the GNU Library General Public License 10// as published by the Free Software Foundation; either version 2, or 11// (at your option) any later version. 12 13// In addition to the permissions in the GNU Library General Public 14// License, the Free Software Foundation gives you unlimited 15// permission to link the compiled version of this file into 16// combinations with other programs, and to distribute those 17// combinations without any restriction coming from the use of this 18// file. (The Library Public License restrictions do apply in other 19// respects; for example, they cover modification of the file, and 20/// distribution when not linked into a combined executable.) 21 22// This program is distributed in the hope that it will be useful, but 23// WITHOUT ANY WARRANTY; without even the implied warranty of 24// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25// Library General Public License for more details. 26 27// You should have received a copy of the GNU Library General Public 28// License along with this program; if not, write to the Free Software 29// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 30// 02110-1301, USA. 31 32// This header file defines the class Elf_file which can be used to 33// read useful data from an ELF file. The functions here are all 34// templates which take a file interface object as a parameter. This 35// type must have a subtype View. This type must support two methods: 36// View view(off_t file_offset, off_t data_size) 37// returns a View for the specified part of the file. 38// void error(const char* printf_format, ...) 39// prints an error message and does not return. The subtype View must 40// support a method 41// const unsigned char* data() 42// which returns a pointer to a buffer containing the requested data. 43// This general interface is used to read data from the file. Objects 44// of type View will never survive longer than the elfcpp function. 45 46// Some of these functions must return a reference to part of the 47// file. To use these, the file interface must support a subtype 48// Location: 49// Location(off_t file_offset, off_t data_size) 50// To use this in conjunction with the accessors types Shdr, etc., the 51// file interface should support an overload of view: 52// View view(Location) 53// This permits writing 54// elfcpp::Shdr shdr(file, ef.section_header(n)); 55 56#ifndef ELFCPP_FILE_H 57#define ELFCPP_FILE_H 58 59#include <string> 60#include <cstdio> 61#include <cstring> 62 63#include "elfcpp.h" 64 65namespace elfcpp 66{ 67 68// A simple helper class to recognize if a file has an ELF header. 69 70class Elf_recognizer 71{ 72 public: 73 // Maximum header size. The user should try to read this much of 74 // the file when using this class. 75 76 static const int max_header_size = Elf_sizes<64>::ehdr_size; 77 78 // Checks if the file contains the ELF magic. Other header fields 79 // are not checked. 80 81 static bool 82 is_elf_file(const unsigned char* ehdr_buf, int size); 83 84 // Check if EHDR_BUF/BUFSIZE is a valid header of a 32-bit or 85 // 64-bit, little-endian or big-endian ELF file. Assumes 86 // is_elf_file() has been checked to be true. If the header is not 87 // valid, *ERROR contains a human-readable error message. If is is, 88 // *SIZE is set to either 32 or 64, *BIG_ENDIAN is set to indicate 89 // whether the file is big-endian. 90 91 static bool 92 is_valid_header(const unsigned char* ehdr_buf, off_t bufsize, 93 int* size, bool* big_endian, 94 std::string* error); 95}; 96 97// This object is used to read an ELF file. 98// SIZE: The size of file, 32 or 64. 99// BIG_ENDIAN: Whether the file is in big-endian format. 100// FILE: A file reading type as described above. 101 102template<int size, bool big_endian, typename File> 103class Elf_file 104{ 105 private: 106 typedef Elf_file<size, big_endian, File> This; 107 108 public: 109 static const int ehdr_size = Elf_sizes<size>::ehdr_size; 110 static const int phdr_size = Elf_sizes<size>::phdr_size; 111 static const int shdr_size = Elf_sizes<size>::shdr_size; 112 static const int sym_size = Elf_sizes<size>::sym_size; 113 static const int rel_size = Elf_sizes<size>::rel_size; 114 static const int rela_size = Elf_sizes<size>::rela_size; 115 116 typedef Ehdr<size, big_endian> Ef_ehdr; 117 typedef Phdr<size, big_endian> Ef_phdr; 118 typedef Shdr<size, big_endian> Ef_shdr; 119 typedef Sym<size, big_endian> Ef_sym; 120 121 // Construct an Elf_file given an ELF file header. 122 Elf_file(File* file, const Ef_ehdr& ehdr) 123 { this->construct(file, ehdr); } 124 125 // Construct an ELF file. 126 inline 127 Elf_file(File* file); 128 129 // Return the file offset to the section headers. 130 off_t 131 shoff() const 132 { return this->shoff_; } 133 134 // Find the first section with an sh_type field equal to TYPE and 135 // return its index. Returns SHN_UNDEF if there is no such section. 136 unsigned int 137 find_section_by_type(unsigned int type); 138 139 // Return the number of sections. 140 unsigned int 141 shnum() 142 { 143 this->initialize_shnum(); 144 return this->shnum_; 145 } 146 147 // Return the section index of the section name string table. 148 unsigned int 149 shstrndx() 150 { 151 this->initialize_shnum(); 152 return this->shstrndx_; 153 } 154 155 // Return the value to subtract from section indexes >= 156 // SHN_LORESERVE. See the comment in initialize_shnum. 157 int 158 large_shndx_offset() 159 { 160 this->initialize_shnum(); 161 return this->large_shndx_offset_; 162 } 163 164 // Return the location of the header of section SHNDX. 165 typename File::Location 166 section_header(unsigned int shndx) 167 { 168 return typename File::Location(this->section_header_offset(shndx), 169 shdr_size); 170 } 171 172 // Return the name of section SHNDX. 173 std::string 174 section_name(unsigned int shndx); 175 176 // Return the location of the contents of section SHNDX. 177 typename File::Location 178 section_contents(unsigned int shndx); 179 180 // Return the size of section SHNDX. 181 typename Elf_types<size>::Elf_WXword 182 section_size(unsigned int shndx); 183 184 // Return the flags of section SHNDX. 185 typename Elf_types<size>::Elf_WXword 186 section_flags(unsigned int shndx); 187 188 // Return the address of section SHNDX. 189 typename Elf_types<size>::Elf_Addr 190 section_addr(unsigned int shndx); 191 192 // Return the type of section SHNDX. 193 Elf_Word 194 section_type(unsigned int shndx); 195 196 // Return the link field of section SHNDX. 197 Elf_Word 198 section_link(unsigned int shndx); 199 200 // Return the info field of section SHNDX. 201 Elf_Word 202 section_info(unsigned int shndx); 203 204 // Return the addralign field of section SHNDX. 205 typename Elf_types<size>::Elf_WXword 206 section_addralign(unsigned int shndx); 207 208 private: 209 // Shared constructor code. 210 void 211 construct(File* file, const Ef_ehdr& ehdr); 212 213 // Initialize shnum_ and shstrndx_. 214 void 215 initialize_shnum(); 216 217 // Return the file offset of the header of section SHNDX. 218 off_t 219 section_header_offset(unsigned int shndx); 220 221 // The file we are reading. 222 File* file_; 223 // The file offset to the section headers. 224 off_t shoff_; 225 // The number of sections. 226 unsigned int shnum_; 227 // The section index of the section name string table. 228 unsigned int shstrndx_; 229 // Offset to add to sections larger than SHN_LORESERVE. 230 int large_shndx_offset_; 231}; 232 233// A small wrapper around SHT_STRTAB data mapped to memory. It checks that the 234// index is not out of bounds and the string is NULL-terminated. 235 236class Elf_strtab 237{ 238 public: 239 // Construct an Elf_strtab for a section with contents *P and size SIZE. 240 Elf_strtab(const unsigned char* p, size_t size); 241 242 // Return the file offset to the section headers. 243 bool 244 get_c_string(size_t offset, const char** cstring) const 245 { 246 if (offset >= this->usable_size_) 247 return false; 248 *cstring = this->base_ + offset; 249 return true; 250 } 251 252 private: 253 // Contents of the section mapped to memory. 254 const char* base_; 255 // One larger that the position of the last NULL character in the section. 256 // For valid SHT_STRTAB sections, this is the size of the section. 257 size_t usable_size_; 258}; 259 260// Inline function definitions. 261 262// Check for presence of the ELF magic number. 263 264inline bool 265Elf_recognizer::is_elf_file(const unsigned char* ehdr_buf, int size) 266{ 267 if (size < 4) 268 return false; 269 270 static unsigned char elfmagic[4] = 271 { 272 elfcpp::ELFMAG0, elfcpp::ELFMAG1, 273 elfcpp::ELFMAG2, elfcpp::ELFMAG3 274 }; 275 return memcmp(ehdr_buf, elfmagic, 4) == 0; 276} 277 278namespace 279{ 280 281// Print a number to a string. 282 283inline std::string 284internal_printf_int(const char* format, int arg) 285{ 286 char buf[256]; 287 snprintf(buf, sizeof(buf), format, arg); 288 return std::string(buf); 289} 290 291} // End anonymous namespace. 292 293// Check the validity of the ELF header. 294 295inline bool 296Elf_recognizer::is_valid_header( 297 const unsigned char* ehdr_buf, 298 off_t bufsize, 299 int* size, 300 bool* big_endian, 301 std::string* error) 302{ 303 if (bufsize < elfcpp::EI_NIDENT) 304 { 305 *error = _("ELF file too short"); 306 return false; 307 } 308 309 int v = ehdr_buf[elfcpp::EI_VERSION]; 310 if (v != elfcpp::EV_CURRENT) 311 { 312 if (v == elfcpp::EV_NONE) 313 *error = _("invalid ELF version 0"); 314 else 315 *error = internal_printf_int(_("unsupported ELF version %d"), v); 316 return false; 317 } 318 319 int c = ehdr_buf[elfcpp::EI_CLASS]; 320 if (c == elfcpp::ELFCLASSNONE) 321 { 322 *error = _("invalid ELF class 0"); 323 return false; 324 } 325 else if (c != elfcpp::ELFCLASS32 326 && c != elfcpp::ELFCLASS64) 327 { 328 *error = internal_printf_int(_("unsupported ELF class %d"), c); 329 return false; 330 } 331 332 int d = ehdr_buf[elfcpp::EI_DATA]; 333 if (d == elfcpp::ELFDATANONE) 334 { 335 *error = _("invalid ELF data encoding"); 336 return false; 337 } 338 else if (d != elfcpp::ELFDATA2LSB 339 && d != elfcpp::ELFDATA2MSB) 340 { 341 *error = internal_printf_int(_("unsupported ELF data encoding %d"), d); 342 return false; 343 } 344 345 *big_endian = (d == elfcpp::ELFDATA2MSB); 346 347 if (c == elfcpp::ELFCLASS32) 348 { 349 if (bufsize < elfcpp::Elf_sizes<32>::ehdr_size) 350 { 351 *error = _("ELF file too short"); 352 return false; 353 } 354 *size = 32; 355 } 356 else 357 { 358 if (bufsize < elfcpp::Elf_sizes<64>::ehdr_size) 359 { 360 *error = _("ELF file too short"); 361 return false; 362 } 363 *size = 64; 364 } 365 366 return true; 367} 368 369// Template function definitions. 370 371// Construct an Elf_file given an ELF file header. 372 373template<int size, bool big_endian, typename File> 374void 375Elf_file<size, big_endian, File>::construct(File* file, const Ef_ehdr& ehdr) 376{ 377 this->file_ = file; 378 this->shoff_ = ehdr.get_e_shoff(); 379 this->shnum_ = ehdr.get_e_shnum(); 380 this->shstrndx_ = ehdr.get_e_shstrndx(); 381 this->large_shndx_offset_ = 0; 382 if (ehdr.get_e_ehsize() != This::ehdr_size) 383 file->error(_("bad e_ehsize (%d != %d)"), 384 ehdr.get_e_ehsize(), This::ehdr_size); 385 if (ehdr.get_e_shentsize() != This::shdr_size) 386 file->error(_("bad e_shentsize (%d != %d)"), 387 ehdr.get_e_shentsize(), This::shdr_size); 388} 389 390// Construct an ELF file. 391 392template<int size, bool big_endian, typename File> 393inline 394Elf_file<size, big_endian, File>::Elf_file(File* file) 395{ 396 typename File::View v(file->view(file_header_offset, This::ehdr_size)); 397 this->construct(file, Ef_ehdr(v.data())); 398} 399 400// Initialize the shnum_ and shstrndx_ fields, handling overflow. 401 402template<int size, bool big_endian, typename File> 403void 404Elf_file<size, big_endian, File>::initialize_shnum() 405{ 406 if ((this->shnum_ == 0 || this->shstrndx_ == SHN_XINDEX) 407 && this->shoff_ != 0) 408 { 409 typename File::View v(this->file_->view(this->shoff_, This::shdr_size)); 410 Ef_shdr shdr(v.data()); 411 412 if (this->shnum_ == 0) 413 this->shnum_ = shdr.get_sh_size(); 414 415 if (this->shstrndx_ == SHN_XINDEX) 416 { 417 this->shstrndx_ = shdr.get_sh_link(); 418 419 // Versions of the GNU binutils between 2.12 and 2.18 did 420 // not handle objects with more than SHN_LORESERVE sections 421 // correctly. All large section indexes were offset by 422 // 0x100. Some information can be found here: 423 // http://sourceware.org/bugzilla/show_bug.cgi?id=5900 . 424 // Fortunately these object files are easy to detect, as the 425 // GNU binutils always put the section header string table 426 // near the end of the list of sections. Thus if the 427 // section header string table index is larger than the 428 // number of sections, then we know we have to subtract 429 // 0x100 to get the real section index. 430 if (this->shstrndx_ >= this->shnum_) 431 { 432 if (this->shstrndx_ >= elfcpp::SHN_LORESERVE + 0x100) 433 { 434 this->large_shndx_offset_ = - 0x100; 435 this->shstrndx_ -= 0x100; 436 } 437 if (this->shstrndx_ >= this->shnum_) 438 this->file_->error(_("bad shstrndx: %u >= %u"), 439 this->shstrndx_, this->shnum_); 440 } 441 } 442 } 443} 444 445// Find section with sh_type equal to TYPE and return its index. 446// Returns SHN_UNDEF if not found. 447 448template<int size, bool big_endian, typename File> 449unsigned int 450Elf_file<size, big_endian, File>::find_section_by_type(unsigned int type) 451{ 452 unsigned int shnum = this->shnum(); 453 typename File::View v(this->file_->view(this->shoff_, 454 This::shdr_size * shnum)); 455 for (unsigned int i = 0; i < shnum; i++) 456 { 457 Ef_shdr shdr(v.data() + This::shdr_size * i); 458 if (shdr.get_sh_type() == type) 459 return i; 460 } 461 return SHN_UNDEF; 462} 463 464// Return the file offset of the section header of section SHNDX. 465 466template<int size, bool big_endian, typename File> 467off_t 468Elf_file<size, big_endian, File>::section_header_offset(unsigned int shndx) 469{ 470 if (shndx >= this->shnum()) 471 this->file_->error(_("section_header_offset: bad shndx %u >= %u"), 472 shndx, this->shnum()); 473 return this->shoff_ + This::shdr_size * shndx; 474} 475 476// Return the name of section SHNDX. 477 478template<int size, bool big_endian, typename File> 479std::string 480Elf_file<size, big_endian, File>::section_name(unsigned int shndx) 481{ 482 File* const file = this->file_; 483 484 // Get the section name offset. 485 unsigned int sh_name; 486 { 487 typename File::View v(file->view(this->section_header_offset(shndx), 488 This::shdr_size)); 489 Ef_shdr shdr(v.data()); 490 sh_name = shdr.get_sh_name(); 491 } 492 493 // Get the file offset for the section name string table data. 494 off_t shstr_off; 495 typename Elf_types<size>::Elf_WXword shstr_size; 496 { 497 const unsigned int shstrndx = this->shstrndx_; 498 typename File::View v(file->view(this->section_header_offset(shstrndx), 499 This::shdr_size)); 500 Ef_shdr shstr_shdr(v.data()); 501 shstr_off = shstr_shdr.get_sh_offset(); 502 shstr_size = shstr_shdr.get_sh_size(); 503 } 504 505 if (sh_name >= shstr_size) 506 file->error(_("bad section name offset for section %u: %u"), 507 shndx, sh_name); 508 509 typename File::View v(file->view(shstr_off, shstr_size)); 510 511 const unsigned char* datau = v.data(); 512 const char* data = reinterpret_cast<const char*>(datau); 513 const void* p = ::memchr(data + sh_name, '\0', shstr_size - sh_name); 514 if (p == NULL) 515 file->error(_("missing null terminator for name of section %u"), 516 shndx); 517 518 size_t len = static_cast<const char*>(p) - (data + sh_name); 519 520 return std::string(data + sh_name, len); 521} 522 523// Return the contents of section SHNDX. 524 525template<int size, bool big_endian, typename File> 526typename File::Location 527Elf_file<size, big_endian, File>::section_contents(unsigned int shndx) 528{ 529 File* const file = this->file_; 530 531 if (shndx >= this->shnum()) 532 file->error(_("section_contents: bad shndx %u >= %u"), 533 shndx, this->shnum()); 534 535 typename File::View v(file->view(this->section_header_offset(shndx), 536 This::shdr_size)); 537 Ef_shdr shdr(v.data()); 538 return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size()); 539} 540 541// Get the size of section SHNDX. 542 543template<int size, bool big_endian, typename File> 544typename Elf_types<size>::Elf_WXword 545Elf_file<size, big_endian, File>::section_size(unsigned int shndx) 546{ 547 File* const file = this->file_; 548 549 if (shndx >= this->shnum()) 550 file->error(_("section_size: bad shndx %u >= %u"), 551 shndx, this->shnum()); 552 553 typename File::View v(file->view(this->section_header_offset(shndx), 554 This::shdr_size)); 555 556 Ef_shdr shdr(v.data()); 557 return shdr.get_sh_size(); 558} 559 560// Return the section flags of section SHNDX. 561 562template<int size, bool big_endian, typename File> 563typename Elf_types<size>::Elf_WXword 564Elf_file<size, big_endian, File>::section_flags(unsigned int shndx) 565{ 566 File* const file = this->file_; 567 568 if (shndx >= this->shnum()) 569 file->error(_("section_flags: bad shndx %u >= %u"), 570 shndx, this->shnum()); 571 572 typename File::View v(file->view(this->section_header_offset(shndx), 573 This::shdr_size)); 574 575 Ef_shdr shdr(v.data()); 576 return shdr.get_sh_flags(); 577} 578 579// Return the address of section SHNDX. 580 581template<int size, bool big_endian, typename File> 582typename Elf_types<size>::Elf_Addr 583Elf_file<size, big_endian, File>::section_addr(unsigned int shndx) 584{ 585 File* const file = this->file_; 586 587 if (shndx >= this->shnum()) 588 file->error(_("section_flags: bad shndx %u >= %u"), 589 shndx, this->shnum()); 590 591 typename File::View v(file->view(this->section_header_offset(shndx), 592 This::shdr_size)); 593 594 Ef_shdr shdr(v.data()); 595 return shdr.get_sh_addr(); 596} 597 598// Return the type of section SHNDX. 599 600template<int size, bool big_endian, typename File> 601Elf_Word 602Elf_file<size, big_endian, File>::section_type(unsigned int shndx) 603{ 604 File* const file = this->file_; 605 606 if (shndx >= this->shnum()) 607 file->error(_("section_type: bad shndx %u >= %u"), 608 shndx, this->shnum()); 609 610 typename File::View v(file->view(this->section_header_offset(shndx), 611 This::shdr_size)); 612 613 Ef_shdr shdr(v.data()); 614 return shdr.get_sh_type(); 615} 616 617// Return the sh_link field of section SHNDX. 618 619template<int size, bool big_endian, typename File> 620Elf_Word 621Elf_file<size, big_endian, File>::section_link(unsigned int shndx) 622{ 623 File* const file = this->file_; 624 625 if (shndx >= this->shnum()) 626 file->error(_("section_link: bad shndx %u >= %u"), 627 shndx, this->shnum()); 628 629 typename File::View v(file->view(this->section_header_offset(shndx), 630 This::shdr_size)); 631 632 Ef_shdr shdr(v.data()); 633 return shdr.get_sh_link(); 634} 635 636// Return the sh_info field of section SHNDX. 637 638template<int size, bool big_endian, typename File> 639Elf_Word 640Elf_file<size, big_endian, File>::section_info(unsigned int shndx) 641{ 642 File* const file = this->file_; 643 644 if (shndx >= this->shnum()) 645 file->error(_("section_info: bad shndx %u >= %u"), 646 shndx, this->shnum()); 647 648 typename File::View v(file->view(this->section_header_offset(shndx), 649 This::shdr_size)); 650 651 Ef_shdr shdr(v.data()); 652 return shdr.get_sh_info(); 653} 654 655// Return the sh_addralign field of section SHNDX. 656 657template<int size, bool big_endian, typename File> 658typename Elf_types<size>::Elf_WXword 659Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx) 660{ 661 File* const file = this->file_; 662 663 if (shndx >= this->shnum()) 664 file->error(_("section_addralign: bad shndx %u >= %u"), 665 shndx, this->shnum()); 666 667 typename File::View v(file->view(this->section_header_offset(shndx), 668 This::shdr_size)); 669 670 Ef_shdr shdr(v.data()); 671 return shdr.get_sh_addralign(); 672} 673 674inline 675Elf_strtab::Elf_strtab(const unsigned char* p, size_t size) 676{ 677 // Check if the section is NUL-terminated. If it isn't, we ignore 678 // the last part to make sure we don't return non-NUL-terminated 679 // strings. 680 while (size > 0 && p[size - 1] != 0) 681 size--; 682 this->base_ = reinterpret_cast<const char*>(p); 683 this->usable_size_ = size; 684} 685 686} // End namespace elfcpp. 687 688#endif // !defined(ELFCPP_FILE_H) 689