diff --git a/llvm/include/llvm/MC/MCAsmLayout.h b/llvm/include/llvm/MC/MCAsmLayout.h index 1b20d5b804a4ba546ddf2bc541421600848d1e5d..802b5739c545f92bda54b55713a17dc6096fcd8d 100644 --- a/llvm/include/llvm/MC/MCAsmLayout.h +++ b/llvm/include/llvm/MC/MCAsmLayout.h @@ -39,7 +39,7 @@ class MCAsmLayout { /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. - void ensureValid(const MCFragment *F) const; + bool ensureValid(const MCFragment *F) const; /// \brief Is the layout for this fragment valid? bool isFragmentValid(const MCFragment *F) const; @@ -73,7 +73,7 @@ public: /// @{ /// \brief Get the offset of the given fragment inside its containing section. - uint64_t getFragmentOffset(const MCFragment *F) const; + uint64_t getFragmentOffset(const MCFragment *F, bool &valid) const; /// @} /// \name Utility Functions diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 10f3228002c5227695db219644a681dbfff07e18..8262a6a266068fd44d57d4888bf1b1fc29149a06 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -618,7 +618,8 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, bool &IsPCRel, uint64_t &FixedValue) { const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent()); uint64_t C = Target.getConstant(); - uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + bool valid; + uint64_t FixupOffset = Layout.getFragmentOffset(Fragment, valid) + Fixup.getOffset(); MCContext &Ctx = Asm.getContext(); if (const MCSymbolRefExpr *RefB = Target.getSymB()) { diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index dac547fd6f1ce83731fc34414eb5cc9df95ecbbf..0d969de1eef74a1fd31bd37feac2e9f9974986bf 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -213,7 +213,12 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, "FKF_IsAlignedDownTo32Bits is only allowed on PC-relative fixups!"); if (IsPCRel) { - uint64_t Offset = Layout.getFragmentOffset(DF) + Fixup.getOffset(); + bool valid; + uint64_t Offset = Layout.getFragmentOffset(DF, valid) + Fixup.getOffset(); + if (!valid) { + KsError = KS_ERR_ASM_FRAGMENT_INVALID; + return false; + } // A number of ARM fixups in Thumb mode require that the effective PC // address be determined as the 32-bit aligned version of the actual offset. @@ -251,7 +256,10 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_Align: { const MCAlignFragment &AF = cast<MCAlignFragment>(F); - unsigned Offset = Layout.getFragmentOffset(&AF); + unsigned Offset = Layout.getFragmentOffset(&AF, valid); + if (!valid) { + return 0; + } unsigned Size = OffsetToAlignment(Offset, AF.getAlignment()); // If we are padding with nops, force the padding to be larger than the // minimum nop size. @@ -274,7 +282,10 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, } // FIXME: We need a way to communicate this error. - uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); + uint64_t FragmentOffset = Layout.getFragmentOffset(&OF, valid); + if (!valid) { + return 0; + } int64_t TargetLocation = Value.getConstant(); if (const MCSymbolRefExpr *A = Value.getSymA()) { uint64_t Val; @@ -868,6 +879,7 @@ bool MCAssembler::layoutOnce(MCAsmLayout &Layout) void MCAssembler::finishLayout(MCAsmLayout &Layout) { // The layout is done. Mark every fragment as valid. for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { - Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin()); + bool valid; + Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin(), valid); } } diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 444009a750bb323c987a5fef71a6c102a10ce3f7..8e0ec62738790c7f429c89c601403a71f93fd316 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -59,7 +59,8 @@ void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { LastValidFragment[F->getParent()] = F->getPrevNode(); } -void MCAsmLayout::ensureValid(const MCFragment *F) const { +bool MCAsmLayout::ensureValid(const MCFragment *F) const +{ MCSection *Sec = F->getParent(); MCSection::iterator I; if (MCFragment *Cur = LastValidFragment[Sec]) @@ -69,29 +70,47 @@ void MCAsmLayout::ensureValid(const MCFragment *F) const { // Advance the layout position until the fragment is valid. while (!isFragmentValid(F)) { - assert(I != Sec->end() && "Layout bookkeeping error"); + //assert(I != Sec->end() && "Layout bookkeeping error"); + if (I == Sec->end()) + return false; const_cast<MCAsmLayout *>(this)->layoutFragment(&*I); ++I; } + + return true; } -uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F) const { - ensureValid(F); - assert(F->Offset != ~UINT64_C(0) && "Address not set!"); +uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F, bool &valid) const +{ + valid = true; + if (!ensureValid(F)) { + valid = false; + return 0; + } + //assert(F->Offset != ~UINT64_C(0) && "Address not set!"); + if (F->Offset == ~UINT64_C(0)) { + valid = false; + return 0; + } + return F->Offset; } // Simple getSymbolOffset helper for the non-varibale case. static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, - bool ReportError, uint64_t &Val) { + bool ReportError, uint64_t &Val) +{ if (!S.getFragment()) { if (ReportError) report_fatal_error("unable to evaluate offset to undefined symbol '" + S.getName() + "'"); return false; } - Val = Layout.getFragmentOffset(S.getFragment()) + S.getOffset(); - return true; + + bool valid; + Val = Layout.getFragmentOffset(S.getFragment(), valid) + S.getOffset(); + + return valid; } static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, @@ -174,11 +193,12 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { return &ASym; } -uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const { +uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const +{ // The size is the last fragment's end offset. const MCFragment &F = Sec->getFragmentList().back(); - bool valid; - return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F, valid); + bool valid, valid2; + return getFragmentOffset(&F, valid2) + getAssembler().computeFragmentSize(*this, F, valid); } uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const {