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