From c62f41e28191d880b57ff6be2f7b90b73711be55 Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 18 Jan 2016 15:29:15 -0500 Subject: [PATCH] Add disassembler option to show byte offset The option is disabled by default. The offset is printed in hex, as a comment after each instruction. --- include/libspirv/libspirv.h | 1 + source/disassemble.cpp | 26 +++++++++++++++++++++++--- test/BinaryToText.cpp | 18 ++++++++++++++++++ tools/dis/dis.cpp | 9 +++++++-- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/libspirv/libspirv.h b/include/libspirv/libspirv.h index 8d94539..3395759 100644 --- a/include/libspirv/libspirv.h +++ b/include/libspirv/libspirv.h @@ -251,6 +251,7 @@ typedef enum spv_binary_to_text_options_t { SPV_BINARY_TO_TEXT_OPTION_PRINT = SPV_BIT(1), SPV_BINARY_TO_TEXT_OPTION_COLOR = SPV_BIT(2), SPV_BINARY_TO_TEXT_OPTION_INDENT = SPV_BIT(3), + SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET = SPV_BIT(4), SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t) } spv_binary_to_text_options_t; diff --git a/source/disassemble.cpp b/source/disassemble.cpp index 927914a..1605924 100644 --- a/source/disassemble.cpp +++ b/source/disassemble.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include "assembly_grammar.h" @@ -48,8 +49,7 @@ namespace { // representation. class Disassembler { public: - Disassembler(const libspirv::AssemblyGrammar& grammar, - uint32_t options) + Disassembler(const libspirv::AssemblyGrammar& grammar, uint32_t options) : grammar_(grammar), print_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)), color_(print_ && @@ -59,7 +59,10 @@ class Disassembler { : 0), text_(), out_(print_ ? out_stream() : out_stream(text_)), - stream_(out_.get()) {} + stream_(out_.get()), + show_byte_offset_(spvIsInBitfield( + SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)), + byte_offset_(0) {} // Emits the assembly header for the module, and sets up internal state // so subsequent callbacks can handle the cases where the entire module @@ -120,6 +123,8 @@ class Disassembler { std::stringstream text_; // Captures the text, if not printing. out_stream out_; // The Output stream. Either to text_ or standard output. std::ostream& stream_; // The output std::stream. + const bool show_byte_offset_; // Should we print byte offset, in hex? + size_t byte_offset_; // The number of bytes processed so far. }; spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, @@ -145,6 +150,8 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, << "; Schema: " << schema << "\n"; ResetColor(); + byte_offset_ = SPV_INDEX_INSTRUCTION * sizeof(uint32_t); + return SPV_SUCCESS; } @@ -185,6 +192,19 @@ spv_result_t Disassembler::HandleInstruction( EmitOperand(inst, i); } + if (show_byte_offset_) { + SetGrey(); + auto saved_flags = stream_.flags(); + auto saved_fill = stream_.fill(); + stream_ << " ; 0x" << std::setw(8) << std::hex << std::setfill('0') + << byte_offset_; + stream_.flags(saved_flags); + stream_.fill(saved_fill); + ResetColor(); + } + + byte_offset_ += inst.num_words * sizeof(uint32_t); + stream_ << "\n"; return SPV_SUCCESS; } diff --git a/test/BinaryToText.cpp b/test/BinaryToText.cpp index 264337e..4c2548e 100644 --- a/test/BinaryToText.cpp +++ b/test/BinaryToText.cpp @@ -392,6 +392,24 @@ OpStore %2 %3 Aligned|Volatile 4 ; bogus, but not indented expected); } +TEST_F(TextToBinaryTest, ShowByteOffsetsWhenRequested) { + const std::string input = R"( +OpCapability Shader +OpMemoryModel Logical GLSL450 +%1 = OpTypeInt 32 0 +%2 = OpTypeVoid +)"; + const std::string expected = + R"(OpCapability Shader ; 0x00000014 +OpMemoryModel Logical GLSL450 ; 0x0000001c +%1 = OpTypeInt 32 0 ; 0x00000028 +%2 = OpTypeVoid ; 0x00000038 +)"; + EXPECT_THAT(EncodeAndDecodeSuccessfully( + input, SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET), + expected); +} + // Test version string. TEST_F(TextToBinaryTest, VersionString) { auto words = CompileSuccessfully(""); diff --git a/tools/dis/dis.cpp b/tools/dis/dis.cpp index d29836d..48664de 100644 --- a/tools/dis/dis.cpp +++ b/tools/dis/dis.cpp @@ -52,6 +52,8 @@ Options: The default when output goes to a file. --no-indent Don't indent instructions. + + --offsets Show byte offsets for each instruction. )", argv0, argv0); } @@ -65,6 +67,7 @@ int main(int argc, char** argv) { allow_color = true; #endif bool allow_indent = true; + bool show_byte_offsets = false; for (int argi = 1; argi < argc; ++argi) { if ('-' == argv[argi][0]) { @@ -84,6 +87,7 @@ int main(int argc, char** argv) { // Long options if (0 == strcmp(argv[argi], "--no-color")) allow_color = false; if (0 == strcmp(argv[argi], "--no-indent")) allow_indent = false; + if (0 == strcmp(argv[argi], "--offsets")) show_byte_offsets = true; if (0 == strcmp(argv[argi], "--help")) { print_usage(argv[0]); return 0; @@ -114,8 +118,9 @@ int main(int argc, char** argv) { uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE; - if (allow_indent) - options |= SPV_BINARY_TO_TEXT_OPTION_INDENT; + if (allow_indent) options |= SPV_BINARY_TO_TEXT_OPTION_INDENT; + + if (show_byte_offsets) options |= SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET; if (!outFile || (0 == strcmp("-", outFile))) { // Print to standard output. -- 2.7.4