/* Copyright (C) 2007-2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
*/

/*
 * Contains implementation of ElfFile classes that encapsulate an ELF file.
 */

#include "string.h"
#include "elf_file.h"
#include "elf_alloc.h"
#include "dwarf_cu.h"
#include "dwarf_utils.h"

#include <fcntl.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif

/* Tags to parse when collecting info about routines. */
static const Dwarf_Tag parse_rt_tags[] = {
  DW_TAG_compile_unit,
  DW_TAG_partial_unit,
  DW_TAG_inlined_subroutine,
  DW_TAG_subprogram,
  0
};
static const DwarfParseContext parse_rt_context = { parse_rt_tags };

//=============================================================================
// Base ElfFile implementation
//=============================================================================

ElfFile::ElfFile()
    : fixed_base_address_(0),
      elf_handle_((MapFile*)-1),
      elf_file_path_(NULL),
      allocator_(NULL),
      sec_table_(NULL),
      sec_count_(0),
      sec_entry_size_(0),
      last_cu_(NULL),
      cu_count_(0),
      is_exec_(0) {
}

ElfFile::~ElfFile() {
  DwarfCU* cu_to_del = last_cu_;
  while (cu_to_del != NULL) {
    DwarfCU* next_cu_to_del = cu_to_del->prev_cu_;
    delete cu_to_del;
    cu_to_del = next_cu_to_del;
  }

  if (mapfile_is_valid(elf_handle_)) {
    mapfile_close(elf_handle_);
  }

  if (elf_file_path_ != NULL) {
    delete[] elf_file_path_;
  }

  if (sec_table_ != NULL) {
    delete[] reinterpret_cast<Elf_Byte*>(sec_table_);
  }

  /* Must be deleted last! */
  if (allocator_ != NULL) {
    delete allocator_;
  }
}

ElfFile* ElfFile::Create(const char* path) {
  ElfFile* ret = NULL;
  /* Allocate enough space on the stack to fit the largest ELF file header. */
  Elf64_FHdr header;
  const Elf_CommonHdr* elf_hdr = &header.common;

  assert(path != NULL && *path != '\0');
  if (path == NULL || *path == '\0') {
    _set_errno(EINVAL);
    return NULL;
  }

  /*
   * Open ELF file, and read its header (the largest one possible).
   */
  MapFile* file_handle = mapfile_open(path, O_RDONLY | O_BINARY, 0);
  if (!mapfile_is_valid(file_handle)) {
    return NULL;
  }
  const ssize_t read_bytes = mapfile_read(file_handle, &header, sizeof(header));
  mapfile_close(file_handle);
  assert(read_bytes != -1 && read_bytes == sizeof(header));
  if (read_bytes == -1 || read_bytes != sizeof(header)) {
    if (read_bytes != -1) {
      _set_errno(EINVAL);
    }
    return NULL;
  }

  /* Lets see if this is an ELF file at all. */
  if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG) != 0) {
    /* File is not an ELF file. */
    _set_errno(ENOEXEC);
    return NULL;
  }

  /* Lets check ELF's "bitness". */
  assert(elf_hdr->ei_info.ei_class == ELFCLASS32 ||
         elf_hdr->ei_info.ei_class == ELFCLASS64);
  if (elf_hdr->ei_info.ei_class != ELFCLASS32 &&
      elf_hdr->ei_info.ei_class != ELFCLASS64) {
    /* Neither 32, or 64-bit ELF file. Something wrong here. */
    _set_errno(EBADF);
    return NULL;
  }

  /* Lets instantiate appropriate ElfFileImpl object for this ELF. */
  if (elf_hdr->ei_info.ei_class == ELFCLASS32) {
    ret = new ElfFileImpl<Elf32_Addr, Elf32_Off>;
  } else {
    ret = new ElfFileImpl<Elf64_Addr, Elf64_Off>;
  }
  assert(ret != NULL);
  if (ret != NULL) {
    if (!ret->initialize(elf_hdr, path)) {
      delete ret;
      ret = NULL;
    }
  } else {
    _set_errno(ENOMEM);
  }

  return ret;
}

bool ElfFile::initialize(const Elf_CommonHdr* elf_hdr, const char* path) {
  /* Must be created first! */
  allocator_ = new ElfAllocator();
  assert(allocator_ != NULL);
  if (allocator_ == NULL) {
    _set_errno(ENOMEM);
    return false;
  }

  /* Copy file path. */
  size_t path_len = strlen(path) + 1;
  elf_file_path_ = new char[path_len];
  assert(elf_file_path_ != NULL);
  if (elf_file_path_ == NULL) {
    _set_errno(ENOMEM);
    return false;
  }
  memcpy(elf_file_path_, path, path_len);

  /* Cache some basic ELF properties. */
  is_ELF_64_ = elf_hdr->ei_info.ei_class == ELFCLASS64;
  is_elf_big_endian_ = elf_hdr->ei_info.ei_data == ELFDATA2MSB;
  same_endianness_ = is_elf_little_endian() == is_little_endian_cpu();
  is_exec_ = elf_hdr->e_type == 2;

  /* Reopen file for further reads and mappings. */
  elf_handle_ = mapfile_open(elf_file_path_, O_RDONLY | O_BINARY, 0);
  return mapfile_is_valid(elf_handle_);
}

bool ElfFile::get_pc_address_info(Elf_Xword address,
                                  Elf_AddressInfo* address_info) {
  assert(address_info != NULL);
  if (address_info == NULL) {
    _set_errno(EINVAL);
    return false;
  }

  /* Collect routine information for all CUs in this file. */
  if (parse_compilation_units(&parse_rt_context) == -1) {
    return false;
  }

  /* Iterate through the collected CUs looking for the one that
   * contains the given address. */
  address_info->inline_stack = NULL;
  DwarfCU* cu = last_cu();
  while (cu != NULL) {
    /* Find a leaf DIE object in the current CU that contains the address. */
    Dwarf_AddressInfo info;
    info.die_obj = cu->get_leaf_die_for_address(address);
    if (info.die_obj != NULL) {
      /* Convert the address to a location inside source file. */
      if (cu->get_pc_address_file_info(address, &info)) {
          /* Copy location information to the returning structure. */
          address_info->file_name = info.file_name;
          address_info->dir_name = info.dir_name;
          address_info->line_number = info.line_number;
      } else {
          address_info->file_name = NULL;
          address_info->dir_name = NULL;
          address_info->line_number = 0;
      }

      /* Lets see if the DIE represents a routine (rather than
       * a lexical block, for instance). */
      Dwarf_Tag tag = info.die_obj->get_tag();
      while (!dwarf_tag_is_routine(tag)) {
        /* This is not a routine DIE. Lets loop trhough the parents of that
         * DIE looking for the first routine DIE. */
        info.die_obj = info.die_obj->parent_die();
        if (info.die_obj == NULL) {
          /* Reached compilation unit DIE. Can't go any further. */
          address_info->routine_name = "<unknown>";
          return true;
        }
        tag = info.die_obj->get_tag();
      }

      /* Save name of the routine that contains the address. */
      address_info->routine_name = info.die_obj->get_name();
      if (address_info->routine_name == NULL) {
        /* In some cases (minimum debugging info in the file) routine
         * name may be not avaible. We, however, are obliged by API
         * considerations to return something in this field. */
          address_info->routine_name = "<unknown>";
      }

      /* Lets see if address belongs to an inlined routine. */
      if (tag != DW_TAG_inlined_subroutine) {
        address_info->inline_stack = NULL;
        return true;
      }

      /*
       * Address belongs to an inlined routine. Create inline stack.
       */

      /* Allocate inline stack array big enough to fit all parent entries. */
      address_info->inline_stack =
        new Elf_InlineInfo[info.die_obj->get_level() + 1];
      assert(address_info->inline_stack != NULL);
      if (address_info->inline_stack == NULL) {
        _set_errno(ENOMEM);
        return false;
      }
      memset(address_info->inline_stack, 0,
             sizeof(Elf_InlineInfo) * (info.die_obj->get_level() + 1));

      /* Reverse DIEs filling in inline stack entries for inline
       * routine tags. */
      int inl_index = 0;
      do {
        /* Save source file information. */
        DIEAttrib file_desc;
        if (info.die_obj->get_attrib(DW_AT_call_file, &file_desc)) {
          const Dwarf_STMTL_FileDesc* desc =
              cu->get_stmt_file_info(file_desc.value()->u32);
          if (desc != NULL) {
            address_info->inline_stack[inl_index].inlined_in_file =
                desc->file_name;
            address_info->inline_stack[inl_index].inlined_in_file_dir =
                cu->get_stmt_dir_name(desc->get_dir_index());
          }
        }
        if (address_info->inline_stack[inl_index].inlined_in_file == NULL) {
          address_info->inline_stack[inl_index].inlined_in_file = "<unknown>";
          address_info->inline_stack[inl_index].inlined_in_file_dir = NULL;
        }

        /* Save source line information. */
        if (info.die_obj->get_attrib(DW_AT_call_line, &file_desc)) {
          address_info->inline_stack[inl_index].inlined_at_line = file_desc.value()->u32;
        }

        /* Advance DIE to the parent routine, and save its name. */
        info.die_obj = info.die_obj->parent_die();
        assert(info.die_obj != NULL);
        if (info.die_obj != NULL) {
          tag = info.die_obj->get_tag();
          while (!dwarf_tag_is_routine(tag)) {
            info.die_obj = info.die_obj->parent_die();
            if (info.die_obj == NULL) {
              break;
            }
            tag = info.die_obj->get_tag();
          }
          if (info.die_obj != NULL) {
            address_info->inline_stack[inl_index].routine_name =
                info.die_obj->get_name();
          }
        }
        if (address_info->inline_stack[inl_index].routine_name == NULL) {
          address_info->inline_stack[inl_index].routine_name = "<unknown>";
        }

        /* Continue with the parent DIE. */
        inl_index++;
      } while (info.die_obj != NULL && tag == DW_TAG_inlined_subroutine);

      return true;
    }
    cu = cu->prev_cu();
  }

  return false;
}

void ElfFile::free_pc_address_info(Elf_AddressInfo* address_info) const {
  assert(address_info != NULL);
  if (address_info != NULL && address_info->inline_stack != NULL) {
    delete address_info->inline_stack;
    address_info->inline_stack = NULL;
  }
}

//=============================================================================
// ElfFileImpl
//=============================================================================

template <typename Elf_Addr, typename Elf_Off>
bool ElfFileImpl<Elf_Addr, Elf_Off>::initialize(const Elf_CommonHdr* elf_hdr,
                                                const char* path) {
  /* Must be called first! */
  if (!ElfFile::initialize(elf_hdr, path)) {
    return false;
  }

  /* Cache some header data, so later we can discard the header. */
  const Elf_FHdr<Elf_Addr, Elf_Off>* header =
      reinterpret_cast<const Elf_FHdr<Elf_Addr, Elf_Off>*>(elf_hdr);
  sec_count_ = pull_val(header->e_shnum);
  sec_entry_size_ = pull_val(header->e_shentsize);
  fixed_base_address_ = pull_val(header->e_entry) & ~0xFFF;

  /* Cache section table (must have one!) */
  const Elf_Off sec_table_off = pull_val(header->e_shoff);
  assert(sec_table_off != 0 && sec_count_ != 0);
  if (sec_table_off == 0 || sec_count_ == 0) {
    _set_errno(EBADF);
    return false;
  }
  const size_t sec_table_size = sec_count_ * sec_entry_size_;
  sec_table_ = new Elf_Byte[sec_table_size];
  assert(sec_table_ != NULL);
  if (sec_table_ == NULL) {
    _set_errno(ENOMEM);
    return false;
  }
  if (mapfile_read_at(elf_handle_, sec_table_off, sec_table_,
                      sec_table_size) < 0) {
      return false;
  }

  /* Map ELF's string section (must have one!). */
  const Elf_Half str_sec_index = pull_val(header->e_shstrndx);
  assert(str_sec_index != SHN_UNDEF);
  if (str_sec_index == SHN_UNDEF) {
    _set_errno(EBADF);
    return false;
  }
  const Elf_SHdr<Elf_Addr, Elf_Off>* str_sec =
      reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
          (get_section_by_index(str_sec_index));
  assert(str_sec != NULL);
  if (str_sec == NULL) {
    _set_errno(EBADF);
    return false;
  }
  if (!string_section_.map(elf_handle_, pull_val(str_sec->sh_offset),
                           pull_val(str_sec->sh_size))) {
    return false;
  }

  /* Lets determine DWARF format. According to the docs, DWARF is 64 bit, if
   * first 4 bytes in the compilation unit header are set to 0xFFFFFFFF.
   * .debug_info section of the ELF file begins with the first CU header. */
  if (!map_section_by_name(".debug_info", &debug_info_)) {
    _set_errno(EBADF);
    return false;
  }

  /* Note that we don't care about endianness here, since 0xFFFFFFFF is an
   * endianness-independent value, so we don't have to pull_val here. */
  is_DWARF_64_ =
    *reinterpret_cast<const Elf_Word*>(debug_info_.data()) == 0xFFFFFFFF;

  return true;
}

template <typename Elf_Addr, typename Elf_Off>
int ElfFileImpl<Elf_Addr, Elf_Off>::parse_compilation_units(
    const DwarfParseContext* parse_context) {
  /* Lets see if we already parsed the file. */
  if (last_cu() != NULL) {
    return cu_count_;
  }

  /* Cache sections required for this parsing. */
  if (!map_section_by_name(".debug_abbrev", &debug_abbrev_) ||
      !map_section_by_name(".debug_ranges", &debug_ranges_) ||
      !map_section_by_name(".debug_line", &debug_line_) ||
      !map_section_by_name(".debug_str", &debug_str_)) {
    _set_errno(EBADF);
    return false;
  }

  /* .debug_info section opens with the first CU header. */
  const void* next_cu = debug_info_.data();

  /* Iterate through CUs until we reached the end of .debug_info section, or
   * advanced to a CU with zero size, indicating the end of CU list for this
   * file. */
  while (is_valid_cu(next_cu)) {
    /* Instatiate CU, depending on DWARF "bitness". */
    DwarfCU* cu = DwarfCU::create_instance(this, next_cu);
    if (cu == NULL) {
      _set_errno(ENOMEM);
      return -1;
    }

    if (cu->parse(parse_context, &next_cu)) {
      cu->set_prev_cu(last_cu_);
      last_cu_ = cu;
      cu_count_++;
    } else {
      delete cu;
      return -1;
    }
  };

  return cu_count_;
}

template <typename Elf_Addr, typename Elf_Off>
bool ElfFileImpl<Elf_Addr, Elf_Off>::get_section_info_by_name(const char* name,
                                                              Elf_Off* offset,
                                                              Elf_Word* size) {
  const Elf_SHdr<Elf_Addr, Elf_Off>* cur_section =
      reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>(sec_table_);

  for (Elf_Half sec = 0; sec < sec_count_; sec++) {
    const char* sec_name = get_str_sec_str(pull_val(cur_section->sh_name));
    if (sec_name != NULL && strcmp(name, sec_name) == 0) {
      *offset = pull_val(cur_section->sh_offset);
      *size = pull_val(cur_section->sh_size);
      return true;
    }
    cur_section = reinterpret_cast<const Elf_SHdr<Elf_Addr, Elf_Off>*>
                                  (INC_CPTR(cur_section, sec_entry_size_));
  }
  _set_errno(EINVAL);
  return false;
}

template <typename Elf_Addr, typename Elf_Off>
bool ElfFileImpl<Elf_Addr, Elf_Off>::map_section_by_name(
    const char* name,
    ElfMappedSection* section) {
  if (section->is_mapped()) {
    return true;
  }

  Elf_Off offset;
  Elf_Word size;
  if (!get_section_info_by_name(name, &offset, &size)) {
    return false;
  }

  return section->map(elf_handle_, offset, size);
}
