forked from OSchip/llvm-project
Revert D114783 [ELF] Split scanRelocations into scanRelocations/postScanRelocations
May cause a failure for non-preemptible `bcmp` in a glibc -static link.
This commit is contained in:
parent
8bd106a891
commit
ea15b862d7
|
@ -690,11 +690,11 @@ void AArch64BtiPac::writePlt(uint8_t *buf, const Symbol &sym,
|
|||
};
|
||||
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);
|
||||
|
|
|
@ -58,7 +58,7 @@ static std::vector<Defined *> getSymbols() {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -307,8 +307,6 @@ static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
|
|||
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.
|
||||
|
@ -353,7 +351,7 @@ static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
|
|||
// 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)
|
||||
|
@ -384,26 +382,6 @@ template <class ELFT> static void addCopyRelSymbolImpl(SharedSymbol &ss) {
|
|||
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
|
||||
|
@ -1067,7 +1045,7 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
|
|||
" 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;
|
||||
|
@ -1105,8 +1083,20 @@ static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
|
|||
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;
|
||||
}
|
||||
|
@ -1435,6 +1425,14 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
|
|||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -1445,13 +1443,98 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
|
|||
// 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;
|
||||
} 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);
|
||||
|
@ -1532,121 +1615,6 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &s) {
|
|||
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)
|
||||
|
|
|
@ -126,7 +126,6 @@ struct JumpInstrMod {
|
|||
// Call reportUndefinedSymbols() after calling scanRelocations() to emit
|
||||
// the diagnostics.
|
||||
template <class ELFT> void scanRelocations(InputSectionBase &);
|
||||
void postScanRelocations();
|
||||
|
||||
template <class ELFT> void reportUndefinedSymbols();
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ static uint64_t getSymVA(const Symbol &sym, int64_t addend) {
|
|||
// 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) {
|
||||
|
|
|
@ -245,12 +245,16 @@ protected:
|
|||
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;
|
||||
|
@ -275,16 +279,6 @@ public:
|
|||
// 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;
|
||||
|
||||
|
|
|
@ -2175,8 +2175,7 @@ static BssSection *getCommonSec(Symbol *sym) {
|
|||
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
|
||||
|
@ -2251,7 +2250,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
|
|||
|
||||
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
|
||||
|
@ -2262,7 +2261,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
|
|||
// 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;
|
||||
|
|
|
@ -1947,7 +1947,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
|||
if (!config->relocatable) {
|
||||
forEachRelSec(scanRelocations<ELFT>);
|
||||
reportUndefinedSymbols<ELFT>();
|
||||
postScanRelocations();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,13 +35,16 @@
|
|||
# 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]
|
||||
|
@ -49,11 +52,10 @@
|
|||
# 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"
|
||||
|
|
|
@ -36,7 +36,7 @@ low_target2:
|
|||
// 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
|
||||
|
@ -57,7 +57,7 @@ high_target:
|
|||
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
|
||||
|
@ -90,13 +90,13 @@ 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
|
||||
|
|
|
@ -27,10 +27,10 @@ _start:
|
|||
// 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
|
||||
|
|
|
@ -118,8 +118,8 @@ _start:
|
|||
// 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
|
||||
|
|
|
@ -139,15 +139,15 @@ arm_caller:
|
|||
// 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
|
||||
|
@ -229,8 +229,8 @@ thumb_caller:
|
|||
// 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>
|
||||
|
@ -365,11 +365,11 @@ _start:
|
|||
// 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
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
# 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: }
|
||||
|
||||
|
@ -62,8 +62,8 @@
|
|||
# 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: }
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
// 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
|
||||
|
@ -80,7 +80,7 @@
|
|||
// 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
|
||||
|
@ -114,18 +114,18 @@
|
|||
// 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
|
||||
|
|
|
@ -24,28 +24,28 @@
|
|||
|
||||
## 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
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
# 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
|
||||
|
@ -22,7 +21,9 @@
|
|||
# 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
|
||||
|
@ -40,3 +41,6 @@ func:
|
|||
.globl _start
|
||||
_start:
|
||||
bl func+0x8000@plt
|
||||
|
||||
lis 9, func@ha
|
||||
la 9, func@l(9)
|
||||
|
|
|
@ -12,21 +12,19 @@
|
|||
## 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
|
||||
# HEX: 0x1002020c {{[0-9a-f]+}} 00000000 00000000 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)
|
||||
## 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)
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
# 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
|
||||
|
||||
|
@ -32,23 +32,23 @@
|
|||
# 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:
|
||||
|
@ -57,17 +57,19 @@
|
|||
## 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
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
// 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
|
||||
|
|
|
@ -25,39 +25,39 @@
|
|||
# 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
|
||||
|
|
|
@ -105,8 +105,8 @@
|
|||
# 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>:
|
||||
|
@ -121,8 +121,8 @@
|
|||
# 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>:
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
# 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
|
||||
|
|
|
@ -9,23 +9,23 @@
|
|||
// 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:
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
// 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: ]
|
||||
|
|
|
@ -23,22 +23,22 @@
|
|||
# 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
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
# 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>
|
||||
|
@ -37,12 +37,12 @@
|
|||
# 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>
|
||||
|
@ -55,12 +55,12 @@
|
|||
# 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>
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
# 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>
|
||||
|
@ -27,12 +27,12 @@
|
|||
# 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>
|
||||
|
|
Loading…
Reference in New Issue