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 24using namespace mcld; 25using namespace mcld::sys::fs; 26using namespace mcldtest; 27 28// Constructor can do set-up work for all test here. 29ELFReaderTest::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. 49ELFReaderTest::~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. 61void 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. 79void ELFReaderTest::TearDown() 80{ 81} 82 83//===----------------------------------------------------------------------===// 84// Testcases 85//===----------------------------------------------------------------------===// 86TEST_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 100TEST_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 152TEST_F( ELFReaderTest, read_regular_sections ) { 153 ASSERT_TRUE( m_pELFObjReader->readSections(*m_pInput) ); 154} 155 156TEST_F( ELFReaderTest, is_my_format ) { 157 bool doContinue; 158 ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput, doContinue) ); 159} 160 161 162