15389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Copyright (C) 2007-2010 The Android Open Source Project 25389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** 35389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** This software is licensed under the terms of the GNU General Public 45389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and 55389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** may be copied, distributed, and modified under those terms. 65389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** 75389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** This program is distributed in the hope that it will be useful, 85389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of 95389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** GNU General Public License for more details. 115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine*/ 125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* 145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Contains implementation of ElfFile classes that encapsulate an ELF file. 155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "string.h" 185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "elf_file.h" 195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "elf_alloc.h" 205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "dwarf_cu.h" 215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "dwarf_utils.h" 225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 23c6375cb970388a3d4f691350fecdfd528eb334dfDavid 'Digit' Turner#include <fcntl.h> 24c6375cb970388a3d4f691350fecdfd528eb334dfDavid 'Digit' Turner#ifndef O_BINARY 25c6375cb970388a3d4f691350fecdfd528eb334dfDavid 'Digit' Turner#define O_BINARY 0 26c6375cb970388a3d4f691350fecdfd528eb334dfDavid 'Digit' Turner#endif 27c6375cb970388a3d4f691350fecdfd528eb334dfDavid 'Digit' Turner 285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Tags to parse when collecting info about routines. */ 295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic const Dwarf_Tag parse_rt_tags[] = { 305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DW_TAG_compile_unit, 315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DW_TAG_partial_unit, 325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DW_TAG_inlined_subroutine, 335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DW_TAG_subprogram, 345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 0 355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine}; 365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic const DwarfParseContext parse_rt_context = { parse_rt_tags }; 375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine//============================================================================= 395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// Base ElfFile implementation 405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine//============================================================================= 415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir ChtchetkineElfFile::ElfFile() 434e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner : fixed_base_address_(0), 444e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner elf_handle_((MapFile*)-1), 455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elf_file_path_(NULL), 464e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner allocator_(NULL), 474e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner sec_table_(NULL), 485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine sec_count_(0), 494e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner sec_entry_size_(0), 505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine last_cu_(NULL), 514e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner cu_count_(0), 524e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner is_exec_(0) { 535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir ChtchetkineElfFile::~ElfFile() { 565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DwarfCU* cu_to_del = last_cu_; 575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (cu_to_del != NULL) { 585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DwarfCU* next_cu_to_del = cu_to_del->prev_cu_; 595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete cu_to_del; 605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu_to_del = next_cu_to_del; 615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 638339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine if (mapfile_is_valid(elf_handle_)) { 648339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine mapfile_close(elf_handle_); 655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elf_file_path_ != NULL) { 685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete[] elf_file_path_; 695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (sec_table_ != NULL) { 725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete[] reinterpret_cast<Elf_Byte*>(sec_table_); 735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Must be deleted last! */ 765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (allocator_ != NULL) { 775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete allocator_; 785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir ChtchetkineElfFile* ElfFile::Create(const char* path) { 825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ElfFile* ret = NULL; 835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Allocate enough space on the stack to fit the largest ELF file header. */ 845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf64_FHdr header; 855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_CommonHdr* elf_hdr = &header.common; 865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(path != NULL && *path != '\0'); 885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (path == NULL || *path == '\0') { 895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EINVAL); 905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return NULL; 915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* 945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Open ELF file, and read its header (the largest one possible). 955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 968339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine MapFile* file_handle = mapfile_open(path, O_RDONLY | O_BINARY, 0); 978339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine if (!mapfile_is_valid(file_handle)) { 985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return NULL; 995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1008339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine const ssize_t read_bytes = mapfile_read(file_handle, &header, sizeof(header)); 1018339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine mapfile_close(file_handle); 1025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(read_bytes != -1 && read_bytes == sizeof(header)); 1035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (read_bytes == -1 || read_bytes != sizeof(header)) { 1045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (read_bytes != -1) { 1055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EINVAL); 1065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return NULL; 1085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if this is an ELF file at all. */ 1115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) { 1125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* File is not an ELF file. */ 1135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOEXEC); 1145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return NULL; 1155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets check ELF's "bitness". */ 1185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(elf_hdr->ei_info.ei_class == ELFCLASS32 || 1195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elf_hdr->ei_info.ei_class == ELFCLASS64); 1205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elf_hdr->ei_info.ei_class != ELFCLASS32 && 1215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elf_hdr->ei_info.ei_class != ELFCLASS64) { 1225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Neither 32, or 64-bit ELF file. Something wrong here. */ 1235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 1245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return NULL; 1255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets instantiate appropriate ElfFileImpl object for this ELF. */ 1285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elf_hdr->ei_info.ei_class == ELFCLASS32) { 1295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ret = new ElfFileImpl<Elf32_Addr, Elf32_Off>; 1305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 1315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ret = new ElfFileImpl<Elf64_Addr, Elf64_Off>; 1325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(ret != NULL); 1345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (ret != NULL) { 1355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!ret->initialize(elf_hdr, path)) { 1365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete ret; 1375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ret = NULL; 1385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 1405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 1415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return ret; 1445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 1455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinebool ElfFile::initialize(const Elf_CommonHdr* elf_hdr, const char* path) { 1475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Must be created first! */ 1485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine allocator_ = new ElfAllocator(); 1495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(allocator_ != NULL); 1505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (allocator_ == NULL) { 1515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 1525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 1535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Copy file path. */ 1565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine size_t path_len = strlen(path) + 1; 1575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elf_file_path_ = new char[path_len]; 1585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(elf_file_path_ != NULL); 1595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elf_file_path_ == NULL) { 1605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 1615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 1625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcpy(elf_file_path_, path, path_len); 1645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Cache some basic ELF properties. */ 1665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_ELF_64_ = elf_hdr->ei_info.ei_class == ELFCLASS64; 1675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_elf_big_endian_ = elf_hdr->ei_info.ei_data == ELFDATA2MSB; 1685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine same_endianness_ = is_elf_little_endian() == is_little_endian_cpu(); 1695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_exec_ = elf_hdr->e_type == 2; 1705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Reopen file for further reads and mappings. */ 1728339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine elf_handle_ = mapfile_open(elf_file_path_, O_RDONLY | O_BINARY, 0); 1738339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine return mapfile_is_valid(elf_handle_); 1745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 1755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinebool ElfFile::get_pc_address_info(Elf_Xword address, 1775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_AddressInfo* address_info) { 1785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(address_info != NULL); 1795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info == NULL) { 1805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EINVAL); 1815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 1825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Collect routine information for all CUs in this file. */ 1855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (parse_compilation_units(&parse_rt_context) == -1) { 1865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 1875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Iterate through the collected CUs looking for the one that 1905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * contains the given address. */ 1915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack = NULL; 1925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DwarfCU* cu = last_cu(); 1935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (cu != NULL) { 1945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Find a leaf DIE object in the current CU that contains the address. */ 1955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Dwarf_AddressInfo info; 1965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine info.die_obj = cu->get_leaf_die_for_address(address); 1975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj != NULL) { 1985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Convert the address to a location inside source file. */ 1995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (cu->get_pc_address_file_info(address, &info)) { 2005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Copy location information to the returning structure. */ 2015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->file_name = info.file_name; 2025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->dir_name = info.dir_name; 2035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->line_number = info.line_number; 2045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 2055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->file_name = NULL; 2065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->dir_name = NULL; 2075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->line_number = 0; 2085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if the DIE represents a routine (rather than 2115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * a lexical block, for instance). */ 2125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Dwarf_Tag tag = info.die_obj->get_tag(); 2135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (!dwarf_tag_is_routine(tag)) { 2145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* This is not a routine DIE. Lets loop trhough the parents of that 2155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * DIE looking for the first routine DIE. */ 2165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine info.die_obj = info.die_obj->parent_die(); 2175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj == NULL) { 2185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Reached compilation unit DIE. Can't go any further. */ 2195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->routine_name = "<unknown>"; 2205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 2215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine tag = info.die_obj->get_tag(); 2235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Save name of the routine that contains the address. */ 2265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->routine_name = info.die_obj->get_name(); 2275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info->routine_name == NULL) { 2285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* In some cases (minimum debugging info in the file) routine 2295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * name may be not avaible. We, however, are obliged by API 2305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * considerations to return something in this field. */ 2315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->routine_name = "<unknown>"; 2325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if address belongs to an inlined routine. */ 2355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (tag != DW_TAG_inlined_subroutine) { 2365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack = NULL; 2375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 2385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* 2415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Address belongs to an inlined routine. Create inline stack. 2425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 2435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Allocate inline stack array big enough to fit all parent entries. */ 2455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack = 2465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine new Elf_InlineInfo[info.die_obj->get_level() + 1]; 2475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(address_info->inline_stack != NULL); 2485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info->inline_stack == NULL) { 2495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 2505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 2515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memset(address_info->inline_stack, 0, 2535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine sizeof(Elf_InlineInfo) * (info.die_obj->get_level() + 1)); 2545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Reverse DIEs filling in inline stack entries for inline 2565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * routine tags. */ 2575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int inl_index = 0; 2585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine do { 2595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Save source file information. */ 2605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DIEAttrib file_desc; 2615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj->get_attrib(DW_AT_call_file, &file_desc)) { 2625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Dwarf_STMTL_FileDesc* desc = 2635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu->get_stmt_file_info(file_desc.value()->u32); 2645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (desc != NULL) { 2655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].inlined_in_file = 2665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc->file_name; 2675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].inlined_in_file_dir = 2685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu->get_stmt_dir_name(desc->get_dir_index()); 2695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info->inline_stack[inl_index].inlined_in_file == NULL) { 2725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].inlined_in_file = "<unknown>"; 2735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].inlined_in_file_dir = NULL; 2745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Save source line information. */ 2775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj->get_attrib(DW_AT_call_line, &file_desc)) { 2785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].inlined_at_line = file_desc.value()->u32; 2795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Advance DIE to the parent routine, and save its name. */ 2825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine info.die_obj = info.die_obj->parent_die(); 2835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(info.die_obj != NULL); 2845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj != NULL) { 2855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine tag = info.die_obj->get_tag(); 2865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (!dwarf_tag_is_routine(tag)) { 2875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine info.die_obj = info.die_obj->parent_die(); 2885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj == NULL) { 2895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 2905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine tag = info.die_obj->get_tag(); 2925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (info.die_obj != NULL) { 2945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].routine_name = 2955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine info.die_obj->get_name(); 2965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info->inline_stack[inl_index].routine_name == NULL) { 2995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack[inl_index].routine_name = "<unknown>"; 3005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Continue with the parent DIE. */ 3035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl_index++; 3045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } while (info.die_obj != NULL && tag == DW_TAG_inlined_subroutine); 3055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 3075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu = cu->prev_cu(); 3095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 3135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid ElfFile::free_pc_address_info(Elf_AddressInfo* address_info) const { 3155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(address_info != NULL); 3165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (address_info != NULL && address_info->inline_stack != NULL) { 3175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete address_info->inline_stack; 3185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine address_info->inline_stack = NULL; 3195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 3215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine//============================================================================= 3235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ElfFileImpl 3245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine//============================================================================= 3255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinetemplate <typename Elf_Addr, typename Elf_Off> 3275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinebool ElfFileImpl<Elf_Addr, Elf_Off>::initialize(const Elf_CommonHdr* elf_hdr, 3285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const char* path) { 3295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Must be called first! */ 3305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!ElfFile::initialize(elf_hdr, path)) { 3315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Cache some header data, so later we can discard the header. */ 3355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_FHdr<Elf_Addr, Elf_Off>* header = 3365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine reinterpret_cast<const Elf_FHdr<Elf_Addr, Elf_Off>*>(elf_hdr); 3375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine sec_count_ = pull_val(header->e_shnum); 3385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine sec_entry_size_ = pull_val(header->e_shentsize); 3395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine fixed_base_address_ = pull_val(header->e_entry) & ~0xFFF; 3405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Cache section table (must have one!) */ 3425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_Off sec_table_off = pull_val(header->e_shoff); 3435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(sec_table_off != 0 && sec_count_ != 0); 3445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (sec_table_off == 0 || sec_count_ == 0) { 3455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 3465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const size_t sec_table_size = sec_count_ * sec_entry_size_; 3495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine sec_table_ = new Elf_Byte[sec_table_size]; 3505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(sec_table_ != NULL); 3515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (sec_table_ == NULL) { 3525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 3535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3558339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine if (mapfile_read_at(elf_handle_, sec_table_off, sec_table_, 3568339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine sec_table_size) < 0) { 3578339d18223eed408bfefcd00f649a2b13ccac52cVladimir Chtchetkine return false; 3585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Map ELF's string section (must have one!). */ 3615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_Half str_sec_index = pull_val(header->e_shstrndx); 3625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(str_sec_index != SHN_UNDEF); 3635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (str_sec_index == SHN_UNDEF) { 3645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 3655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_SHdr<Elf_Addr, Elf_Off>* str_sec = 3685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*> 3695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine (get_section_by_index(str_sec_index)); 3705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine assert(str_sec != NULL); 3715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (str_sec == NULL) { 3725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 3735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!string_section_.map(elf_handle_, pull_val(str_sec->sh_offset), 3765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine pull_val(str_sec->sh_size))) { 3775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets determine DWARF format. According to the docs, DWARF is 64 bit, if 3815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * first 4 bytes in the compilation unit header are set to 0xFFFFFFFF. 3825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * .debug_info section of the ELF file begins with the first CU header. */ 3835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!map_section_by_name(".debug_info", &debug_info_)) { 3845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 3855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 3865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Note that we don't care about endianness here, since 0xFFFFFFFF is an 3895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * endianness-independent value, so we don't have to pull_val here. */ 3905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_DWARF_64_ = 3915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *reinterpret_cast<const Elf_Word*>(debug_info_.data()) == 0xFFFFFFFF; 3925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 3945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 3955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinetemplate <typename Elf_Addr, typename Elf_Off> 3975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint ElfFileImpl<Elf_Addr, Elf_Off>::parse_compilation_units( 3985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const DwarfParseContext* parse_context) { 3995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if we already parsed the file. */ 4005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (last_cu() != NULL) { 4015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return cu_count_; 4025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Cache sections required for this parsing. */ 4055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!map_section_by_name(".debug_abbrev", &debug_abbrev_) || 4065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine !map_section_by_name(".debug_ranges", &debug_ranges_) || 4075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine !map_section_by_name(".debug_line", &debug_line_) || 4085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine !map_section_by_name(".debug_str", &debug_str_)) { 4095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EBADF); 4105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 4115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* .debug_info section opens with the first CU header. */ 4145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const void* next_cu = debug_info_.data(); 4155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Iterate through CUs until we reached the end of .debug_info section, or 4175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * advanced to a CU with zero size, indicating the end of CU list for this 4185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * file. */ 4195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (is_valid_cu(next_cu)) { 4205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Instatiate CU, depending on DWARF "bitness". */ 4215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine DwarfCU* cu = DwarfCU::create_instance(this, next_cu); 4225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (cu == NULL) { 4235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(ENOMEM); 4245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return -1; 4255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (cu->parse(parse_context, &next_cu)) { 4285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu->set_prev_cu(last_cu_); 4295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine last_cu_ = cu; 4305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cu_count_++; 4315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 4325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine delete cu; 4335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return -1; 4345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine }; 4365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return cu_count_; 4385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 4395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinetemplate <typename Elf_Addr, typename Elf_Off> 4415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinebool ElfFileImpl<Elf_Addr, Elf_Off>::get_section_info_by_name(const char* name, 4425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_Off* offset, 4435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_Word* size) { 4445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_SHdr<Elf_Addr, Elf_Off>* cur_section = 4455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>(sec_table_); 4465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine for (Elf_Half sec = 0; sec < sec_count_; sec++) { 4485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const char* sec_name = get_str_sec_str(pull_val(cur_section->sh_name)); 4495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (sec_name != NULL && strcmp(name, sec_name) == 0) { 4505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *offset = pull_val(cur_section->sh_offset); 4515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *size = pull_val(cur_section->sh_size); 4525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 4535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine cur_section = reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*> 4555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine (INC_CPTR(cur_section, sec_entry_size_)); 4565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine _set_errno(EINVAL); 4585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 4595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 4605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinetemplate <typename Elf_Addr, typename Elf_Off> 4625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinebool ElfFileImpl<Elf_Addr, Elf_Off>::map_section_by_name( 4635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const char* name, 4645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ElfMappedSection* section) { 4655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (section->is_mapped()) { 4665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return true; 4675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_Off offset; 4705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_Word size; 4715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!get_section_info_by_name(name, &offset, &size)) { 4725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return false; 4735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return section->map(elf_handle_, offset, size); 4765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 477