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