forked from OSchip/llvm-project
[ELF][ARM] Revert Redesign of .ARM.exidx handling to use a SyntheticSection
There is a reproducible buildbot failure (segfault) on the 2 stage clang-cmake-armv8-lld bot. Reverting while I investigate. Differential Revision: https://reviews.llvm.org/D59216 llvm-svn: 356684
This commit is contained in:
parent
4719502941
commit
54dab70bb7
|
@ -289,9 +289,7 @@ void OutputSection::finalize() {
|
|||
// SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
|
||||
// need to translate the InputSection sh_link to the OutputSection sh_link,
|
||||
// all InputSections in the OutputSection have the same dependency.
|
||||
if (auto *EX = dyn_cast<ARMExidxSyntheticSection>(First))
|
||||
Link = EX->getLinkOrderDep()->getParent()->SectionIndex;
|
||||
else if (auto *D = First->getLinkOrderDep())
|
||||
if (auto *D = First->getLinkOrderDep())
|
||||
Link = D->getParent()->SectionIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -3052,183 +3052,33 @@ MipsRldMapSection::MipsRldMapSection()
|
|||
: SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize,
|
||||
".rld_map") {}
|
||||
|
||||
ARMExidxSyntheticSection::ARMExidxSyntheticSection()
|
||||
ARMExidxSentinelSection::ARMExidxSentinelSection()
|
||||
: SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX,
|
||||
Config->Wordsize, ".ARM.exidx") {
|
||||
for (InputSectionBase *&IS : InputSections) {
|
||||
if (isa<InputSection>(IS) && IS->Type == SHT_ARM_EXIDX) {
|
||||
ExidxSections.push_back(cast<InputSection>(IS));
|
||||
IS = nullptr;
|
||||
} else if (IS->Live && isa<InputSection>(IS) &&
|
||||
IS->kind() != SectionBase::Synthetic &&
|
||||
(IS->Flags & SHF_ALLOC) && (IS->Flags & SHF_EXECINSTR) &&
|
||||
IS->getSize() > 0) {
|
||||
ExecutableSections.push_back(cast<InputSection>(IS));
|
||||
}
|
||||
}
|
||||
setSizeAndOffsets();
|
||||
Config->Wordsize, ".ARM.exidx") {}
|
||||
|
||||
std::vector<InputSectionBase *> &V = InputSections;
|
||||
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
|
||||
// Write a terminating sentinel entry to the end of the .ARM.exidx table.
|
||||
// This section will have been sorted last in the .ARM.exidx table.
|
||||
// This table entry will have the form:
|
||||
// | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND |
|
||||
// The sentinel must have the PREL31 value of an address higher than any
|
||||
// address described by any other table entry.
|
||||
void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
|
||||
assert(Highest);
|
||||
uint64_t S = Highest->getVA(Highest->getSize());
|
||||
uint64_t P = getVA();
|
||||
Target->relocateOne(Buf, R_ARM_PREL31, S - P);
|
||||
write32le(Buf + 4, 1);
|
||||
}
|
||||
|
||||
static InputSection *findExidxSection(InputSection *IS) {
|
||||
for (InputSection *D : IS->DependentSections)
|
||||
if (D->Type == SHT_ARM_EXIDX)
|
||||
return D;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ARMExidxSyntheticSection::setSizeAndOffsets() {
|
||||
size_t Offset = 0;
|
||||
Size = 0;
|
||||
for (InputSection *IS : ExecutableSections) {
|
||||
if (InputSection *D = findExidxSection(IS)) {
|
||||
D->OutSecOff = Offset;
|
||||
D->Parent = getParent();
|
||||
Offset += D->getSize();
|
||||
Empty = false;
|
||||
} else {
|
||||
Offset += 8;
|
||||
}
|
||||
}
|
||||
// Size includes Sentinel.
|
||||
Size = Offset + 8;
|
||||
}
|
||||
|
||||
// References to .ARM.Extab Sections have bit 31 clear and are not the
|
||||
// special EXIDX_CANTUNWIND bit-pattern.
|
||||
static bool isExtabRef(uint32_t Unwind) {
|
||||
return (Unwind & 0x80000000) == 0 && Unwind != 0x1;
|
||||
}
|
||||
|
||||
// Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx
|
||||
// section Prev, where Cur follows Prev in the table. This can be done if the
|
||||
// unwinding instructions in Cur are identical to Prev. Linker generated
|
||||
// EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an
|
||||
// InputSection.
|
||||
static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
|
||||
|
||||
struct ExidxEntry {
|
||||
ulittle32_t Fn;
|
||||
ulittle32_t Unwind;
|
||||
};
|
||||
// Get the last table Entry from the previous .ARM.exidx section. If Prev is
|
||||
// nullptr then it will be a synthesized EXIDX_CANTUNWIND entry.
|
||||
ExidxEntry PrevEntry = {ulittle32_t(0), ulittle32_t(1)};
|
||||
if (Prev)
|
||||
PrevEntry = Prev->getDataAs<ExidxEntry>().back();
|
||||
if (isExtabRef(PrevEntry.Unwind))
|
||||
return false;
|
||||
|
||||
// We consider the unwind instructions of an .ARM.exidx table entry
|
||||
// a duplicate if the previous unwind instructions if:
|
||||
// - Both are the special EXIDX_CANTUNWIND.
|
||||
// - Both are the same inline unwind instructions.
|
||||
// We do not attempt to follow and check links into .ARM.extab tables as
|
||||
// consecutive identical entries are rare and the effort to check that they
|
||||
// are identical is high.
|
||||
|
||||
// If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry.
|
||||
if (Cur == nullptr)
|
||||
return PrevEntry.Unwind == 1;
|
||||
|
||||
for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
|
||||
if (isExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
|
||||
// The sentinel has to be removed if there are no other .ARM.exidx entries.
|
||||
bool ARMExidxSentinelSection::empty() const {
|
||||
for (InputSection *IS : getInputSections(getParent()))
|
||||
if (!isa<ARMExidxSentinelSection>(IS))
|
||||
return false;
|
||||
|
||||
// All table entries in this .ARM.exidx Section can be merged into the
|
||||
// previous Section.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The .ARM.exidx table must be sorted in ascending order of the address of the
|
||||
// functions the table describes. Optionally duplicate adjacent table entries
|
||||
// can be removed. At the end of the function the ExecutableSections must be
|
||||
// sorted in ascending order of address, Sentinel is set to the InputSection
|
||||
// with the highest address and any InputSections that have mergeable
|
||||
// .ARM.exidx table entries are removed from it.
|
||||
void ARMExidxSyntheticSection::finalizeContents() {
|
||||
// Sort the executable sections that may or may not have associated
|
||||
// .ARM.exidx sections by order of ascending address. This requires the
|
||||
// relative positions of InputSections to be known.
|
||||
auto CompareByFilePosition = [](const InputSection *A,
|
||||
const InputSection *B) {
|
||||
OutputSection *AOut = A->getParent();
|
||||
OutputSection *BOut = B->getParent();
|
||||
|
||||
if (AOut != BOut)
|
||||
return AOut->SectionIndex < BOut->SectionIndex;
|
||||
return A->OutSecOff < B->OutSecOff;
|
||||
};
|
||||
std::stable_sort(ExecutableSections.begin(), ExecutableSections.end(),
|
||||
CompareByFilePosition);
|
||||
Sentinel = ExecutableSections.back();
|
||||
// Optionally merge adjacent duplicate entries.
|
||||
if (Config->MergeArmExidx) {
|
||||
std::vector<InputSection *> SelectedSections;
|
||||
SelectedSections.reserve(ExecutableSections.size());
|
||||
SelectedSections.push_back(ExecutableSections[0]);
|
||||
size_t Prev = 0;
|
||||
for (size_t I = 1; I < ExecutableSections.size(); ++I) {
|
||||
InputSection *EX1 = findExidxSection(ExecutableSections[Prev]);
|
||||
InputSection *EX2 = findExidxSection(ExecutableSections[I]);
|
||||
if (!isDuplicateArmExidxSec(EX1, EX2)) {
|
||||
SelectedSections.push_back(ExecutableSections[I]);
|
||||
Prev = I;
|
||||
}
|
||||
}
|
||||
ExecutableSections = std::move(SelectedSections);
|
||||
}
|
||||
setSizeAndOffsets();
|
||||
}
|
||||
|
||||
InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const {
|
||||
for (InputSection *IS : ExecutableSections)
|
||||
if (findExidxSection(IS))
|
||||
return IS;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// To write the .ARM.exidx table from the ExecutableSections we have three cases
|
||||
// 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections.
|
||||
// We write the .ARM.exidx section contents and apply its relocations.
|
||||
// 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We
|
||||
// must write the contents of an EXIDX_CANTUNWIND directly. We use the
|
||||
// start of the InputSection as the purpose of the linker generated
|
||||
// section is to terminate the address range of the previous entry.
|
||||
// 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of
|
||||
// the table to terminate the address range of the final entry.
|
||||
void ARMExidxSyntheticSection::writeTo(uint8_t *Buf) {
|
||||
|
||||
const uint8_t CantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target
|
||||
1, 0, 0, 0}; // EXIDX_CANTUNWIND
|
||||
|
||||
uint64_t Offset = 0;
|
||||
for (InputSection *IS : ExecutableSections) {
|
||||
assert(IS->getParent() != nullptr);
|
||||
if (InputSection *D = findExidxSection(IS)) {
|
||||
memcpy(Buf + Offset, D->data().data(), D->data().size());
|
||||
D->relocateAlloc(Buf, Buf + D->getSize());
|
||||
Offset += D->getSize();
|
||||
} else {
|
||||
// A Linker generated CANTUNWIND section.
|
||||
memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData));
|
||||
uint64_t S = IS->getVA();
|
||||
uint64_t P = getVA() + Offset;
|
||||
Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P);
|
||||
Offset += 8;
|
||||
}
|
||||
}
|
||||
// Write Sentinel.
|
||||
memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData));
|
||||
uint64_t S = Sentinel->getVA(Sentinel->getSize());
|
||||
uint64_t P = getVA() + Offset;
|
||||
Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P);
|
||||
assert(Size == Offset + 8);
|
||||
}
|
||||
|
||||
bool ARMExidxSyntheticSection::classof(const SectionBase *D) {
|
||||
bool ARMExidxSentinelSection::classof(const SectionBase *D) {
|
||||
return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX;
|
||||
}
|
||||
|
||||
|
|
|
@ -936,76 +936,19 @@ public:
|
|||
void writeTo(uint8_t *Buf) override {}
|
||||
};
|
||||
|
||||
// Representation of the combined .ARM.Exidx input sections. We process these
|
||||
// as a SyntheticSection like .eh_frame as we need to merge duplicate entries
|
||||
// and add terminating sentinel entries.
|
||||
//
|
||||
// The .ARM.exidx input sections after SHF_LINK_ORDER processing is done form
|
||||
// a table that the unwinder can derive (Addresses are encoded as offsets from
|
||||
// table):
|
||||
// | Address of function | Unwind instructions for function |
|
||||
// where the unwind instructions are either a small number of unwind or the
|
||||
// special EXIDX_CANTUNWIND entry representing no unwinding information.
|
||||
// When an exception is thrown from an address A, the unwinder searches the
|
||||
// table for the closest table entry with Address of function <= A. This means
|
||||
// that for two consecutive table entries:
|
||||
// | A1 | U1 |
|
||||
// | A2 | U2 |
|
||||
// The range of addresses described by U1 is [A1, A2)
|
||||
//
|
||||
// There are two cases where we need a linker generated table entry to fixup
|
||||
// the address ranges in the table
|
||||
// Case 1:
|
||||
// - A sentinel entry added with an address higher than all
|
||||
// executable sections. This was needed to work around libunwind bug pr31091.
|
||||
// - After address assignment we need to find the highest addressed executable
|
||||
// section and use the limit of that section so that the unwinder never
|
||||
// matches it.
|
||||
// Case 2:
|
||||
// - InputSections without a .ARM.exidx section (usually from Assembly)
|
||||
// need a table entry so that they terminate the range of the previously
|
||||
// function. This is pr40277.
|
||||
//
|
||||
// Instead of storing pointers to the .ARM.exidx InputSections from
|
||||
// InputObjects, we store pointers to the executable sections that need
|
||||
// .ARM.exidx sections. We can then use the dependentSections of these to
|
||||
// either find the .ARM.exidx section or know that we need to generate one.
|
||||
class ARMExidxSyntheticSection : public SyntheticSection {
|
||||
class ARMExidxSentinelSection : public SyntheticSection {
|
||||
public:
|
||||
ARMExidxSyntheticSection();
|
||||
size_t getSize() const override { return Size; }
|
||||
ARMExidxSentinelSection();
|
||||
size_t getSize() const override { return 8; }
|
||||
void writeTo(uint8_t *Buf) override;
|
||||
bool empty() const override { return Empty; }
|
||||
// Sort and remove duplicate entries.
|
||||
void finalizeContents() override;
|
||||
InputSection *getLinkOrderDep() const;
|
||||
bool empty() const override;
|
||||
|
||||
static bool classof(const SectionBase *D);
|
||||
|
||||
// Links to the ARMExidxSections so we can transfer the relocations once the
|
||||
// layout is known.
|
||||
std::vector<InputSection *> ExidxSections;
|
||||
|
||||
private:
|
||||
// Derive Size from contents of ExecutableSections, including any linker
|
||||
// generated sentinels. Also set the OutSecOff of the ExidxSections.
|
||||
void setSizeAndOffsets();
|
||||
size_t Size;
|
||||
|
||||
// Empty if ExecutableSections contains no dependent .ARM.exidx sections.
|
||||
bool Empty = true;
|
||||
|
||||
// Instead of storing pointers to the .ARM.exidx InputSections from
|
||||
// InputObjects, we store pointers to the executable sections that need
|
||||
// .ARM.exidx sections. We can then use the dependentSections of these to
|
||||
// either find the .ARM.exidx section or know that we need to generate one.
|
||||
std::vector<InputSection *> ExecutableSections;
|
||||
|
||||
// The executable InputSection with the highest address to use for the
|
||||
// sentinel. We store separately from ExecutableSections as merging of
|
||||
// duplicate entries may mean this InputSection is removed from
|
||||
// ExecutableSections.
|
||||
InputSection *Sentinel = nullptr;
|
||||
// The last section referenced by a regular .ARM.exidx section.
|
||||
// It is found and filled in Writer<ELFT>::resolveShfLinkOrder().
|
||||
// The sentinel points at the end of that section.
|
||||
InputSection *Highest = nullptr;
|
||||
};
|
||||
|
||||
// A container for one or more linker generated thunks. Instances of these
|
||||
|
@ -1060,7 +1003,6 @@ Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,
|
|||
// Linker generated sections which can be used as inputs.
|
||||
struct InStruct {
|
||||
InputSection *ARMAttributes;
|
||||
ARMExidxSyntheticSection *ARMExidx;
|
||||
BssSection *Bss;
|
||||
BssSection *BssRelRo;
|
||||
BuildIdSection *BuildId;
|
||||
|
|
|
@ -435,12 +435,10 @@ template <class ELFT> static void createSyntheticSections() {
|
|||
if (In.StrTab)
|
||||
Add(In.StrTab);
|
||||
|
||||
if (Config->EMachine == EM_ARM && !Config->Relocatable) {
|
||||
// The ARMExidxsyntheticsection replaces all the individual .ARM.exidx
|
||||
// InputSections.
|
||||
In.ARMExidx = make<ARMExidxSyntheticSection>();
|
||||
Add(In.ARMExidx);
|
||||
}
|
||||
if (Config->EMachine == EM_ARM && !Config->Relocatable)
|
||||
// Add a sentinel to terminate .ARM.exidx. It helps an unwinder
|
||||
// to find the exact address range of the last entry.
|
||||
Add(make<ARMExidxSentinelSection>());
|
||||
}
|
||||
|
||||
// The main function of the writer.
|
||||
|
@ -923,9 +921,6 @@ void Writer<ELFT>::forEachRelSec(
|
|||
Fn(*IS);
|
||||
for (EhInputSection *ES : In.EhFrame->Sections)
|
||||
Fn(*ES);
|
||||
if (In.ARMExidx)
|
||||
for (InputSection *Ex : In.ARMExidx->ExidxSections)
|
||||
Fn(*Ex);
|
||||
}
|
||||
|
||||
// This function generates assignments for predefined symbols (e.g. _end or
|
||||
|
@ -1388,6 +1383,11 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
|
|||
}
|
||||
|
||||
static bool compareByFilePosition(InputSection *A, InputSection *B) {
|
||||
// Synthetic, i. e. a sentinel section, should go last.
|
||||
if (A->kind() == InputSectionBase::Synthetic ||
|
||||
B->kind() == InputSectionBase::Synthetic)
|
||||
return A->kind() != InputSectionBase::Synthetic;
|
||||
|
||||
InputSection *LA = A->getLinkOrderDep();
|
||||
InputSection *LB = B->getLinkOrderDep();
|
||||
OutputSection *AOut = LA->getParent();
|
||||
|
@ -1398,6 +1398,53 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) {
|
|||
return LA->OutSecOff < LB->OutSecOff;
|
||||
}
|
||||
|
||||
// This function is used by the --merge-exidx-entries to detect duplicate
|
||||
// .ARM.exidx sections. It is Arm only.
|
||||
//
|
||||
// The .ARM.exidx section is of the form:
|
||||
// | PREL31 offset to function | Unwind instructions for function |
|
||||
// where the unwind instructions are either a small number of unwind
|
||||
// instructions inlined into the table entry, the special CANT_UNWIND value of
|
||||
// 0x1 or a PREL31 offset into a .ARM.extab Section that contains unwind
|
||||
// instructions.
|
||||
//
|
||||
// We return true if all the unwind instructions in the .ARM.exidx entries of
|
||||
// Cur can be merged into the last entry of Prev.
|
||||
static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
|
||||
|
||||
// References to .ARM.Extab Sections have bit 31 clear and are not the
|
||||
// special EXIDX_CANTUNWIND bit-pattern.
|
||||
auto IsExtabRef = [](uint32_t Unwind) {
|
||||
return (Unwind & 0x80000000) == 0 && Unwind != 0x1;
|
||||
};
|
||||
|
||||
struct ExidxEntry {
|
||||
ulittle32_t Fn;
|
||||
ulittle32_t Unwind;
|
||||
};
|
||||
|
||||
// Get the last table Entry from the previous .ARM.exidx section.
|
||||
const ExidxEntry &PrevEntry = Prev->getDataAs<ExidxEntry>().back();
|
||||
if (IsExtabRef(PrevEntry.Unwind))
|
||||
return false;
|
||||
|
||||
// We consider the unwind instructions of an .ARM.exidx table entry
|
||||
// a duplicate if the previous unwind instructions if:
|
||||
// - Both are the special EXIDX_CANTUNWIND.
|
||||
// - Both are the same inline unwind instructions.
|
||||
// We do not attempt to follow and check links into .ARM.extab tables as
|
||||
// consecutive identical entries are rare and the effort to check that they
|
||||
// are identical is high.
|
||||
|
||||
for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())
|
||||
if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)
|
||||
return false;
|
||||
|
||||
// All table entries in this .ARM.exidx Section can be merged into the
|
||||
// previous Section.
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
|
||||
for (OutputSection *Sec : OutputSections) {
|
||||
if (!(Sec->Flags & SHF_LINK_ORDER))
|
||||
|
@ -1415,17 +1462,46 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
|
||||
// this processing inside the ARMExidxsyntheticsection::finalizeContents().
|
||||
if (!Config->Relocatable && Config->EMachine == EM_ARM &&
|
||||
Sec->Type == SHT_ARM_EXIDX)
|
||||
continue;
|
||||
|
||||
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
|
||||
|
||||
if (!Config->Relocatable && Config->EMachine == EM_ARM &&
|
||||
Sec->Type == SHT_ARM_EXIDX) {
|
||||
|
||||
if (auto *Sentinel = dyn_cast<ARMExidxSentinelSection>(Sections.back())) {
|
||||
assert(Sections.size() >= 2 &&
|
||||
"We should create a sentinel section only if there are "
|
||||
"alive regular exidx sections.");
|
||||
|
||||
// The last executable section is required to fill the sentinel.
|
||||
// Remember it here so that we don't have to find it again.
|
||||
Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
|
||||
}
|
||||
|
||||
// The EHABI for the Arm Architecture permits consecutive identical
|
||||
// table entries to be merged. We use a simple implementation that
|
||||
// removes a .ARM.exidx Input Section if it can be merged into the
|
||||
// previous one. This does not require any rewriting of InputSection
|
||||
// contents but misses opportunities for fine grained deduplication
|
||||
// where only a subset of the InputSection contents can be merged.
|
||||
if (Config->MergeArmExidx) {
|
||||
size_t Prev = 0;
|
||||
// The last one is a sentinel entry which should not be removed.
|
||||
for (size_t I = 1; I < Sections.size() - 1; ++I) {
|
||||
if (isDuplicateArmExidxSec(Sections[Prev], Sections[I]))
|
||||
Sections[I] = nullptr;
|
||||
else
|
||||
Prev = I;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int I = 0, N = Sections.size(); I < N; ++I)
|
||||
*ScriptSections[I] = Sections[I];
|
||||
|
||||
// Remove the Sections we marked as duplicate earlier.
|
||||
for (BaseCommand *Base : Sec->SectionCommands)
|
||||
if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
|
||||
llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1695,7 +1771,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
// Dynamic section must be the last one in this list and dynamic
|
||||
// symbol table section (DynSymTab) must be the first one.
|
||||
finalizeSynthetic(In.DynSymTab);
|
||||
finalizeSynthetic(In.ARMExidx);
|
||||
finalizeSynthetic(In.Bss);
|
||||
finalizeSynthetic(In.BssRelRo);
|
||||
finalizeSynthetic(In.GnuHashTab);
|
||||
|
@ -1722,8 +1797,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
if (!Script->HasSectionsCommand && !Config->Relocatable)
|
||||
fixSectionAlignments();
|
||||
|
||||
// SHFLinkOrder processing must be processed after relative section placements are
|
||||
// known but before addresses are allocated.
|
||||
// After link order processing .ARM.exidx sections can be deduplicated, which
|
||||
// needs to be resolved before any other address dependent operation.
|
||||
resolveShfLinkOrder();
|
||||
|
||||
// Jump instructions in many ISAs have small displacements, and therefore they
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj --arm-add-build-attributes -o %t.o
|
||||
// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o
|
||||
// RUN: echo "SECTIONS { \
|
||||
// RUN: .text : { *(.text) } \
|
||||
// RUN: .prel.test : { *(.ARM.exidx) } \
|
||||
// RUN: .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \
|
||||
// RUN: .TEST1 : { *(.TEST1) } } " > %t.script
|
||||
// RUN: ld.lld --script %t.script %t.o -o %t
|
||||
// RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s
|
||||
|
@ -46,14 +47,17 @@ __aeabi_unwind_cpp_pr0:
|
|||
// The expected value of the exception table is
|
||||
// Word0 0 in bit 31, -4 encoded in 31-bit signed offset
|
||||
// Word1 Inline table entry EHT Inline Personality Routine #0
|
||||
// Word3 0 in bit 31, +10 encoded in 31-bit signed offset
|
||||
// Word4 Inline table entry EHT Inline Personality Routine #0
|
||||
// set vsp = r11
|
||||
// pop r11, r14
|
||||
// Word5 Sentinel +18 EXIDX_CANTUNWIND
|
||||
|
||||
// CHECK: Name: .prel.test
|
||||
// CHECK: SectionData (
|
||||
// CHECK: 0000: FCFFFF7F B0B0B080 10000000 80849B80
|
||||
// CHECK: 0010: 18000000 01000000
|
||||
// CHECK: 0000: FCFFFF7F B0B0B080
|
||||
// CHECK: )
|
||||
|
||||
// The expected value of the exception table is
|
||||
// Word0 0 in bit 31, +8 encoded in 31-bit signed offset
|
||||
// Word1 Inline table entry EHT Inline Personality Routine #0
|
||||
// set vsp = r11
|
||||
// pop r11, r14
|
||||
// CHECK: Name: .prel.test.TEST1
|
||||
// CHECK: SectionData (
|
||||
// CHECK: 0000: 08000000 80849B80
|
||||
// CHECK: )
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t
|
||||
// RUN: ld-lld %t --no-merge-exidx-entries -o %t2
|
||||
// RUN: llvm-objdump -s %t2 | FileCheck %s
|
||||
// RUN: ld-lld %t -o %t3
|
||||
// RUN: llvm-objdump -s %t3 | FileCheck %s -check-prefix=CHECK-MERGE
|
||||
|
||||
// The ARM.exidx section is a table of 8-byte entries of the form:
|
||||
// | PREL31 Relocation to start of function | Unwinding information |
|
||||
// The range of addresses covered by the table entry is terminated by the
|
||||
// next table entry. This means that an executable section without a .ARM.exidx
|
||||
// section does not terminate the range of addresses. To fix this the linker
|
||||
// synthesises an EXIDX_CANTUNWIND entry for each section wihout a .ARM.exidx
|
||||
// section.
|
||||
|
||||
.syntax unified
|
||||
|
||||
// Expect inline unwind instructions
|
||||
.section .text.01, "ax", %progbits
|
||||
.global f1
|
||||
f1:
|
||||
.fnstart
|
||||
bx lr
|
||||
.save {r7, lr}
|
||||
.setfp r7, sp, #0
|
||||
.fnend
|
||||
|
||||
// Expect no unwind information from assembler. The linker must
|
||||
// synthesise an EXIDX_CANTUNWIND entry to prevent an exception
|
||||
// thrown through f2 from matching against the unwind instructions
|
||||
// for f1.
|
||||
.section .text.02, "ax", %progbits
|
||||
.global f2
|
||||
f2:
|
||||
bx lr
|
||||
|
||||
|
||||
// Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker
|
||||
// generated EXIDX_CANTUNWIND as if the assembler had generated it.
|
||||
.section .text.03, "ax",%progbits
|
||||
.global f3
|
||||
f3:
|
||||
.fnstart
|
||||
bx lr
|
||||
.cantunwind
|
||||
.fnend
|
||||
|
||||
// Dummy implementation of personality routines to satisfy reference
|
||||
// from exception tables, linker will generate EXIDX_CANTUNWIND.
|
||||
.section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
|
||||
.global __aeabi_unwind_cpp_pr0
|
||||
__aeabi_unwind_cpp_pr0:
|
||||
bx lr
|
||||
|
||||
// f1, f2
|
||||
// CHECK: 100d4 2c0f0000 08849780 280f0000 01000000
|
||||
// f3, __aeabi_unwind_cpp_pr0
|
||||
// CHECK-NEXT: 100e4 240f0000 01000000 200f0000 01000000
|
||||
// sentinel
|
||||
// CHECK-NEXT: 100f4 1c0f0000 01000000
|
||||
|
||||
// f1, (f2, f3, __aeabi_unwind_cpp_pr0)
|
||||
// CHECK-MERGE: 100d4 2c0f0000 08849780 280f0000 01000000
|
||||
// sentinel
|
||||
// CHECK-MERGE-NEXT: 100e4 2c0f0000 01000000
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld %t -o %t2
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld %t -o %t2 2>&1
|
||||
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
|
||||
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
|
||||
// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
|
||||
|
@ -66,14 +66,15 @@ _start:
|
|||
// CHECK: __aeabi_unwind_cpp_pr0:
|
||||
// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr
|
||||
|
||||
// 100d4 + f2c = 11000 = main (linker generated cantunwind)
|
||||
// 100dc + f30 = 1100c = func1 (inline unwinding data)
|
||||
// CHECK-EXIDX: 100d4 2c0f0000 01000000 300f0000 08849780
|
||||
// 100e4 + f2c = 11010 = func2 (100e8 + 14 = 100fc = .ARM.extab entry)
|
||||
// 100ec + f28 = 11014 = __gcc_personality_v0 (linker generated cantunwind)
|
||||
// CHECK-EXIDX-NEXT: 100e4 2c0f0000 14000000 280f0000 01000000
|
||||
// 100f4 + f28 = 1101c = sentinel
|
||||
// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000
|
||||
// CHECK-EXIDX: Contents of section .ARM.exidx:
|
||||
// 100d4 + f38 = 1100c = func1 (inline unwinding data)
|
||||
// 100dc + f34 = 11010 = func2 (100e0 + c = 100ec = .ARM.extab entry)
|
||||
// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 0c000000
|
||||
// 100e4 + f30 = 11014 = terminate = func2 + sizeof(func2)
|
||||
// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000
|
||||
// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:
|
||||
// 100ec + f28 = 11014 = __gxx_personality_v0
|
||||
// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000
|
||||
|
||||
// CHECK-PT: Name: .ARM.exidx
|
||||
// CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001)
|
||||
|
@ -83,14 +84,14 @@ _start:
|
|||
// CHECK-PT-NEXT: ]
|
||||
// CHECK-PT-NEXT: Address: 0x100D4
|
||||
// CHECK-PT-NEXT: Offset: 0xD4
|
||||
// CHECK-PT-NEXT: Size: 40
|
||||
// CHECK-PT-NEXT: Size: 24
|
||||
|
||||
// CHECK-PT: Type: PT_ARM_EXIDX (0x70000001)
|
||||
// CHECK-PT-NEXT: Offset: 0xD4
|
||||
// CHECK-PT-NEXT: VirtualAddress: 0x100D4
|
||||
// CHECK-PT-NEXT: PhysicalAddress: 0x100D4
|
||||
// CHECK-PT-NEXT: FileSize: 40
|
||||
// CHECK-PT-NEXT: MemSize: 40
|
||||
// CHECK-PT-NEXT: FileSize: 24
|
||||
// CHECK-PT-NEXT: MemSize: 24
|
||||
// CHECK-PT-NEXT: Flags [ (0x4)
|
||||
// CHECK-PT-NEXT: PF_R (0x4)
|
||||
// CHECK-PT-NEXT: ]
|
||||
|
|
|
@ -1,29 +1,27 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld %t --no-merge-exidx-entries -o %t2
|
||||
// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s
|
||||
// RUN: ld.lld %t -o %t3
|
||||
// RUN: llvm-objdump -s %t3 | FileCheck %s
|
||||
|
||||
// Test that lld can at least remove duplicate .ARM.exidx sections. A more
|
||||
// fine grained implementation will be able to remove duplicate entries within
|
||||
// a .ARM.exidx section.
|
||||
|
||||
// With duplicate entries
|
||||
// CHECK-DUPS: Contents of section .ARM.exidx:
|
||||
// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780
|
||||
// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 24000000
|
||||
// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000
|
||||
// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780
|
||||
// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 14000000
|
||||
// CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 01000000
|
||||
// CHECK-DUPS-NEXT: Contents of section .ARM.extab:
|
||||
|
||||
// After duplicate entry removal
|
||||
// CHECK: Contents of section .ARM.exidx:
|
||||
// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780
|
||||
// CHECK-NEXT: 100e4 380f0000 1c000000 340f0000 20000000
|
||||
// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000
|
||||
// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780
|
||||
// CHECK-NEXT: 100e4 380f0000 14000000 340f0000 18000000
|
||||
// CHECK-NEXT: 100f4 300f0000 01000000
|
||||
// CHECK-NEXT: Contents of section .ARM.extab:
|
||||
.syntax unified
|
||||
|
||||
|
@ -115,9 +113,8 @@ f8:
|
|||
.long 0
|
||||
.fnend
|
||||
|
||||
// Dummy implementation of personality routines to satisfy reference from
|
||||
// exception tables
|
||||
// Expect Linker generated EXIDX_CANTUNWIND tables
|
||||
// Dummy implementation of personality routines to satisfy reference from
|
||||
// exception tables
|
||||
.section .text.__gcc_personality_v0, "ax", %progbits
|
||||
.global __gxx_personality_v0
|
||||
__gxx_personality_v0:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1
|
||||
// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
|
||||
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
|
||||
|
@ -111,15 +111,14 @@ _start:
|
|||
// CHECK-NOT: __gxx_personality_v1
|
||||
|
||||
// CHECK-EXIDX: Contents of section .ARM.exidx:
|
||||
// 100d4 + f2c = 11000
|
||||
// 100dc + f30 = 1100c = func1
|
||||
// CHECK-EXIDX-NEXT: 100d4 2c0f0000 01000000 300f0000 08849780
|
||||
// 100e4 + f2c = 11010 = func2 (100e8 + 1c = 10104 = .ARM.extab)
|
||||
// 100ec + f28 = 11014 = __gxx_personality_v0
|
||||
// CHECK-EXIDX-NEXT: 100e4 2c0f0000 1c000000 280f0000 01000000
|
||||
// 100f4 + f24 = 11018 = __aeabi_unwind_cpp_pr0
|
||||
// 100fc + f20 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)
|
||||
// CHECK-EXIDX-NEXT: 100f4 240f0000 01000000 200f0000 01000000
|
||||
// 100d4 + f38 = 1100c = func1
|
||||
// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab)
|
||||
// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 1c000000
|
||||
// 100e4 + f30 = 11014 = __gxx_personality_v0
|
||||
// 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0
|
||||
// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000
|
||||
// 100f4 + f28 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)
|
||||
// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000
|
||||
// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:
|
||||
// 10104 + f10 = 11014 = __gxx_personality_v0
|
||||
// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000
|
||||
// 100fc + f18 = 11014 = __gxx_personality_v0
|
||||
// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t
|
||||
// RUN: ld-lld %t -o %t2
|
||||
// RUN: llvm-objdump -s %t2 | FileCheck %s
|
||||
|
||||
// We do not want to generate missing EXIDX_CANTUNWIND entries if there are no
|
||||
// input .ARM.exidx sections.
|
||||
|
||||
// CHECK-NOT: .ARM.exidx
|
||||
.syntax unified
|
||||
.text
|
||||
.globl _start
|
||||
.type _start, %function
|
||||
_start:
|
||||
bx lr
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
// REQUIRES: arm
|
||||
// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
|
||||
// RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1
|
||||
// RUN: llvm-readobj --relocations %t2 | FileCheck %s
|
||||
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB-NEXT %s
|
||||
// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s
|
||||
|
||||
// Check that the relative R_ARM_PREL31 relocation can access a PLT entry
|
||||
// for when the personality routine is referenced from a shared library.
|
||||
|
@ -41,5 +41,5 @@ __aeabi_unwind_cpp_pr0:
|
|||
// CHECK-NEXT: 0x300C R_ARM_JUMP_SLOT __gxx_personality_v0
|
||||
|
||||
// CHECK-EXTAB: Contents of section .ARM.extab:
|
||||
// 0x0238 + 0xdf8 = 0x1030 = __gxx_personality_v0(PLT)
|
||||
// CHECK-EXTAB-NEXT: 0238 f80d0000 b0b0b000 00000000
|
||||
// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT)
|
||||
// CHECK-EXTAB-NEXT: 0230 000e0000 b0b0b000 00000000
|
||||
|
|
Loading…
Reference in New Issue