//===- ELFObjectReader.cpp ------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/ELFObjectReader.h>

#include <string>
#include <cassert>

#include <llvm/Support/ELF.h>
#include <llvm/ADT/Twine.h>

#include <mcld/IRBuilder.h>
#include <mcld/MC/MCLDInput.h>
#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/LD/ELFReader.h>
#include <mcld/LD/EhFrameReader.h>
#include <mcld/LD/EhFrame.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Object/ObjectBuilder.h>

using namespace mcld;

//===----------------------------------------------------------------------===//
// ELFObjectReader
//===----------------------------------------------------------------------===//
/// constructor
ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
  : ObjectReader(),
    m_pELFReader(NULL),
    m_pEhFrameReader(NULL),
    m_Linker(pLinker),
    m_ReadFlag(ParseEhFrame),
    m_Backend(pBackend) {
  if (32 == pBackend.bitclass() && pBackend.isLittleEndian()) {
    m_pELFReader = new ELFReader<32, true>(pBackend);
  }

  m_pEhFrameReader = new EhFrameReader();
}

/// destructor
ELFObjectReader::~ELFObjectReader()
{
  delete m_pELFReader;
  delete m_pEhFrameReader;
}

/// isMyFormat
bool ELFObjectReader::isMyFormat(Input &pInput) const
{
  assert(pInput.hasMemArea());

  // Don't warning about the frequently requests.
  // MemoryArea has a list of cache to handle this.
  size_t hdr_size = m_pELFReader->getELFHeaderSize();
  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
                                                     hdr_size);

  uint8_t* ELF_hdr = region->start();
  bool result = true;
  if (!m_pELFReader->isELF(ELF_hdr))
    result = false;
  else if (!m_pELFReader->isMyEndian(ELF_hdr))
    result = false;
  else if (!m_pELFReader->isMyMachine(ELF_hdr))
    result = false;
  else if (Input::Object != m_pELFReader->fileType(ELF_hdr))
    result = false;
  pInput.memArea()->release(region);
  return result;
}

/// readHeader - read section header and create LDSections.
bool ELFObjectReader::readHeader(Input& pInput)
{
  assert(pInput.hasMemArea());

  size_t hdr_size = m_pELFReader->getELFHeaderSize();
  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
                                                     hdr_size);
  uint8_t* ELF_hdr = region->start();
  bool result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
  pInput.memArea()->release(region);
  return result;
}

/// readSections - read all regular sections.
bool ELFObjectReader::readSections(Input& pInput)
{
  // handle sections
  LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
  for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
    // ignore the section if the LDSection* in input context is NULL
    if (NULL == *section)
        continue;

    switch((*section)->kind()) {
      /** group sections **/
      case LDFileFormat::Group: {
        assert(NULL != (*section)->getLink());
        ResolveInfo* signature =
              m_pELFReader->readSignature(pInput,
                                          *(*section)->getLink(),
                                          (*section)->getInfo());

        bool exist = false;
        if (0 == signature->nameSize() &&
            ResolveInfo::Section == signature->type()) {
          // if the signature is a section symbol in input object, we use the
          // section name as group signature.
          signatures().insert((*section)->name(), exist);
        } else {
          signatures().insert(signature->name(), exist);
        }

        if (exist) {
          // if this is not the first time we see this group signature, then
          // ignore all the members in this group (set Ignore)
          MemoryRegion* region = pInput.memArea()->request(
               pInput.fileOffset() + (*section)->offset(), (*section)->size());
          llvm::ELF::Elf32_Word* value =
                     reinterpret_cast<llvm::ELF::Elf32_Word*>(region->start());

          size_t size = region->size() / sizeof(llvm::ELF::Elf32_Word);
          if (llvm::ELF::GRP_COMDAT == *value) {
            for (size_t index = 1; index < size; ++index) {
              pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore);
            }
          }
          pInput.memArea()->release(region);
        }
        ResolveInfo::Destroy(signature);
        break;
      }
      /** relocation sections **/
      case LDFileFormat::Relocation: {
        assert(NULL != (*section)->getLink());
        size_t link_index = (*section)->getLink()->index();
        LDSection* link_sect = pInput.context()->getSection(link_index);
        if (NULL == link_sect || LDFileFormat::Ignore == link_sect->kind()) {
          // Relocation sections of group members should also be part of the
          // group. Thus, if the associated member sections are ignored, the
          // related relocations should be also ignored.
          (*section)->setKind(LDFileFormat::Ignore);
        }
        break;
      }
      /** normal sections **/
      // FIXME: support Version Kind
      case LDFileFormat::Version:
      // FIXME: support GCCExceptTable Kind
      case LDFileFormat::GCCExceptTable:
      /** Fall through **/
      case LDFileFormat::Regular:
      case LDFileFormat::Note:
      case LDFileFormat::MetaData: {
        SectionData* sd = IRBuilder::CreateSectionData(**section);
        if (!m_pELFReader->readRegularSection(pInput, *sd))
          fatal(diag::err_cannot_read_section) << (*section)->name();
        break;
      }
      case LDFileFormat::Debug: {
        if (m_Linker.getLDInfo().options().stripDebug()) {
          (*section)->setKind(LDFileFormat::Ignore);
        }
        else {
          SectionData* sd = IRBuilder::CreateSectionData(**section);
          if (!m_pELFReader->readRegularSection(pInput, *sd)) {
            fatal(diag::err_cannot_read_section) << (*section)->name();
          }
        }
        break;
      }
      case LDFileFormat::EhFrame: {
        EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);

        if (m_Linker.getLDInfo().options().hasEhFrameHdr() &&
            (m_ReadFlag & ParseEhFrame)) {

          // if --eh-frame-hdr option is given, parse .eh_frame.
          if (!m_pEhFrameReader->read<32, true>(pInput, *eh_frame)) {
            // if we failed to parse a .eh_frame, we should not parse the rest
            // .eh_frame.
            m_ReadFlag ^= ParseEhFrame;
          }
        }
        else {
          if (!m_pELFReader->readRegularSection(pInput,
                                                eh_frame->getSectionData())) {
            fatal(diag::err_cannot_read_section) << (*section)->name();
          }
        }
        break;
      }
      /** target dependent sections **/
      case LDFileFormat::Target: {
        SectionData* sd = IRBuilder::CreateSectionData(**section);
        if (!m_Backend.readSection(pInput, *sd)) {
          fatal(diag::err_cannot_read_target_section) << (*section)->name();
        }
        break;
      }
      /** BSS sections **/
      case LDFileFormat::BSS: {
        IRBuilder::CreateBSS(**section);
        break;
      }
      // ignore
      case LDFileFormat::Null:
      case LDFileFormat::NamePool:
      case LDFileFormat::Ignore:
      case LDFileFormat::StackNote:
        continue;
      // warning
      case LDFileFormat::EhFrameHdr:
      default: {
        warning(diag::warn_illegal_input_section) << (*section)->name()
                                                  << pInput.name()
                                                  << pInput.path();
        break;
      }
    }
  } // end of for all sections

  return true;
}

/// readSymbols - read symbols into FragmentLinker from the input relocatable object.
bool ELFObjectReader::readSymbols(Input& pInput)
{
  assert(pInput.hasMemArea());

  LDSection* symtab_shdr = pInput.context()->getSection(".symtab");
  if (NULL == symtab_shdr) {
    note(diag::note_has_no_symtab) << pInput.name()
                                   << pInput.path()
                                   << ".symtab";
    return true;
  }

  LDSection* strtab_shdr = symtab_shdr->getLink();
  if (NULL == strtab_shdr) {
    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
                                          << pInput.path()
                                          << ".symtab";
    return false;
  }

  MemoryRegion* symtab_region = pInput.memArea()->request(
             pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
  MemoryRegion* strtab_region = pInput.memArea()->request(
             pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
  char* strtab = reinterpret_cast<char*>(strtab_region->start());
  bool result = m_pELFReader->readSymbols(pInput,
                                          m_Linker,
                                          *symtab_region,
                                          strtab);
  pInput.memArea()->release(symtab_region);
  pInput.memArea()->release(strtab_region);
  return result;
}

bool ELFObjectReader::readRelocations(Input& pInput)
{
  assert(pInput.hasMemArea());

  MemoryArea* mem = pInput.memArea();
  LDContext::sect_iterator rs, rsEnd = pInput.context()->relocSectEnd();
  for (rs = pInput.context()->relocSectBegin(); rs != rsEnd; ++rs) {
    if (LDFileFormat::Ignore == (*rs)->kind())
      continue;

    uint32_t offset = pInput.fileOffset() + (*rs)->offset();
    uint32_t size = (*rs)->size();
    MemoryRegion* region = mem->request(offset, size);
    IRBuilder::CreateRelocData(**rs); ///< create relocation data for the header
    switch ((*rs)->type()) {
      case llvm::ELF::SHT_RELA: {
        if (!m_pELFReader->readRela(pInput, m_Linker, **rs, *region)) {
          mem->release(region);
          return false;
        }
        break;
      }
      case llvm::ELF::SHT_REL: {
        if (!m_pELFReader->readRel(pInput, m_Linker, **rs, *region)) {
          mem->release(region);
          return false;
        }
        break;
      }
      default: { ///< should not enter
        mem->release(region);
        return false;
      }
    } // end of switch

    mem->release(region);
  } // end of for all relocation data

  return true;
}

