From 070b5add699add385384c5a17835cc614cbb62b9 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh <aquynh@gmail.com> Date: Tue, 31 May 2016 15:08:32 +0800 Subject: [PATCH] x86: fix crash-21-x64-llvm-error-expected-absolute-expression.c --- bindings/go/keystone/keystone_const.go | 1 + bindings/nodejs/consts/keystone.js | 1 + bindings/python/keystone/keystone_const.py | 1 + .../lib/keystone/keystone_const.rb | 1 + bindings/rust/src/keystone_const.rs | 1 + include/keystone/keystone.h | 1 + llvm/include/llvm/MC/MCAssembler.h | 5 +- llvm/keystone/ks.cpp | 2 + llvm/lib/MC/ELFObjectWriter.cpp | 2 + llvm/lib/MC/MCAssembler.cpp | 57 ++++++++++++++----- llvm/lib/MC/MCFragment.cpp | 3 +- 11 files changed, 59 insertions(+), 16 deletions(-) diff --git a/bindings/go/keystone/keystone_const.go b/bindings/go/keystone/keystone_const.go index 0c232a2..1b89932 100644 --- a/bindings/go/keystone/keystone_const.go +++ b/bindings/go/keystone/keystone_const.go @@ -95,6 +95,7 @@ const ( ERR_ASM_INSN_UNSUPPORTED Error = 158 ERR_ASM_FIXUP_INVALID Error = 159 ERR_ASM_LABEL_INVALID Error = 160 + ERR_ASM_FRAGMENT_INVALID Error = 161 ERR_ASM_INVALIDOPERAND Error = 512 ERR_ASM_MISSINGFEATURE Error = 513 ERR_ASM_MNEMONICFAIL Error = 514 diff --git a/bindings/nodejs/consts/keystone.js b/bindings/nodejs/consts/keystone.js index e8d33bf..d08941b 100644 --- a/bindings/nodejs/consts/keystone.js +++ b/bindings/nodejs/consts/keystone.js @@ -71,6 +71,7 @@ module.exports.ERR_ASM_TOKEN_INVALID = 157 module.exports.ERR_ASM_INSN_UNSUPPORTED = 158 module.exports.ERR_ASM_FIXUP_INVALID = 159 module.exports.ERR_ASM_LABEL_INVALID = 160 +module.exports.ERR_ASM_FRAGMENT_INVALID = 161 module.exports.ERR_ASM_INVALIDOPERAND = 512 module.exports.ERR_ASM_MISSINGFEATURE = 513 module.exports.ERR_ASM_MNEMONICFAIL = 514 diff --git a/bindings/python/keystone/keystone_const.py b/bindings/python/keystone/keystone_const.py index 853e0f7..b19e620 100644 --- a/bindings/python/keystone/keystone_const.py +++ b/bindings/python/keystone/keystone_const.py @@ -71,6 +71,7 @@ KS_ERR_ASM_TOKEN_INVALID = 157 KS_ERR_ASM_INSN_UNSUPPORTED = 158 KS_ERR_ASM_FIXUP_INVALID = 159 KS_ERR_ASM_LABEL_INVALID = 160 +KS_ERR_ASM_FRAGMENT_INVALID = 161 KS_ERR_ASM_INVALIDOPERAND = 512 KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 diff --git a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb index bdcc354..d21c7a8 100644 --- a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb +++ b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb @@ -73,6 +73,7 @@ module Keystone KS_ERR_ASM_INSN_UNSUPPORTED = 158 KS_ERR_ASM_FIXUP_INVALID = 159 KS_ERR_ASM_LABEL_INVALID = 160 + KS_ERR_ASM_FRAGMENT_INVALID = 161 KS_ERR_ASM_INVALIDOPERAND = 512 KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 diff --git a/bindings/rust/src/keystone_const.rs b/bindings/rust/src/keystone_const.rs index b138756..ba04139 100644 --- a/bindings/rust/src/keystone_const.rs +++ b/bindings/rust/src/keystone_const.rs @@ -140,6 +140,7 @@ bitflags! { const ERR_ASM_INSN_UNSUPPORTED = 158, const ERR_ASM_FIXUP_INVALID = 159, const ERR_ASM_LABEL_INVALID = 160, + const ERR_ASM_FRAGMENT_INVALID = 161, const ERR_ASM_INVALIDOPERAND = 512, const ERR_ASM_MISSINGFEATURE = 513, const ERR_ASM_MNEMONICFAIL = 514, diff --git a/include/keystone/keystone.h b/include/keystone/keystone.h index ad8bff1..515e7ab 100644 --- a/include/keystone/keystone.h +++ b/include/keystone/keystone.h @@ -130,6 +130,7 @@ typedef enum ks_err { KS_ERR_ASM_INSN_UNSUPPORTED, // this instruction is unsupported in this mode KS_ERR_ASM_FIXUP_INVALID, // invalid fixup KS_ERR_ASM_LABEL_INVALID, // invalid label + KS_ERR_ASM_FRAGMENT_INVALID, // invalid fragment // generic input assembly errors - architecture specific KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH, diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 1e504fd..93542b6 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -55,8 +55,11 @@ struct DataRegionData { class MCAssembler { friend class MCAsmLayout; + mutable unsigned KsError; public: + void setError(unsigned E) const { KsError = E; } + unsigned getError() const { return KsError; } typedef std::vector<MCSection *> SectionListType; typedef std::vector<const MCSymbol *> SymbolDataListType; @@ -200,7 +203,7 @@ public: /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, - const MCFragment &F) const; + const MCFragment &F, bool &valid) const; /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp index 1602c79..65c836c 100644 --- a/llvm/keystone/ks.cpp +++ b/llvm/keystone/ks.cpp @@ -134,6 +134,8 @@ const char *ks_strerror(ks_err code) return "Invalid fixup (KS_ERR_ASM_FIXUP_INVALID)"; case KS_ERR_ASM_LABEL_INVALID: return "Invalid label (KS_ERR_ASM_LABEL_INVALID)"; + case KS_ERR_ASM_FRAGMENT_INVALID: + return "Invalid fragment (KS_ERR_ASM_FRAGMENT_INVALID)"; } } diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 8f17f7d..10f3228 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1185,6 +1185,8 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm, const MCSymbolELF *SignatureSymbol = Section.getGroup(); writeSectionData(Asm, Section, Layout); + if (Asm.getError()) + return; uint64_t SecEnd = getStream().tell(); SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 7a8407c..dac547f 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -230,7 +230,9 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, } uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, - const MCFragment &F) const { + const MCFragment &F, bool &valid) const +{ + valid = true; switch (F.getKind()) { case MCFragment::FT_Data: return cast<MCDataFragment>(F).getContents().size(); @@ -265,22 +267,31 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, case MCFragment::FT_Org: { const MCOrgFragment &OF = cast<MCOrgFragment>(F); MCValue Value; - if (!OF.getOffset().evaluateAsValue(Value, Layout)) - report_fatal_error("expected assembly-time absolute expression"); + if (!OF.getOffset().evaluateAsValue(Value, Layout)) { + //report_fatal_error("expected assembly-time absolute expression"); + valid = false; + return 0; + } // FIXME: We need a way to communicate this error. uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); int64_t TargetLocation = Value.getConstant(); if (const MCSymbolRefExpr *A = Value.getSymA()) { uint64_t Val; - if (!Layout.getSymbolOffset(A->getSymbol(), Val)) - report_fatal_error("expected absolute expression"); + if (!Layout.getSymbolOffset(A->getSymbol(), Val)) { + //report_fatal_error("expected absolute expression"); + valid = false; + return 0; + } TargetLocation += Val; } int64_t Size = TargetLocation - FragmentOffset; - if (Size < 0 || Size >= 0x40000000) - report_fatal_error("invalid .org offset '" + Twine(TargetLocation) + - "' (at offset '" + Twine(FragmentOffset) + "')"); + if (Size < 0 || Size >= 0x40000000) { + //report_fatal_error("invalid .org offset '" + Twine(TargetLocation) + + // "' (at offset '" + Twine(FragmentOffset) + "')"); + valid = false; + return 0; + } return Size; } @@ -295,7 +306,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, llvm_unreachable("invalid fragment kind"); } -void MCAsmLayout::layoutFragment(MCFragment *F) { +void MCAsmLayout::layoutFragment(MCFragment *F) +{ MCFragment *Prev = F->getPrevNode(); // We should never try to recompute something which is valid. @@ -305,11 +317,15 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { assert((!Prev || isFragmentValid(Prev)) && "Attempt to compute fragment before its predecessor!"); + bool valid = true; // Compute fragment offset and size. if (Prev) - F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); + F->Offset = Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev, valid); else F->Offset = getAssembler().getContext().getBaseAddress(); + if (!valid) { + return; + } LastValidFragment[F->getParent()] = F; // If bundling is enabled and this fragment has instructions in it, it has to @@ -342,7 +358,8 @@ void MCAsmLayout::layoutFragment(MCFragment *F) { if (Assembler.isBundlingEnabled() && F->hasInstructions()) { assert(isa<MCEncodedFragment>(F) && "Only MCEncodedFragment implementations have instructions"); - uint64_t FSize = Assembler.computeFragmentSize(*this, *F); + bool valid; + uint64_t FSize = Assembler.computeFragmentSize(*this, *F, valid); if (!Assembler.getRelaxAll() && FSize > Assembler.getBundleAlignSize()) report_fatal_error("Fragment can't be larger than a bundle size"); @@ -400,11 +417,20 @@ void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize, /// \brief Write the fragment \p F to the output file. static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment &F) { + const MCFragment &F) +{ + if (Asm.getError()) + return; + MCObjectWriter *OW = &Asm.getWriter(); + bool valid; // FIXME: Embed in fragments instead? - uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); + uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F, valid); + if (!valid) { + Asm.setError(KS_ERR_ASM_FRAGMENT_INVALID); + return; + } Asm.writeFragmentPadding(F, FragmentSize, OW); @@ -524,7 +550,8 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, } void MCAssembler::writeSectionData(const MCSection *Sec, - const MCAsmLayout &Layout) const { + const MCAsmLayout &Layout) const +{ // Ignore virtual sections. if (Sec->isVirtualSection()) { assert(Layout.getSectionFileSize(Sec) == 0 && "Invalid size for section!"); @@ -570,6 +597,7 @@ void MCAssembler::writeSectionData(const MCSection *Sec, uint64_t Start = getWriter().getStream().tell(); (void)Start; + setError(0); for (const MCFragment &F : *Sec) writeFragment(*this, Layout, F); @@ -695,6 +723,7 @@ void MCAssembler::Finish(unsigned int &KsError) { // Write the object file. if (!KsError) getWriter().writeObject(*this, Layout); + KsError = getError(); } bool MCAssembler::fixupNeedsRelaxation(const MCFixup &Fixup, diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index 3113b60..444009a 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -177,7 +177,8 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const { // The size is the last fragment's end offset. const MCFragment &F = Sec->getFragmentList().back(); - return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F); + bool valid; + return getFragmentOffset(&F) + getAssembler().computeFragmentSize(*this, F, valid); } uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const { -- GitLab