MC: Rework .weakref
Use a variable symbol without any specifier instead of VK_WEAKREF. Add code in ELFObjectWriter::executePostLayoutBinding to check whether the target should be made an undefined weak symbol. This change fixes several issues: * Unreferenced `.weakref alias, target` no longer creates an undefined `target`. * When `alias` is already defined, report an error instead of crashing. .weakref is specific to ELF. llvm-ml has reused the VK_WEAKREF name for a different concept. wasm incorrectly copied the ELF implementation. Remove it.
This commit is contained in:
@@ -110,10 +110,10 @@ foo:
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weak_var0 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weak_var1 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weak_var2 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 temp 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weakref_alias_var0 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weakref_alias_var1 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 weakref_alias_var2 0x0
|
||||
# CHECK-NEXT: R_AMDGPU_ABS64 temp 0x0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
|
||||
|
||||
@@ -149,6 +149,8 @@ public:
|
||||
|
||||
DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
|
||||
DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
|
||||
// .weakref aliases
|
||||
SmallVector<const MCSymbolELF *, 0> Weakrefs;
|
||||
bool IsLittleEndian = false;
|
||||
bool SeenGnuAbi = false;
|
||||
std::optional<uint8_t> OverrideABIVersion;
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
|
||||
void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F,
|
||||
uint64_t Offset) override;
|
||||
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
|
||||
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) override;
|
||||
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
|
||||
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
Align ByteAlignment) override;
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
SMLoc Loc = SMLoc()) override;
|
||||
void emitULEB128Value(const MCExpr *Value) override;
|
||||
void emitSLEB128Value(const MCExpr *Value) override;
|
||||
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
|
||||
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) override;
|
||||
void changeSection(MCSection *Section, uint32_t Subsection = 0) override;
|
||||
void switchSectionNoPrint(MCSection *Section) override;
|
||||
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
|
||||
|
||||
@@ -38,8 +38,8 @@ public:
|
||||
|
||||
bool isBindingSet() const;
|
||||
|
||||
void setIsWeakrefUsedInReloc() const;
|
||||
bool isWeakrefUsedInReloc() const;
|
||||
void setIsWeakref() const;
|
||||
bool isWeakref() const;
|
||||
|
||||
void setIsSignature() const;
|
||||
bool isSignature() const;
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
|
||||
void emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc, MCDataFragment &F,
|
||||
uint64_t Offset) override;
|
||||
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
|
||||
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
|
||||
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
Align ByteAlignment) override;
|
||||
|
||||
@@ -476,10 +476,9 @@ bool ELFWriter::isInSymtab(const MCSymbolELF &Symbol, bool Used, bool Renamed) {
|
||||
if (const auto *T = dyn_cast<MCTargetExpr>(Expr))
|
||||
if (T->inlineAssignedExpr())
|
||||
return false;
|
||||
if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
|
||||
if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
|
||||
return false;
|
||||
}
|
||||
// The .weakref alias does not appear in the symtab.
|
||||
if (Symbol.isWeakref())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Used)
|
||||
@@ -531,10 +530,8 @@ void ELFWriter::computeSymbolTable(const RevGroupMapTy &RevGroupMap) {
|
||||
for (auto It : llvm::enumerate(Asm.symbols())) {
|
||||
const auto &Symbol = cast<MCSymbolELF>(It.value());
|
||||
bool Used = Symbol.isUsedInReloc();
|
||||
bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
|
||||
bool isSignature = Symbol.isSignature();
|
||||
|
||||
if (!isInSymtab(Symbol, Used || WeakrefUsed || isSignature,
|
||||
if (!isInSymtab(Symbol, Used || isSignature,
|
||||
OWriter.Renames.count(&Symbol)))
|
||||
continue;
|
||||
|
||||
@@ -1245,6 +1242,21 @@ void ELFObjectWriter::executePostLayoutBinding() {
|
||||
Sym = Sym->getSection().getBeginSymbol();
|
||||
Sym->setUsedInReloc();
|
||||
}
|
||||
|
||||
// For each `.weakref alias, target`, if the variable `alias` is registered
|
||||
// (typically through MCObjectStreamer::visitUsedSymbol), register `target`.
|
||||
// If `target` was unregistered before (not directly referenced or defined),
|
||||
// make it weak.
|
||||
for (const MCSymbol *Alias : Weakrefs) {
|
||||
if (!Alias->isRegistered())
|
||||
continue;
|
||||
auto *Expr = Alias->getVariableValue();
|
||||
if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
|
||||
auto &Sym = cast<MCSymbolELF>(Inner->getSymbol());
|
||||
if (Asm->registerSymbol(Sym))
|
||||
Sym.setBinding(ELF::STB_WEAK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It is always valid to create a relocation with a symbol. It is preferable
|
||||
@@ -1323,17 +1335,6 @@ void ELFObjectWriter::recordRelocation(const MCFragment &F,
|
||||
MCContext &Ctx = getContext();
|
||||
|
||||
const auto *SymA = cast_or_null<MCSymbolELF>(Target.getAddSym());
|
||||
bool ViaWeakRef = false;
|
||||
if (SymA && SymA->isVariable()) {
|
||||
const MCExpr *Expr = SymA->getVariableValue();
|
||||
if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
|
||||
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
|
||||
SymA = cast<MCSymbolELF>(&Inner->getSymbol());
|
||||
ViaWeakRef = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MCSectionELF *SecA = (SymA && SymA->isInSection())
|
||||
? cast<MCSectionELF>(&SymA->getSection())
|
||||
: nullptr;
|
||||
@@ -1393,10 +1394,7 @@ void ELFObjectWriter::recordRelocation(const MCFragment &F,
|
||||
if (const MCSymbolELF *R = Renames.lookup(SymA))
|
||||
SymA = R;
|
||||
|
||||
if (ViaWeakRef)
|
||||
SymA->setIsWeakrefUsedInReloc();
|
||||
else
|
||||
SymA->setUsedInReloc();
|
||||
SymA->setUsedInReloc();
|
||||
}
|
||||
}
|
||||
Relocations[&FixupSection].emplace_back(FixupOffset, SymA, Type, Addend);
|
||||
|
||||
@@ -112,11 +112,16 @@ void MCELFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
|
||||
Asm.registerSymbol(*Section->getBeginSymbol());
|
||||
}
|
||||
|
||||
void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
const MCExpr *Value = MCSymbolRefExpr::create(
|
||||
Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
|
||||
Alias->setVariableValue(Value);
|
||||
void MCELFStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Target) {
|
||||
auto *A = cast<MCSymbolELF>(Alias);
|
||||
if (A->isDefined()) {
|
||||
getContext().reportError(getStartTokLoc(), "symbol '" + A->getName() +
|
||||
"' is already defined");
|
||||
return;
|
||||
}
|
||||
A->setVariableValue(MCSymbolRefExpr::create(Target, getContext()));
|
||||
A->setIsWeakref();
|
||||
getWriter().Weakrefs.push_back(A);
|
||||
}
|
||||
|
||||
// When GNU as encounters more than one .type declaration for an object it seems
|
||||
|
||||
@@ -478,12 +478,7 @@ static bool canExpand(const MCSymbol &Sym, bool InSet) {
|
||||
if (Sym.isWeakExternal())
|
||||
return false;
|
||||
|
||||
const MCExpr *Expr = Sym.getVariableValue();
|
||||
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
|
||||
if (Inner) {
|
||||
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
|
||||
return false;
|
||||
}
|
||||
Sym.getVariableValue(true);
|
||||
|
||||
if (InSet)
|
||||
return true;
|
||||
|
||||
@@ -278,8 +278,8 @@ void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
|
||||
}
|
||||
|
||||
void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
|
||||
const MCSymbol *Symbol) {
|
||||
report_fatal_error("This file format doesn't support weak aliases.");
|
||||
const MCSymbol *Target) {
|
||||
reportFatalUsageError("this file format doesn't support weak aliases");
|
||||
}
|
||||
|
||||
void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
|
||||
|
||||
@@ -30,7 +30,7 @@ enum {
|
||||
ELF_IsSignature_Shift = 10,
|
||||
|
||||
// One bit.
|
||||
ELF_WeakrefUsedInReloc_Shift = 11,
|
||||
ELF_Weakref_Shift = 11,
|
||||
|
||||
// One bit.
|
||||
ELF_BindingSet_Shift = 12,
|
||||
@@ -84,8 +84,6 @@ unsigned MCSymbolELF::getBinding() const {
|
||||
return ELF::STB_LOCAL;
|
||||
if (isUsedInReloc())
|
||||
return ELF::STB_GLOBAL;
|
||||
if (isWeakrefUsedInReloc())
|
||||
return ELF::STB_WEAK;
|
||||
if (isSignature())
|
||||
return ELF::STB_LOCAL;
|
||||
return ELF::STB_GLOBAL;
|
||||
@@ -170,13 +168,13 @@ unsigned MCSymbolELF::getOther() const {
|
||||
return Other << 5;
|
||||
}
|
||||
|
||||
void MCSymbolELF::setIsWeakrefUsedInReloc() const {
|
||||
uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_WeakrefUsedInReloc_Shift);
|
||||
setFlags(OtherFlags | (1 << ELF_WeakrefUsedInReloc_Shift));
|
||||
void MCSymbolELF::setIsWeakref() const {
|
||||
uint32_t OtherFlags = getFlags() & ~(0x1 << ELF_Weakref_Shift);
|
||||
setFlags(OtherFlags | (1 << ELF_Weakref_Shift));
|
||||
}
|
||||
|
||||
bool MCSymbolELF::isWeakrefUsedInReloc() const {
|
||||
return getFlags() & (0x1 << ELF_WeakrefUsedInReloc_Shift);
|
||||
bool MCSymbolELF::isWeakref() const {
|
||||
return getFlags() & (0x1 << ELF_Weakref_Shift);
|
||||
}
|
||||
|
||||
void MCSymbolELF::setIsSignature() const {
|
||||
|
||||
@@ -70,14 +70,6 @@ void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
|
||||
Asm.registerSymbol(*Section->getBeginSymbol());
|
||||
}
|
||||
|
||||
void MCWasmStreamer::emitWeakReference(MCSymbol *Alias,
|
||||
const MCSymbol *Symbol) {
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
const MCExpr *Value = MCSymbolRefExpr::create(
|
||||
Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
|
||||
Alias->setVariableValue(Value);
|
||||
}
|
||||
|
||||
bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
|
||||
assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
|
||||
|
||||
|
||||
@@ -525,13 +525,6 @@ void WasmObjectWriter::recordRelocation(const MCFragment &F,
|
||||
return;
|
||||
}
|
||||
|
||||
if (SymA->isVariable()) {
|
||||
const MCExpr *Expr = SymA->getVariableValue();
|
||||
if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
|
||||
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
|
||||
llvm_unreachable("weakref used in reloc not yet implemented");
|
||||
}
|
||||
|
||||
// Put any constant offset in an addend. Offsets can be negative, and
|
||||
// LLVM expects wrapping, in contrast to wasm's immediates which can't
|
||||
// be negative and don't wrap.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s | llvm-readelf -s - | FileCheck %s
|
||||
# RUN: not llvm-mc -filetype=obj -triple=x86_64 --defsym ERR=1 %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
|
||||
|
||||
// This is a long test that checks that the aliases created by weakref are
|
||||
// never in the symbol table and that the only case it causes a symbol to
|
||||
@@ -12,17 +13,18 @@
|
||||
# CHECK-NEXT: 3: 0000000000000018 0 NOTYPE LOCAL DEFAULT 2 bar7
|
||||
# CHECK-NEXT: 4: 000000000000001c 0 NOTYPE LOCAL DEFAULT 2 bar8
|
||||
# CHECK-NEXT: 5: 0000000000000020 0 NOTYPE LOCAL DEFAULT 2 bar9
|
||||
# CHECK-NEXT: 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar1
|
||||
# CHECK-NEXT: 7: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar2
|
||||
# CHECK-NEXT: 8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND bar3
|
||||
# CHECK-NEXT: 9: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar4
|
||||
# CHECK-NEXT: 10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar5
|
||||
# CHECK-NEXT: 11: 0000000000000028 0 NOTYPE GLOBAL DEFAULT 2 bar10
|
||||
# CHECK-NEXT: 12: 0000000000000030 0 NOTYPE GLOBAL DEFAULT 2 bar11
|
||||
# CHECK-NEXT: 13: 0000000000000030 0 NOTYPE GLOBAL DEFAULT 2 bar12
|
||||
# CHECK-NEXT: 14: 0000000000000034 0 NOTYPE GLOBAL DEFAULT 2 bar13
|
||||
# CHECK-NEXT: 15: 0000000000000038 0 NOTYPE GLOBAL DEFAULT 2 bar14
|
||||
# CHECK-NEXT: 16: 0000000000000040 0 NOTYPE GLOBAL DEFAULT 2 bar15
|
||||
# CHECK-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar2
|
||||
# CHECK-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar4
|
||||
# CHECK-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar5
|
||||
# CHECK-NEXT: 0000000000000028 0 NOTYPE GLOBAL DEFAULT 2 bar10
|
||||
# CHECK-NEXT: 0000000000000030 0 NOTYPE GLOBAL DEFAULT 2 bar11
|
||||
# CHECK-NEXT: 0000000000000030 0 NOTYPE GLOBAL DEFAULT 2 bar12
|
||||
# CHECK-NEXT: 0000000000000034 0 NOTYPE GLOBAL DEFAULT 2 bar13
|
||||
# CHECK-NEXT: 0000000000000038 0 NOTYPE GLOBAL DEFAULT 2 bar14
|
||||
# CHECK-NEXT: 0000000000000040 0 NOTYPE GLOBAL DEFAULT 2 bar15
|
||||
# CHECK-NEXT: 0000000000000000 0 NOTYPE WEAK DEFAULT UND bar3
|
||||
# CHECK-NEXT: 0000000000000000 0 NOTYPE WEAK DEFAULT UND bar16
|
||||
# CHECK-EMPTY:
|
||||
|
||||
.weakref foo1, bar1
|
||||
|
||||
@@ -87,3 +89,20 @@ bar15:
|
||||
.weakref foo15, bar15
|
||||
.long bar15
|
||||
.long foo15
|
||||
|
||||
.long foo16
|
||||
.weakref foo16, bar16
|
||||
|
||||
.ifdef ERR
|
||||
alias:
|
||||
.weakref alias, target
|
||||
# ERR: [[#@LINE-1]]:1: error: symbol 'alias' is already defined
|
||||
|
||||
.set alias1, 1
|
||||
.weakref alias1, target
|
||||
# ERR: [[#@LINE-1]]:1: error: symbol 'alias1' is already defined
|
||||
|
||||
.weakref alias2, target
|
||||
.set alias2, 1
|
||||
|
||||
.endif
|
||||
|
||||
Reference in New Issue
Block a user