summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2015-04-07 16:30:20 -0700
committerStephen Hines <srhines@google.com>2015-04-07 16:30:20 -0700
commit04c59f3b00def22b7c75f5a490c323cec58a7c71 (patch)
tree28edce8d679cd33e7bcbd473026755b8ee9d68d6
parentfdc86e090cd0308ba880937cf55ed162abfd20a0 (diff)
downloadmclinker-04c59f3b00def22b7c75f5a490c323cec58a7c71.tar.gz
Update mclinker for llvm rebase to r233350.
Change-Id: Ic2e8c152e881681d6b827f9ace76bcb87b907147
-rw-r--r--include/mcld/GeneralOptions.h7
-rw-r--r--include/mcld/Support/CommandLine.h8
-rw-r--r--include/mcld/Target/TargetLDBackend.h28
-rw-r--r--lib/Core/GeneralOptions.cpp1
-rw-r--r--lib/LD/GarbageCollection.cpp4
-rw-r--r--lib/Object/ObjectLinker.cpp17
-rw-r--r--lib/Script/ScriptScanner.ll11
-rw-r--r--lib/Target/AArch64/AArch64Relocator.cpp11
-rw-r--r--lib/Target/ARM/ARMException.cpp98
-rw-r--r--lib/Target/ARM/ARMLDBackend.cpp5
-rw-r--r--lib/Target/ELFDynamic.cpp10
-rw-r--r--lib/Target/Hexagon/HexagonAbsoluteStub.cpp2
-rw-r--r--tools/mcld/include/mcld/DynamicSectionOptions.h1
-rw-r--r--tools/mcld/lib/DynamicSectionOptions.cpp9
14 files changed, 192 insertions, 20 deletions
diff --git a/include/mcld/GeneralOptions.h b/include/mcld/GeneralOptions.h
index 58e4eb3..165c027 100644
--- a/include/mcld/GeneralOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -107,6 +107,12 @@ class GeneralOptions {
m_NoUndefined = (pEnable ? YES : NO);
}
+ void setNumSpareDTags(uint32_t pNum) {
+ m_NumSpareDTags = pNum;
+ }
+
+ unsigned getNumSpareDTags() const { return m_NumSpareDTags; }
+
void setMulDefs(bool pEnable = true) { m_MulDefs = (pEnable ? YES : NO); }
void setEhFrameHdr(bool pEnable = true) { m_bCreateEhFrameHdr = pEnable; }
@@ -322,6 +328,7 @@ class GeneralOptions {
int8_t m_Verbose; // --verbose[=0,1,2]
uint16_t m_MaxErrorNum; // --error-limit=N
uint16_t m_MaxWarnNum; // --warning-limit=N
+ unsigned m_NumSpareDTags; // --spare-dynamic-tags
status m_ExecStack; // execstack, noexecstack
status m_NoUndefined; // defs, --no-undefined
status m_MulDefs; // muldefs, --allow-multiple-definition
diff --git a/include/mcld/Support/CommandLine.h b/include/mcld/Support/CommandLine.h
index 6911e46..0a67ee8 100644
--- a/include/mcld/Support/CommandLine.h
+++ b/include/mcld/Support/CommandLine.h
@@ -25,7 +25,7 @@ namespace cl {
//===----------------------------------------------------------------------===//
class SearchDirParser : public basic_parser<std::string> {
public:
- SearchDirParser(Option &O) : basic_parser(O) { }
+ explicit SearchDirParser(Option &O) : basic_parser(O) { }
// parse - Return true on error.
bool parse(Option& pOption,
@@ -48,7 +48,7 @@ class SearchDirParser : public basic_parser<std::string> {
//===----------------------------------------------------------------------===//
class FalseParser : public parser<bool> {
public:
- FalseParser(Option &O) : parser<bool>(O) { }
+ explicit FalseParser(Option &O) : parser<bool>(O) { }
// parse - Return true on error.
bool parse(cl::Option& O, StringRef ArgName, StringRef Arg, bool& Val) {
@@ -65,7 +65,7 @@ class FalseParser : public parser<bool> {
template <>
class parser<mcld::sys::fs::Path> : public basic_parser<mcld::sys::fs::Path> {
public:
- parser(Option &O) : basic_parser(O) { }
+ explicit parser(Option &O) : basic_parser(O) { }
bool parse(Option& O,
StringRef ArgName,
@@ -86,7 +86,7 @@ class parser<mcld::sys::fs::Path> : public basic_parser<mcld::sys::fs::Path> {
template <>
class parser<mcld::ZOption> : public basic_parser<mcld::ZOption> {
public:
- parser(Option &O) : basic_parser(O) { }
+ explicit parser(Option &O) : basic_parser(O) { }
bool parse(Option& O, StringRef ArgName, StringRef Arg, mcld::ZOption& Val);
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index c1e4e8e..e774a9c 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -8,18 +8,21 @@
//===----------------------------------------------------------------------===//
#ifndef MCLD_TARGET_TARGETLDBACKEND_H_
#define MCLD_TARGET_TARGETLDBACKEND_H_
+#include "mcld/Fragment/Relocation.h"
#include "mcld/LD/GarbageCollection.h"
#include "mcld/Support/Compiler.h"
+#include "mcld/Support/GCFactoryListTraits.h"
#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/ilist.h>
#include <llvm/Support/DataTypes.h>
namespace mcld {
class ArchiveReader;
-class BranchIslandFactory;
class BinaryReader;
class BinaryWriter;
+class BranchIslandFactory;
class DynObjReader;
class DynObjWriter;
class ExecWriter;
@@ -43,6 +46,11 @@ class StubFactory;
/// TargetLDBackend - Generic interface to target specific assembler backends.
//===----------------------------------------------------------------------===//
class TargetLDBackend {
+ public:
+ typedef llvm::iplist<Relocation, GCFactoryListTraits<Relocation> >
+ ExtraRelocList;
+ typedef ExtraRelocList::iterator extra_reloc_iterator;
+
protected:
explicit TargetLDBackend(const LinkerConfig& pConfig);
@@ -182,12 +190,30 @@ class TargetLDBackend {
virtual bool mayHaveUnsafeFunctionPointerAccess(
const LDSection& pSection) const = 0;
+ extra_reloc_iterator extra_reloc_begin() {
+ return m_ExtraReloc.begin();
+ }
+
+ extra_reloc_iterator extra_reloc_end() {
+ return m_ExtraReloc.end();
+ }
+
protected:
const LinkerConfig& config() const { return m_Config; }
+ /// addExtraRelocation - Add an extra relocation which are automatically
+ /// generated by the LD backend.
+ void addExtraRelocation(Relocation* reloc) {
+ m_ExtraReloc.push_back(reloc);
+ }
+
private:
const LinkerConfig& m_Config;
+ /// m_ExtraReloc - Extra relocations that are automatically generated by the
+ /// linker.
+ ExtraRelocList m_ExtraReloc;
+
private:
DISALLOW_COPY_AND_ASSIGN(TargetLDBackend);
};
diff --git a/lib/Core/GeneralOptions.cpp b/lib/Core/GeneralOptions.cpp
index 521ffa5..6f7b57f 100644
--- a/lib/Core/GeneralOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -20,6 +20,7 @@ GeneralOptions::GeneralOptions()
: m_Verbose(-1),
m_MaxErrorNum(-1),
m_MaxWarnNum(-1),
+ m_NumSpareDTags(1),
m_ExecStack(Unknown),
m_NoUndefined(Unknown),
m_MulDefs(Unknown),
diff --git a/lib/LD/GarbageCollection.cpp b/lib/LD/GarbageCollection.cpp
index 89a97e2..6236b57 100644
--- a/lib/LD/GarbageCollection.cpp
+++ b/lib/LD/GarbageCollection.cpp
@@ -240,8 +240,8 @@ void GarbageCollection::getEntrySections(SectionVecTy& pEntry) {
if (!m_Config.options().exportDynamic()) {
NamePool::syminfo_iterator info_it,
info_end = m_Module.getNamePool().syminfo_end();
- for (info_it = m_Module.getNamePool().syminfo_begin(); info_it != info_end;
- ++info_it) {
+ for (info_it = m_Module.getNamePool().syminfo_begin();
+ info_it != info_end; ++info_it) {
ResolveInfo* info = info_it.getEntry();
if (!info->isDefine() || info->isLocal())
continue;
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
index 0ab7315..801cbaf 100644
--- a/lib/Object/ObjectLinker.cpp
+++ b/lib/Object/ObjectLinker.cpp
@@ -383,7 +383,8 @@ bool ObjectLinker::mergeSections() {
// FIXME: disable debug string merge when doing partial link.
if (LinkerConfig::Object == m_Config.codeGenType())
(*sect)->setKind(LDFileFormat::Debug);
- } // Fall through
+ }
+ // Fall through
default: {
if (!(*sect)->hasSectionData())
continue; // skip
@@ -835,6 +836,13 @@ bool ObjectLinker::relocation() {
(*iter)->apply(*m_LDBackend.getRelocator());
}
+ // apply relocations created by LD backend
+ for (TargetLDBackend::extra_reloc_iterator
+ iter = m_LDBackend.extra_reloc_begin(),
+ end = m_LDBackend.extra_reloc_end(); iter != end; ++iter) {
+ iter->apply(*m_LDBackend.getRelocator());
+ }
+
return true;
}
@@ -907,6 +915,13 @@ void ObjectLinker::normalSyncRelocationResult(FileOutputBuffer& pOutput) {
writeRelocationResult(*reloc, data);
}
}
+
+ // sync relocations created by LD backend
+ for (TargetLDBackend::extra_reloc_iterator
+ iter = m_LDBackend.extra_reloc_begin(),
+ end = m_LDBackend.extra_reloc_end(); iter != end; ++iter) {
+ writeRelocationResult(*iter, data);
+ }
}
void ObjectLinker::partialSyncRelocationResult(FileOutputBuffer& pOutput) {
diff --git a/lib/Script/ScriptScanner.ll b/lib/Script/ScriptScanner.ll
index c1c3f74..97bff76 100644
--- a/lib/Script/ScriptScanner.ll
+++ b/lib/Script/ScriptScanner.ll
@@ -23,6 +23,13 @@ typedef mcld::ScriptParser::token_type token_type;
#define YY_NO_UNISTD_H
%}
+%{
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-register"
+#endif
+%}
+
/* Flex Declarations and Options */
%option c++
%option batch
@@ -377,6 +384,10 @@ void ScriptScanner::popLexState()
} /* namespace mcld */
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
#ifdef yylex
#undef yylex
#endif
diff --git a/lib/Target/AArch64/AArch64Relocator.cpp b/lib/Target/AArch64/AArch64Relocator.cpp
index 5da37b9..9f1e9b9 100644
--- a/lib/Target/AArch64/AArch64Relocator.cpp
+++ b/lib/Target/AArch64/AArch64Relocator.cpp
@@ -246,11 +246,12 @@ void AArch64Relocator::scanGlobalReloc(Relocation& pReloc,
getTarget().checkAndSetHasTextRel(*pSection.getLink());
if (llvm::ELF::R_AARCH64_ABS64 == pReloc.type() &&
helper_use_relative_reloc(*rsym, *this)) {
- Relocation& reloc = helper_DynRela_init(rsym,
- *pReloc.targetRef().frag(),
- pReloc.targetRef().offset(),
- llvm::ELF::R_AARCH64_RELATIVE,
- *this);
+ Relocation& reloc =
+ helper_DynRela_init(rsym,
+ *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(),
+ llvm::ELF::R_AARCH64_RELATIVE,
+ *this);
getRelRelMap().record(pReloc, reloc);
} else {
Relocation& reloc = helper_DynRela_init(rsym,
diff --git a/lib/Target/ARM/ARMException.cpp b/lib/Target/ARM/ARMException.cpp
index 9b86f98..3893190 100644
--- a/lib/Target/ARM/ARMException.cpp
+++ b/lib/Target/ARM/ARMException.cpp
@@ -19,6 +19,13 @@
#include <memory>
+static const char g_CantUnwindEntry[8] = {
+ // Relocation to text section.
+ 0, 0, 0, 0,
+ // EXIDX_CANTUNWIND (little endian.)
+ 1, 0, 0, 0,
+};
+
namespace mcld {
void ARMExData::addInputMap(Input* pInput,
@@ -168,7 +175,7 @@ class ExIdxFragmentComparator {
const ARMExData& m_ExData;
public:
- ExIdxFragmentComparator(const ARMExData& pExData)
+ explicit ExIdxFragmentComparator(const ARMExData& pExData)
: m_ExData(pExData) {
}
@@ -187,6 +194,36 @@ class ExIdxFragmentComparator {
}
};
+static mcld::ResolveInfo*
+CreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) {
+ // Create and add symbol to the name pool.
+ mcld::ResolveInfo* resolveInfo =
+ pModule.getNamePool().createSymbol(/* pName */"",
+ /* pIsDyn */false,
+ mcld::ResolveInfo::Section,
+ mcld::ResolveInfo::Define,
+ mcld::ResolveInfo::Local,
+ /* pSize */0,
+ mcld::ResolveInfo::Hidden);
+ if (resolveInfo == nullptr) {
+ return nullptr;
+ }
+
+ // Create input symbol.
+ mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo);
+ if (inputSym == nullptr) {
+ return nullptr;
+ }
+
+ inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size()));
+ inputSym->setValue(/* pValue */0);
+
+ // The output symbol is simply an alias to the input symbol.
+ resolveInfo->setSymPtr(inputSym);
+
+ return resolveInfo;
+}
+
void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
if (!m_pEXIDX->hasSectionData()) {
// Return if this is empty section.
@@ -196,7 +233,8 @@ void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
SectionData* sectData = m_pEXIDX->getSectionData();
SectionData::FragmentListType& list = sectData->getFragmentList();
- // Move the first and last fragment to temporary list.
+ // Move the first fragment (align fragment) and last fragment (null fragment)
+ // to temporary list because we would only like to sort the region fragment.
SectionData::FragmentListType tmp;
{
SectionData::iterator first = sectData->begin();
@@ -213,7 +251,58 @@ void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
// Sort the region fragments in the .ARM.exidx output section.
sort(list, ExIdxFragmentComparator(m_ExData));
- // Add the first and last fragment back.
+ // Fix the coverage of the .ARM.exidx table.
+ llvm::StringRef cantUnwindRegion(g_CantUnwindEntry,
+ sizeof(g_CantUnwindEntry));
+
+ SectionData::FragmentListType::iterator it = list.begin();
+ if (it != list.end()) {
+ Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
+ uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() +
+ prevTextFrag->getOffset() +
+ prevTextFrag->size();
+ ++it;
+ while (it != list.end()) {
+ Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
+ uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() +
+ currTextFrag->getOffset();
+
+ if (currTextBegin > prevTextEnd) {
+ // Found a gap. Insert a can't unwind entry.
+ RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
+ frag->setParent(sectData);
+ list.insert(it, frag);
+
+ // Add PREL31 reference to the beginning of the uncovered region.
+ Relocation* reloc =
+ Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
+ *FragmentRef::Create(*frag, /* pOffset */0),
+ /* pAddend */0);
+ reloc->setSymInfo(
+ CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
+ addExtraRelocation(reloc);
+ }
+
+ prevTextEnd = currTextBegin + currTextFrag->size();
+ prevTextFrag = currTextFrag;
+ ++it;
+ }
+
+ // Add a can't unwind entry to terminate .ARM.exidx section.
+ RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
+ frag->setParent(sectData);
+ list.push_back(frag);
+
+ // Add PREL31 reference to the end of the .text section.
+ Relocation* reloc =
+ Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
+ *FragmentRef::Create(*frag, /* pOffset */0),
+ /* pAddend */0);
+ reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
+ addExtraRelocation(reloc);
+ }
+
+ // Add the first and the last fragment back.
list.splice(list.begin(), tmp, tmp.begin());
list.splice(list.end(), tmp, tmp.begin());
@@ -225,6 +314,9 @@ void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
offset += it->size();
}
+ // Update the section size.
+ m_pEXIDX->setSize(offset);
+
// Rebuild the section header.
setOutputSectionAddress(pModule);
}
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index db691af..5d7bc56 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -636,8 +636,11 @@ unsigned int ARMGNULDBackend::getTargetSectionOrder(
/// relax - the relaxation pass
bool ARMGNULDBackend::relax(Module& pModule, IRBuilder& pBuilder) {
+ if (!GNULDBackend::relax(pModule, pBuilder)) {
+ return false;
+ }
rewriteARMExIdxSection(pModule);
- return GNULDBackend::relax(pModule, pBuilder);
+ return true;
}
/// doRelax
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index 4318bfa..47005cc 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -183,7 +183,10 @@ void ELFDynamic::reserveEntries(const ELFFileFormat& pFormat) {
reserveOne(llvm::ELF::DT_FLAGS_1);
}
- reserveOne(llvm::ELF::DT_NULL);
+ unsigned num_spare_dtags = m_Config.options().getNumSpareDTags();
+ for (unsigned i = 0; i < num_spare_dtags; ++i) {
+ reserveOne(llvm::ELF::DT_NULL);
+ }
}
/// applyEntries - apply entries
@@ -305,7 +308,10 @@ void ELFDynamic::applyEntries(const ELFFileFormat& pFormat) {
if (dt_flags_1 != 0x0)
applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1);
- applyOne(llvm::ELF::DT_NULL, 0x0);
+ unsigned num_spare_dtags = m_Config.options().getNumSpareDTags();
+ for (unsigned i = 0; i < num_spare_dtags; ++i) {
+ applyOne(llvm::ELF::DT_NULL, 0x0);
+ }
}
/// symbolSize
diff --git a/lib/Target/Hexagon/HexagonAbsoluteStub.cpp b/lib/Target/Hexagon/HexagonAbsoluteStub.cpp
index 3ddf08b..1d6113c 100644
--- a/lib/Target/Hexagon/HexagonAbsoluteStub.cpp
+++ b/lib/Target/Hexagon/HexagonAbsoluteStub.cpp
@@ -34,7 +34,7 @@ const uint32_t HexagonAbsoluteStub::TEMPLATE[] = {
};
#define FITS_IN_NBITS(D, B) \
- (llvm::abs64(D) < (~(~(int64_t)0 << ((B)-1)) & -(4 * 4)))
+ (std::abs(D) < (~(~(int64_t)0 << ((B)-1)) & -(4 * 4)))
HexagonAbsoluteStub::HexagonAbsoluteStub(bool pIsOutputPIC)
: Stub(), m_Name("HexagonTrampoline"), m_pData(NULL), m_Size(0x0) {
diff --git a/tools/mcld/include/mcld/DynamicSectionOptions.h b/tools/mcld/include/mcld/DynamicSectionOptions.h
index 67e7c40..2902118 100644
--- a/tools/mcld/include/mcld/DynamicSectionOptions.h
+++ b/tools/mcld/include/mcld/DynamicSectionOptions.h
@@ -34,6 +34,7 @@ class DynamicSectionOptions {
llvm::cl::list<ZOption, bool, llvm::cl::parser<ZOption> >& m_ZOptionList;
llvm::cl::opt<std::string>& m_Dyld;
llvm::cl::opt<bool>& m_EnableNewDTags;
+ llvm::cl::opt<unsigned>& m_NumSpareDTags;
llvm::cl::list<std::string>& m_Auxiliary;
llvm::cl::opt<std::string>& m_Filter;
diff --git a/tools/mcld/lib/DynamicSectionOptions.cpp b/tools/mcld/lib/DynamicSectionOptions.cpp
index 6bd8ccd..958a94d 100644
--- a/tools/mcld/lib/DynamicSectionOptions.cpp
+++ b/tools/mcld/lib/DynamicSectionOptions.cpp
@@ -66,6 +66,11 @@ llvm::cl::opt<bool> ArgEnableNewDTags(
llvm::cl::desc("Enable use of DT_RUNPATH and DT_FLAGS"),
llvm::cl::init(false));
+llvm::cl::opt<unsigned> ArgNumSpareDTags(
+ "spare-dynamic-tags",
+ llvm::cl::desc("Set the number of spare dyanmic tags (DT_NULL)"),
+ llvm::cl::init(5));
+
// Not supported yet {
llvm::cl::list<std::string> ArgAuxiliary(
"f",
@@ -105,6 +110,7 @@ DynamicSectionOptions::DynamicSectionOptions()
m_ZOptionList(ArgZOptionList),
m_Dyld(ArgDyld),
m_EnableNewDTags(ArgEnableNewDTags),
+ m_NumSpareDTags(ArgNumSpareDTags),
m_Auxiliary(ArgAuxiliary),
m_Filter(ArgFilter) {
}
@@ -144,6 +150,9 @@ bool DynamicSectionOptions::parse(LinkerConfig& pConfig,
// set --enable-new-dtags
pConfig.options().setNewDTags(m_EnableNewDTags);
+ // set --spare-dyanmic-tags
+ pConfig.options().setNumSpareDTags(m_NumSpareDTags);
+
// set --auxiliary, -f
llvm::cl::list<std::string>::iterator aux;
llvm::cl::list<std::string>::iterator auxEnd = m_Auxiliary.end();