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