@@ -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+
779783void 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
0 commit comments