Skip to content

Commit 7bef4c7

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.5
2 parents dd36a69 + defd68d commit 7bef4c7

File tree

11 files changed

+74
-104
lines changed

11 files changed

+74
-104
lines changed

lld/ELF/Arch/Mips.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ template <class ELFT> class MIPS final : public TargetInfo {
4040
};
4141
} // namespace
4242

43+
uint64_t elf::getMipsPageAddr(uint64_t addr) {
44+
return (addr + 0x8000) & ~0xffff;
45+
}
46+
4347
template <class ELFT> MIPS<ELFT>::MIPS(Ctx &ctx) : TargetInfo(ctx) {
4448
gotPltHeaderEntriesNum = 2;
4549
defaultMaxPageSize = 65536;

lld/ELF/Config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,8 @@ struct Ctx : CommonLinkerContext {
701701
std::unique_ptr<llvm::TarWriter> tar;
702702
// InputFile for linker created symbols with no source location.
703703
InputFile *internalFile = nullptr;
704+
// Dummy Undefined for relocations without a symbol.
705+
Undefined *dummySym = nullptr;
704706
// True if symbols can be exported (isExported) or preemptible.
705707
bool hasDynsym = false;
706708
// True if SHT_LLVM_SYMPART is used.

lld/ELF/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3138,6 +3138,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
31383138
ctx.symtab->insert(arg->getValue())->traced = true;
31393139

31403140
ctx.internalFile = createInternalFile(ctx, "<internal>");
3141+
ctx.dummySym = make<Undefined>(ctx.internalFile, "", STB_LOCAL, 0, 0);
31413142

31423143
// Handle -u/--undefined before input files. If both a.a and b.so define foo,
31433144
// -u foo a.a b.so will extract a.a.

lld/ELF/InputSection.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,11 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
861861
return ctx.in.mipsGot->getVA() +
862862
ctx.in.mipsGot->getPageEntryOffset(file, *r.sym, a) -
863863
ctx.in.mipsGot->getGp(file);
864+
case RE_MIPS_OSEC_LOCAL_PAGE:
865+
// This is used by the MIPS multi-GOT implementation. It relocates
866+
// addresses of 64kb pages that lie inside the output section that sym is
867+
// a representative for.
868+
return getMipsPageAddr(r.sym->getOutputSection()->addr) + a;
864869
case RE_MIPS_GOT_OFF:
865870
case RE_MIPS_GOT_OFF32:
866871
// In case of MIPS if a GOT relocation has non-zero addend this addend

lld/ELF/Relocations.cpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -885,10 +885,12 @@ static void addPltEntry(Ctx &ctx, PltSection &plt, GotPltSection &gotPlt,
885885
RelocationBaseSection &rel, RelType type, Symbol &sym) {
886886
plt.addEntry(sym);
887887
gotPlt.addEntry(sym);
888-
rel.addReloc({type, &gotPlt, sym.getGotPltOffset(ctx),
889-
sym.isPreemptible ? DynamicReloc::AgainstSymbol
890-
: DynamicReloc::AddendOnlyWithTargetVA,
891-
sym, 0, R_ABS});
888+
if (sym.isPreemptible)
889+
rel.addReloc(
890+
{type, &gotPlt, sym.getGotPltOffset(ctx), true, sym, 0, R_ADDEND});
891+
else
892+
rel.addReloc(
893+
{type, &gotPlt, sym.getGotPltOffset(ctx), false, sym, 0, R_ABS});
892894
}
893895

894896
void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
@@ -897,9 +899,8 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
897899

898900
// If preemptible, emit a GLOB_DAT relocation.
899901
if (sym.isPreemptible) {
900-
ctx.mainPart->relaDyn->addReloc({ctx.target->gotRel, ctx.in.got.get(), off,
901-
DynamicReloc::AgainstSymbol, sym, 0,
902-
R_ABS});
902+
ctx.mainPart->relaDyn->addReloc(
903+
{ctx.target->gotRel, ctx.in.got.get(), off, true, sym, 0, R_ADDEND});
903904
return;
904905
}
905906

@@ -920,15 +921,13 @@ static void addGotAuthEntry(Ctx &ctx, Symbol &sym) {
920921
// If preemptible, emit a GLOB_DAT relocation.
921922
if (sym.isPreemptible) {
922923
ctx.mainPart->relaDyn->addReloc({R_AARCH64_AUTH_GLOB_DAT, ctx.in.got.get(),
923-
off, DynamicReloc::AgainstSymbol, sym, 0,
924-
R_ABS});
924+
off, true, sym, 0, R_ADDEND});
925925
return;
926926
}
927927

928928
// Signed GOT requires dynamic relocation.
929929
ctx.in.got->getPartition(ctx).relaDyn->addReloc(
930-
{R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off,
931-
DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS});
930+
{R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off, false, sym, 0, R_ABS});
932931
}
933932

934933
static void addTpOffsetGotEntry(Ctx &ctx, Symbol &sym) {
@@ -1159,9 +1158,8 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
11591158
sec->addReloc({expr, type, offset, addend, &sym});
11601159
part.relrAuthDyn->relocs.push_back({sec, sec->relocs().size() - 1});
11611160
} else {
1162-
part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset,
1163-
DynamicReloc::AddendOnlyWithTargetVA, sym,
1164-
addend, R_ABS});
1161+
part.relaDyn->addReloc({R_AARCH64_AUTH_RELATIVE, sec, offset, false,
1162+
sym, addend, R_ABS});
11651163
}
11661164
return;
11671165
}
@@ -1948,13 +1946,12 @@ void elf::postScanRelocations(Ctx &ctx) {
19481946

19491947
GotSection *got = ctx.in.got.get();
19501948
if (ctx.needsTlsLd.load(std::memory_order_relaxed) && got->addTlsIndex()) {
1951-
static Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0);
19521949
if (ctx.arg.shared)
19531950
ctx.mainPart->relaDyn->addReloc(
19541951
{ctx.target->tlsModuleIndexRel, got, got->getTlsIndexOff()});
19551952
else
19561953
got->addConstant({R_ADDEND, ctx.target->symbolicRel,
1957-
got->getTlsIndexOff(), 1, &dummy});
1954+
got->getTlsIndexOff(), 1, ctx.dummySym});
19581955
}
19591956

19601957
assert(ctx.symAux.size() == 1);

lld/ELF/Relocations.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ enum RelExpr {
110110
RE_MIPS_GOT_LOCAL_PAGE,
111111
RE_MIPS_GOT_OFF,
112112
RE_MIPS_GOT_OFF32,
113+
RE_MIPS_OSEC_LOCAL_PAGE,
113114
RE_MIPS_TLSGD,
114115
RE_MIPS_TLSLD,
115116
RE_PPC32_PLTREL,

lld/ELF/SyntheticSections.cpp

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,6 @@ void GotSection::writeTo(uint8_t *buf) {
769769
}
770770
}
771771

772-
static uint64_t getMipsPageAddr(uint64_t addr) {
773-
return (addr + 0x8000) & ~0xffff;
774-
}
775-
776772
static uint64_t getMipsPageCount(uint64_t size) {
777773
return (size + 0xfffe) / 0xffff + 1;
778774
}
@@ -786,7 +782,7 @@ void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend,
786782
FileGot &g = getGot(file);
787783
if (expr == RE_MIPS_GOT_LOCAL_PAGE) {
788784
if (const OutputSection *os = sym.getOutputSection())
789-
g.pagesMap.insert({os, {}});
785+
g.pagesMap.insert({os, {&sym}});
790786
else
791787
g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(ctx, addend))}, 0});
792788
} else if (sym.isTls())
@@ -1066,8 +1062,7 @@ void MipsGotSection::build() {
10661062
// be allocated before us in the static TLS block.
10671063
if (s->isPreemptible || ctx.arg.shared)
10681064
ctx.mainPart->relaDyn->addReloc(
1069-
{ctx.target->tlsGotRel, this, offset,
1070-
DynamicReloc::AgainstSymbolWithTargetVA, *s, 0, R_ABS});
1065+
{ctx.target->tlsGotRel, this, offset, true, *s, 0, R_ABS});
10711066
}
10721067
for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) {
10731068
Symbol *s = p.first;
@@ -1115,15 +1110,16 @@ void MipsGotSection::build() {
11151110
size_t pageCount = l.second.count;
11161111
for (size_t pi = 0; pi < pageCount; ++pi) {
11171112
uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize;
1118-
ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset,
1119-
l.first, int64_t(pi * 0x10000)});
1113+
ctx.mainPart->relaDyn->addReloc(
1114+
{ctx.target->relativeRel, this, offset, false, *l.second.repSym,
1115+
int64_t(pi * 0x10000), RE_MIPS_OSEC_LOCAL_PAGE});
11201116
}
11211117
}
11221118
for (const std::pair<GotEntry, size_t> &p : got.local16) {
11231119
uint64_t offset = p.second * ctx.arg.wordsize;
11241120
ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset,
1125-
DynamicReloc::AddendOnlyWithTargetVA,
1126-
*p.first.first, p.first.second, R_ABS});
1121+
false, *p.first.first, p.first.second,
1122+
R_ABS});
11271123
}
11281124
}
11291125
}
@@ -1646,24 +1642,10 @@ uint64_t DynamicReloc::getOffset() const {
16461642
}
16471643

16481644
int64_t DynamicReloc::computeAddend(Ctx &ctx) const {
1649-
switch (kind) {
1650-
case AddendOnly:
1651-
assert(sym == nullptr);
1652-
return addend;
1653-
case AgainstSymbol:
1654-
assert(sym != nullptr);
1655-
return addend;
1656-
case AddendOnlyWithTargetVA:
1657-
case AgainstSymbolWithTargetVA: {
1658-
uint64_t ca = inputSec->getRelocTargetVA(
1659-
ctx, Relocation{expr, type, 0, addend, sym}, getOffset());
1660-
return ctx.arg.is64 ? ca : SignExtend64<32>(ca);
1661-
}
1662-
case MipsMultiGotPage:
1663-
assert(sym == nullptr);
1664-
return getMipsPageAddr(outputSec->addr) + addend;
1665-
}
1666-
llvm_unreachable("Unknown DynamicReloc::Kind enum");
1645+
assert(!isFinal && "addend already computed");
1646+
uint64_t ca = inputSec->getRelocTargetVA(
1647+
ctx, Relocation{expr, type, 0, addend, sym}, getOffset());
1648+
return ctx.arg.is64 ? ca : SignExtend64<32>(ca);
16671649
}
16681650

16691651
uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
@@ -1691,20 +1673,18 @@ RelocationBaseSection::RelocationBaseSection(Ctx &ctx, StringRef name,
16911673
void RelocationBaseSection::addSymbolReloc(
16921674
RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym,
16931675
int64_t addend, std::optional<RelType> addendRelType) {
1694-
addReloc(DynamicReloc::AgainstSymbol, dynType, isec, offsetInSec, sym, addend,
1695-
R_ADDEND, addendRelType ? *addendRelType : ctx.target->noneRel);
1676+
addReloc(true, dynType, isec, offsetInSec, sym, addend, R_ADDEND,
1677+
addendRelType ? *addendRelType : ctx.target->noneRel);
16961678
}
16971679

16981680
void RelocationBaseSection::addAddendOnlyRelocIfNonPreemptible(
16991681
RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym,
17001682
RelType addendRelType) {
17011683
// No need to write an addend to the section for preemptible symbols.
17021684
if (sym.isPreemptible)
1703-
addReloc({dynType, &isec, offsetInSec, DynamicReloc::AgainstSymbol, sym, 0,
1704-
R_ABS});
1685+
addReloc({dynType, &isec, offsetInSec, true, sym, 0, R_ADDEND});
17051686
else
1706-
addReloc(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec, offsetInSec,
1707-
sym, 0, R_ABS, addendRelType);
1687+
addReloc(false, dynType, isec, offsetInSec, sym, 0, R_ABS, addendRelType);
17081688
}
17091689

17101690
void RelocationBaseSection::mergeRels() {
@@ -1744,17 +1724,17 @@ void RelocationBaseSection::finalizeContents() {
17441724
}
17451725
}
17461726

1747-
void DynamicReloc::computeRaw(Ctx &ctx, SymbolTableBaseSection *symt) {
1727+
void DynamicReloc::finalize(Ctx &ctx, SymbolTableBaseSection *symt) {
17481728
r_offset = getOffset();
17491729
r_sym = getSymIndex(symt);
17501730
addend = computeAddend(ctx);
1751-
kind = AddendOnly; // Catch errors
1731+
isFinal = true; // Catch errors
17521732
}
17531733

17541734
void RelocationBaseSection::computeRels() {
17551735
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
17561736
parallelForEach(relocs, [&ctx = ctx, symTab](DynamicReloc &rel) {
1757-
rel.computeRaw(ctx, symTab);
1737+
rel.finalize(ctx, symTab);
17581738
});
17591739

17601740
auto irelative = std::stable_partition(

lld/ELF/SyntheticSections.h

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,11 @@ class MipsGotSection final : public SyntheticSection {
327327
size_t startIndex = 0;
328328

329329
struct PageBlock {
330+
Symbol *repSym; // Representative symbol for the OutputSection
330331
size_t firstIndex;
331332
size_t count;
332-
PageBlock() : firstIndex(0), count(0) {}
333+
PageBlock(Symbol *repSym = nullptr)
334+
: repSym(repSym), firstIndex(0), count(0) {}
333335
};
334336

335337
// Map output sections referenced by MIPS GOT relocations
@@ -418,61 +420,31 @@ class StringTableSection final : public SyntheticSection {
418420

419421
class DynamicReloc {
420422
public:
421-
enum Kind {
422-
/// The resulting dynamic relocation does not reference a symbol (#sym must
423-
/// be nullptr) and uses #addend as the result of computeAddend(ctx).
424-
AddendOnly,
425-
/// The resulting dynamic relocation will not reference a symbol: #sym is
426-
/// only used to compute the addend with InputSection::getRelocTargetVA().
427-
/// Useful for various relative and TLS relocations (e.g. R_X86_64_TPOFF64).
428-
AddendOnlyWithTargetVA,
429-
/// The resulting dynamic relocation references symbol #sym from the dynamic
430-
/// symbol table and uses #addend as the value of computeAddend(ctx).
431-
AgainstSymbol,
432-
/// The resulting dynamic relocation references symbol #sym from the dynamic
433-
/// symbol table and uses InputSection::getRelocTargetVA() + #addend for the
434-
/// final addend. It can be used for relocations that write the symbol VA as
435-
// the addend (e.g. R_MIPS_TLS_TPREL64) but still reference the symbol.
436-
AgainstSymbolWithTargetVA,
437-
/// This is used by the MIPS multi-GOT implementation. It relocates
438-
/// addresses of 64kb pages that lie inside the output section.
439-
MipsMultiGotPage,
440-
};
441-
/// This constructor records a relocation against a symbol.
423+
/// This constructor records a normal relocation.
442424
DynamicReloc(RelType type, const InputSectionBase *inputSec,
443-
uint64_t offsetInSec, Kind kind, Symbol &sym, int64_t addend,
444-
RelExpr expr)
425+
uint64_t offsetInSec, bool isAgainstSymbol, Symbol &sym,
426+
int64_t addend, RelExpr expr)
445427
: sym(&sym), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
446-
addend(addend), kind(kind), expr(expr) {}
428+
addend(addend), isAgainstSymbol(isAgainstSymbol), isFinal(false),
429+
expr(expr) {}
447430
/// This constructor records a relative relocation with no symbol.
448431
DynamicReloc(RelType type, const InputSectionBase *inputSec,
449432
uint64_t offsetInSec, int64_t addend = 0)
450-
: sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec), type(type),
451-
addend(addend), kind(AddendOnly), expr(R_ADDEND) {}
452-
/// This constructor records dynamic relocation settings used by the MIPS
453-
/// multi-GOT implementation.
454-
DynamicReloc(RelType type, const InputSectionBase *inputSec,
455-
uint64_t offsetInSec, const OutputSection *outputSec,
456-
int64_t addend)
457-
: sym(nullptr), outputSec(outputSec), inputSec(inputSec),
458-
offsetInSec(offsetInSec), type(type), addend(addend),
459-
kind(MipsMultiGotPage), expr(R_ADDEND) {}
433+
: DynamicReloc(type, inputSec, offsetInSec, false,
434+
*inputSec->getCtx().dummySym, addend, R_ADDEND) {}
460435

461436
uint64_t getOffset() const;
462437
uint32_t getSymIndex(SymbolTableBaseSection *symTab) const;
463-
bool needsDynSymIndex() const {
464-
return kind == AgainstSymbol || kind == AgainstSymbolWithTargetVA;
465-
}
438+
bool needsDynSymIndex() const { return isAgainstSymbol; }
466439

467440
/// Computes the addend of the dynamic relocation. Note that this is not the
468441
/// same as the #addend member variable as it may also include the symbol
469442
/// address/the address of the corresponding GOT entry/etc.
470443
int64_t computeAddend(Ctx &) const;
471444

472-
void computeRaw(Ctx &, SymbolTableBaseSection *symt);
445+
void finalize(Ctx &, SymbolTableBaseSection *symt);
473446

474447
Symbol *sym;
475-
const OutputSection *outputSec = nullptr;
476448
const InputSectionBase *inputSec;
477449
uint64_t offsetInSec;
478450
uint64_t r_offset;
@@ -483,7 +455,15 @@ class DynamicReloc {
483455
int64_t addend;
484456

485457
private:
486-
Kind kind;
458+
/// Whether this was constructed with a Kind of AgainstSymbol.
459+
LLVM_PREFERRED_TYPE(bool)
460+
uint8_t isAgainstSymbol : 1;
461+
462+
/// The resulting dynamic relocation has already had its addend computed.
463+
/// Calling computeAddend() is an error.
464+
LLVM_PREFERRED_TYPE(bool)
465+
uint8_t isFinal : 1;
466+
487467
// The kind of expression used to calculate the added (required e.g. for
488468
// relative GOT relocations).
489469
RelExpr expr;
@@ -528,8 +508,8 @@ class RelocationBaseSection : public SyntheticSection {
528508
uint64_t offsetInSec, Symbol &sym, int64_t addend,
529509
RelType addendRelType, RelExpr expr) {
530510
assert(expr != R_ADDEND && "expected non-addend relocation expression");
531-
addReloc<shard>(DynamicReloc::AddendOnlyWithTargetVA, dynType, isec,
532-
offsetInSec, sym, addend, expr, addendRelType);
511+
addReloc<shard>(false, dynType, isec, offsetInSec, sym, addend, expr,
512+
addendRelType);
533513
}
534514
/// Add a dynamic relocation using the target address of \p sym as the addend
535515
/// if \p sym is non-preemptible. Otherwise add a relocation against \p sym.
@@ -538,14 +518,15 @@ class RelocationBaseSection : public SyntheticSection {
538518
uint64_t offsetInSec, Symbol &sym,
539519
RelType addendRelType);
540520
template <bool shard = false>
541-
void addReloc(DynamicReloc::Kind kind, RelType dynType, InputSectionBase &sec,
521+
void addReloc(bool isAgainstSymbol, RelType dynType, InputSectionBase &sec,
542522
uint64_t offsetInSec, Symbol &sym, int64_t addend, RelExpr expr,
543523
RelType addendRelType) {
544524
// Write the addends to the relocated address if required. We skip
545525
// it if the written value would be zero.
546526
if (ctx.arg.writeAddends && (expr != R_ADDEND || addend != 0))
547527
sec.addReloc({expr, addendRelType, offsetInSec, addend, &sym});
548-
addReloc<shard>({dynType, &sec, offsetInSec, kind, sym, addend, expr});
528+
addReloc<shard>(
529+
{dynType, &sec, offsetInSec, isAgainstSymbol, sym, addend, expr});
549530
}
550531
bool isNeeded() const override {
551532
return !relocs.empty() ||

lld/ELF/Target.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,9 @@ ErrorPlace elf::getErrorPlace(Ctx &ctx, const uint8_t *loc) {
105105
if (isecLoc <= loc && loc < isecLoc + isec->getSize()) {
106106
std::string objLoc = isec->getLocation(loc - isecLoc);
107107
// Return object file location and source file location.
108-
Undefined dummy(ctx.internalFile, "", STB_LOCAL, 0, 0);
109108
ELFSyncStream msg(ctx, DiagLevel::None);
110109
if (isec->file)
111-
msg << isec->getSrcMsg(dummy, loc - isecLoc);
110+
msg << isec->getSrcMsg(*ctx.dummySym, loc - isecLoc);
112111
return {isec, objLoc + ": ", std::string(msg.str())};
113112
}
114113
}

lld/ELF/Target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ void processArmCmseSymbols(Ctx &);
214214
template <class ELFT> uint32_t calcMipsEFlags(Ctx &);
215215
uint8_t getMipsFpAbiFlag(Ctx &, InputFile *file, uint8_t oldFlag,
216216
uint8_t newFlag);
217+
uint64_t getMipsPageAddr(uint64_t addr);
217218
bool isMipsN32Abi(Ctx &, const InputFile &f);
218219
bool isMicroMips(Ctx &);
219220
bool isMipsR6(Ctx &);

0 commit comments

Comments
 (0)