forked from OSchip/llvm-project
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:
parent
c74503ea21
commit
fee224f942
|
@ -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;
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue