1 /* Copyright (C) 2007-2010 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 /* 14 * Contains declaration of ElfFile classes that encapsulate an ELF file. 15 */ 16 17 #ifndef ELFF_ELF_FILE_H_ 18 #define ELFF_ELF_FILE_H_ 19 20 #include "dwarf_die.h" 21 #include "elf_mapped_section.h" 22 #include "elff_api.h" 23 #include "android/utils/mapfile.h" 24 25 /* Encapsulates architecture-independent functionality of an ELF file. 26 * 27 * This class is a base class for templated ElfFileImpl. This class implements 28 * functionality around an ELF file that is independent from particulars of the 29 * ELF's CPU architectire, while ElfFileImpl handles all particulars of CPU 30 * architecture (namely, 32 or 64-bit), for which ELF file has been built. 31 * 32 * NOTE: This class operates on ELF sections that have been mapped to memory. 33 * 34 */ 35 class ElfFile { 36 public: 37 /* Constructs ElfFile instance. */ 38 ElfFile(); 39 40 /* Destructs ElfFile instance. */ 41 virtual ~ElfFile(); 42 43 /* Creates ElfFileImpl instance, depending on ELF file CPU architecture. 44 * This method will collect initial information about requested ELF file, 45 * and will instantiate appropriate ElfFileImpl class object for it. 46 * Param: 47 * path - Full path to the ELF file. 48 * Return: 49 * Initialized ElfFileImpl instance, typecasted back to ElfFile object on 50 * success, or NULL on failure, with errno providing extended error 51 * information. 52 */ 53 static ElfFile* Create(const char* path); 54 55 /* Checks if ELF file is a 64, or 32-bit ELF file. */ 56 bool is_ELF_64() const { 57 return is_ELF_64_; 58 } 59 bool is_ELF_32() const { 60 return !is_ELF_64_; 61 } 62 63 /* Checks if ELF file data format is big, or little-endian. */ 64 bool is_elf_big_endian() const { 65 return is_elf_big_endian_; 66 } 67 bool is_elf_little_endian() const { 68 return !is_elf_big_endian_; 69 } 70 71 /* Checks whether or not endianness of CPU this library is built for matches 72 * endianness of the ELF file that is represented with this instance. */ 73 bool same_endianness() const { 74 return same_endianness_; 75 } 76 77 /* Checks if format of DWARF data in this file is 64, or 32-bit. */ 78 bool is_DWARF_64() const { 79 return is_DWARF_64_; 80 } 81 bool is_DWARF_32() const { 82 return !is_DWARF_64_; 83 } 84 85 /* Gets DWARF objects allocator for this instance. */ 86 class ElfAllocator* allocator() const { 87 return allocator_; 88 } 89 90 /* Gets head of compilation unit list, collected during parsing of this file. 91 * NOTE: list of collected compilation units returned from this method is 92 * in reverse order relatively to the order CUs have been added to the list 93 * during ELF file parsing. 94 */ 95 class DwarfCU* last_cu() const { 96 return last_cu_; 97 } 98 99 /* Gets number of compilation units, collected during parsing of 100 * this ELF file with parse_compilation_units() method. 101 */ 102 int cu_count() const { 103 return cu_count_; 104 } 105 106 /* Gets executable file flag */ 107 bool is_exec() const { 108 return is_exec_; 109 } 110 111 protected: 112 /* Initializes ElfFile instance. This method is called from Create method of 113 * this class after appropriate ElfFileImpl instance has been created. Note, 114 * that Create() method will validate that requested file is an ELF file, 115 * prior to instantiating of an ElfFileImpl object, and calling this method. 116 * Param: 117 * elf_hdr - Address of the common ELF file header. 118 * path - See Create(). 119 * Return: 120 * true on success, or false on failure, with errno containing extended 121 * error information. 122 */ 123 virtual bool initialize(const Elf_CommonHdr* elf_hdr, const char* path); 124 125 /*============================================================================= 126 * Endianness helper methods. 127 * Since endianness of ELF file may differ from the endianness of the CPU this 128 * library runs on, every time a value is required from a section of the ELF 129 * file, it must be first pulled out of that section to a local variable, and 130 * then used from that local variable. While value is pulled from ELF file 131 * section, it must be converted accordingly to the endianness of the CPU and 132 * ELF file. Routines bellow provide such functionality. 133 =============================================================================*/ 134 135 public: 136 /* Pulls one byte value from ELF file. Note that for one byte we don't need 137 * to do any endianness conversion, and these two methods are provided purely 138 * for completness of the API. 139 * Param: 140 * val - References value inside ELF file buffer to pull data from. 141 * Return 142 * Pulled value with endianness appropriate for the CPU this library is 143 * running on. 144 */ 145 uint8_t pull_val(const uint8_t* val) const { 146 return *val; 147 } 148 uint8_t pull_val(const uint8_t& val) const { 149 return val; 150 } 151 int8_t pull_val(const int8_t* val) const { 152 return *val; 153 } 154 int8_t pull_val(const int8_t& val) const { 155 return val; 156 } 157 158 /* Pulls two byte value from ELF file. 159 * Param: 160 * val - References value inside ELF file buffer to pull data from. 161 * Return 162 * Pulled value with endianness appropriate for the CPU this library is 163 * running on. 164 */ 165 uint16_t pull_val(const uint16_t* val) const { 166 if (same_endianness()) { 167 return *val; 168 } 169 if (is_elf_big_endian()) { 170 return (uint16_t)get_byte(val, 0) << 8 | get_byte(val, 1); 171 } else { 172 return (uint16_t)get_byte(val, 1) << 8 | get_byte(val, 0); 173 } 174 } 175 uint16_t pull_val(const uint16_t& val) const { 176 return same_endianness() ? val : pull_val(&val); 177 } 178 int16_t pull_val(const int16_t* val) const { 179 return static_cast<int16_t> 180 (pull_val(reinterpret_cast<const uint16_t*>(val))); 181 } 182 int16_t pull_val(const int16_t& val) const { 183 return static_cast<int16_t> 184 (pull_val(reinterpret_cast<const uint16_t&>(val))); 185 } 186 187 /* Pulls four byte value from ELF file. 188 * Param: 189 * val - References value inside ELF file buffer to pull data from. 190 * Return 191 * Pulled value with endianness appropriate for the CPU this library is 192 * running on. 193 */ 194 uint32_t pull_val(const uint32_t* val) const { 195 if (same_endianness()) { 196 return *val; 197 } 198 if (is_elf_big_endian()) { 199 return (uint32_t)get_byte(val, 0) << 24 | 200 (uint32_t)get_byte(val, 1) << 16 | 201 (uint32_t)get_byte(val, 2) << 8 | 202 (uint32_t)get_byte(val, 3); 203 } else { 204 return (uint32_t)get_byte(val, 3) << 24 | 205 (uint32_t)get_byte(val, 2) << 16 | 206 (uint32_t)get_byte(val, 1) << 8 | 207 (uint32_t)get_byte(val, 0); 208 } 209 } 210 uint32_t pull_val(const uint32_t& val) const { 211 return same_endianness() ? val : pull_val(&val); 212 } 213 int32_t pull_val(const int32_t* val) const { 214 return static_cast<int32_t> 215 (pull_val(reinterpret_cast<const uint32_t*>(val))); 216 } 217 int32_t pull_val(const int32_t& val) const { 218 return static_cast<int32_t> 219 (pull_val(reinterpret_cast<const uint32_t&>(val))); 220 } 221 222 /* Pulls eight byte value from ELF file. 223 * Param: 224 * val - References value inside ELF file buffer to pull data from. 225 * Return 226 * Pulled value with endianness appropriate for the CPU this library is 227 * running on. 228 */ 229 uint64_t pull_val(const uint64_t* val) const { 230 if (same_endianness()) { 231 return *val; 232 } 233 if (is_elf_big_endian()) { 234 return (uint64_t)get_byte(val, 0) << 56 | 235 (uint64_t)get_byte(val, 1) << 48 | 236 (uint64_t)get_byte(val, 2) << 40 | 237 (uint64_t)get_byte(val, 3) << 32 | 238 (uint64_t)get_byte(val, 4) << 24 | 239 (uint64_t)get_byte(val, 5) << 16 | 240 (uint64_t)get_byte(val, 6) << 8 | 241 (uint64_t)get_byte(val, 7); 242 } else { 243 return (uint64_t)get_byte(val, 7) << 56 | 244 (uint64_t)get_byte(val, 6) << 48 | 245 (uint64_t)get_byte(val, 5) << 40 | 246 (uint64_t)get_byte(val, 4) << 32 | 247 (uint64_t)get_byte(val, 3) << 24 | 248 (uint64_t)get_byte(val, 2) << 16 | 249 (uint64_t)get_byte(val, 1) << 8 | 250 (uint64_t)get_byte(val, 0); 251 } 252 } 253 uint64_t pull_val(const uint64_t& val) const { 254 return same_endianness() ? val : pull_val(&val); 255 } 256 int64_t pull_val(const int64_t* val) const { 257 return static_cast<int64_t> 258 (pull_val(reinterpret_cast<const uint64_t*>(val))); 259 } 260 int64_t pull_val(const int64_t& val) const { 261 return static_cast<int64_t> 262 (pull_val(reinterpret_cast<const uint64_t&>(val))); 263 } 264 265 //============================================================================= 266 // ELF file section management. 267 //============================================================================= 268 269 public: 270 /* Gets a string contained in ELF's string section by index. 271 * Param: 272 * index - String index (byte offset) in the ELF's string section. 273 * Return: 274 * Pointer to the requested string, or NULL if string index exceeds ELF's 275 * string section size. 276 * NOTE: pointer returned from this method points to a mapped section of 277 * ELF file. 278 */ 279 const char* get_str_sec_str(Elf_Xword index) const { 280 assert(string_section_.is_mapped() && index < string_section_.size()); 281 if (string_section_.is_mapped() && index < string_section_.size()) { 282 return INC_CPTR_T(char, string_section_.data(), index); 283 } else { 284 _set_errno(EINVAL); 285 return NULL; 286 } 287 } 288 289 /* Gets a string contained in ELF's debug string section (.debug_str) 290 * by index. 291 * Param: 292 * index - String index (byte offset) in the ELF's debug string section. 293 * Return: 294 * Pointer to the requested string, or NULL if string index exceeds ELF's 295 * debug string section size. 296 * NOTE: pointer returned from this method points to a mapped section of 297 * ELF file. 298 */ 299 const char* get_debug_str(Elf_Xword index) const { 300 assert(debug_str_.is_mapped() && index < debug_str_.size()); 301 if (debug_str_.is_mapped() && index < debug_str_.size()) { 302 return INC_CPTR_T(char, debug_str_.data(), index); 303 } else { 304 _set_errno(EINVAL); 305 return NULL; 306 } 307 } 308 309 protected: 310 /* Gets pointer to a section header, given section index within ELF's 311 * section table. 312 * Param: 313 * index - Section index within ELF's section table. 314 * Return: 315 * Pointer to a section header (ElfXX_SHdr flavor, depending on ELF's CPU 316 * architecture) on success, or NULL if section index exceeds number of 317 * sections for this ELF file. 318 */ 319 const void* get_section_by_index(Elf_Half index) const { 320 assert(index < sec_count_); 321 if (index < sec_count_) { 322 return INC_CPTR(sec_table_, static_cast<size_t>(index) * sec_entry_size_); 323 } else { 324 _set_errno(EINVAL); 325 return NULL; 326 } 327 } 328 329 //============================================================================= 330 // DWARF management. 331 //============================================================================= 332 333 protected: 334 /* Parses DWARF, and buids a list of compilation units for this ELF file. 335 * Compilation unit, collected with this methods are linked together in a 336 * list, head of which is available via last_cu() method of this class. 337 * NOTE: CUs in the list returned via last_cu() method are in reverse order 338 * relatively to the order in which CUs are stored in .debug_info section. 339 * This is ELF and DWARF data format - dependent method. 340 * Param: 341 * parse_context - Parsing context that defines which tags, and which 342 * properties for which tag should be collected during parsing. NULL 343 * passed in this parameter indicates that all properties for all tags 344 * should be collected. 345 * Return: 346 * Number of compilation units, collected in this method on success, 347 * or -1 on failure. 348 */ 349 virtual int parse_compilation_units(const DwarfParseContext* parse_context) = 0; 350 351 public: 352 /* Gets PC address information. 353 * Param: 354 * address - PC address to get information for. The address must be relative 355 * to the beginning of ELF file represented by this class. 356 * address_info - Upon success contains information about routine(s) that 357 * contain the given address. 358 * Return: 359 * true if routine(s) containing has been found and its information has been 360 * saved into address_info, or false if no appropriate routine for that 361 * address has been found, or there was a memory error when collecting 362 * routine(s) information. In case of failure, errno contains extended error 363 * information. 364 */ 365 bool get_pc_address_info(Elf_Xword address, Elf_AddressInfo* address_info); 366 367 /* Frees resources aqcuired for address information in successful call to 368 * get_pc_address_info(). 369 * Param: 370 * address_info - Address information structure, initialized in successful 371 * call to get_pc_address_info() routine. 372 */ 373 void free_pc_address_info(Elf_AddressInfo* address_info) const; 374 375 /* Gets beginning of the .debug_info section data. 376 * Return: 377 * Beginning of the .debug_info section data. 378 * NOTE: pointer returned from this method points to a mapped section of 379 * ELF file. 380 */ 381 const void* get_debug_info_data() const { 382 return debug_info_.data(); 383 } 384 385 /* Gets beginning of the .debug_abbrev section data. 386 * Return: 387 * Beginning of the .debug_abbrev section data. 388 * NOTE: pointer returned from this method points to a mapped section of 389 * ELF file. 390 */ 391 const void* get_debug_abbrev_data() const { 392 return debug_abbrev_.data(); 393 } 394 395 /* Gets beginning of the .debug_ranges section data. 396 * Return: 397 * Beginning of the .debug_ranges section data. 398 * NOTE: pointer returned from this method points to a mapped section of 399 * ELF file. 400 */ 401 const void* get_debug_ranges_data() const { 402 return debug_ranges_.data(); 403 } 404 405 /* Gets beginning of the .debug_line section data. 406 * Return: 407 * Beginning of the .debug_line section data. 408 * NOTE: pointer returned from this method points to a mapped section of 409 * ELF file. 410 */ 411 const void* get_debug_line_data() const { 412 return debug_line_.data(); 413 } 414 415 /* Checks, if given address range is contained in the mapped .debug_info 416 * section of this file. 417 * Param: 418 * ptr - Starting address of the range. 419 * size - Range size in bytes. 420 * Return: 421 * true if given address range is contained in the mapped .debug_info 422 * section of this file, or false if any part of the range doesn't belong 423 * to that section. 424 */ 425 bool is_valid_die_ptr(const void* ptr, size_t size) const { 426 return debug_info_.is_contained(ptr, size); 427 } 428 429 /* Checks, if given address range is contained in the mapped .debug_abbrev 430 * section of this file. 431 * Param: 432 * ptr - Starting address of the range. 433 * size - Range size in bytes. 434 * Return: 435 * true if given address range is contained in the mapped .debug_abbrev 436 * section of this file, or false if any part of the range doesn't belong 437 * to that section. 438 */ 439 bool is_valid_abbr_ptr(const void* ptr, size_t size) const { 440 return debug_abbrev_.is_contained(ptr, size); 441 } 442 443 /* Checks if given pointer addresses a valid compilation unit header in the 444 * mapped .debug_info section of the ELF file. 445 * Param: 446 * cu_header - Pointer to a compilation unit header to check. 447 * Return 448 * true, if given pointer addresses a valid compilation unit header, or 449 * false, if it's not. A valid CU header must be fully conained inside 450 * .debug_info section of the ELF file, and its size must not be zero. 451 */ 452 bool is_valid_cu(const void* cu_header) const { 453 if (is_DWARF_64()) { 454 return is_valid_die_ptr(cu_header, sizeof(Dwarf64_CUHdr)) && 455 reinterpret_cast<const Dwarf64_CUHdr*>(cu_header)->size_hdr.size != 0; 456 } else { 457 return is_valid_die_ptr(cu_header, sizeof(Dwarf32_CUHdr)) && 458 reinterpret_cast<const Dwarf32_CUHdr*>(cu_header)->size_hdr.size != 0; 459 } 460 } 461 462 /* Gets range's low and high pc for the given range reference in the mapped 463 * .debug_ranges section of an ELF file. 464 * Template param: 465 * AddrType - Defines pointer type for the CU the range belongs to. CU's 466 * pointer type can be defined independently from ELF and DWARF types, 467 * and is encoded in address_size field of the CU header in .debug_info 468 * section of ELF file. 469 * Param: 470 * offset - Byte offset within .debug_ranges section of the range record. 471 * low - Upon successful return contains value for range's low pc. 472 * high - Upon successful return contains value for range's high pc. 473 * Return: 474 * true on success, or false, if requested record is not fully contained 475 * in the .debug_ranges section. 476 */ 477 template<typename AddrType> 478 bool get_range(Elf_Word offset, AddrType* low, AddrType* high) { 479 const AddrType* ptr = INC_CPTR_T(AddrType, debug_ranges_.data(), offset); 480 assert(debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2)); 481 if (!debug_ranges_.is_contained(ptr, sizeof(AddrType) * 2)) { 482 _set_errno(EINVAL); 483 return false; 484 } 485 *low = pull_val(ptr); 486 *high = pull_val(ptr + 1); 487 return true; 488 } 489 490 protected: 491 /* Mapped ELF string section. */ 492 ElfMappedSection string_section_; 493 494 /* Mapped .debug_info section. */ 495 ElfMappedSection debug_info_; 496 497 /* Mapped .debug_abbrev section. */ 498 ElfMappedSection debug_abbrev_; 499 500 /* Mapped .debug_str section. */ 501 ElfMappedSection debug_str_; 502 503 /* Mapped .debug_line section. */ 504 ElfMappedSection debug_line_; 505 506 /* Mapped .debug_ranges section. */ 507 ElfMappedSection debug_ranges_; 508 509 /* Base address of the loaded module (if fixed), or 0 if module doesn't get 510 * loaded at fixed address. */ 511 Elf_Xword fixed_base_address_; 512 513 /* Handle to the ELF file represented with this instance. */ 514 MapFile* elf_handle_; 515 516 /* Path to the ELF file represented with this instance. */ 517 char* elf_file_path_; 518 519 /* DWARF objects allocator for this instance. */ 520 class ElfAllocator* allocator_; 521 522 /* Beginning of the cached ELF's section table. */ 523 void* sec_table_; 524 525 /* Number of sections in the ELF file wrapped by this instance. */ 526 Elf_Half sec_count_; 527 528 /* Byte size of an entry in the section table. */ 529 Elf_Half sec_entry_size_; 530 531 /* Head of compilation unit list, collected during the parsing. */ 532 class DwarfCU* last_cu_; 533 534 /* Number of compilation units in last_cu_ list. */ 535 int cu_count_; 536 537 /* Flags ELF's CPU architecture: 64 (true), or 32 bits (false). */ 538 bool is_ELF_64_; 539 540 /* Flags endianness of the processed ELF file. true indicates that ELF file 541 * data is stored in big-endian form, false indicates that ELF file data is 542 * stored in big-endian form. 543 */ 544 bool is_elf_big_endian_; 545 546 /* Flags whether or not endianness of CPU this library is built for matches 547 * endianness of the ELF file that is represented with this instance. 548 */ 549 bool same_endianness_; 550 551 /* Flags DWARF format: 64, or 32 bits. DWARF format is determined by looking 552 * at the first 4 bytes of .debug_info section (which is the beginning of the 553 * first compilation unit header). If first 4 bytes contain 0xFFFFFFFF, the 554 * DWARF is 64 bit. Otherwise, DWARF is 32 bit. */ 555 bool is_DWARF_64_; 556 557 /* Flags executable file. If this member is 1, ELF file represented with this 558 * instance is an executable. If this member is 0, file is a shared library. 559 */ 560 bool is_exec_; 561 }; 562 563 /* Encapsulates architecture-dependent functionality of an ELF file. 564 * Template param: 565 * Elf_Addr - type for an address field in ELF file. Must be: 566 * - Elf32_Addr for 32-bit CPU, or 567 * - Elf64_Addr for 64-bit CPU. 568 * Elf_Off - type for an offset field in ELF file. Must be: 569 * - Elf64_Off for 32-bit CPU, or 570 * - Elf64_Off for 64-bit CPU. 571 */ 572 template <typename Elf_Addr, typename Elf_Off> 573 class ElfFileImpl : protected ElfFile { 574 /* Instance of this class must be instantiated from 575 * ElfFile::Create() method only. */ 576 friend class ElfFile; 577 protected: 578 /* Constructs ElfFileImpl instance. */ 579 ElfFileImpl() { 580 }; 581 582 /* Destructs ElfFileImpl instance. */ 583 ~ElfFileImpl() { 584 } 585 586 protected: 587 /* Initializes instance. This is an override of the base class method. 588 * See ElfFile::initialize(). 589 */ 590 bool initialize(const Elf_CommonHdr* elf_hdr, const char* path); 591 592 /* Parses DWARF, and buids list of compilation units for this ELF file. 593 * This is an implementation of the base class' abstract method. 594 * See ElfFile::parse_compilation_units(). 595 */ 596 virtual int parse_compilation_units(const DwarfParseContext* parse_context); 597 598 /* Gets section information by section name. 599 * Param: 600 * name - Name of the section to get information for. 601 * offset - Upon success contains offset of the section data in ELF file. 602 * size - Upon success contains size of the section data in ELF file. 603 * Return: 604 * true on sucess, or false if section with such name doesn't exist in 605 * this ELF file. 606 */ 607 bool get_section_info_by_name(const char* name, 608 Elf_Off* offset, 609 Elf_Word* size); 610 611 /* Maps section by its name. 612 * Param: 613 * name - Name of the section to map. 614 * section - Upon success contains section's mapping information. 615 * Return: 616 * true on sucess, or false if section with such name doesn't exist in 617 * this ELF file, or mapping has failed. 618 */ 619 bool map_section_by_name(const char* name, ElfMappedSection* section); 620 }; 621 622 #endif // ELFF_ELF_FILE_H_ 623