blob: 0447fa1cce428db16b6abb6eb7a0e46936cefc6a [file] [log] [blame]
Stephen Hines6f757552013-03-04 19:51:03 -08001//===- 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//===----------------------------------------------------------------------===//
Stephen Hines37b74a32014-11-26 18:48:20 -08009#include "ELFReaderTest.h"
Stephen Hines6f757552013-03-04 19:51:03 -080010
Stephen Hines37b74a32014-11-26 18:48:20 -080011#include "mcld/IRBuilder.h"
12#include "mcld/TargetOptions.h"
13#include "mcld/LD/ELFReader.h"
14#include "mcld/LD/LDContext.h"
15#include "mcld/MC/Input.h"
16#include "mcld/Support/Path.h"
17#include "mcld/Support/MemoryArea.h"
Stephen Hines6f757552013-03-04 19:51:03 -080018#include <../lib/Target/X86/X86LDBackend.h>
19#include <../lib/Target/X86/X86GNUInfo.h>
20
Stephen Hines37b74a32014-11-26 18:48:20 -080021#include <llvm/ADT/StringRef.h>
22#include <llvm/Support/ELF.h>
23
24#include <cstdio>
Stephen Hines6f757552013-03-04 19:51:03 -080025
26using namespace mcld;
27using namespace mcld::sys::fs;
28using namespace mcldtest;
29
30// Constructor can do set-up work for all test here.
Stephen Hines37b74a32014-11-26 18:48:20 -080031ELFReaderTest::ELFReaderTest() : m_pInput(NULL) {
Stephen Hines6f757552013-03-04 19:51:03 -080032 m_pConfig = new LinkerConfig("x86_64-linux-gnueabi");
Stephen Hines37b74a32014-11-26 18:48:20 -080033 m_pConfig->targets().setEndian(TargetOptions::Little);
34 m_pConfig->targets().setBitClass(64);
35 Relocation::SetUp(*m_pConfig);
Stephen Hines6f757552013-03-04 19:51:03 -080036
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070037 m_pScript = new LinkerScript();
Stephen Hines37b74a32014-11-26 18:48:20 -080038 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);
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070041 m_pModule = new Module(*m_pScript);
Stephen Hines37b74a32014-11-26 18:48:20 -080042 m_pIRBuilder = new IRBuilder(*m_pModule, *m_pConfig);
43 m_pELFObjReader =
44 new ELFObjectReader(*m_pLDBackend, *m_pIRBuilder, *m_pConfig);
Stephen Hines6f757552013-03-04 19:51:03 -080045}
46
47// Destructor can do clean-up work that doesn't throw exceptions here.
Stephen Hines37b74a32014-11-26 18:48:20 -080048ELFReaderTest::~ELFReaderTest() {
Stephen Hines6f757552013-03-04 19:51:03 -080049 delete m_pConfig;
50 delete m_pLDBackend;
51 delete m_pELFReader;
Stephen Hinesf7ac0f12013-05-03 19:09:24 -070052 delete m_pScript;
Stephen Hines6f757552013-03-04 19:51:03 -080053 delete m_pModule;
54 delete m_pIRBuilder;
55 delete m_pELFObjReader;
56}
57
58// SetUp() will be called immediately before each test.
Stephen Hines37b74a32014-11-26 18:48:20 -080059void ELFReaderTest::SetUp() {
Stephen Hines6f757552013-03-04 19:51:03 -080060 Path path(TOPDIR);
61 path.append("unittests/test_x86_64.o");
62
63 m_pInput = m_pIRBuilder->ReadInput("test_x86_64", path);
Stephen Hines37b74a32014-11-26 18:48:20 -080064 ASSERT_TRUE(NULL != m_pInput);
Stephen Hines6f757552013-03-04 19:51:03 -080065
66 ASSERT_TRUE(m_pInput->hasMemArea());
67 size_t hdr_size = m_pELFReader->getELFHeaderSize();
Stephen Hines37b74a32014-11-26 18:48:20 -080068 llvm::StringRef region =
69 m_pInput->memArea()->request(m_pInput->fileOffset(), hdr_size);
Stephen Hinesf33f6de2014-02-14 18:00:16 -080070 const char* ELF_hdr = region.begin();
Stephen Hines6f757552013-03-04 19:51:03 -080071 bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr);
Stephen Hines6f757552013-03-04 19:51:03 -080072 ASSERT_TRUE(shdr_result);
73}
74
75// TearDown() will be called immediately after each test.
Stephen Hines37b74a32014-11-26 18:48:20 -080076void ELFReaderTest::TearDown() {
Stephen Hines6f757552013-03-04 19:51:03 -080077}
78
79//===----------------------------------------------------------------------===//
80// Testcases
81//===----------------------------------------------------------------------===//
Stephen Hines37b74a32014-11-26 18:48:20 -080082TEST_F(ELFReaderTest, read_section_headers) {
Stephen Hinesa6c24df2015-03-18 14:53:18 -070083 ASSERT_EQ(m_pInput->context()->numOfSections(), 13u);
Stephen Hines6f757552013-03-04 19:51:03 -080084 LDContext::const_sect_iterator iter = m_pInput->context()->sectBegin();
Stephen Hines37b74a32014-11-26 18:48:20 -080085 ++iter; /// test section[1]
Stephen Hines6f757552013-03-04 19:51:03 -080086 ASSERT_EQ(".text", (*iter)->name());
87 ASSERT_EQ(llvm::ELF::SHT_PROGBITS, (*iter)->type());
Stephen Hinesa6c24df2015-03-18 14:53:18 -070088 ASSERT_EQ(0x40u, (*iter)->offset());
89 ASSERT_EQ(0x15u, (*iter)->size());
Stephen Hines37b74a32014-11-26 18:48:20 -080090 ASSERT_TRUE(llvm::ELF::SHF_ALLOC & (*iter)->flag()); // AX
Stephen Hinesa6c24df2015-03-18 14:53:18 -070091 ASSERT_EQ(0x4u, (*iter)->align());
Stephen Hines6f757552013-03-04 19:51:03 -080092 ASSERT_EQ(NULL, (*iter)->getLink());
Stephen Hinesa6c24df2015-03-18 14:53:18 -070093 ASSERT_EQ(0u, (*iter)->getInfo());
Stephen Hines6f757552013-03-04 19:51:03 -080094}
95
Stephen Hines37b74a32014-11-26 18:48:20 -080096TEST_F(ELFReaderTest, read_symbol_and_rela) {
Stephen Hines6f757552013-03-04 19:51:03 -080097 ASSERT_TRUE(m_pInput->hasMemArea());
98 ASSERT_TRUE(m_pInput->hasContext());
99 m_pInput->setType(Input::Object);
100
101 // -- read symbols
102 LDSection* symtab_shdr = m_pInput->context()->getSection(".symtab");
Stephen Hines37b74a32014-11-26 18:48:20 -0800103 ASSERT_TRUE(NULL != symtab_shdr);
Stephen Hines6f757552013-03-04 19:51:03 -0800104
105 LDSection* strtab_shdr = symtab_shdr->getLink();
Stephen Hines37b74a32014-11-26 18:48:20 -0800106 ASSERT_TRUE(NULL != strtab_shdr);
Stephen Hines6f757552013-03-04 19:51:03 -0800107
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800108 llvm::StringRef symtab_region = m_pInput->memArea()->request(
109 m_pInput->fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
Stephen Hines6f757552013-03-04 19:51:03 -0800110
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800111 llvm::StringRef strtab_region = m_pInput->memArea()->request(
112 m_pInput->fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
113 const char* strtab = strtab_region.begin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800114 bool result = m_pELFReader->readSymbols(
115 *m_pInput, *m_pIRBuilder, symtab_region, strtab);
Stephen Hines6f757552013-03-04 19:51:03 -0800116 ASSERT_TRUE(result);
117 ASSERT_EQ("hello.c", std::string(m_pInput->context()->getSymbol(1)->name()));
118 ASSERT_EQ("puts", std::string(m_pInput->context()->getSymbol(10)->name()));
Stephen Hines37b74a32014-11-26 18:48:20 -0800119 ASSERT_TRUE(NULL == m_pInput->context()->getSymbol(11));
Stephen Hines6f757552013-03-04 19:51:03 -0800120
121 // -- read relocations
122 MemoryArea* mem = m_pInput->memArea();
123 LDContext::sect_iterator rs = m_pInput->context()->relocSectBegin();
Stephen Hines37b74a32014-11-26 18:48:20 -0800124 ASSERT_TRUE(rs != m_pInput->context()->relocSectEnd());
Stephen Hines6f757552013-03-04 19:51:03 -0800125 ASSERT_EQ(".rela.text", (*rs)->name());
126
127 uint64_t offset = m_pInput->fileOffset() + (*rs)->offset();
128 uint64_t size = (*rs)->size();
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800129 llvm::StringRef region = mem->request(offset, size);
Stephen Hines37b74a32014-11-26 18:48:20 -0800130 IRBuilder::CreateRelocData(**rs); /// create relocation data for the header
Stephen Hines6f757552013-03-04 19:51:03 -0800131
132 ASSERT_EQ(llvm::ELF::SHT_RELA, (*rs)->type());
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800133 ASSERT_TRUE(m_pELFReader->readRela(*m_pInput, **rs, region));
Stephen Hines6f757552013-03-04 19:51:03 -0800134
Stephen Hines37b74a32014-11-26 18:48:20 -0800135 const RelocData::RelocationListType& rRelocs =
136 (*rs)->getRelocData()->getRelocationList();
Stephen Hines6f757552013-03-04 19:51:03 -0800137 RelocData::const_iterator rReloc = rRelocs.begin();
Stephen Hinesa6c24df2015-03-18 14:53:18 -0700138 ASSERT_EQ(2u, rRelocs.size());
Stephen Hines37b74a32014-11-26 18:48:20 -0800139 ASSERT_TRUE(rRelocs.end() != rReloc);
140 ++rReloc; /// test rRelocs[1]
Stephen Hines6f757552013-03-04 19:51:03 -0800141 ASSERT_EQ("puts", std::string(rReloc->symInfo()->name()));
142 ASSERT_EQ(llvm::ELF::R_X86_64_PC32, rReloc->type());
Stephen Hinesa6c24df2015-03-18 14:53:18 -0700143 ASSERT_EQ(0x0u, rReloc->symValue());
144 ASSERT_EQ(static_cast<mcld::Relocation::Address>(-0x4), rReloc->addend());
Stephen Hines6f757552013-03-04 19:51:03 -0800145}
146
Stephen Hines37b74a32014-11-26 18:48:20 -0800147TEST_F(ELFReaderTest, read_regular_sections) {
148 ASSERT_TRUE(m_pELFObjReader->readSections(*m_pInput));
Stephen Hines6f757552013-03-04 19:51:03 -0800149}
150
Stephen Hines37b74a32014-11-26 18:48:20 -0800151TEST_F(ELFReaderTest, is_my_format) {
Stephen Hinesf33f6de2014-02-14 18:00:16 -0800152 bool doContinue;
Stephen Hines37b74a32014-11-26 18:48:20 -0800153 ASSERT_TRUE(m_pELFObjReader->isMyFormat(*m_pInput, doContinue));
Stephen Hines6f757552013-03-04 19:51:03 -0800154}