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.

llvm-svn: 207711
This commit is contained in:
Rafael Espindola 2014-04-30 21:51:13 +00:00
parent c74503ea21
commit fee224f942
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
/// 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;
/// @}

View File

@ -486,34 +486,16 @@ void ELFObjectWriter::WriteHeader(const MCAssembler &Asm,
Write16(ShstrtabIndex);
}
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &OrigData,
uint64_t ELFObjectWriter::SymbolValue(MCSymbolData &Data,
const MCAsmLayout &Layout) {
MCSymbolData *Data = &OrigData;
if (Data->isCommon() && Data->isExternal())
return Data->getCommonAlignment();
if (Data.isCommon() && Data.isExternal())
return Data.getCommonAlignment();
const MCSymbol *Symbol = &Data->getSymbol();
MCAssembler &Asm = Layout.getAssembler();
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())
uint64_t Res;
if (!Layout.getSymbolOffset(&Data, Res))
return 0;
uint64_t Res = Layout.getSymbolOffset(Data);
if (IsThumb)
if (Layout.getAssembler().isThumbFunc(&Data.getSymbol()))
Res |= 1;
return Res;

View File

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