16f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===- ELFReaderTest.cpp --------------------------------------------------===// 26f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 36f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// The MCLinker Project 46f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 56f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// This file is distributed under the University of Illinois Open Source 66f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// License. See LICENSE.TXT for details. 76f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// 86f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 96f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <cstdio> 106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/ADT/StringRef.h> 126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ELF.h> 136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/IRBuilder.h> 146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/TargetOptions.h> 156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/LD/ELFReader.h> 16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/MC/Input.h> 176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <mcld/Support/Path.h> 18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/MemoryArea.h> 196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <../lib/Target/X86/X86LDBackend.h> 206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <../lib/Target/X86/X86GNUInfo.h> 216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include "ELFReaderTest.h" 236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld; 256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld::sys::fs; 266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcldtest; 276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Constructor can do set-up work for all test here. 296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReaderTest::ELFReaderTest() 306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : m_pInput(NULL) 316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pConfig = new LinkerConfig("x86_64-linux-gnueabi"); 336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pConfig->targets().setEndian( TargetOptions::Little ); 346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pConfig->targets().setBitClass( 64 ); 356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::SetUp( *m_pConfig ); 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 37f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pScript = new LinkerScript(); 386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pInfo = new X86_64GNUInfo( m_pConfig->targets().triple() ); 396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pLDBackend = new X86_64GNULDBackend( *m_pConfig, m_pInfo ); 406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pELFReader = new ELFReader<64, true>( *m_pLDBackend ); 41f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines m_pModule = new Module(*m_pScript); 426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pIRBuilder = new IRBuilder( *m_pModule, *m_pConfig); 436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pELFObjReader = new ELFObjectReader(*m_pLDBackend, 446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *m_pIRBuilder, 456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *m_pConfig); 466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Destructor can do clean-up work that doesn't throw exceptions here. 496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReaderTest::~ELFReaderTest() 506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pConfig; 526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pLDBackend; 536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pELFReader; 54f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines delete m_pScript; 556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pModule; 566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pIRBuilder; 576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pELFObjReader; 586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// SetUp() will be called immediately before each test. 616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFReaderTest::SetUp() 626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Path path(TOPDIR); 646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines path.append("unittests/test_x86_64.o"); 656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pInput = m_pIRBuilder->ReadInput("test_x86_64", path); 676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(NULL!=m_pInput); 686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(m_pInput->hasMemArea()); 706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines size_t hdr_size = m_pELFReader->getELFHeaderSize(); 71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef region = m_pInput->memArea()->request(m_pInput->fileOffset(), 72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines hdr_size); 73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines const char* ELF_hdr = region.begin(); 746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr); 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(shdr_result); 766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// TearDown() will be called immediately after each test. 796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid ELFReaderTest::TearDown() 806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Testcases 856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===// 866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesTEST_F( ELFReaderTest, read_section_headers ) { 876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(m_pInput->context()->numOfSections(), 13); 886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDContext::const_sect_iterator iter = m_pInput->context()->sectBegin(); 896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++iter; /// test section[1] 906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(".text", (*iter)->name()); 916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(llvm::ELF::SHT_PROGBITS, (*iter)->type()); 926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(0x40, (*iter)->offset()); 936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(0x15, (*iter)->size()); 946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(llvm::ELF::SHF_ALLOC & (*iter)->flag()); //AX 956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(0x4, (*iter)->align()); 966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(NULL, (*iter)->getLink()); 976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(0, (*iter)->getInfo()); 986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesTEST_F( ELFReaderTest, read_symbol_and_rela ) 1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 1026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(m_pInput->hasMemArea()); 1036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(m_pInput->hasContext()); 1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pInput->setType(Input::Object); 1056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // -- read symbols 1076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection* symtab_shdr = m_pInput->context()->getSection(".symtab"); 1086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(NULL!=symtab_shdr); 1096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection* strtab_shdr = symtab_shdr->getLink(); 1116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(NULL!=strtab_shdr); 1126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 113f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef symtab_region = m_pInput->memArea()->request( 114f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines m_pInput->fileOffset() + symtab_shdr->offset(), symtab_shdr->size()); 1156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 116f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef strtab_region = m_pInput->memArea()->request( 117f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines m_pInput->fileOffset() + strtab_shdr->offset(), strtab_shdr->size()); 118f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines const char* strtab = strtab_region.begin(); 1196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool result = m_pELFReader->readSymbols(*m_pInput, *m_pIRBuilder, 120f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines symtab_region, strtab); 1216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(result); 1226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ("hello.c", std::string(m_pInput->context()->getSymbol(1)->name())); 1236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ("puts", std::string(m_pInput->context()->getSymbol(10)->name())); 1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(NULL==m_pInput->context()->getSymbol(11)); 1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // -- read relocations 1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines MemoryArea* mem = m_pInput->memArea(); 1286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDContext::sect_iterator rs = m_pInput->context()->relocSectBegin(); 1296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(rs!=m_pInput->context()->relocSectEnd()); 1306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(".rela.text", (*rs)->name()); 1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t offset = m_pInput->fileOffset() + (*rs)->offset(); 1336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t size = (*rs)->size(); 134f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines llvm::StringRef region = mem->request(offset, size); 1356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder::CreateRelocData(**rs); /// create relocation data for the header 1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(llvm::ELF::SHT_RELA, (*rs)->type()); 138f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines ASSERT_TRUE(m_pELFReader->readRela(*m_pInput, **rs, region)); 1396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const RelocData::RelocationListType &rRelocs = 1416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (*rs)->getRelocData()->getRelocationList(); 1426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RelocData::const_iterator rReloc = rRelocs.begin(); 1436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(2, rRelocs.size()); 1446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE(rRelocs.end()!=rReloc); 1456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++rReloc; /// test rRelocs[1] 1466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ("puts", std::string(rReloc->symInfo()->name())); 1476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(llvm::ELF::R_X86_64_PC32, rReloc->type()); 1486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(0x0, rReloc->symValue()); 1496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_EQ(-0x4, rReloc->addend()); 1506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesTEST_F( ELFReaderTest, read_regular_sections ) { 1536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ASSERT_TRUE( m_pELFObjReader->readSections(*m_pInput) ); 1546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesTEST_F( ELFReaderTest, is_my_format ) { 157f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines bool doContinue; 158f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput, doContinue) ); 1596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 1606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 1616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 162