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 implementation of ElfFile classes that encapsulate an ELF file.
15 */
16
17#include "string.h"
18#include "elf_file.h"
19#include "elf_alloc.h"
20#include "dwarf_cu.h"
21#include "dwarf_utils.h"
22
23/* Tags to parse when collecting info about routines. */
24static const Dwarf_Tag parse_rt_tags[] = {
25  DW_TAG_compile_unit,
26  DW_TAG_partial_unit,
27  DW_TAG_inlined_subroutine,
28  DW_TAG_subprogram,
29  0
30};
31static const DwarfParseContext parse_rt_context = { parse_rt_tags };
32
33//=============================================================================
34// Base ElfFile implementation
35//=============================================================================
36
37ElfFile::ElfFile()
38    : sec_table_(NULL),
39      elf_file_path_(NULL),
40      sec_count_(0),
41      cu_count_(0),
42      last_cu_(NULL),
43      allocator_(NULL),
44      fixed_base_address_(0),
45      is_exec_(0),
46      elf_handle_((MapFile*)-1),
47      sec_entry_size_(0) {
48}
49
50ElfFile::~ElfFile() {
51  DwarfCU* cu_to_del = last_cu_;
52  while (cu_to_del != NULL) {
53    DwarfCU* next_cu_to_del = cu_to_del->prev_cu_;
54    delete cu_to_del;
55    cu_to_del = next_cu_to_del;
56  }
57
58  if (mapfile_is_valid(elf_handle_)) {
59    mapfile_close(elf_handle_);
60  }
61
62  if (elf_file_path_ != NULL) {
63    delete[] elf_file_path_;
64  }
65
66  if (sec_table_ != NULL) {
67    delete[] reinterpret_cast<Elf_Byte*>(sec_table_);
68  }
69
70  /* Must be deleted last! */
71  if (allocator_ != NULL) {
72    delete allocator_;
73  }
74}
75
76ElfFile* ElfFile::Create(const char* path) {
77  ElfFile* ret = NULL;
78  /* Allocate enough space on the stack to fit the largest ELF file header. */
79  Elf64_FHdr header;
80  const Elf_CommonHdr* elf_hdr = &header.common;
81
82  assert(path != NULL && *path != '\0');
83  if (path == NULL || *path == '\0') {
84    _set_errno(EINVAL);
85    return NULL;
86  }
87
88  /*
89   * Open ELF file, and read its header (the largest one possible).
90   */
91  MapFile* file_handle = mapfile_open(path, O_RDONLY | O_BINARY, 0);
92  if (!mapfile_is_valid(file_handle)) {
93    return NULL;
94  }
95  const ssize_t read_bytes = mapfile_read(file_handle, &header, sizeof(header));
96  mapfile_close(file_handle);
97  assert(read_bytes != -1 && read_bytes == sizeof(header));
98  if (read_bytes == -1 || read_bytes != sizeof(header)) {
99    if (read_bytes != -1) {
100      _set_errno(EINVAL);
101    }
102    return NULL;
103  }
104
105  /* Lets see if this is an ELF file at all. */
106  if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) {
107    /* File is not an ELF file. */
108    _set_errno(ENOEXEC);
109    return NULL;
110  }
111
112  /* Lets check ELF's "bitness". */
113  assert(elf_hdr->ei_info.ei_class == ELFCLASS32 ||
114         elf_hdr->ei_info.ei_class == ELFCLASS64);
115  if (elf_hdr->ei_info.ei_class != ELFCLASS32 &&
116      elf_hdr->ei_info.ei_class != ELFCLASS64) {
117    /* Neither 32, or 64-bit ELF file. Something wrong here. */
118    _set_errno(EBADF);
119    return NULL;
120  }
121
122  /* Lets instantiate appropriate ElfFileImpl object for this ELF. */
123  if (elf_hdr->ei_info.ei_class == ELFCLASS32) {
124    ret = new ElfFileImpl<Elf32_Addr, Elf32_Off>;
125  } else {
126    ret = new ElfFileImpl<Elf64_Addr, Elf64_Off>;
127  }
128  assert(ret != NULL);
129  if (ret != NULL) {
130    if (!ret->initialize(elf_hdr, path)) {
131      delete ret;
132      ret = NULL;
133    }
134  } else {
135    _set_errno(ENOMEM);
136  }
137
138  return ret;
139}
140
141bool ElfFile::initialize(const Elf_CommonHdr* elf_hdr, const char* path) {
142  /* Must be created first! */
143  allocator_ = new ElfAllocator();
144  assert(allocator_ != NULL);
145  if (allocator_ == NULL) {
146    _set_errno(ENOMEM);
147    return false;
148  }
149
150  /* Copy file path. */
151  size_t path_len = strlen(path) + 1;
152  elf_file_path_ = new char[path_len];
153  assert(elf_file_path_ != NULL);
154  if (elf_file_path_ == NULL) {
155    _set_errno(ENOMEM);
156    return false;
157  }
158  memcpy(elf_file_path_, path, path_len);
159
160  /* Cache some basic ELF properties. */
161  is_ELF_64_ = elf_hdr->ei_info.ei_class == ELFCLASS64;
162  is_elf_big_endian_ = elf_hdr->ei_info.ei_data == ELFDATA2MSB;
163  same_endianness_ = is_elf_little_endian() == is_little_endian_cpu();
164  is_exec_ = elf_hdr->e_type == 2;
165
166  /* Reopen file for further reads and mappings. */
167  elf_handle_ = mapfile_open(elf_file_path_, O_RDONLY | O_BINARY, 0);
168  return mapfile_is_valid(elf_handle_);
169}
170
171bool ElfFile::get_pc_address_info(Elf_Xword address,
172                                  Elf_AddressInfo* address_info) {
173  assert(address_info != NULL);
174  if (address_info == NULL) {
175    _set_errno(EINVAL);
176    return false;
177  }
178
179  /* Collect routine information for all CUs in this file. */
180  if (parse_compilation_units(&parse_rt_context) == -1) {
181    return false;
182  }
183
184  /* Iterate through the collected CUs looking for the one that
185   * contains the given address. */
186  address_info->inline_stack = NULL;
187  DwarfCU* cu = last_cu();
188  while (cu != NULL) {
189    /* Find a leaf DIE object in the current CU that contains the address. */
190    Dwarf_AddressInfo info;
191    info.die_obj = cu->get_leaf_die_for_address(address);
192    if (info.die_obj != NULL) {
193      /* Convert the address to a location inside source file. */
194      if (cu->get_pc_address_file_info(address, &info)) {
195          /* Copy location information to the returning structure. */
196          address_info->file_name = info.file_name;
197          address_info->dir_name = info.dir_name;
198          address_info->line_number = info.line_number;
199      } else {
200          address_info->file_name = NULL;
201          address_info->dir_name = NULL;
202          address_info->line_number = 0;
203      }
204
205      /* Lets see if the DIE represents a routine (rather than
206       * a lexical block, for instance). */
207      Dwarf_Tag tag = info.die_obj->get_tag();
208      while (!dwarf_tag_is_routine(tag)) {
209        /* This is not a routine DIE. Lets loop trhough the parents of that
210         * DIE looking for the first routine DIE. */
211        info.die_obj = info.die_obj->parent_die();
212        if (info.die_obj == NULL) {
213          /* Reached compilation unit DIE. Can't go any further. */
214          address_info->routine_name = "<unknown>";
215          return true;
216        }
217        tag = info.die_obj->get_tag();
218      }
219
220      /* Save name of the routine that contains the address. */
221      address_info->routine_name = info.die_obj->get_name();
222      if (address_info->routine_name == NULL) {
223        /* In some cases (minimum debugging info in the file) routine
224         * name may be not avaible. We, however, are obliged by API
225         * considerations to return something in this field. */
226          address_info->routine_name = "<unknown>";
227      }
228
229      /* Lets see if address belongs to an inlined routine. */
230      if (tag != DW_TAG_inlined_subroutine) {
231        address_info->inline_stack = NULL;
232        return true;
233      }
234
235      /*
236       * Address belongs to an inlined routine. Create inline stack.
237       */
238
239      /* Allocate inline stack array big enough to fit all parent entries. */
240      address_info->inline_stack =
241        new Elf_InlineInfo[info.die_obj->get_level() + 1];
242      assert(address_info->inline_stack != NULL);
243      if (address_info->inline_stack == NULL) {
244        _set_errno(ENOMEM);
245        return false;
246      }
247      memset(address_info->inline_stack, 0,
248             sizeof(Elf_InlineInfo) * (info.die_obj->get_level() + 1));
249
250      /* Reverse DIEs filling in inline stack entries for inline
251       * routine tags. */
252      int inl_index = 0;
253      do {
254        /* Save source file information. */
255        DIEAttrib file_desc;
256        if (info.die_obj->get_attrib(DW_AT_call_file, &file_desc)) {
257          const Dwarf_STMTL_FileDesc* desc =
258              cu->get_stmt_file_info(file_desc.value()->u32);
259          if (desc != NULL) {
260            address_info->inline_stack[inl_index].inlined_in_file =
261                desc->file_name;
262            address_info->inline_stack[inl_index].inlined_in_file_dir =
263                cu->get_stmt_dir_name(desc->get_dir_index());
264          }
265        }
266        if (address_info->inline_stack[inl_index].inlined_in_file == NULL) {
267          address_info->inline_stack[inl_index].inlined_in_file = "<unknown>";
268          address_info->inline_stack[inl_index].inlined_in_file_dir = NULL;
269        }
270
271        /* Save source line information. */
272        if (info.die_obj->get_attrib(DW_AT_call_line, &file_desc)) {
273          address_info->inline_stack[inl_index].inlined_at_line = file_desc.value()->u32;
274        }
275
276        /* Advance DIE to the parent routine, and save its name. */
277        info.die_obj = info.die_obj->parent_die();
278        assert(info.die_obj != NULL);
279        if (info.die_obj != NULL) {
280          tag = info.die_obj->get_tag();
281          while (!dwarf_tag_is_routine(tag)) {
282            info.die_obj = info.die_obj->parent_die();
283            if (info.die_obj == NULL) {
284              break;
285            }
286            tag = info.die_obj->get_tag();
287          }
288          if (info.die_obj != NULL) {
289            address_info->inline_stack[inl_index].routine_name =
290                info.die_obj->get_name();
291          }
292        }
293        if (address_info->inline_stack[inl_index].routine_name == NULL) {
294          address_info->inline_stack[inl_index].routine_name = "<unknown>";
295        }
296
297        /* Continue with the parent DIE. */
298        inl_index++;
299      } while (info.die_obj != NULL && tag == DW_TAG_inlined_subroutine);
300
301      return true;
302    }
303    cu = cu->prev_cu();
304  }
305
306  return false;
307}
308
309void ElfFile::free_pc_address_info(Elf_AddressInfo* address_info) const {
310  assert(address_info != NULL);
311  if (address_info != NULL && address_info->inline_stack != NULL) {
312    delete address_info->inline_stack;
313    address_info->inline_stack = NULL;
314  }
315}
316
317//=============================================================================
318// ElfFileImpl
319//=============================================================================
320
321template <typename Elf_Addr, typename Elf_Off>
322bool ElfFileImpl<Elf_Addr, Elf_Off>::initialize(const Elf_CommonHdr* elf_hdr,
323                                                const char* path) {
324  /* Must be called first! */
325  if (!ElfFile::initialize(elf_hdr, path)) {
326    return false;
327  }
328
329  /* Cache some header data, so later we can discard the header. */
330  const Elf_FHdr<Elf_Addr, Elf_Off>* header =
331      reinterpret_cast<const Elf_FHdr<Elf_Addr, Elf_Off>*>(elf_hdr);
332  sec_count_ = pull_val(header->e_shnum);
333  sec_entry_size_ = pull_val(header->e_shentsize);
334  fixed_base_address_ = pull_val(header->e_entry) & ~0xFFF;
335
336  /* Cache section table (must have one!) */
337  const Elf_Off sec_table_off = pull_val(header->e_shoff);
338  assert(sec_table_off != 0 && sec_count_ != 0);
339  if (sec_table_off == 0 || sec_count_ == 0) {
340    _set_errno(EBADF);
341    return false;
342  }
343  const size_t sec_table_size = sec_count_ * sec_entry_size_;
344  sec_table_ = new Elf_Byte[sec_table_size];
345  assert(sec_table_ != NULL);
346  if (sec_table_ == NULL) {
347    _set_errno(ENOMEM);
348    return false;
349  }
350  if (mapfile_read_at(elf_handle_, sec_table_off, sec_table_,
351                      sec_table_size) < 0) {
352      return false;
353  }
354
355  /* Map ELF's string section (must have one!). */
356  const Elf_Half str_sec_index = pull_val(header->e_shstrndx);
357  assert(str_sec_index != SHN_UNDEF);
358  if (str_sec_index == SHN_UNDEF) {
359    _set_errno(EBADF);
360    return false;
361  }
362  const Elf_SHdr<Elf_Addr, Elf_Off>* str_sec =
363      reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
364          (get_section_by_index(str_sec_index));
365  assert(str_sec != NULL);
366  if (str_sec == NULL) {
367    _set_errno(EBADF);
368    return false;
369  }
370  if (!string_section_.map(elf_handle_, pull_val(str_sec->sh_offset),
371                           pull_val(str_sec->sh_size))) {
372    return false;
373  }
374
375  /* Lets determine DWARF format. According to the docs, DWARF is 64 bit, if
376   * first 4 bytes in the compilation unit header are set to 0xFFFFFFFF.
377   * .debug_info section of the ELF file begins with the first CU header. */
378  if (!map_section_by_name(".debug_info", &debug_info_)) {
379    _set_errno(EBADF);
380    return false;
381  }
382
383  /* Note that we don't care about endianness here, since 0xFFFFFFFF is an
384   * endianness-independent value, so we don't have to pull_val here. */
385  is_DWARF_64_ =
386    *reinterpret_cast<const Elf_Word*>(debug_info_.data()) == 0xFFFFFFFF;
387
388  return true;
389}
390
391template <typename Elf_Addr, typename Elf_Off>
392int ElfFileImpl<Elf_Addr, Elf_Off>::parse_compilation_units(
393    const DwarfParseContext* parse_context) {
394  /* Lets see if we already parsed the file. */
395  if (last_cu() != NULL) {
396    return cu_count_;
397  }
398
399  /* Cache sections required for this parsing. */
400  if (!map_section_by_name(".debug_abbrev", &debug_abbrev_) ||
401      !map_section_by_name(".debug_ranges", &debug_ranges_) ||
402      !map_section_by_name(".debug_line", &debug_line_) ||
403      !map_section_by_name(".debug_str", &debug_str_)) {
404    _set_errno(EBADF);
405    return false;
406  }
407
408  /* .debug_info section opens with the first CU header. */
409  const void* next_cu = debug_info_.data();
410
411  /* Iterate through CUs until we reached the end of .debug_info section, or
412   * advanced to a CU with zero size, indicating the end of CU list for this
413   * file. */
414  while (is_valid_cu(next_cu)) {
415    /* Instatiate CU, depending on DWARF "bitness". */
416    DwarfCU* cu = DwarfCU::create_instance(this, next_cu);
417    if (cu == NULL) {
418      _set_errno(ENOMEM);
419      return -1;
420    }
421
422    if (cu->parse(parse_context, &next_cu)) {
423      cu->set_prev_cu(last_cu_);
424      last_cu_ = cu;
425      cu_count_++;
426    } else {
427      delete cu;
428      return -1;
429    }
430  };
431
432  return cu_count_;
433}
434
435template <typename Elf_Addr, typename Elf_Off>
436bool ElfFileImpl<Elf_Addr, Elf_Off>::get_section_info_by_name(const char* name,
437                                                              Elf_Off* offset,
438                                                              Elf_Word* size) {
439  const Elf_SHdr<Elf_Addr, Elf_Off>* cur_section =
440      reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>(sec_table_);
441
442  for (Elf_Half sec = 0; sec < sec_count_; sec++) {
443    const char* sec_name = get_str_sec_str(pull_val(cur_section->sh_name));
444    if (sec_name != NULL && strcmp(name, sec_name) == 0) {
445      *offset = pull_val(cur_section->sh_offset);
446      *size = pull_val(cur_section->sh_size);
447      return true;
448    }
449    cur_section = reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
450                                  (INC_CPTR(cur_section, sec_entry_size_));
451  }
452  _set_errno(EINVAL);
453  return false;
454}
455
456template <typename Elf_Addr, typename Elf_Off>
457bool ElfFileImpl<Elf_Addr, Elf_Off>::map_section_by_name(
458    const char* name,
459    ElfMappedSection* section) {
460  if (section->is_mapped()) {
461    return true;
462  }
463
464  Elf_Off offset;
465  Elf_Word size;
466  if (!get_section_info_by_name(name, &offset, &size)) {
467    return false;
468  }
469
470  return section->map(elf_handle_, offset, size);
471}
472