From eef53eb33facbb0d44a42bac6a07679a33c27cda Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 16 Jan 2017 16:51:59 -0500 Subject: [PATCH 1/3] added regress test for effect of .word directive on relative jumps. --- suite/regress/all_archs_value_directive.py | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 suite/regress/all_archs_value_directive.py diff --git a/suite/regress/all_archs_value_directive.py b/suite/regress/all_archs_value_directive.py new file mode 100755 index 0000000..814450f --- /dev/null +++ b/suite/regress/all_archs_value_directive.py @@ -0,0 +1,51 @@ +#!/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): + return + 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): + return + 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() From c513bef6f244d766b062cdd627d3fa7847d11a74 Mon Sep 17 00:00:00 2001 From: Jatin Kataria Date: Mon, 16 Jan 2017 16:43:47 -0500 Subject: [PATCH 2/3] added support to get current fragment size in the streamer interface. This fixes the address update issue in case of directive emitting values in between instructions and breaking the follow up relative jumps --- llvm/include/llvm/MC/MCObjectStreamer.h | 1 + llvm/include/llvm/MC/MCStreamer.h | 4 ++++ llvm/lib/MC/MCObjectStreamer.cpp | 11 +++++++++-- llvm/lib/MC/MCParser/AsmParser.cpp | 9 +++++++-- 4 files changed, 21 insertions(+), 4 deletions(-) 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. From 1c3a6387d5b61bd2f836510c4b56aa135399d325 Mon Sep 17 00:00:00 2001 From: jatin Date: Mon, 16 Jan 2017 18:57:41 -0500 Subject: [PATCH 3/3] enabling regression test --- suite/regress/all_archs_value_directive.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/suite/regress/all_archs_value_directive.py b/suite/regress/all_archs_value_directive.py index 814450f..0691cc4 100755 --- a/suite/regress/all_archs_value_directive.py +++ b/suite/regress/all_archs_value_directive.py @@ -20,7 +20,6 @@ bl #3230052712 """ def runTest(self): - return 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, @@ -39,7 +38,6 @@ bl 0xc008; """ def runTest(self): - return 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,