diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2014-03-14 20:09:04 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2014-03-14 20:09:04 +0000 |
commit | 8953f81f671fc6077b46ac1f600b4d29456aa265 (patch) | |
tree | e9e39ed279c17c796b695d730f3f810a92581cd4 /llvm/lib/MC/ELFObjectWriter.cpp | |
parent | 622831b7399d0672d390c3ada9726febf8d86e6a (diff) | |
download | bcm5719-llvm-8953f81f671fc6077b46ac1f600b4d29456aa265.tar.gz bcm5719-llvm-8953f81f671fc6077b46ac1f600b4d29456aa265.zip |
Correctly handle an ELF symbol defined with "a = b + expr".
We were marking the symbol as absolute instead of computing b's offset + the
expression value.
This fixes pr19126.
llvm-svn: 203962
Diffstat (limited to 'llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 909ea800830..0f3fa04c079 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); |