Home | History | Annotate | Download | only in unittests
      1 //===- ELFReaderTest.cpp --------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include "ELFReaderTest.h"
     10 
     11 #include "mcld/IRBuilder.h"
     12 #include "mcld/TargetOptions.h"
     13 #include "mcld/LD/ELFReader.h"
     14 #include "mcld/LD/LDContext.h"
     15 #include "mcld/MC/Input.h"
     16 #include "mcld/Support/Path.h"
     17 #include "mcld/Support/MemoryArea.h"
     18 #include <../lib/Target/X86/X86LDBackend.h>
     19 #include <../lib/Target/X86/X86GNUInfo.h>
     20 
     21 #include <llvm/ADT/StringRef.h>
     22 #include <llvm/Support/ELF.h>
     23 
     24 #include <cstdio>
     25 
     26 using namespace mcld;
     27 using namespace mcld::sys::fs;
     28 using namespace mcldtest;
     29 
     30 // Constructor can do set-up work for all test here.
     31 ELFReaderTest::ELFReaderTest() : m_pInput(NULL) {
     32   m_pConfig = new LinkerConfig("x86_64-linux-gnueabi");
     33   m_pConfig->targets().setEndian(TargetOptions::Little);
     34   m_pConfig->targets().setBitClass(64);
     35   Relocation::SetUp(*m_pConfig);
     36 
     37   m_pScript = new LinkerScript();
     38   m_pInfo = new X86_64GNUInfo(m_pConfig->targets().triple());
     39   m_pLDBackend = new X86_64GNULDBackend(*m_pConfig, m_pInfo);
     40   m_pELFReader = new ELFReader<64, true>(*m_pLDBackend);
     41   m_pModule = new Module(*m_pScript);
     42   m_pIRBuilder = new IRBuilder(*m_pModule, *m_pConfig);
     43   m_pELFObjReader =
     44       new ELFObjectReader(*m_pLDBackend, *m_pIRBuilder, *m_pConfig);
     45 }
     46 
     47 // Destructor can do clean-up work that doesn't throw exceptions here.
     48 ELFReaderTest::~ELFReaderTest() {
     49   delete m_pConfig;
     50   delete m_pLDBackend;
     51   delete m_pELFReader;
     52   delete m_pScript;
     53   delete m_pModule;
     54   delete m_pIRBuilder;
     55   delete m_pELFObjReader;
     56 }
     57 
     58 // SetUp() will be called immediately before each test.
     59 void ELFReaderTest::SetUp() {
     60   Path path(TOPDIR);
     61   path.append("unittests/test_x86_64.o");
     62 
     63   m_pInput = m_pIRBuilder->ReadInput("test_x86_64", path);
     64   ASSERT_TRUE(NULL != m_pInput);
     65 
     66   ASSERT_TRUE(m_pInput->hasMemArea());
     67   size_t hdr_size = m_pELFReader->getELFHeaderSize();
     68   llvm::StringRef region =
     69       m_pInput->memArea()->request(m_pInput->fileOffset(), hdr_size);
     70   const char* ELF_hdr = region.begin();
     71   bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr);
     72   ASSERT_TRUE(shdr_result);
     73 }
     74 
     75 // TearDown() will be called immediately after each test.
     76 void ELFReaderTest::TearDown() {
     77 }
     78 
     79 //===----------------------------------------------------------------------===//
     80 // Testcases
     81 //===----------------------------------------------------------------------===//
     82 TEST_F(ELFReaderTest, read_section_headers) {
     83   ASSERT_EQ(m_pInput->context()->numOfSections(), 13u);
     84   LDContext::const_sect_iterator iter = m_pInput->context()->sectBegin();
     85   ++iter;  /// test section[1]
     86   ASSERT_EQ(".text", (*iter)->name());
     87   ASSERT_EQ(llvm::ELF::SHT_PROGBITS, (*iter)->type());
     88   ASSERT_EQ(0x40u, (*iter)->offset());
     89   ASSERT_EQ(0x15u, (*iter)->size());
     90   ASSERT_TRUE(llvm::ELF::SHF_ALLOC & (*iter)->flag());  // AX
     91   ASSERT_EQ(0x4u, (*iter)->align());
     92   ASSERT_EQ(NULL, (*iter)->getLink());
     93   ASSERT_EQ(0u, (*iter)->getInfo());
     94 }
     95 
     96 TEST_F(ELFReaderTest, read_symbol_and_rela) {
     97   ASSERT_TRUE(m_pInput->hasMemArea());
     98   ASSERT_TRUE(m_pInput->hasContext());
     99   m_pInput->setType(Input::Object);
    100 
    101   // -- read symbols
    102   LDSection* symtab_shdr = m_pInput->context()->getSection(".symtab");
    103   ASSERT_TRUE(NULL != symtab_shdr);
    104 
    105   LDSection* strtab_shdr = symtab_shdr->getLink();
    106   ASSERT_TRUE(NULL != strtab_shdr);
    107 
    108   llvm::StringRef symtab_region = m_pInput->memArea()->request(
    109       m_pInput->fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
    110 
    111   llvm::StringRef strtab_region = m_pInput->memArea()->request(
    112       m_pInput->fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
    113   const char* strtab = strtab_region.begin();
    114   bool result = m_pELFReader->readSymbols(
    115       *m_pInput, *m_pIRBuilder, symtab_region, strtab);
    116   ASSERT_TRUE(result);
    117   ASSERT_EQ("hello.c", std::string(m_pInput->context()->getSymbol(1)->name()));
    118   ASSERT_EQ("puts", std::string(m_pInput->context()->getSymbol(10)->name()));
    119   ASSERT_TRUE(NULL == m_pInput->context()->getSymbol(11));
    120 
    121   // -- read relocations
    122   MemoryArea* mem = m_pInput->memArea();
    123   LDContext::sect_iterator rs = m_pInput->context()->relocSectBegin();
    124   ASSERT_TRUE(rs != m_pInput->context()->relocSectEnd());
    125   ASSERT_EQ(".rela.text", (*rs)->name());
    126 
    127   uint64_t offset = m_pInput->fileOffset() + (*rs)->offset();
    128   uint64_t size = (*rs)->size();
    129   llvm::StringRef region = mem->request(offset, size);
    130   IRBuilder::CreateRelocData(**rs);  /// create relocation data for the header
    131 
    132   ASSERT_EQ(llvm::ELF::SHT_RELA, (*rs)->type());
    133   ASSERT_TRUE(m_pELFReader->readRela(*m_pInput, **rs, region));
    134 
    135   const RelocData::RelocationListType& rRelocs =
    136       (*rs)->getRelocData()->getRelocationList();
    137   RelocData::const_iterator rReloc = rRelocs.begin();
    138   ASSERT_EQ(2u, rRelocs.size());
    139   ASSERT_TRUE(rRelocs.end() != rReloc);
    140   ++rReloc;  /// test rRelocs[1]
    141   ASSERT_EQ("puts", std::string(rReloc->symInfo()->name()));
    142   ASSERT_EQ(llvm::ELF::R_X86_64_PC32, rReloc->type());
    143   ASSERT_EQ(0x0u, rReloc->symValue());
    144   ASSERT_EQ(static_cast<mcld::Relocation::Address>(-0x4), rReloc->addend());
    145 }
    146 
    147 TEST_F(ELFReaderTest, read_regular_sections) {
    148   ASSERT_TRUE(m_pELFObjReader->readSections(*m_pInput));
    149 }
    150 
    151 TEST_F(ELFReaderTest, is_my_format) {
    152   bool doContinue;
    153   ASSERT_TRUE(m_pELFObjReader->isMyFormat(*m_pInput, doContinue));
    154 }
    155