Provide a version of getSymbolOffset that returns false on error.

This simplifies ELFObjectWriter::SymbolValue a bit more. This new version
will also be used in the COFF writer to fix pr19147.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207711 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2014-04-30 21:51:13 +00:00
parent b861d48f79
commit 593cb79eb5
3 changed files with 53 additions and 38 deletions

View File

@ -102,6 +102,10 @@ public:
/// \brief Get the offset of the given symbol, as computed in the current /// \brief Get the offset of the given symbol, as computed in the current
/// layout. /// layout.
/// \result True on success.
bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const;
/// \brief Variant that reports a fatal error if the offset is not computable.
uint64_t getSymbolOffset(const MCSymbolData *SD) const; uint64_t getSymbolOffset(const MCSymbolData *SD) const;
/// @} /// @}

View File

@ -486,34 +486,16 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
Write16(ShstrtabIndex); Write16(ShstrtabIndex);
} }
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData, uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
const MCAsmLayout &Layout) { const MCAsmLayout &Layout) {
MCSymbolData *Data = &OrigData; if (Data.isCommon() && Data.isExternal())
if (Data->isCommon() && Data->isExternal()) return Data.getCommonAlignment();
return Data->getCommonAlignment();
const MCSymbol *Symbol = &Data->getSymbol(); uint64_t Res;
MCAssembler &Asm = Layout.getAssembler(); if (!Layout.getSymbolOffset(&Data, Res))
bool IsThumb = Asm.isThumbFunc(Symbol);
// Given how we implement symver, we can end up with an symbol reference
// to an undefined symbol. Walk past it first.
if (Symbol->isVariable()) {
const MCExpr *Expr = Symbol->getVariableValue();
if (auto *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
if (Ref->getKind() == MCSymbolRefExpr::VK_None) {
Symbol = &Ref->getSymbol();
Data = &Asm.getOrCreateSymbolData(*Symbol);
}
}
}
if (!Symbol->isVariable() && !Data->getFragment())
return 0; return 0;
uint64_t Res = Layout.getSymbolOffset(Data); if (Layout.getAssembler().isThumbFunc(&Data.getSymbol()))
if (IsThumb)
Res |= 1; Res |= 1;
return Res; return Res;

View File

@ -118,37 +118,66 @@ uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const {
} }
// Simple getSymbolOffset helper for the non-varibale case. // Simple getSymbolOffset helper for the non-varibale case.
static uint64_t getLabelOffset(const MCAsmLayout &Layout, static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbolData &SD,
const MCSymbolData &SD) { bool ReportError, uint64_t &Val) {
if (!SD.getFragment()) if (!SD.getFragment()) {
report_fatal_error("unable to evaluate offset to undefined symbol '" + if (ReportError)
SD.getSymbol().getName() + "'"); report_fatal_error("unable to evaluate offset to undefined symbol '" +
return Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset(); SD.getSymbol().getName() + "'");
return false;
}
Val = Layout.getFragmentOffset(SD.getFragment()) + SD.getOffset();
return true;
} }
uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const { static bool getSymbolOffsetImpl(const MCAsmLayout &Layout,
const MCSymbolData *SD, bool ReportError,
uint64_t &Val) {
const MCSymbol &S = SD->getSymbol(); const MCSymbol &S = SD->getSymbol();
if (!S.isVariable()) if (!S.isVariable())
return getLabelOffset(*this, *SD); return getLabelOffset(Layout, *SD, ReportError, Val);
// If SD is a variable, evaluate it. // If SD is a variable, evaluate it.
MCValue Target; MCValue Target;
if (!S.getVariableValue()->EvaluateAsValue(Target, this)) if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout))
report_fatal_error("unable to evaluate offset for variable '" + report_fatal_error("unable to evaluate offset for variable '" +
S.getName() + "'"); S.getName() + "'");
uint64_t Offset = Target.getConstant(); uint64_t Offset = Target.getConstant();
const MCAssembler &Asm = Layout.getAssembler();
const MCSymbolRefExpr *A = Target.getSymA(); const MCSymbolRefExpr *A = Target.getSymA();
if (A) if (A) {
Offset += getLabelOffset(*this, Assembler.getSymbolData(A->getSymbol())); uint64_t ValA;
if (!getLabelOffset(Layout, Asm.getSymbolData(A->getSymbol()), ReportError,
ValA))
return false;
Offset += ValA;
}
const MCSymbolRefExpr *B = Target.getSymB(); const MCSymbolRefExpr *B = Target.getSymB();
if (B) if (B) {
Offset -= getLabelOffset(*this, Assembler.getSymbolData(B->getSymbol())); uint64_t ValB;
if (!getLabelOffset(Layout, Asm.getSymbolData(B->getSymbol()), ReportError,
ValB))
return false;
Offset -= ValB;
}
return Offset; Val = Offset;
return true;
}
bool MCAsmLayout::getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const {
return getSymbolOffsetImpl(*this, SD, false, Val);
}
uint64_t MCAsmLayout::getSymbolOffset(const MCSymbolData *SD) const {
uint64_t Val;
getSymbolOffsetImpl(*this, SD, true, Val);
return Val;
} }
uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const { uint64_t MCAsmLayout::getSectionAddressSize(const MCSectionData *SD) const {