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_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. 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. 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. 78 void ELFReaderTest::TearDown() 79 { 80 } 81 82 //===----------------------------------------------------------------------===// 83 // Testcases 84 //===----------------------------------------------------------------------===// 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 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 156 TEST_F( ELFReaderTest, read_regular_sections ) { 157 ASSERT_TRUE( m_pELFObjReader->readSections(*m_pInput) ); 158 } 159 160 TEST_F( ELFReaderTest, is_my_format ) { 161 ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput) ); 162 } 163 164 165