C++程序  |  127行  |  3.89 KB

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

#include "mcld/IRBuilder.h"
#include "mcld/LinkerConfig.h"
#include "mcld/MC/Input.h"
#include "mcld/Support/MemoryArea.h"

#include <llvm/Support/ELF.h>

#include <cctype>

namespace mcld {

//===----------------------------------------------------------------------===//
// ELFBinaryReader
//===----------------------------------------------------------------------===//
/// constructor
ELFBinaryReader::ELFBinaryReader(IRBuilder& pBuilder,
                                 const LinkerConfig& pConfig)
    : m_Builder(pBuilder), m_Config(pConfig) {
}

/// destructor
ELFBinaryReader::~ELFBinaryReader() {
}

bool ELFBinaryReader::isMyFormat(Input& pInput, bool& pContinue) const {
  pContinue = true;
  return m_Config.options().isBinaryInput();
}

bool ELFBinaryReader::readBinary(Input& pInput) {
  // section: NULL
  m_Builder.CreateELFHeader(
      pInput, "", LDFileFormat::Null, llvm::ELF::SHT_NULL, 0x0);

  // section: .data
  LDSection* data_sect =
      m_Builder.CreateELFHeader(pInput,
                                ".data",
                                LDFileFormat::DATA,
                                llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC,
                                0x1);

  SectionData* data = m_Builder.CreateSectionData(*data_sect);
  size_t data_size = pInput.memArea()->size();
  Fragment* frag = m_Builder.CreateRegion(pInput, 0x0, data_size);
  m_Builder.AppendFragment(*frag, *data);

  // section: .shstrtab
  m_Builder.CreateELFHeader(
      pInput, ".shstrtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x1);

  // section: .symtab
  m_Builder.CreateELFHeader(pInput,
                            ".symtab",
                            LDFileFormat::NamePool,
                            llvm::ELF::SHT_SYMTAB,
                            m_Config.targets().bitclass() / 8);

  // symbol: .data
  m_Builder.AddSymbol(pInput,
                      ".data",
                      ResolveInfo::Section,
                      ResolveInfo::Define,
                      ResolveInfo::Local,
                      0x0,
                      0x0,
                      data_sect);

  // Note: in Win32, the filename is wstring. Is it correct to convert
  // filename to std::string?
  std::string mangled_name = pInput.path().filename().native();
  for (std::string::iterator it = mangled_name.begin(), ie = mangled_name.end();
       it != ie;
       ++it) {
    if (isalnum(*it) == 0)
      *it = '_';
  }

  // symbol: _start
  m_Builder.AddSymbol(pInput,
                      "_binary_" + mangled_name + "_start",
                      ResolveInfo::NoType,
                      ResolveInfo::Define,
                      ResolveInfo::Global,
                      0x0,
                      0x0,
                      data_sect);

  // symbol: _end
  m_Builder.AddSymbol(pInput,
                      "_binary_" + mangled_name + "_end",
                      ResolveInfo::NoType,
                      ResolveInfo::Define,
                      ResolveInfo::Global,
                      0x0,
                      data_size,
                      data_sect);

  // symbol: _size
  m_Builder.AddSymbol(pInput,
                      "_binary_" + mangled_name + "_size",
                      ResolveInfo::NoType,
                      ResolveInfo::Define,
                      ResolveInfo::Global,
                      0x0,
                      data_size,
                      data_sect);

  // section: .strtab
  m_Builder.CreateELFHeader(
      pInput, ".strtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x1);

  return true;
}

}  // namespace mcld