diff --git a/include/rtdisasm.h b/include/rtdisasm.h index ffe357f..298c07e 100644 --- a/include/rtdisasm.h +++ b/include/rtdisasm.h @@ -18,4 +18,11 @@ int rtdisasm_analyze_single(const uint8_t* code, unsigned limit, const instructi // and non-zero integer is offset from "code" int rtdisasm_find_target(const uint8_t* code, unsigned limit, unsigned rt_target); +// will analyze all instructions until "wanted" size of bytes is reached +// within instruction boundaries, therefore making that address suitable +// for patching and not break instruction fetching. on success returns +// non-zero value - patch size, within instructions aligned, +// returns 0 if unknown instruction met and -1 if "limit" is reached. +int rtdisasm_estimate_patch(const uint8_t* code, unsigned limit, int wanted); + #endif \ No newline at end of file diff --git a/src/rtdisasm.c b/src/rtdisasm.c index 986ad07..fd5201a 100644 --- a/src/rtdisasm.c +++ b/src/rtdisasm.c @@ -394,3 +394,32 @@ int rtdisasm_find_target(const uint8_t* code, unsigned limit, unsigned rt_target if (cur >= end) return -1; } while (1); } + +int rtdisasm_estimate_patch(const uint8_t* code, unsigned limit, int wanted) +{ + const uint8_t* cur = code; + const uint8_t* const end = code + limit; + unsigned remaining = limit; + unsigned patch = 0; + if (cur == end) return -1; + + do { + const instruction_t* ins; + int len = rtdisasm_analyze_single(cur, remaining, &ins); + TRACE("rtdisasm_analyze_single len %d\n", len); + if (len < 1) return len; + + // advance past instruction and check if we hit limit + // cuz we don't want patch on the limit + cur += len; + remaining -= len; + if (cur >= end) return -1; + + // we're good, let's go until we have enough bytes for patch + patch += len; + } while(patch < wanted); + + // at this point it should contain patch size + // aligned with instruction boundaries + return patch; +} diff --git a/src/rtdisasm_test.c b/src/rtdisasm_test.c index 32666cf..ea89a73 100644 --- a/src/rtdisasm_test.c +++ b/src/rtdisasm_test.c @@ -37,6 +37,7 @@ static void test_3() __m256 odds = _mm256_set_ps(1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0); __m256 result = _mm256_sub_ps(evens, odds); + (void)result; __asm__("nop"); // TARGET } static void test_3_end() {} @@ -69,5 +70,11 @@ int main() printf("test3 %d\n", rtdisasm_find_target((const uint8_t*)test_3, size, RT_TARGET_NOP)); + printf("\n== TEST 4 ==\n"); + printf("test1 patch %d\n", rtdisasm_estimate_patch((const uint8_t*)test_1, 16, 8)); + printf("test2 patch %d\n", rtdisasm_estimate_patch((const uint8_t*)test_2, 16, 8)); + printf("test3 patch %d\n", rtdisasm_estimate_patch((const uint8_t*)test_3, 16, 8)); + + return 0; } \ No newline at end of file