diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 99e705e596f..7da4d7c15e3 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -138,6 +138,11 @@ namespace llvm { 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); /// @} diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index e11d68e8d8d..18d8e74216b 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -504,31 +504,6 @@ static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout) { 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(Value); - S = &Ref->getSymbol(); - break; - } - case MCExpr::Target: { - const MCTargetExpr *TExp = static_cast(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. @@ -536,7 +511,7 @@ void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { 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. @@ -572,7 +547,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, 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(); @@ -673,28 +648,24 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, const MCValue &Target, const MCFragment &F) const { const MCSymbol &Symbol = Target.getSymA()->getSymbol(); - const MCSymbol &ASymbol = AliasedSymbol(Symbol); - const MCSymbol *RenamedP = Renames.lookup(&Symbol); + const MCSymbol &ASymbol = Symbol.AliasedSymbol(); + const MCSymbol *Renamed = Renames.lookup(&Symbol); + const MCSymbolData &SD = Asm.getSymbolData(Symbol); - if (!RenamedP) { - if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None || - Asm.getSymbolData(Symbol).getFlags() & ELF_Other_Weakref) - RenamedP = &ASymbol; - else - RenamedP = &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(Symbol.getSection()); + static_cast(ASymbol.getSection()); if (Section.getKind().isBSS()) return NULL; @@ -706,13 +677,18 @@ const MCSymbol *ELFObjectWriter::SymbolToReloc(const MCAssembler &Asm, 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; @@ -742,7 +718,7 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, 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; @@ -761,7 +737,7 @@ static bool isLocal(const MCSymbolData &Data, bool isSignature, 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) @@ -830,7 +806,7 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, 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. @@ -1104,13 +1080,13 @@ bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, 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) @@ -1413,6 +1389,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, 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()); @@ -1432,7 +1409,7 @@ void X86ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, } if (!RelocSymbol) { - MCSymbolData &SD = Asm.getSymbolData(Symbol); + MCSymbolData &SD = Asm.getSymbolData(ASymbol); MCFragment *F = SD.getFragment(); Index = F->getParent()->getOrdinal(); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 8e87d5b5ee9..c80dc3c2483 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -285,14 +285,16 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, 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; } diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index a2d94f5ba15..157c0c0b647 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -240,49 +240,6 @@ void MCELFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 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(Section)->getGroup(); if (Grp) @@ -294,16 +251,7 @@ void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 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); } diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index b1617ecc5ec..eea736e559f 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -336,9 +336,14 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, 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; diff --git a/lib/MC/MCSymbol.cpp b/lib/MC/MCSymbol.cpp index ebd3144a153..1c71f267a4b 100644 --- a/lib/MC/MCSymbol.cpp +++ b/lib/MC/MCSymbol.cpp @@ -39,6 +39,18 @@ static bool NameNeedsQuoting(StringRef Str) { 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(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!"); diff --git a/test/MC/ELF/alias-reloc.s b/test/MC/ELF/alias-reloc.s index 352a2a2a042..6ad11343aec 100644 --- a/test/MC/ELF/alias-reloc.s +++ b/test/MC/ELF/alias-reloc.s @@ -8,6 +8,15 @@ bar = foo .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) @@ -18,9 +27,26 @@ bar = foo // 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: ),