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