diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 86 | ||||
-rw-r--r-- | llvm/lib/MC/MCSymbol.cpp | 17 |
2 files changed, 66 insertions, 37 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 909ea80..0f3fa04 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -271,6 +271,7 @@ class ELFObjectWriter : public MCObjectWriter { /// \param RevGroupMap - Maps a signature symbol to the group section. /// \param NumRegularSections - Number of non-relocation sections. void ComputeSymbolTable(MCAssembler &Asm, + const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, RevGroupMapTy RevGroupMap, unsigned NumRegularSections); @@ -462,33 +463,43 @@ void ELFObjectWriter::WriteSymbolEntry(MCDataFragment *SymtabF, } } -uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data, +uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData, const MCAsmLayout &Layout) { - if (Data.isCommon() && Data.isExternal()) - return Data.getCommonAlignment(); - - const MCSymbol &Symbol = Data.getSymbol(); - - if (Symbol.isAbsolute() && Symbol.isVariable()) { - if (const MCExpr *Value = Symbol.getVariableValue()) { - int64_t IntValue; - if (Value->EvaluateAsAbsolute(IntValue, Layout)) - return (uint64_t)IntValue; - } + MCSymbolData *Data = &OrigData; + if (Data->isCommon() && Data->isExternal()) + return Data->getCommonAlignment(); + + const MCSymbol *Symbol = &Data->getSymbol(); + + uint64_t Res = 0; + if (Symbol->isVariable()) { + const MCExpr *Expr = Symbol->getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + return 0; + if (Value.getSymB()) + return 0; + Res = Value.getConstant(); + + const MCSymbolRefExpr *A = Value.getSymA(); + if (!A) + return Res; + + Symbol = &A->getSymbol(); + Data = &Layout.getAssembler().getSymbolData(*Symbol); } - if (!Symbol.isInSection()) + if (!Symbol->isInSection()) return 0; + if (!Data->getFragment()) + return 0; - if (Data.getFragment()) { - if (Data.getFlags() & ELF_Other_ThumbFunc) - return Layout.getSymbolOffset(&Data)+1; - else - return Layout.getSymbolOffset(&Data); - } + Res += Layout.getSymbolOffset(Data); + if (Data->getFlags() & ELF_Other_ThumbFunc) + ++Res; - return 0; + return Res; } void ELFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, @@ -586,7 +597,7 @@ void ELFObjectWriter::WriteSymbol(MCDataFragment *SymtabF, uint8_t Other = MCELF::getOther(OrigData) << (ELF_STO_Shift - ELF_STV_Shift); Other |= Visibility; - uint64_t Value = SymbolValue(Data, Layout); + uint64_t Value = SymbolValue(OrigData, Layout); uint64_t Size = 0; assert(!(Data.isCommon() && !Data.isExternal())); @@ -897,10 +908,11 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, } } -void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, - const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap, - unsigned NumRegularSections) { +void +ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, + const SectionIndexMapTy &SectionIndexMap, + RevGroupMapTy RevGroupMap, + unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? if (NeedsGOT) { @@ -948,33 +960,33 @@ void ELFObjectWriter::ComputeSymbolTable(MCAssembler &Asm, ELFSymbolData MSD; MSD.SymbolData = it; - const MCSymbol &RefSymbol = Symbol.AliasedSymbol(); + const MCSymbol *BaseSymbol = Symbol.getBaseSymbol(Layout); // Undefined symbols are global, but this is the first place we // are able to set it. bool Local = isLocal(*it, isSignature, Used); if (!Local && MCELF::GetBinding(*it) == ELF::STB_LOCAL) { - MCSymbolData &SD = Asm.getSymbolData(RefSymbol); + assert(BaseSymbol); + MCSymbolData &SD = Asm.getSymbolData(*BaseSymbol); MCELF::SetBinding(*it, ELF::STB_GLOBAL); MCELF::SetBinding(SD, ELF::STB_GLOBAL); } - if (RefSymbol.isUndefined() && !Used && WeakrefUsed) - MCELF::SetBinding(*it, ELF::STB_WEAK); - - if (it->isCommon()) { + if (!BaseSymbol) { + MSD.SectionIndex = ELF::SHN_ABS; + } else if (it->isCommon()) { assert(!Local); MSD.SectionIndex = ELF::SHN_COMMON; - } else if (Symbol.isAbsolute() || RefSymbol.isVariable()) { - MSD.SectionIndex = ELF::SHN_ABS; - } else if (RefSymbol.isUndefined()) { + } else if (BaseSymbol->isUndefined()) { if (isSignature && !Used) MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); else MSD.SectionIndex = ELF::SHN_UNDEF; + if (!Used && WeakrefUsed) + MCELF::SetBinding(*it, ELF::STB_WEAK); } else { const MCSectionELF &Section = - static_cast<const MCSectionELF&>(RefSymbol.getSection()); + static_cast<const MCSectionELF&>(BaseSymbol->getSection()); MSD.SectionIndex = SectionIndexMap.lookup(&Section); if (MSD.SectionIndex >= ELF::SHN_LORESERVE) NeedsSymtabShndx = true; @@ -1560,8 +1572,8 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm, unsigned NumRegularSections = NumUserSections + NumIndexedSections; // Compute symbol table information. - ComputeSymbolTable(Asm, SectionIndexMap, RevGroupMap, NumRegularSections); - + ComputeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, + NumRegularSections); WriteRelocations(Asm, const_cast<MCAsmLayout&>(Layout), RelMap); diff --git a/llvm/lib/MC/MCSymbol.cpp b/llvm/lib/MC/MCSymbol.cpp index 2416525..d0283a6 100644 --- a/llvm/lib/MC/MCSymbol.cpp +++ b/llvm/lib/MC/MCSymbol.cpp @@ -9,6 +9,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -51,6 +52,22 @@ const MCSymbol &MCSymbol::AliasedSymbol() const { return *S; } +const MCSymbol *MCSymbol::getBaseSymbol(const MCAsmLayout &Layout) const { + if (!isVariable()) + return this; + + const MCExpr *Expr = getVariableValue(); + MCValue Value; + if (!Expr->EvaluateAsRelocatable(Value, &Layout)) + return nullptr; + + if (Value.getSymB()) + return nullptr; + if (const MCSymbolRefExpr *A = Value.getSymA()) + return &A->getSymbol(); + return nullptr; +} + void MCSymbol::setVariableValue(const MCExpr *Value) { assert(!IsUsed && "Cannot set a variable that has already been used."); assert(Value && "Invalid variable value!"); |