Add r224985 back with two fixes.
One is that AArch64 has additional restrictions on when local relocations can
be used. We have to take those into consideration when deciding to put a L
symbol in the symbol table or not.
The other is that ld64 requires the relocations to cstring to use linker
visible symbols on AArch64.
Thanks to Michael Zolotukhin for testing this!
Remove doesSectionRequireSymbols.
In an assembly expression like
bar:
.long L0 + 1
the intended semantics is that bar will contain a pointer one byte past L0.
In sections that are merged by content (strings, 4 byte constants, etc), a
single position in the section doesn't give the linker enough information.
For example, it would not be able to tell a relocation must point to the
end of a string, since that would look just like the start of the next.
The solution used in ELF to use relocation with symbols if there is a non-zero
addend.
In MachO before this patch we would just keep all symbols in some sections.
This would miss some cases (only cstrings on x86_64 were implemented) and was
inefficient since most relocations have an addend of 0 and can be represented
without the symbol.
This patch implements the non-zero addend logic for MachO too.
llvm-svn: 225644
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index e4442e1..83a76dc 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -219,7 +219,7 @@
const MCSymbolData *SD, uint64_t C,
unsigned Type) const;
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
@@ -789,13 +789,11 @@
return nullptr;
}
-void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm,
+void ELFObjectWriter::RecordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- bool &IsPCRel,
- uint64_t &FixedValue) {
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
const MCSectionData *FixupSection = Fragment->getParent();
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
diff --git a/llvm/lib/MC/MCAsmInfoDarwin.cpp b/llvm/lib/MC/MCAsmInfoDarwin.cpp
index 04cc0ff..f705490 100644
--- a/llvm/lib/MC/MCAsmInfoDarwin.cpp
+++ b/llvm/lib/MC/MCAsmInfoDarwin.cpp
@@ -27,22 +27,7 @@
// contain.
// Sections holding 2 byte strings require symbols in order to be atomized.
// There is no dedicated section for 4 byte strings.
- if (SMO.getKind().isMergeable1ByteCString())
- return false;
-
- if (SMO.getSegmentName() == "__TEXT" &&
- SMO.getSectionName() == "__objc_classname" &&
- SMO.getType() == MachO::S_CSTRING_LITERALS)
- return false;
-
- if (SMO.getSegmentName() == "__TEXT" &&
- SMO.getSectionName() == "__objc_methname" &&
- SMO.getType() == MachO::S_CSTRING_LITERALS)
- return false;
-
- if (SMO.getSegmentName() == "__TEXT" &&
- SMO.getSectionName() == "__objc_methtype" &&
- SMO.getType() == MachO::S_CSTRING_LITERALS)
+ if (SMO.getType() == MachO::S_CSTRING_LITERALS)
return false;
if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring")
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 459488b..a4af21e 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -425,6 +425,16 @@
return true;
}
+void MCAssembler::addLocalUsedInReloc(const MCSymbol &Sym) {
+ assert(Sym.isTemporary());
+ LocalsUsedInReloc.insert(&Sym);
+}
+
+bool MCAssembler::isLocalUsedInReloc(const MCSymbol &Sym) const {
+ assert(Sym.isTemporary());
+ return LocalsUsedInReloc.count(&Sym);
+}
+
bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const {
// Non-temporary labels should always be visible to the linker.
if (!Symbol.isTemporary())
@@ -434,8 +444,10 @@
if (!Symbol.isInSection())
return false;
- // Otherwise, check if the section requires symbols even for temporary labels.
- return getBackend().doesSectionRequireSymbols(Symbol.getSection());
+ if (isLocalUsedInReloc(Symbol))
+ return true;
+
+ return false;
}
const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const {
diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index d3751bd..588d424 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -448,14 +448,11 @@
assert(OS.tell() - Start == Size);
}
-
-void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
+void MachObjectWriter::RecordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- bool &IsPCRel,
- uint64_t &FixedValue) {
+ const MCFixup &Fixup, MCValue Target,
+ bool &IsPCRel, uint64_t &FixedValue) {
TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup,
Target, FixedValue);
}
@@ -616,6 +613,22 @@
ExternalSymbolData[i].SymbolData->setIndex(Index++);
for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
UndefinedSymbolData[i].SymbolData->setIndex(Index++);
+
+ for (const MCSectionData &SD : Asm) {
+ std::vector<RelAndSymbol> &Relocs = Relocations[&SD];
+ for (RelAndSymbol &Rel : Relocs) {
+ if (!Rel.Sym)
+ continue;
+
+ // Set the Index and the IsExtern bit.
+ unsigned Index = Rel.Sym->getIndex();
+ assert(isInt<24>(Index));
+ if (IsLittleEndian)
+ Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (-1 << 24)) | Index | (1 << 27);
+ else
+ Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
+ }
+ }
}
void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
@@ -662,10 +675,6 @@
// Mark symbol difference expressions in variables (from .set or = directives)
// as absolute.
markAbsoluteVariableSymbols(Asm, Layout);
-
- // Compute symbol table information and bind symbol indices.
- ComputeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
- UndefinedSymbolData);
}
bool MachObjectWriter::
@@ -749,6 +758,10 @@
void MachObjectWriter::WriteObject(MCAssembler &Asm,
const MCAsmLayout &Layout) {
+ // Compute symbol table information and bind symbol indices.
+ ComputeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
+ UndefinedSymbolData);
+
unsigned NumSections = Asm.size();
const MCAssembler::VersionMinInfoType &VersionInfo =
Layout.getAssembler().getVersionMinInfo();
@@ -839,7 +852,7 @@
uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
for (MCAssembler::const_iterator it = Asm.begin(),
ie = Asm.end(); it != ie; ++it) {
- std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
+ std::vector<RelAndSymbol> &Relocs = Relocations[it];
unsigned NumRelocs = Relocs.size();
uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
@@ -933,10 +946,10 @@
ie = Asm.end(); it != ie; ++it) {
// Write the section relocation entries, in reverse order to match 'as'
// (approximately, the exact algorithm is more complicated than this).
- std::vector<MachO::any_relocation_info> &Relocs = Relocations[it];
+ std::vector<RelAndSymbol> &Relocs = Relocations[it];
for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
- Write32(Relocs[e - i - 1].r_word0);
- Write32(Relocs[e - i - 1].r_word1);
+ Write32(Relocs[e - i - 1].MRE.r_word0);
+ Write32(Relocs[e - i - 1].MRE.r_word1);
}
}
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 2180b42..2cb247a 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -175,7 +175,7 @@
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
- void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
+ void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, bool &IsPCRel,
uint64_t &FixedValue) override;
@@ -661,13 +661,9 @@
InSet, IsPCRel);
}
-void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- bool &IsPCRel,
- uint64_t &FixedValue) {
+void WinCOFFObjectWriter::RecordRelocation(
+ MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) {
assert(Target.getSymA() && "Relocation must reference a symbol!");
const MCSymbol &Symbol = Target.getSymA()->getSymbol();