Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9fb61d9

Browse files
authored
[NFCI][ELF][Mips] Refactor MipsGotSection to avoid explicit writes (#178561)
Splitting the VA / addend calculations between build and writeTo means having to keep them in sync and duplicating some of the logic. Move all such calculations into build, mirroring how the normal non-MIPS code in Relocations.cpp ensures the addend and initial memory contents are set.
1 parent 495a783 commit 9fb61d9

3 files changed

Lines changed: 68 additions & 78 deletions

File tree

lld/ELF/Arch/Mips.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
713713

714714
switch (type) {
715715
case R_MIPS_32:
716+
case R_MIPS_REL32:
716717
case R_MIPS_GPREL32:
717718
case R_MIPS_TLS_DTPREL32:
718719
case R_MIPS_TLS_TPREL32:
@@ -721,6 +722,7 @@ void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,
721722
case R_MIPS_64:
722723
case R_MIPS_TLS_DTPREL64:
723724
case R_MIPS_TLS_TPREL64:
725+
case (R_MIPS_64 << 8) | R_MIPS_REL32:
724726
write64(ctx, loc, val);
725727
break;
726728
case R_MIPS_26:

lld/ELF/SyntheticSections.cpp

Lines changed: 65 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,10 @@ MipsGotSection::MipsGotSection(Ctx &ctx)
776776
: SyntheticSection(ctx, ".got", SHT_PROGBITS,
777777
SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, 16) {}
778778

779+
void MipsGotSection::addConstant(const Relocation &r) {
780+
relocations.push_back(r);
781+
}
782+
779783
void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend,
780784
RelExpr expr) {
781785
FileGot &g = getGot(file);
@@ -1050,75 +1054,104 @@ void MipsGotSection::build() {
10501054
ctx.symAux.back().gotIdx = p.second;
10511055
}
10521056

1053-
// Create dynamic relocations.
1057+
// Create relocations.
1058+
//
1059+
// Note the primary GOT's local and global relocations are implicit, and the
1060+
// MIPS ABI requires the VA be written even for the global entries, so we
1061+
// treat both as constants here.
10541062
for (FileGot &got : gots) {
1055-
// Create dynamic relocations for TLS entries.
1063+
// Create relocations for TLS entries.
10561064
for (std::pair<Symbol *, size_t> &p : got.tls) {
10571065
Symbol *s = p.first;
10581066
uint64_t offset = p.second * ctx.arg.wordsize;
10591067
// When building a shared library we still need a dynamic relocation
10601068
// for the TP-relative offset as we don't know how much other data will
10611069
// be allocated before us in the static TLS block.
1062-
if (s->isPreemptible || ctx.arg.shared)
1070+
if (!s->isPreemptible && !ctx.arg.shared)
1071+
addConstant({R_TPREL, ctx.target->symbolicRel, offset, 0, s});
1072+
else
10631073
ctx.mainPart->relaDyn->addAddendOnlyRelocIfNonPreemptible(
10641074
ctx.target->tlsGotRel, *this, offset, *s, ctx.target->symbolicRel);
10651075
}
10661076
for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) {
10671077
Symbol *s = p.first;
10681078
uint64_t offset = p.second * ctx.arg.wordsize;
10691079
if (s == nullptr) {
1070-
if (!ctx.arg.shared)
1071-
continue;
1072-
ctx.mainPart->relaDyn->addReloc(
1073-
{ctx.target->tlsModuleIndexRel, this, offset});
1080+
if (ctx.arg.shared)
1081+
ctx.mainPart->relaDyn->addReloc(
1082+
{ctx.target->tlsModuleIndexRel, this, offset});
1083+
else
1084+
addConstant(
1085+
{R_ADDEND, ctx.target->symbolicRel, offset, 1, ctx.dummySym});
10741086
} else {
10751087
// When building a shared library we still need a dynamic relocation
10761088
// for the module index. Therefore only checking for
10771089
// S->isPreemptible is not sufficient (this happens e.g. for
10781090
// thread-locals that have been marked as local through a linker script)
10791091
if (!s->isPreemptible && !ctx.arg.shared)
1080-
continue;
1081-
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsModuleIndexRel,
1082-
*this, offset, *s);
1092+
// Write one to the GOT slot.
1093+
addConstant({R_ADDEND, ctx.target->symbolicRel, offset, 1, s});
1094+
else
1095+
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsModuleIndexRel,
1096+
*this, offset, *s);
1097+
offset += ctx.arg.wordsize;
10831098
// However, we can skip writing the TLS offset reloc for non-preemptible
10841099
// symbols since it is known even in shared libraries
1085-
if (!s->isPreemptible)
1086-
continue;
1087-
offset += ctx.arg.wordsize;
1088-
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *this,
1089-
offset, *s);
1100+
if (s->isPreemptible)
1101+
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->tlsOffsetRel, *this,
1102+
offset, *s);
1103+
else
1104+
addConstant({R_ABS, ctx.target->tlsOffsetRel, offset, 0, s});
10901105
}
10911106
}
10921107

1093-
// Do not create dynamic relocations for non-TLS
1094-
// entries in the primary GOT.
1095-
if (&got == primGot)
1096-
continue;
1097-
1098-
// Dynamic relocations for "global" entries.
1108+
// Relocations for "global" entries.
10991109
for (const std::pair<Symbol *, size_t> &p : got.global) {
11001110
uint64_t offset = p.second * ctx.arg.wordsize;
1101-
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->relativeRel, *this,
1102-
offset, *p.first);
1111+
if (&got == primGot)
1112+
addConstant({R_ABS, ctx.target->relativeRel, offset, 0, p.first});
1113+
else
1114+
ctx.mainPart->relaDyn->addSymbolReloc(ctx.target->relativeRel, *this,
1115+
offset, *p.first);
11031116
}
1104-
if (!ctx.arg.isPic)
1105-
continue;
1106-
// Dynamic relocations for "local" entries in case of PIC.
1117+
// Relocation-only entries exist as dummy entries for dynamic symbols that
1118+
// aren't otherwise in the primary GOT, as the ABI requires an entry for
1119+
// each dynamic symbol. Secondary GOTs have no need for them.
1120+
assert((got.relocs.empty() || &got == primGot) &&
1121+
"Relocation-only entries should only be in the primary GOT");
1122+
for (const std::pair<Symbol *, size_t> &p : got.relocs) {
1123+
uint64_t offset = p.second * ctx.arg.wordsize;
1124+
addConstant({R_ABS, ctx.target->relativeRel, offset, 0, p.first});
1125+
}
1126+
1127+
// Relocations for "local" entries
11071128
for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
11081129
got.pagesMap) {
11091130
size_t pageCount = l.second.count;
11101131
for (size_t pi = 0; pi < pageCount; ++pi) {
11111132
uint64_t offset = (l.second.firstIndex + pi) * ctx.arg.wordsize;
1112-
ctx.mainPart->relaDyn->addReloc(
1113-
{ctx.target->relativeRel, this, offset, false, *l.second.repSym,
1114-
int64_t(pi * 0x10000), RE_MIPS_OSEC_LOCAL_PAGE});
1133+
int64_t addend = int64_t(pi * 0x10000);
1134+
if (!ctx.arg.isPic || &got == primGot)
1135+
addConstant({RE_MIPS_OSEC_LOCAL_PAGE, ctx.target->relativeRel, offset,
1136+
addend, l.second.repSym});
1137+
else
1138+
ctx.mainPart->relaDyn->addRelativeReloc(
1139+
ctx.target->relativeRel, *this, offset, *l.second.repSym, addend,
1140+
ctx.target->relativeRel, RE_MIPS_OSEC_LOCAL_PAGE);
11151141
}
11161142
}
11171143
for (const std::pair<GotEntry, size_t> &p : got.local16) {
11181144
uint64_t offset = p.second * ctx.arg.wordsize;
1119-
ctx.mainPart->relaDyn->addReloc({ctx.target->relativeRel, this, offset,
1120-
false, *p.first.first, p.first.second,
1121-
R_ABS});
1145+
if (p.first.first == nullptr)
1146+
addConstant({R_ADDEND, ctx.target->relativeRel, offset, p.first.second,
1147+
ctx.dummySym});
1148+
else if (!ctx.arg.isPic || &got == primGot)
1149+
addConstant({R_ABS, ctx.target->relativeRel, offset, p.first.second,
1150+
p.first.first});
1151+
else
1152+
ctx.mainPart->relaDyn->addRelativeReloc(
1153+
ctx.target->relativeRel, *this, offset, *p.first.first,
1154+
p.first.second, ctx.target->relativeRel, R_ABS);
11221155
}
11231156
}
11241157
}
@@ -1156,52 +1189,6 @@ void MipsGotSection::writeTo(uint8_t *buf) {
11561189
writeUint(ctx, buf + ctx.arg.wordsize,
11571190
(uint64_t)1 << (ctx.arg.wordsize * 8 - 1));
11581191
ctx.target->relocateAlloc(*this, buf);
1159-
for (const FileGot &g : gots) {
1160-
auto write = [&](size_t i, const Symbol *s, int64_t a) {
1161-
uint64_t va = a;
1162-
if (s)
1163-
va = s->getVA(ctx, a);
1164-
writeUint(ctx, buf + i * ctx.arg.wordsize, va);
1165-
};
1166-
// Write 'page address' entries to the local part of the GOT.
1167-
for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
1168-
g.pagesMap) {
1169-
size_t pageCount = l.second.count;
1170-
uint64_t firstPageAddr = getMipsPageAddr(l.first->addr);
1171-
for (size_t pi = 0; pi < pageCount; ++pi)
1172-
write(l.second.firstIndex + pi, nullptr, firstPageAddr + pi * 0x10000);
1173-
}
1174-
// Local, global, TLS, reloc-only entries.
1175-
// If TLS entry has a corresponding dynamic relocations, leave it
1176-
// initialized by zero. Write down adjusted TLS symbol's values otherwise.
1177-
// To calculate the adjustments use offsets for thread-local storage.
1178-
// http://web.archive.org/web/20190324223224/https://www.linux-mips.org/wiki/NPTL
1179-
for (const std::pair<GotEntry, size_t> &p : g.local16)
1180-
write(p.second, p.first.first, p.first.second);
1181-
// Write VA to the primary GOT only. For secondary GOTs that
1182-
// will be done by REL32 dynamic relocations.
1183-
if (&g == &gots.front())
1184-
for (const std::pair<Symbol *, size_t> &p : g.global)
1185-
write(p.second, p.first, 0);
1186-
for (const std::pair<Symbol *, size_t> &p : g.relocs)
1187-
write(p.second, p.first, 0);
1188-
for (const std::pair<Symbol *, size_t> &p : g.tls) {
1189-
if (!p.first->isPreemptible && !ctx.arg.shared)
1190-
write(p.second, p.first, -0x7000);
1191-
}
1192-
for (const std::pair<Symbol *, size_t> &p : g.dynTlsSymbols) {
1193-
if (p.first == nullptr && !ctx.arg.shared)
1194-
write(p.second, nullptr, 1);
1195-
else if (p.first && !p.first->isPreemptible) {
1196-
// If we are emitting a shared library with relocations we mustn't write
1197-
// anything to the GOT here. When using Elf_Rel relocations the value
1198-
// one will be treated as an addend and will cause crashes at runtime
1199-
if (!ctx.arg.shared)
1200-
write(p.second, nullptr, 1);
1201-
write(p.second + 1, p.first, -0x8000);
1202-
}
1203-
}
1204-
}
12051192
}
12061193

12071194
// On PowerPC the .plt section is used to hold the table of function addresses

lld/ELF/SyntheticSections.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ class MipsGotSection final : public SyntheticSection {
204204
// primary and optional multiple secondary GOTs.
205205
void build();
206206

207+
void addConstant(const Relocation &r);
207208
void addEntry(InputFile &file, Symbol &sym, int64_t addend, RelExpr expr);
208209
void addDynTlsEntry(InputFile &file, Symbol &sym);
209210
void addTlsIndex(InputFile &file);

0 commit comments

Comments
 (0)