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