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