diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index 1493fa2..eba5b08 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -150,6 +150,7 @@ public: unsigned Size) override; bool mayHaveInstructions(MCSection &Sec) const override; + uint64_t getCurrentFragmentSize() override; }; } // end namespace llvm diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 22db69f..d55b5da 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -230,6 +230,10 @@ public: void generateCompactUnwindEncodings(MCAsmBackend *MAB); + // \brief Returns the current size of the fragment to which the streamer + // is emitting code to. + virtual uint64_t getCurrentFragmentSize() {return 0; } + /// \name Assembly File Formatting. /// @{ diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index cbb96e5..a3648bd 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -463,7 +463,7 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), + DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); } @@ -473,7 +473,7 @@ void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) { MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), + DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 8, 0); } @@ -526,3 +526,10 @@ unsigned int MCObjectStreamer::FinishImpl() return KsError; } + +uint64_t MCObjectStreamer::getCurrentFragmentSize() { + auto *F = dyn_cast_or_null(getCurrentFragment()); + if (nullptr != F) + return F->getContents().size(); + return 0; +} diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9bc787c..44a6179 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -1680,8 +1680,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, // First query the target-specific parser. It will return 'true' if it // isn't interested in this directive. - if (!getTargetParser().ParseDirective(ID)) - return false; + uint64_t BytesInFragment = getStreamer().getCurrentFragmentSize(); + if (!getTargetParser().ParseDirective(ID)){ + // increment the address for the next statement if the directive + // has emitted any value to the streamer. + Address += getStreamer().getCurrentFragmentSize() - BytesInFragment; + return false; + } // Next, check the extension directive map to see if any extension has // registered itself to parse this directive. diff --git a/suite/regress/all_archs_value_directive.py b/suite/regress/all_archs_value_directive.py new file mode 100755 index 0000000..0691cc4 --- /dev/null +++ b/suite/regress/all_archs_value_directive.py @@ -0,0 +1,49 @@ +#!/usr/bin/python + +# Test for relative branch offsets validation after an instruction encoded which +# is specified using in byte encoded form using .word directive. + +# Author: Jatin Kataria + +from keystone import (Ks, KS_ARCH_ARM, KS_ARCH_PPC, KS_MODE_ARM, + KS_MODE_PPC32, KS_MODE_BIG_ENDIAN) +import regress + + +class TestARM(regress.RegressTest): + asm = b""" +mov r0, #0x30 +bl #3230052728 +.word 0xe6000010 +mov r0, #0x41 +bl #3230052712 +""" + + def runTest(self): + ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) + encoding, count = ks.asm(self.asm, 0xc0000000) + expected_encoding = [48, 0, 160, 227, 91, 172, 33, 235, 16, + 0, 0, 230, 65, 0, 160, 227, 84, 172, 33, 235] + self.assertEqual(encoding, expected_encoding) + + +class TestPPC(regress.RegressTest): + asm = b""" +li 4, 1; +addi 4, 4, 1; +bl 0xc000; +.long 0x38800001; +addi 5, 5, 1; +bl 0xc008; +""" + + def runTest(self): + ks = Ks(KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN) + encoding, count = ks.asm(self.asm, 0xc0000000) + expected_encoding = [56, 128, 0, 1, 56, 132, 0, 1, 72, 0, 191, 249, 56, + 128, 0, 1, 56, 165, 0, 1, 72, 0, 191, 249] + self.assertEqual(encoding, expected_encoding) + + +if __name__ == '__main__': + regress.main()