May cause a failure for non-preemptible `bcmp` in a glibc -static link.
};
const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
- // needsCopy indicates a non-ifunc canonical PLT entry whose address may
+ // needsPltAddr indicates a non-ifunc canonical PLT entry whose address may
// escape to shared objects. isInIplt indicates a non-preemptible ifunc. Its
// address may escape if referenced by a direct relocation. The condition is
// conservative.
- bool hasBti = btiHeader && (sym.needsCopy || sym.isInIplt);
+ bool hasBti = btiHeader && (sym.needsPltAddr || sym.isInIplt);
if (hasBti) {
memcpy(buf, btiData, sizeof(btiData));
buf += sizeof(btiData);
for (Symbol *b : file->getSymbols())
if (auto *dr = dyn_cast<Defined>(b))
if (!dr->isSection() && dr->section && dr->section->isLive() &&
- (dr->file == file || dr->needsCopy || dr->section->bss))
+ (dr->file == file || dr->needsPltAddr || dr->section->bss))
v.push_back(dr);
return v;
}
sym.verdefIndex = old.verdefIndex;
sym.exportDynamic = true;
sym.isUsedInRegularObj = true;
- // A copy relocated alias may need a GOT entry.
- sym.needsGot = old.needsGot;
}
// Reserve space in .bss or .bss.rel.ro for copy relocation.
// to the variable in .bss. This kind of issue is sometimes very hard to
// debug. What's a solution? Instead of exporting a variable V from a DSO,
// define an accessor getV().
-template <class ELFT> static void addCopyRelSymbolImpl(SharedSymbol &ss) {
+template <class ELFT> static void addCopyRelSymbol(SharedSymbol &ss) {
// Copy relocation against zero-sized symbol doesn't make sense.
uint64_t symSize = ss.getSize();
if (symSize == 0 || ss.alignment == 0)
mainPart->relaDyn->addSymbolReloc(target->copyRel, sec, 0, ss);
}
-static void addCopyRelSymbol(SharedSymbol &ss) {
- const SharedFile &file = ss.getFile();
- switch (file.ekind) {
- case ELF32LEKind:
- addCopyRelSymbolImpl<ELF32LE>(ss);
- break;
- case ELF32BEKind:
- addCopyRelSymbolImpl<ELF32BE>(ss);
- break;
- case ELF64LEKind:
- addCopyRelSymbolImpl<ELF64LE>(ss);
- break;
- case ELF64BEKind:
- addCopyRelSymbolImpl<ELF64BE>(ss);
- break;
- default:
- llvm_unreachable("");
- }
-}
-
// MIPS has an odd notion of "paired" relocations to calculate addends.
// For example, if a relocation is of R_MIPS_HI16, there must be a
// R_MIPS_LO16 relocation after that, and an addend is calculated using
" against symbol '" + toString(*ss) +
"'; recompile with -fPIC or remove '-z nocopyreloc'" +
getLocation(sec, sym, offset));
- sym.needsCopy = true;
+ addCopyRelSymbol<ELFT>(*ss);
}
sec.relocations.push_back({expr, type, offset, addend, &sym});
return;
errorOrWarn("symbol '" + toString(sym) +
"' cannot be preempted; recompile with -fPIE" +
getLocation(sec, sym, offset));
- sym.needsCopy = true;
- sym.needsPlt = true;
+ if (!sym.isInPlt())
+ addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
+ if (!sym.isDefined()) {
+ replaceWithDefined(
+ sym, in.plt,
+ target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
+ if (config->emachine == EM_PPC) {
+ // PPC32 canonical PLT entries are at the beginning of .glink
+ cast<Defined>(sym).value = in.plt->headerSize;
+ in.plt->headerSize += 16;
+ cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
+ }
+ }
+ sym.needsPltAddr = true;
sec.relocations.push_back({expr, type, offset, addend, &sym});
return;
}
return;
}
- if (needsGot(expr)) {
- if (config->emachine == EM_MIPS) {
- // MIPS ABI has special rules to process GOT entries and doesn't
- // require relocation entries for them. A special case is TLS
- // relocations. In that case dynamic loader applies dynamic
- // relocations to initialize TLS GOT entries.
- // See "Global Offset Table" in Chapter 5 in the following document
- // for detailed description:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- in.mipsGot->addEntry(*sec.file, sym, addend, expr);
- } else {
- sym.needsGot = true;
+ // Non-preemptible ifuncs require special handling. First, handle the usual
+ // case where the symbol isn't one of these.
+ if (!sym.isGnuIFunc() || sym.isPreemptible) {
+ // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
+ if (needsPlt(expr) && !sym.isInPlt())
+ addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
+
+ // Create a GOT slot if a relocation needs GOT.
+ if (needsGot(expr)) {
+ if (config->emachine == EM_MIPS) {
+ // MIPS ABI has special rules to process GOT entries and doesn't
+ // require relocation entries for them. A special case is TLS
+ // relocations. In that case dynamic loader applies dynamic
+ // relocations to initialize TLS GOT entries.
+ // See "Global Offset Table" in Chapter 5 in the following document
+ // for detailed description:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ in.mipsGot->addEntry(*sec.file, sym, addend, expr);
+ } else if (!sym.isInGot()) {
+ addGotEntry(sym);
+ }
}
- } else if (needsPlt(expr)) {
- sym.needsPlt = true;
} else {
- sym.hasDirectReloc = true;
+ // Handle a reference to a non-preemptible ifunc. These are special in a
+ // few ways:
+ //
+ // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
+ // a fixed value. But assuming that all references to the ifunc are
+ // GOT-generating or PLT-generating, the handling of an ifunc is
+ // relatively straightforward. We create a PLT entry in Iplt, which is
+ // usually at the end of .plt, which makes an indirect call using a
+ // matching GOT entry in igotPlt, which is usually at the end of .got.plt.
+ // The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
+ // which is usually at the end of .rela.plt. Unlike most relocations in
+ // .rela.plt, which may be evaluated lazily without -z now, dynamic
+ // loaders evaluate IRELATIVE relocs eagerly, which means that for
+ // IRELATIVE relocs only, GOT-generating relocations can point directly to
+ // .got.plt without requiring a separate GOT entry.
+ //
+ // - Despite the fact that an ifunc does not have a fixed value, compilers
+ // that are not passed -fPIC will assume that they do, and will emit
+ // direct (non-GOT-generating, non-PLT-generating) relocations to the
+ // symbol. This means that if a direct relocation to the symbol is
+ // seen, the linker must set a value for the symbol, and this value must
+ // be consistent no matter what type of reference is made to the symbol.
+ // This can be done by creating a PLT entry for the symbol in the way
+ // described above and making it canonical, that is, making all references
+ // point to the PLT entry instead of the resolver. In lld we also store
+ // the address of the PLT entry in the dynamic symbol table, which means
+ // that the symbol will also have the same value in other modules.
+ // Because the value loaded from the GOT needs to be consistent with
+ // the value computed using a direct relocation, a non-preemptible ifunc
+ // may end up with two GOT entries, one in .got.plt that points to the
+ // address returned by the resolver and is used only by the PLT entry,
+ // and another in .got that points to the PLT entry and is used by
+ // GOT-generating relocations.
+ //
+ // - The fact that these symbols do not have a fixed value makes them an
+ // exception to the general rule that a statically linked executable does
+ // not require any form of dynamic relocation. To handle these relocations
+ // correctly, the IRELATIVE relocations are stored in an array which a
+ // statically linked executable's startup code must enumerate using the
+ // linker-defined symbols __rela?_iplt_{start,end}.
+ if (!sym.isInPlt()) {
+ // Create PLT and GOTPLT slots for the symbol.
+ sym.isInIplt = true;
+
+ // Create a copy of the symbol to use as the target of the IRELATIVE
+ // relocation in the igotPlt. This is in case we make the PLT canonical
+ // later, which would overwrite the original symbol.
+ //
+ // FIXME: Creating a copy of the symbol here is a bit of a hack. All
+ // that's really needed to create the IRELATIVE is the section and value,
+ // so ideally we should just need to copy those.
+ auto *directSym = make<Defined>(cast<Defined>(sym));
+ addPltEntry(in.iplt, in.igotPlt, in.relaIplt, target->iRelativeRel,
+ *directSym);
+ sym.pltIndex = directSym->pltIndex;
+ }
+ if (needsGot(expr)) {
+ // Redirect GOT accesses to point to the Igot.
+ //
+ // This field is also used to keep track of whether we ever needed a GOT
+ // entry. If we did and we make the PLT canonical later, we'll need to
+ // create a GOT entry pointing to the PLT entry for Sym.
+ sym.gotInIgot = true;
+ } else if (!needsPlt(expr)) {
+ // Make the ifunc's PLT entry canonical by changing the value of its
+ // symbol to redirect all references to point to it.
+ auto &d = cast<Defined>(sym);
+ d.section = in.iplt;
+ d.value = sym.pltIndex * target->ipltEntrySize;
+ d.size = 0;
+ // It's important to set the symbol type here so that dynamic loaders
+ // don't try to call the PLT as if it were an ifunc resolver.
+ d.type = STT_FUNC;
+
+ if (sym.gotInIgot) {
+ // We previously encountered a GOT generating reference that we
+ // redirected to the Igot. Now that the PLT entry is canonical we must
+ // clear the redirection to the Igot and add a GOT entry. As we've
+ // changed the symbol type to STT_FUNC future GOT generating references
+ // will naturally use this GOT entry.
+ //
+ // We don't need to worry about creating a MIPS GOT here because ifuncs
+ // aren't a thing on MIPS.
+ sym.gotInIgot = false;
+ addGotEntry(sym);
+ }
+ }
}
processRelocAux<ELFT>(sec, expr, type, offset, sym, addend);
scanRelocs<ELFT>(s, rels.relas);
}
-static bool handleNonPreemptibleIfunc(Symbol &sym) {
- // Handle a reference to a non-preemptible ifunc. These are special in a
- // few ways:
- //
- // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
- // a fixed value. But assuming that all references to the ifunc are
- // GOT-generating or PLT-generating, the handling of an ifunc is
- // relatively straightforward. We create a PLT entry in Iplt, which is
- // usually at the end of .plt, which makes an indirect call using a
- // matching GOT entry in igotPlt, which is usually at the end of .got.plt.
- // The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
- // which is usually at the end of .rela.plt. Unlike most relocations in
- // .rela.plt, which may be evaluated lazily without -z now, dynamic
- // loaders evaluate IRELATIVE relocs eagerly, which means that for
- // IRELATIVE relocs only, GOT-generating relocations can point directly to
- // .got.plt without requiring a separate GOT entry.
- //
- // - Despite the fact that an ifunc does not have a fixed value, compilers
- // that are not passed -fPIC will assume that they do, and will emit
- // direct (non-GOT-generating, non-PLT-generating) relocations to the
- // symbol. This means that if a direct relocation to the symbol is
- // seen, the linker must set a value for the symbol, and this value must
- // be consistent no matter what type of reference is made to the symbol.
- // This can be done by creating a PLT entry for the symbol in the way
- // described above and making it canonical, that is, making all references
- // point to the PLT entry instead of the resolver. In lld we also store
- // the address of the PLT entry in the dynamic symbol table, which means
- // that the symbol will also have the same value in other modules.
- // Because the value loaded from the GOT needs to be consistent with
- // the value computed using a direct relocation, a non-preemptible ifunc
- // may end up with two GOT entries, one in .got.plt that points to the
- // address returned by the resolver and is used only by the PLT entry,
- // and another in .got that points to the PLT entry and is used by
- // GOT-generating relocations.
- //
- // - The fact that these symbols do not have a fixed value makes them an
- // exception to the general rule that a statically linked executable does
- // not require any form of dynamic relocation. To handle these relocations
- // correctly, the IRELATIVE relocations are stored in an array which a
- // statically linked executable's startup code must enumerate using the
- // linker-defined symbols __rela?_iplt_{start,end}.
- if (!sym.isGnuIFunc() || sym.isPreemptible || config->zIfuncNoplt)
- return false;
-
- sym.isInIplt = true;
-
- // Create an Iplt and the associated IRELATIVE relocation pointing to the
- // original section/value pairs. For non-GOT non-PLT relocation case below, we
- // may alter section/value, so create a copy of the symbol to make
- // section/value fixed.
- auto *directSym = make<Defined>(cast<Defined>(sym));
- addPltEntry(in.iplt, in.igotPlt, in.relaIplt, target->iRelativeRel,
- *directSym);
- sym.pltIndex = directSym->pltIndex;
-
- if (sym.hasDirectReloc) {
- // Change the value to the IPLT and redirect all references to it.
- auto &d = cast<Defined>(sym);
- d.section = in.iplt;
- d.value = sym.pltIndex * target->ipltEntrySize;
- d.size = 0;
- // It's important to set the symbol type here so that dynamic loaders
- // don't try to call the PLT as if it were an ifunc resolver.
- d.type = STT_FUNC;
-
- if (sym.needsGot)
- addGotEntry(sym);
- } else if (sym.needsGot) {
- // Redirect GOT accesses to point to the Igot.
- sym.gotInIgot = true;
- }
- return true;
-}
-
-void elf::postScanRelocations() {
- auto fn = [](Symbol &sym) {
- if (handleNonPreemptibleIfunc(sym))
- return;
- if (sym.needsGot)
- addGotEntry(sym);
- if (sym.needsPlt)
- addPltEntry(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
- if (sym.needsCopy) {
- if (sym.isObject()) {
- addCopyRelSymbol(cast<SharedSymbol>(sym));
- // needsCopy is cleared for sym and its aliases so that in later
- // iterations aliases won't cause redundant copies.
- assert(!sym.needsCopy);
- } else {
- assert(sym.isFunc() && sym.needsPlt);
- if (!sym.isDefined()) {
- replaceWithDefined(
- sym, in.plt,
- target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
- sym.needsCopy = true;
- if (config->emachine == EM_PPC) {
- // PPC32 canonical PLT entries are at the beginning of .glink
- cast<Defined>(sym).value = in.plt->headerSize;
- in.plt->headerSize += 16;
- cast<PPC32GlinkSection>(in.plt)->canonical_plts.push_back(&sym);
- }
- }
- }
- }
- };
- for (Symbol *sym : symtab->symbols())
- fn(*sym);
-
- // Local symbols may need the aforementioned non-preemptible ifunc and GOT
- // handling. They don't need regular PLT.
- for (InputFile *file : objectFiles)
- for (Symbol *sym : cast<ELFFileBase>(file)->getLocalSymbols())
- fn(*sym);
-}
-
static bool mergeCmp(const InputSection *a, const InputSection *b) {
// std::merge requires a strict weak ordering.
if (a->outSecOff < b->outSecOff)
// Call reportUndefinedSymbols() after calling scanRelocations() to emit
// the diagnostics.
template <class ELFT> void scanRelocations(InputSectionBase &);
-void postScanRelocations();
template <class ELFT> void reportUndefinedSymbols();
// field etc) do the same trick as compiler uses to mark microMIPS
// for CPU - set the less-significant bit.
if (config->emachine == EM_MIPS && isMicroMips() &&
- ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsCopy))
+ ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsPltAddr))
va |= 1;
if (d.isTls() && !config->relocatable) {
type(type), stOther(stOther), symbolKind(k), visibility(stOther & 3),
isUsedInRegularObj(!file || file->kind() == InputFile::ObjKind),
exportDynamic(isExportDynamic(k, visibility)), inDynamicList(false),
- canInline(false), referenced(false), traced(false), isInIplt(false),
- gotInIgot(false), isPreemptible(false), used(!config->gcSections),
- needsTocRestore(false), scriptDefined(false), needsCopy(false),
- needsGot(false), needsPlt(false), hasDirectReloc(false) {}
+ canInline(false), referenced(false), traced(false), needsPltAddr(false),
+ isInIplt(false), gotInIgot(false), isPreemptible(false),
+ used(!config->gcSections), needsTocRestore(false),
+ scriptDefined(false) {}
public:
+ // True the symbol should point to its PLT entry.
+ // For SharedSymbol only.
+ uint8_t needsPltAddr : 1;
+
// True if this symbol is in the Iplt sub-section of the Plt and the Igot
// sub-section of the .got.plt or .got.
uint8_t isInIplt : 1;
// True if this symbol is defined by a linker script.
uint8_t scriptDefined : 1;
- // True if this symbol needs a canonical PLT entry, or (during
- // postScanRelocations) a copy relocation.
- uint8_t needsCopy : 1;
-
- // Temporary flags used to communicate which symbol entries need PLT and GOT
- // entries during postScanRelocations();
- uint8_t needsGot : 1;
- uint8_t needsPlt : 1;
- uint8_t hasDirectReloc : 1;
-
// The partition whose dynamic symbol table contains this symbol's definition.
uint8_t partition = 1;
static uint32_t getSymSectionIndex(Symbol *sym) {
if (getCommonSec(sym))
return SHN_COMMON;
- assert(!(sym->needsCopy && sym->isObject()));
- if (!isa<Defined>(sym) || sym->needsCopy)
+ if (!isa<Defined>(sym) || sym->needsPltAddr)
return SHN_UNDEF;
if (const OutputSection *os = sym->getOutputSection())
return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
for (SymbolTableEntry &ent : symbols) {
Symbol *sym = ent.sym;
- if (sym->isInPlt() && sym->needsCopy)
+ if (sym->isInPlt() && sym->needsPltAddr)
eSym->st_other |= STO_MIPS_PLT;
if (isMicroMips()) {
// We already set the less-significant bit for symbols
// like `objdump` will be able to deal with a correct
// symbol position.
if (sym->isDefined() &&
- ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsCopy)) {
+ ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) {
if (!strTabSec.isDynamic())
eSym->st_value &= ~1;
eSym->st_other |= STO_MIPS_MICROMIPS;
if (!config->relocatable) {
forEachRelSec(scanRelocations<ELFT>);
reportUndefinedSymbols<ELFT>();
- postScanRelocations();
}
}
# CHECK-EMPTY:
## The address of ifunc1@plt does not escape so it does not need `bti c`,
## but having bti is not wrong.
-# CHECK-NEXT: 00000000000103e0 <ifunc2>:
+# CHECK-NEXT: 00000000000103e0 <.iplt>:
# CHECK-NEXT: 103e0: bti c
# CHECK-NEXT: adrp x16, 0x30000
# CHECK-NEXT: ldr x17, [x16, #1360]
# CHECK-NEXT: add x16, x16, #1360
# CHECK-NEXT: br x17
# CHECK-NEXT: nop
+# CHECK-EMPTY:
+## The address of ifunc2 (STT_FUNC) escapes, so it must have `bti c`.
+# CHECK-NEXT: 00000000000103f8 <ifunc2>:
# CHECK-NEXT: 103f8: bti c
# CHECK-NEXT: adrp x16, 0x30000
# CHECK-NEXT: ldr x17, [x16, #1368]
# CHECK-NEXT: br x17
# CHECK-NEXT: nop
-## The address of ifunc2 (STT_FUNC) escapes, so it must have `bti c`.
-# SHARED: <ifunc2>:
+# SHARED: <.iplt>:
# SHARED-NEXT: bti c
-# SHARED: nop
+# SHARED: <ifunc2>:
# SHARED-NEXT: bti c
.section ".note.gnu.property", "a"
// adrp calculation is (PC + signed immediate) & (!0xfff)
// CHECK: <__AArch64ADRPThunk_high_target>:
// CHECK-NEXT: 14: adrp x16, 0x10000000
-// CHECK-NEXT: add x16, x16, #0x50
+// CHECK-NEXT: add x16, x16, #0x40
// CHECK-NEXT: br x16
// CHECK: <__AArch64ADRPThunk_high_target2>:
// CHECK-NEXT: 20: adrp x16, 0x10000000
bl low_target
ret
// CHECK: <high_target>:
-// CHECK-NEXT: 10000000: bl 0x10000040 <low_target@plt>
+// CHECK-NEXT: 10000000: bl 0x10000050 <low_target@plt>
// CHECK-NEXT: ret
.hidden high_target2
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-EMPTY:
-// CHECK-NEXT: <low_target@plt>:
+// CHECK-NEXT: <high_target@plt>:
// CHECK-NEXT: 10000040: adrp x16, 0x10000000
// CHECK-NEXT: ldr x17, [x16, #0x200]
// CHECK-NEXT: add x16, x16, #0x200
// CHECK-NEXT: br x17
// CHECK-EMPTY:
-// CHECK-NEXT: <high_target@plt>:
+// CHECK-NEXT: <low_target@plt>:
// CHECK-NEXT: 10000050: adrp x16, 0x10000000
// CHECK-NEXT: ldr x17, [x16, #0x208]
// CHECK-NEXT: add x16, x16, #0x208
// CHECK-NEXT: 201e4: 00 00 00 ea b 0x201ec <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>
// CHECK-NEXT: 201e8: 02 00 00 eb bl 0x201f8 <__ARMv7ABSLongThunk_bar2>
// CHECK: <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>:
-// CHECK-NEXT: 201ec: 40 c2 00 e3 movw r12, #576
+// CHECK-NEXT: 201ec: 30 c2 00 e3 movw r12, #560
// CHECK-NEXT: 201f0: 02 c2 40 e3 movt r12, #514
// CHECK-NEXT: 201f4: 1c ff 2f e1 bx r12
// CHECK: <__ARMv7ABSLongThunk_bar2>:
-// CHECK-NEXT: 201f8: 30 c2 00 e3 movw r12, #560
+// CHECK-NEXT: 201f8: 40 c2 00 e3 movw r12, #576
// CHECK-NEXT: 201fc: 02 c2 40 e3 movt r12, #514
// CHECK-NEXT: 20200: 1c ff 2f e1 bx r12
// DISASM: <bar>:
// DISASM-NEXT: 20108: bx lr
// DISASM: <_start>:
-// DISASM-NEXT: 2010c: bl 0x20140
-// DISASM-NEXT: 20110: bl 0x20130
+// DISASM-NEXT: 2010c: bl 0x20130
+// DISASM-NEXT: 20110: bl 0x20140
// 1 * 65536 + 244 = 0x100f4 __rel_iplt_start
// DISASM-NEXT: 20114: movw r0, #244
// DISASM-NEXT: 20118: movt r0, #1
// CHECK-ARM-PLT: Disassembly of section .arm_caller:
// CHECK-ARM-PLT-EMPTY:
// CHECK-ARM-PLT-NEXT: <arm_caller>:
-// CHECK-ARM-PLT-NEXT: 1300: bl 0x1630
-// CHECK-ARM-PLT-NEXT: 1304: bl 0x1630
-// CHECK-ARM-PLT-NEXT: 1308: b 0x1630
-// CHECK-ARM-PLT-NEXT: 130c: b 0x1630
+// CHECK-ARM-PLT-NEXT: 1300: bl 0x1650
+// CHECK-ARM-PLT-NEXT: 1304: bl 0x1650
+// CHECK-ARM-PLT-NEXT: 1308: b 0x1650
+// CHECK-ARM-PLT-NEXT: 130c: b 0x1650
// CHECK-ARM-PLT-NEXT: 1310: b 0x1660
// CHECK-ARM-PLT-NEXT: 1314: b 0x1670
-// CHECK-ARM-PLT-NEXT: 1318: b 0x1640
-// CHECK-ARM-PLT-NEXT: 131c: beq 0x1680
-// CHECK-ARM-PLT-NEXT: 1320: bne 0x1690
+// CHECK-ARM-PLT-NEXT: 1318: b 0x1680
+// CHECK-ARM-PLT-NEXT: 131c: beq 0x1690
+// CHECK-ARM-PLT-NEXT: 1320: bne 0x16a0
// CHECK-ARM-PLT-NEXT: 1324: bx lr
.section .thumb_caller, "ax", %progbits
// CHECK-ARM-PLT: Disassembly of section .thumb_caller:
// CHECK-ARM-PLT-EMPTY:
// CHECK-ARM-PLT-NEXT: <thumb_caller>:
-// CHECK-ARM-PLT-NEXT: 1400: blx 0x1640
-// CHECK-ARM-PLT-NEXT: 1404: blx 0x1640
+// CHECK-ARM-PLT-NEXT: 1400: blx 0x1680
+// CHECK-ARM-PLT-NEXT: 1404: blx 0x1680
// CHECK-ARM-PLT-NEXT: 1408: b.w 0x1420 <__ThumbV7PILongThunk_arm_callee1>
// CHECK-ARM-PLT-NEXT: 140c: b.w 0x142c <__ThumbV7PILongThunk_arm_callee2>
// CHECK-ARM-PLT-NEXT: 1410: b.w 0x1438 <__ThumbV7PILongThunk_arm_callee3>
// CHECK-ARM-PLT-NEXT: 000016ac <$d>:
// CHECK-ARM-PLT-NEXT: 16ac: d4 d4 d4 d4 .word 0xd4d4d4d4
-// CHECK-DSO-REL: 0x18C0 R_ARM_JUMP_SLOT thumb_callee1
-// CHECK-DSO-REL-NEXT: 0x18C4 R_ARM_JUMP_SLOT arm_callee1
-// CHECK-DSO-REL-NEXT: 0x18C8 R_ARM_JUMP_SLOT arm_caller
+// CHECK-DSO-REL: 0x18C0 R_ARM_JUMP_SLOT arm_caller
+// CHECK-DSO-REL-NEXT: 0x18C4 R_ARM_JUMP_SLOT thumb_caller
+// CHECK-DSO-REL-NEXT: 0x18C8 R_ARM_JUMP_SLOT thumb_callee1
// CHECK-DSO-REL-NEXT: 0x18CC R_ARM_JUMP_SLOT thumb_callee2
// CHECK-DSO-REL-NEXT: 0x18D0 R_ARM_JUMP_SLOT thumb_callee3
-// CHECK-DSO-REL-NEXT: 0x18D4 R_ARM_JUMP_SLOT arm_callee2
-// CHECK-DSO-REL-NEXT: 0x18D8 R_ARM_JUMP_SLOT arm_callee3
-// CHECK-DSO-REL-NEXT: 0x18DC R_ARM_JUMP_SLOT thumb_caller
+// CHECK-DSO-REL-NEXT: 0x18D4 R_ARM_JUMP_SLOT arm_callee1
+// CHECK-DSO-REL-NEXT: 0x18D8 R_ARM_JUMP_SLOT arm_callee2
+// CHECK-DSO-REL-NEXT: 0x18DC R_ARM_JUMP_SLOT arm_callee3
# REL_DEF-NEXT: }
# REL_DEF-NEXT: .rela.plt {
# REL_DEF-NEXT: R_X86_64_JUMP_SLOT default
-# REL_DEF-NEXT: R_X86_64_JUMP_SLOT notype_default
# REL_DEF-NEXT: R_X86_64_JUMP_SLOT weak_default
# REL_DEF-NEXT: R_X86_64_JUMP_SLOT ext_default
+# REL_DEF-NEXT: R_X86_64_JUMP_SLOT notype_default
# REL_DEF-NEXT: R_X86_64_JUMP_SLOT undef
# REL_DEF-NEXT: }
# REL_GFUN-NEXT: R_X86_64_64 data_default
# REL_GFUN-NEXT: }
# REL_GFUN-NEXT: .rela.plt {
-# REL_GFUN-NEXT: R_X86_64_JUMP_SLOT notype_default
# REL_GFUN-NEXT: R_X86_64_JUMP_SLOT weak_default
+# REL_GFUN-NEXT: R_X86_64_JUMP_SLOT notype_default
# REL_GFUN-NEXT: R_X86_64_JUMP_SLOT undef
# REL_GFUN-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: bar
-// CHECK-NEXT: Value: 0x401100
+// CHECK-NEXT: Value: 0x401110
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Function
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: foo
-// CHECK-NEXT: Value: 0x401110
+// CHECK-NEXT: Value: 0x401100
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Function
// DISASM: <foo_resolver>:
// DISASM-NEXT: 4010e5: retl
// DISASM: <_start>:
-// DISASM-NEXT: 4010e6: calll 0x401110 <foo>
-// DISASM-NEXT: calll 0x401100 <bar>
+// DISASM-NEXT: 4010e6: calll 0x401100 <foo>
+// DISASM-NEXT: calll 0x401110 <bar>
// DISASM-NEXT: movl $4194516, %edx
// DISASM-NEXT: movl $4194532, %edx
// DISASM-EMPTY:
// DISASM-NEXT: Disassembly of section .iplt:
// DISASM-EMPTY:
-// DISASM-NEXT: <bar>:
+// DISASM-NEXT: <foo>:
// DISASM-NEXT: 401100: jmpl *4202784
// DISASM-NEXT: pushl $0
// DISASM-NEXT: jmp 0x0
-// DISASM: <foo>:
+// DISASM: <bar>:
// DISASM-NEXT: 401110: jmpl *4202788
// DISASM-NEXT: pushl $8
// DISASM-NEXT: jmp 0x0
## st_value points to the canonical PLT entry in .glink
# SYM: Symbol table '.dynsym'
-# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func
-# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func2
+# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func
+# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func2
# SYM: 1001024c 0 FUNC GLOBAL DEFAULT UND ifunc
# SYM: Symbol table '.symtab'
-# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func
-# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func2
+# SYM: 1001023c 0 FUNC GLOBAL DEFAULT UND func
+# SYM: 1001022c 0 FUNC GLOBAL DEFAULT UND func2
# SYM: 1001024c 0 FUNC GLOBAL DEFAULT UND ifunc
# HEX: 0x10030318 1001025c 10010260 10010264
-## Canonical PLT entry of func.
-## 0x10030318 = 65536*4099+792
+## Canonical PLT entry of func2.
+## 0x1003031C = 65536*4099+796
# CHECK: 1001022c <.glink>:
# CHECK-NEXT: lis 11, 4099
-# CHECK-NEXT: lwz 11, 792(11)
+# CHECK-NEXT: lwz 11, 796(11)
# CHECK-NEXT: mtctr 11
# CHECK-NEXT: bctr
-## Canonical PLT entry of func2.
-## 0x1003031C = 65536*4099+796
+## Canonical PLT entry of func.
+## 0x10030318 = 65536*4099+792
# CHECK-NEXT: 1001023c: lis 11, 4099
-# CHECK-NEXT: lwz 11, 796(11)
+# CHECK-NEXT: lwz 11, 792(11)
# CHECK-NEXT: mtctr 11
# CHECK-NEXT: bctr
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
# RELOC: .rela.dyn {
-# RELOC-NEXT: 0x3024C R_PPC_RELATIVE - 0x101A0
-# RELOC-NEXT: 0x30250 R_PPC_IRELATIVE - 0x10188
+# RELOC-NEXT: 0x30254 R_PPC_RELATIVE - 0x101A8
+# RELOC-NEXT: 0x30258 R_PPC_IRELATIVE - 0x10188
# RELOC-NEXT: }
-# SYM: 000101a0 0 FUNC GLOBAL DEFAULT {{.*}} func
-# HEX: Hex dump of section '.got2':
-# HEX-NEXT: 0x0003024c 00000000 ....
+# SYM: 000101a8 0 FUNC GLOBAL DEFAULT {{.*}} func
+# HEX: 0x00030254 00000000
.section .got2,"aw"
.long func
# CHECK: <.text>:
# CHECK-NEXT: 10188: blr
# CHECK: <_start>:
-# CHECK-NEXT: bl 0x10190
+# CHECK-NEXT: bl 0x10198
+# CHECK-NEXT: lis 9, 1
+# CHECK-NEXT: addi 9, 9, 424
# CHECK-EMPTY:
# CHECK-NEXT: <00008000.got2.plt_pic32.func>:
## 0x10020114 = 65536*4098+276
.globl _start
_start:
bl func+0x8000@plt
+
+ lis 9, func@ha
+ la 9, func@l(9)
## Check we can handle R_PPC_GOT16, which may be generated by -fpic code.
# RELOC: .rela.dyn {
-# RELOC-NEXT: 0x10020218 R_PPC_GLOB_DAT b 0x0
+# RELOC-NEXT: 0x1002021C R_PPC_GLOB_DAT b 0x0
# RELOC-NEXT: }
-# NM: 1002020c d _GLOBAL_OFFSET_TABLE_
# NM: 10030220 d a
## The GOT slot of a can be filled at link time.
-# HEX: section '.got':
-# HEX: 0x1002020c [[#%x,]] 00000000 00000000 00000000
-# HEX-NEXT: 0x1002021c 10030220
-
-## a: &.got[4] - _GLOBAL_OFFSET_TABLE_ = 0x1002021c - 0x1002020c = 16
-## b: &.got[3] - _GLOBAL_OFFSET_TABLE_ = 0x10020218 - 0x1002020c = 12
-# CHECK: lwz 3, 16(30)
-# CHECK: lwz 4, 12(30)
+# HEX: section '.got':
+# HEX: 0x1002020c {{[0-9a-f]+}} 00000000 00000000 10030220
+
+## a: &.got[3] - _GLOBAL_OFFSET_TABLE_ = 12
+## b: &.got[4] - _GLOBAL_OFFSET_TABLE_ = 16
+# CHECK: lwz 3, 12(30)
+# CHECK: lwz 4, 16(30)
lwz 3,a@got(30)
lwz 4,b@got(30)
# SYM: Value Size Type Bind Vis Ndx
# SYM: 0000000010028298 0 NOTYPE LOCAL HIDDEN 4 .TOC.
-# SYM: 0000000010010268 0 FUNC GLOBAL DEFAULT 3 ifunc1
+# SYM: 0000000010010288 0 FUNC GLOBAL DEFAULT 3 ifunc1
# SYM: 0000000010010210 0 IFUNC GLOBAL DEFAULT 2 ifunc2
-# SYM: 0000000010010288 0 FUNC GLOBAL DEFAULT 3 ifunc3
+# SYM: 0000000010010278 0 FUNC GLOBAL DEFAULT 3 ifunc3
# SECTIONS: .plt NOBITS 00000000100302a0 0002a0 000018 00 WA 0 0 8
# CHECK-NEXT: 10010224: bl 0x10010254
# CHECK-NEXT: ld 2, 24(1)
# CHECK-NEXT: addis 3, 2, -2
-# CHECK-NEXT: addi 3, 3, 32720
-# CHECK-NEXT: addis 3, 2, -2
# CHECK-NEXT: addi 3, 3, 32752
+# CHECK-NEXT: addis 3, 2, -2
+# CHECK-NEXT: addi 3, 3, 32736
-# .plt[1] - .TOC. = 0x100302a0+8 - 0x10028298 = (1<<16) - 32752
+# .plt[0] - .TOC. = 0x100302a0 - 0x10028298 = (1<<16) - 32760
# CHECK: <__plt_ifunc2>:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 1
-# CHECK-NEXT: ld 12, -32752(12)
+# CHECK-NEXT: ld 12, -32760(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
-# .plt[2] - .TOC. = 0x100302a0+16 - 0x10028298 = (1<<16) - 32744
+# .plt[1] - .TOC. = 0x100302a0+8 - 0x10028298 = (1<<16) - 32752
# CHECK: <__plt_ifunc3>:
# CHECK-NEXT: std 2, 24(1)
# CHECK-NEXT: addis 12, 2, 1
-# CHECK-NEXT: ld 12, -32744(12)
+# CHECK-NEXT: ld 12, -32752(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
# CHECK-EMPTY:
## ifunc2 and ifunc3 have the same code sequence as their PLT call stubs.
# CHECK: Disassembly of section .glink:
# CHECK-EMPTY:
-# CHECK-NEXT: 0000000010010268 <ifunc1>:
+# CHECK-NEXT: 0000000010010268 <.glink>:
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32760(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
+# CHECK-EMPTY:
+# CHECK-NEXT: 0000000010010278 <ifunc3>:
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32752(12)
# CHECK-NEXT: mtctr 12
# CHECK-NEXT: bctr
# CHECK-EMPTY:
-# CHECK-NEXT: 0000000010010288 <ifunc3>:
+# CHECK-NEXT: 0000000010010288 <ifunc1>:
# CHECK-NEXT: addis 12, 2, 1
# CHECK-NEXT: ld 12, -32744(12)
# CHECK-NEXT: mtctr 12
// CHECK: unresolvable relocation R_X86_64_32S against symbol 'x'
// CHECK: unresolvable relocation R_X86_64_32S against symbol 'y'
// CHECK: unresolvable relocation R_X86_64_32S against symbol 'z'
-// CHECK: unresolvable relocation R_X86_64_32 against symbol 'x'
-// CHECK: unresolvable relocation R_X86_64_32 against symbol 'y'
-// CHECK: unresolvable relocation R_X86_64_32 against symbol 'z'
.text
.global _start
# SEC64: .got PROGBITS 0000000000012358 000358 000018
# RELOC32: .rela.dyn {
-# RELOC32-NEXT: 0x12210 R_RISCV_32 b 0x0
+# RELOC32-NEXT: 0x12214 R_RISCV_32 b 0x0
# RELOC32-NEXT: }
# RELOC64: .rela.dyn {
-# RELOC64-NEXT: 0x12360 R_RISCV_64 b 0x0
+# RELOC64-NEXT: 0x12368 R_RISCV_64 b 0x0
# RELOC64-NEXT: }
# NM32: 00013218 d a
# NM64: 0000000000013370 d a
## .got[0] = _DYNAMIC
-## .got[1] = 0 (relocated by R_RISCV_32/64 at runtime)
-## .got[2] = a (filled at link time)
+## .got[1] = a (filled at link time)
+## .got[2] = 0 (relocated by R_RISCV_64 at runtime)
# HEX32: section '.got':
-# HEX32: 0x0001220c ac210100 00000000 18320100
+# HEX32: 0x0001220c ac210100 18320100 00000000
# HEX64: section '.got':
-# HEX64: 0x00012358 98220100 00000000 00000000 00000000
-# HEX64: 0x00012368 70330100 00000000
+# HEX64: 0x00012358 98220100 00000000 70330100 00000000
+# HEX64: 0x00012368 00000000 00000000
-## &.got[2]-. = 0x12214-0x1119c = 4096*1+120
+## &.got[1]-. = 0x12210-0x1119c = 4096*1+116
# DIS32: 1119c: auipc a0, 1
-# DIS32-NEXT: lw a0, 120(a0)
-## &.got[1]-. = 0x12210-0x111a4 = 4096*1+108
+# DIS32-NEXT: lw a0, 116(a0)
+## &.got[2]-. = 0x12214-0x111a4 = 4096*1+112
# DIS32: 111a4: auipc a0, 1
-# DIS32-NEXT: lw a0, 108(a0)
+# DIS32-NEXT: lw a0, 112(a0)
-## &.got[2]-. = 0x12368-0x11288 = 4096*1+224
+## &.got[1]-. = 0x12360-0x11288 = 4096*1+216
# DIS64: 11288: auipc a0, 1
-# DIS64-NEXT: ld a0, 224(a0)
-## &.got[1]-. = 0x12360-0x11290 = 4096*1+208
+# DIS64-NEXT: ld a0, 216(a0)
+## &.got[2]-. = 0x12368-0x11290 = 4096*1+216
# DIS64: 11290: auipc a0, 1
-# DIS64-NEXT: ld a0, 208(a0)
+# DIS64-NEXT: ld a0, 216(a0)
la a0,a
la a0,b
# RUN: llvm-objdump -d --no-show-raw-insn %t.w1 | FileCheck %s --check-prefix=W1DIS
# W1REL: .rela.plt {
-# W1REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0
# W1REL-NEXT: R_X86_64_JUMP_SLOT __wrap_foo 0x0
+# W1REL-NEXT: R_X86_64_JUMP_SLOT foo@@v1 0x0
# W1REL-NEXT: }
# W1DIS-LABEL: <.text>:
# RUN: llvm-objdump -d --no-show-raw-insn %t.w2 | FileCheck %s --check-prefix=W2DIS
# W2REL: .rela.plt {
-# W2REL-NEXT: R_X86_64_JUMP_SLOT foo@v1 0x0
# W2REL-NEXT: R_X86_64_JUMP_SLOT __wrap_foo 0x0
+# W2REL-NEXT: R_X86_64_JUMP_SLOT foo@v1 0x0
# W2REL-NEXT: }
# W2DIS-LABEL: <.text>:
# RUN: ld.lld --version-script %t4.script -shared %t.o %tref.o -o %t5.so
# RUN: llvm-readelf -r %t5.so | FileCheck --check-prefix=RELOC %s
-# RELOC: R_X86_64_JUMP_SLOT {{.*}} foo4@@v2 + 0
# RELOC: R_X86_64_JUMP_SLOT {{.*}} foo3@v1 + 0
+# RELOC: R_X86_64_JUMP_SLOT {{.*}} foo4@@v2 + 0
.globl foo1; foo1: ret
.globl foo2; foo2: ret
// RUN: llvm-readelf -s -x .got %t | FileCheck --check-prefix=READELF --implicit-check-not=__real_ %s
// CHECK: <_start>:
-// CHECK-NEXT: movq {{.*}}(%rip), %rax # 0x2021b0
-// CHECK-NEXT: movq {{.*}}(%rip), %rbx # 0x2021b0
-// CHECK-NEXT: movq {{.*}}(%rip), %rcx # 0x2021a8
+// CHECK-NEXT: movq {{.*}}(%rip), %rax # 0x2021a8
+// CHECK-NEXT: movq {{.*}}(%rip), %rbx # 0x2021a8
+// CHECK-NEXT: movq {{.*}}(%rip), %rcx # 0x2021b0
// READELF: 0000000000011000 0 NOTYPE GLOBAL DEFAULT ABS foo
// READELF: 0000000000011010 0 NOTYPE GLOBAL DEFAULT ABS __wrap_foo
// READELF: Hex dump of section '.got':
-// READELF-NEXT: 0x[[#%x,ADDR:]] 00100100 00000000 10100100 00000000
+// READELF-NEXT: 0x[[#%x,ADDR:]] 10100100 00000000 00100100 00000000
// RUN: ld.lld -o %t2 %t1.o %t2.o %t3.so --wrap foo
// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=CHECK2 %s
// RUN: llvm-readelf -s -x .got %t2 | FileCheck --check-prefix=READELF --implicit-check-not=__real_ %s
// CHECK2: <_start>:
-// CHECK2-NEXT: movq {{.*}}(%rip), %rax # 0x2022e8
-// CHECK2-NEXT: movq {{.*}}(%rip), %rbx # 0x2022e8
-// CHECK2-NEXT: movq {{.*}}(%rip), %rcx # 0x2022e0
+// CHECK2-NEXT: movq {{.*}}(%rip), %rax # 0x2022e0
+// CHECK2-NEXT: movq {{.*}}(%rip), %rbx # 0x2022e0
+// CHECK2-NEXT: movq {{.*}}(%rip), %rcx # 0x2022e8
.global _start
_start:
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
-// CHECK-NEXT: R_X86_64_JUMP_SLOT foo 0x0
// CHECK-NEXT: R_X86_64_JUMP_SLOT __wrap_foo 0x0
+// CHECK-NEXT: R_X86_64_JUMP_SLOT foo 0x0
// CHECK-NEXT: R_X86_64_JUMP_SLOT _start 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
# DISASM: <hid>:
# DISASM-NEXT: nop
# DISASM: <_start>:
-# DISASM-NEXT: movq 4375(%rip), %rax
-# DISASM-NEXT: movq 4368(%rip), %rax
-# DISASM-NEXT: movq 4369(%rip), %rax
-# DISASM-NEXT: movq 4362(%rip), %rax
+# DISASM-NEXT: movq 4367(%rip), %rax
+# DISASM-NEXT: movq 4360(%rip), %rax
+# DISASM-NEXT: movq 4361(%rip), %rax
+# DISASM-NEXT: movq 4354(%rip), %rax
# DISASM-NEXT: leaq -36(%rip), %rax
# DISASM-NEXT: leaq -43(%rip), %rax
-# DISASM-NEXT: movq 4325(%rip), %rax
-# DISASM-NEXT: movq 4318(%rip), %rax
-# DISASM-NEXT: movq 4319(%rip), %rax
-# DISASM-NEXT: movq 4312(%rip), %rax
-# DISASM-NEXT: movq 4313(%rip), %rax
-# DISASM-NEXT: movq 4306(%rip), %rax
+# DISASM-NEXT: movq 4341(%rip), %rax
+# DISASM-NEXT: movq 4334(%rip), %rax
+# DISASM-NEXT: movq 4311(%rip), %rax
+# DISASM-NEXT: movq 4304(%rip), %rax
+# DISASM-NEXT: movq 4305(%rip), %rax
+# DISASM-NEXT: movq 4298(%rip), %rax
# DISASM-NEXT: leaq -92(%rip), %rax
# DISASM-NEXT: leaq -99(%rip), %rax
-# DISASM-NEXT: movq 4269(%rip), %rax
-# DISASM-NEXT: movq 4262(%rip), %rax
+# DISASM-NEXT: movq 4285(%rip), %rax
+# DISASM-NEXT: movq 4278(%rip), %rax
.text
.globl foo
# CHECK1: .plt PROGBITS 00000000002012e0 0002e0 000030 00 AX 0 0 16
# CHECK1: .got.plt PROGBITS 00000000002033e0 0003e0 000028 00 WA 0 0 8
# CHECK1: Relocation section '.rela.plt' at offset {{.*}} contains 2 entries:
-# CHECK1: 00000000002033f8 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 weak + 0
-# CHECK1-NEXT: 0000000000203400 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 bar + 0
+# CHECK1: 00000000002033f8 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 bar + 0
+# CHECK1-NEXT: 0000000000203400 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 weak + 0
# CHECK2: Name Type Address Off Size ES Flg Lk Inf Al
# CHECK2: .plt PROGBITS 0000000000001310 000310 000030 00 AX 0 0 16
# CHECK2: .got.plt PROGBITS 0000000000003400 000400 000028 00 WA 0 0 8
# CHECK2: Relocation section '.rela.plt' at offset {{.*}} contains 2 entries:
-# CHECK2: 0000000000003418 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 weak + 0
-# CHECK2-NEXT: 0000000000003420 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 bar + 0
+# CHECK2: 0000000000003418 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 bar + 0
+# CHECK2-NEXT: 0000000000003420 {{.*}} R_X86_64_JUMP_SLOT 0000000000000000 weak + 0
# DISASM: <_start>:
# DISASM-NEXT: callq {{.*}} <local>
# DISASM1-NEXT: jmpq *8452(%rip) # 0x2033f0
# DISASM1-NEXT: nopl (%rax)
# DISASM1-EMPTY:
-# DISASM1-NEXT: <weak@plt>:
+# DISASM1-NEXT: <bar@plt>:
# DISASM1-NEXT: 2012f0: jmpq *8450(%rip) # 0x2033f8
# DISASM1-NEXT: pushq $0
# DISASM1-NEXT: jmp 0x2012e0 <.plt>
# DISASM1-EMPTY:
-# DISASM1-NEXT: <bar@plt>:
+# DISASM1-NEXT: <weak@plt>:
# DISASM1-NEXT: 201300: jmpq *8442(%rip) # 0x203400
# DISASM1-NEXT: pushq $1
# DISASM1-NEXT: jmp 0x2012e0 <.plt>
# DISASM2-NEXT: jmpq *8436(%rip) # 0x3410
# DISASM2-NEXT: nopl (%rax)
# DISASM2-EMPTY:
-# DISASM2-NEXT: <weak@plt>:
+# DISASM2-NEXT: <bar@plt>:
# DISASM2-NEXT: 1320: jmpq *8434(%rip) # 0x3418
# DISASM2-NEXT: pushq $0
# DISASM2-NEXT: jmp 0x1310 <.plt>
# DISASM2-EMPTY:
-# DISASM2-NEXT: <bar@plt>:
+# DISASM2-NEXT: <weak@plt>:
# DISASM2-NEXT: 1330: jmpq *8426(%rip) # 0x3420
# DISASM2-NEXT: pushq $1
# DISASM2-NEXT: jmp 0x1310 <.plt>
# CHECK: .plt PROGBITS 002011e0 0001e0 000030 00 AX 0 0 16
# CHECK: .got.plt PROGBITS 00203278 000278 000028 00 WA 0 0 8
# CHECK: Relocation section '.rela.plt' at offset {{.*}} contains 2 entries:
-# CHECK: 00203290 {{.*}} R_X86_64_JUMP_SLOT 00000000 weak + 0
-# CHECK-NEXT: 00203298 {{.*}} R_X86_64_JUMP_SLOT 00000000 bar + 0
+# CHECK: 00203290 {{.*}} R_X86_64_JUMP_SLOT 00000000 bar + 0
+# CHECK-NEXT: 00203298 {{.*}} R_X86_64_JUMP_SLOT 00000000 weak + 0
# DISASM: <_start>:
# DISASM-NEXT: callq {{.*}} <local>
# DISASM-NEXT: jmpq *8348(%rip) # 0x203288
# DISASM-NEXT: nopl (%rax)
# DISASM-EMPTY:
-# DISASM-NEXT: <weak@plt>:
+# DISASM-NEXT: <bar@plt>:
# DISASM-NEXT: 2011f0: jmpq *8346(%rip) # 0x203290
# DISASM-NEXT: pushq $0
# DISASM-NEXT: jmp 0x2011e0 <.plt>
# DISASM-EMPTY:
-# DISASM-NEXT: <bar@plt>:
+# DISASM-NEXT: <weak@plt>:
# DISASM-NEXT: 201200: jmpq *8338(%rip) # 0x203298
# DISASM-NEXT: pushq $1
# DISASM-NEXT: jmp 0x2011e0 <.plt>