diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index cfd92619a1e15..d56b091822a23 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -544,6 +544,10 @@ static const u8 kPrologueWithShortJump2[] = { // Returns 0 on error. static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { + if (rel_offset) { + *rel_offset = 0; + } + #if SANITIZER_ARM64 // An ARM64 instruction is 4 bytes long. return 4; @@ -907,6 +911,10 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { return 0; } +size_t TestOnlyGetInstructionSize(uptr address, size_t *rel_offset) { + return GetInstructionSize(address, rel_offset); +} + // Returns 0 on error. static size_t RoundUpToInstrBoundary(size_t size, uptr address) { size_t cursor = 0; diff --git a/compiler-rt/lib/interception/interception_win.h b/compiler-rt/lib/interception/interception_win.h index f6eca82191cba..91c7e38bfe7db 100644 --- a/compiler-rt/lib/interception/interception_win.h +++ b/compiler-rt/lib/interception/interception_win.h @@ -63,6 +63,9 @@ bool OverrideFunctionWithTrampoline( // Exposed for unittests void TestOnlyReleaseTrampolineRegions(); +// Exposed for unittests +SIZE_T TestOnlyGetInstructionSize(uptr address, SIZE_T *rel_offset); + } // namespace __interception #if defined(INTERCEPTION_DYNAMIC_CRT) diff --git a/compiler-rt/lib/interception/tests/interception_win_test.cpp b/compiler-rt/lib/interception/tests/interception_win_test.cpp index c004d187768de..0650a45f619a9 100644 --- a/compiler-rt/lib/interception/tests/interception_win_test.cpp +++ b/compiler-rt/lib/interception/tests/interception_win_test.cpp @@ -793,6 +793,41 @@ TEST(Interception, EmptyExportTable) { EXPECT_EQ(0U, FunPtr); } +const struct InstructionSizeData { + size_t size; // hold instruction size or 0 for failure, + // e.g. on control instructions + u8 instr[16]; + size_t rel_offset; + const char *comment; +} data[] = { + /* sorted list */ + {1, {0x50}, 0, "50 : push eax / rax"}, +}; + +std::string dumpInstruction(unsigned arrayIndex, + const InstructionSizeData &data) { + std::stringstream ret; + ret << " with arrayIndex=" << arrayIndex << " {"; + for (size_t i = 0; i < data.size; i++) { + if (i > 0) + ret << ", "; + ret << "0x" << std::setfill('0') << std::setw(2) << std::right << std::hex + << (int)data.instr[i]; + } + ret << "} " << data.comment; + return ret.str(); +} + +TEST(Interception, GetInstructionSize) { + for (unsigned i = 0; i < sizeof(data) / sizeof(*data); i++) { + size_t rel_offset = ~0L; + size_t size = __interception::TestOnlyGetInstructionSize( + (uptr)data[i].instr, &rel_offset); + EXPECT_EQ(data[i].size, size) << dumpInstruction(i, data[i]); + EXPECT_EQ(data[i].rel_offset, rel_offset) << dumpInstruction(i, data[i]); + } +} + } // namespace __interception # endif // !SANITIZER_WINDOWS_ARM64