return Value;
}
+ // AliasedSymbol() - If this is an alias (a = b), return the symbol
+ // we ultimately point to. For a non alias, this just returns the symbol
+ // itself.
+ const MCSymbol &AliasedSymbol() const;
+
void setVariableValue(const MCExpr *Value);
/// @}
return 0;
}
-static const MCSymbol &AliasedSymbol(const MCSymbol &Symbol) {
- const MCSymbol *S = &Symbol;
- while (S->isVariable()) {
- const MCExpr *Value = S->getVariableValue();
- MCExpr::ExprKind Kind = Value->getKind();
- switch (Kind) {
- case MCExpr::SymbolRef: {
- const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
- S = &Ref->getSymbol();
- break;
- }
- case MCExpr::Target: {
- const MCTargetExpr *TExp = static_cast<const MCTargetExpr*>(Value);
- MCValue Res;
- TExp->EvaluateAsRelocatableImpl(Res, NULL);
- S = &Res.getSymA()->getSymbol();
- break;
- }
- default:
- return *S;
- }
- }
- return *S;
-}
-
void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
ie = Asm.symbol_end(); it != ie; ++it) {
const MCSymbol &Alias = it->getSymbol();
- const MCSymbol &Symbol = AliasedSymbol(Alias);
+ const MCSymbol &Symbol = Alias.AliasedSymbol();
MCSymbolData &SD = Asm.getSymbolData(Symbol);
// Not an alias.
const MCAsmLayout &Layout) {
MCSymbolData &OrigData = *MSD.SymbolData;
MCSymbolData &Data =
- Layout.getAssembler().getSymbolData(AliasedSymbol(OrigData.getSymbol()));
+ Layout.getAssembler().getSymbolData(OrigData.getSymbol().AliasedSymbol());
bool IsReserved = Data.isCommon() || Data.getSymbol().isAbsolute() ||
Data.getSymbol().isVariable();
const MCValue &Target,
const MCFragment &F) const {
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
- const MCSymbol &ASymbol = AliasedSymbol(Symbol);
- const MCSymbol *RenamedP = Renames.lookup(&Symbol);
-
- if (!RenamedP) {
- if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None ||
- Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref)
- RenamedP = &ASymbol;
- else
- RenamedP = &Symbol;
+ const MCSymbol &ASymbol = Symbol.AliasedSymbol();
+ const MCSymbol *Renamed = Renames.lookup(&Symbol);
+ const MCSymbolData &SD = Asm.getSymbolData(Symbol);
+
+ if (ASymbol.isUndefined()) {
+ if (Renamed)
+ return Renamed;
+ return &ASymbol;
}
- const MCSymbol &Renamed = *RenamedP;
-
- MCSymbolData &SD = Asm.getSymbolData(Symbol);
-
- if (Symbol.isUndefined())
- return &Renamed;
- if (SD.isExternal())
- return &Renamed;
+ if (SD.isExternal()) {
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
+ }
const MCSectionELF &Section =
- static_cast<const MCSectionELF&>(Symbol.getSection());
+ static_cast<const MCSectionELF&>(ASymbol.getSection());
if (Section.getKind().isBSS())
return NULL;
if (&Sec2 != &Section &&
(Kind == MCSymbolRefExpr::VK_PLT ||
Kind == MCSymbolRefExpr::VK_GOTPCREL ||
- Kind == MCSymbolRefExpr::VK_GOTOFF))
- return &Renamed;
+ Kind == MCSymbolRefExpr::VK_GOTOFF)) {
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
+ }
if (Section.getFlags() & MCSectionELF::SHF_MERGE) {
- if (Target.getConstant() != 0)
- return &Renamed;
- return NULL;
+ if (Target.getConstant() == 0)
+ return NULL;
+ if (Renamed)
+ return Renamed;
+ return &Symbol;
}
return NULL;
if (Symbol.getName() == "_GLOBAL_OFFSET_TABLE_")
return true;
- const MCSymbol &A = AliasedSymbol(Symbol);
+ const MCSymbol &A = Symbol.AliasedSymbol();
if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
return false;
return false;
const MCSymbol &Symbol = Data.getSymbol();
- const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
+ const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
if (RefSymbol.isUndefined() && !RefSymbol.isVariable()) {
if (isSignature && !isUsedInReloc)
ELFSymbolData MSD;
MSD.SymbolData = it;
- const MCSymbol &RefSymbol = AliasedSymbol(Symbol);
+ const MCSymbol &RefSymbol = Symbol.AliasedSymbol();
// Undefined symbols are global, but this is the first place we
// are able to set it.
const MCSection *SectionA = 0;
const MCSymbol *SymbolA = 0;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
- SymbolA = &A->getSymbol();
+ SymbolA = &A->getSymbol().AliasedSymbol();
SectionA = &SymbolA->getSection();
}
const MCSection *SectionB = 0;
if (const MCSymbolRefExpr *B = Target.getSymB()) {
- SectionB = &B->getSymbol().getSection();
+ SectionB = &B->getSymbol().AliasedSymbol().getSection();
}
if (!BaseSection)
int Index = 0;
int64_t Value = Target.getConstant();
const MCSymbol &Symbol = Target.getSymA()->getSymbol();
+ const MCSymbol &ASymbol = Symbol.AliasedSymbol();
const MCSymbol *RelocSymbol = SymbolToReloc(Asm, Target, *Fragment);
bool IsPCRel = isFixupKindX86PCRel(Fixup.getKind());
}
if (!RelocSymbol) {
- MCSymbolData &SD = Asm.getSymbolData(Symbol);
+ MCSymbolData &SD = Asm.getSymbolData(ASymbol);
MCFragment *F = SD.getFragment();
Index = F->getParent()->getOrdinal();
Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
bool IsResolved = true;
if (const MCSymbolRefExpr *A = Target.getSymA()) {
- if (A->getSymbol().isDefined())
- Value += Layout.getSymbolAddress(&getSymbolData(A->getSymbol()));
+ const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
+ if (Sym.isDefined())
+ Value += Layout.getSymbolAddress(&getSymbolData(Sym));
else
IsResolved = false;
}
if (const MCSymbolRefExpr *B = Target.getSymB()) {
- if (B->getSymbol().isDefined())
- Value -= Layout.getSymbolAddress(&getSymbolData(B->getSymbol()));
+ const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
+ if (Sym.isDefined())
+ Value -= Layout.getSymbolAddress(&getSymbolData(Sym));
else
IsResolved = false;
}
Symbol->setVariableValue(AddValueSymbols(Value));
}
-// This is a hack. To be able to implement weakrefs the writer has to be able
-// to distinguish
-// .weakref foo, bar
-// .long foo
-// from
-// .weakref foo, bar
-// .long bar
-// since the first case should produce a weak undefined reference and the second
-// one a strong one.
-// If we created foo as a regular alias pointing to bar (foo = bar), then
-// MCExpr::EvaluateAsRelocatable would recurse on foo and the writer would
-// never see it used in a relocation.
-// What we do is create a MCTargetExpr that when evaluated produces a symbol
-// ref to a temporary symbol. This temporary symbol in turn is a variable
-// that equals the original symbol (tmp = bar). With this hack the writer
-// gets a relocation with tmp and can correctly implement weak references.
-
-namespace {
-class WeakRefExpr : public MCTargetExpr {
-private:
- const MCSymbolRefExpr *Alias;
-
- explicit WeakRefExpr(const MCSymbolRefExpr *Alias_)
- : MCTargetExpr(), Alias(Alias_) {}
-
-public:
- virtual void PrintImpl(raw_ostream &OS) const {
- llvm_unreachable("Unimplemented");
- }
-
- virtual bool EvaluateAsRelocatableImpl(MCValue &Res,
- const MCAsmLayout *Layout) const {
- Res = MCValue::get(Alias, 0, 0);
- return true;
- }
-
- static const WeakRefExpr *Create(const MCSymbol *Alias, MCContext &Ctx) {
- const MCSymbolRefExpr *A = MCSymbolRefExpr::Create(Alias, Ctx);
- return new (Ctx) WeakRefExpr(A);
- }
-};
-} // end anonymous namespace
-
void MCELFStreamer::SwitchSection(const MCSection *Section) {
const MCSymbol *Grp = static_cast<const MCSectionELF *>(Section)->getGroup();
if (Grp)
getAssembler().getOrCreateSymbolData(*Symbol);
MCSymbolData &AliasSD = getAssembler().getOrCreateSymbolData(*Alias);
AliasSD.setFlags(AliasSD.getFlags() | ELF_Other_Weakref);
-
- // Create the alias that actually points to Symbol
- const MCSymbolRefExpr *SymRef = MCSymbolRefExpr::Create(Symbol, getContext());
- MCSymbol *RealAlias = getContext().CreateTempSymbol();
- RealAlias->setVariableValue(SymRef);
-
- MCSymbolData &RealAliasSD = getAssembler().getOrCreateSymbolData(*RealAlias);
- RealAliasSD.setFlags(RealAliasSD.getFlags() | ELF_Other_Weakref);
-
- const MCExpr *Value = WeakRefExpr::Create(RealAlias, getContext());
+ const MCExpr *Value = MCSymbolRefExpr::Create(Symbol, getContext());
Alias->setVariableValue(Value);
}
const MCSymbol &Sym = SRE->getSymbol();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None)
- return Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
- true);
+ if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) {
+ bool Ret = Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+ true);
+ // If we failed to simplify this to a constant, let the target
+ // handle it.
+ if (Ret && !Res.getSymA() && !Res.getSymB())
+ return true;
+ }
Res = MCValue::get(SRE, 0, 0);
return true;
return false;
}
+const MCSymbol &MCSymbol::AliasedSymbol() const {
+ const MCSymbol *S = this;
+ while (S->isVariable()) {
+ const MCExpr *Value = S->getVariableValue();
+ if (Value->getKind() != MCExpr::SymbolRef)
+ return *S;
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Value);
+ S = &Ref->getSymbol();
+ }
+ return *S;
+}
+
void MCSymbol::setVariableValue(const MCExpr *Value) {
assert(!IsUsed && "Cannot set a variable that has already been used.");
assert(Value && "Invalid variable value!");
.section zed, "", @progbits
call bar@PLT
+
+// Test that this produres a relocation with bar2
+
+ .weak foo2
+foo2:
+ .weak bar2
+ .set bar2,foo2
+ .quad bar2
+
// CHECK: # Symbol 0x00000001
// CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
// CHECK-NEXT: ('st_bind', 0x00000000)
// CHECK-NEXT: ('st_size', 0x00000000)
// CHECK-NEXT: ),
+// CHECK: # Symbol 0x00000006
+// CHECK-NEXT: (('st_name', 0x0000000e) # 'bar2'
+// CHECK-NEXT: ('st_bind', 0x00000002)
+// CHECK-NEXT: ('st_type', 0x00000000)
+// CHECK-NEXT: ('st_other', 0x00000000)
+// CHECK-NEXT: ('st_shndx', 0x00000004)
+// CHECK-NEXT: ('st_value', 0x00000005)
+// CHECK-NEXT: ('st_size', 0x00000000)
+// CHECK-NEXT: ),
+
// CHECK: # Relocation 0x00000000
// CHECK-NEXT: (('r_offset', 0x00000001)
// CHECK-NEXT: ('r_sym', 0x00000001)
// CHECK-NEXT: ('r_type', 0x00000004)
// CHECK-NEXT: ('r_addend', 0xfffffffc)
// CHECK-NEXT: ),
+
+// CHECK: # Relocation 0x00000001
+// CHECK-NEXT: (('r_offset', 0x00000005)
+// CHECK-NEXT: ('r_sym', 0x00000006)
+// CHECK-NEXT: ('r_type', 0x00000001)
+// CHECK-NEXT: ('r_addend', 0x00000000)
+// CHECK-NEXT: ),