From 4a64a637bc896503f63e0eb12344f0bffb2f1537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:29:06 +0200 Subject: [PATCH 1/3] Fix #463: Wrong target offset calculated when using bnd prefix --- src/Encoder.c | 3 ++- tools/ZydisTestEncoderAbsolute.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Encoder.c b/src/Encoder.c index 17d84710..27c606e3 100644 --- a/src/Encoder.c +++ b/src/Encoder.c @@ -4373,7 +4373,8 @@ ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstructionAbsolute(ZydisEncoderReques } if ((rel_info->accepts_branch_hints) && (request->prefixes & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | - ZYDIS_ATTRIB_HAS_BRANCH_TAKEN))) + ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | + ZYDIS_ATTRIB_HAS_BND))) { extra_length = 1; } diff --git a/tools/ZydisTestEncoderAbsolute.c b/tools/ZydisTestEncoderAbsolute.c index f910d662..ff6962e0 100644 --- a/tools/ZydisTestEncoderAbsolute.c +++ b/tools/ZydisTestEncoderAbsolute.c @@ -224,6 +224,7 @@ static ZyanBool RunBranchingTests(void) static const ZydisInstructionAttributes prefixes[] = { 0, ZYDIS_ATTRIB_HAS_BRANCH_TAKEN, + ZYDIS_ATTRIB_HAS_BND, }; static const char *str_prefixes[] = { From 975f59981808580eff690d05a84f8399c2f59864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Mon, 27 Nov 2023 01:26:05 +0200 Subject: [PATCH 2/3] Update str_prefixes --- tools/ZydisTestEncoderAbsolute.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/ZydisTestEncoderAbsolute.c b/tools/ZydisTestEncoderAbsolute.c index ff6962e0..82889c2b 100644 --- a/tools/ZydisTestEncoderAbsolute.c +++ b/tools/ZydisTestEncoderAbsolute.c @@ -230,6 +230,7 @@ static ZyanBool RunBranchingTests(void) { "P00", "PBT", + "PBN", }; static const ZydisAddressSizeHint address_hints[] = { From f3d4e33351d4d5f093458b8f5f16d4fabed4752a Mon Sep 17 00:00:00 2001 From: mappzor <34216645+mappzor@users.noreply.github.com> Date: Mon, 27 Nov 2023 03:39:00 +0100 Subject: [PATCH 3/3] Improved size prediction for multiple `BND` scenarios --- include/Zydis/Internal/EncoderData.h | 4 ++++ src/Encoder.c | 16 +++++++++++++--- src/Generated/GetRelInfo.inc | 18 +++++++++--------- tools/ZydisTestEncoderAbsolute.c | 11 +++++++++-- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/include/Zydis/Internal/EncoderData.h b/include/Zydis/Internal/EncoderData.h index 808c1fa5..886e4a7d 100644 --- a/include/Zydis/Internal/EncoderData.h +++ b/include/Zydis/Internal/EncoderData.h @@ -221,6 +221,10 @@ typedef struct ZydisEncoderRelInfo_ * True if instruction accepts branch hint prefixes. */ ZyanBool accepts_branch_hints; + /** + * True if instruction accepts bound (`BND`) prefix. + */ + ZyanBool accepts_bound; } ZydisEncoderRelInfo; /** diff --git a/src/Encoder.c b/src/Encoder.c index 27c606e3..db8eef37 100644 --- a/src/Encoder.c +++ b/src/Encoder.c @@ -4373,10 +4373,20 @@ ZYDIS_EXPORT ZyanStatus ZydisEncoderEncodeInstructionAbsolute(ZydisEncoderReques } if ((rel_info->accepts_branch_hints) && (request->prefixes & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | - ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | - ZYDIS_ATTRIB_HAS_BND))) + ZYDIS_ATTRIB_HAS_BRANCH_TAKEN))) { - extra_length = 1; + extra_length += 1; + } + if ((rel_info->accepts_bound) && (request->prefixes & ZYDIS_ATTRIB_HAS_BND)) + { + extra_length += 1; + // `BND` prefix is not accepted for short `JMP` (Intel SDM Vol. 1) + if ((request->mnemonic == ZYDIS_MNEMONIC_JMP) && + (request->branch_type == ZYDIS_BRANCH_TYPE_NONE) && + (request->branch_width == ZYDIS_BRANCH_WIDTH_NONE)) + { + start_offset = 1; + } } if (request->branch_width == ZYDIS_BRANCH_WIDTH_NONE) { diff --git a/src/Generated/GetRelInfo.inc b/src/Generated/GetRelInfo.inc index 20556267..a7748f81 100644 --- a/src/Generated/GetRelInfo.inc +++ b/src/Generated/GetRelInfo.inc @@ -2,15 +2,15 @@ const ZydisEncoderRelInfo *ZydisGetRelInfo(ZydisMnemonic mnemonic) { static const ZydisEncoderRelInfo info_lookup[9] = { - { { { 0, 3, 6 }, { 0, 4, 5 }, { 0, 0, 5 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 2, 4, 7 }, { 2, 5, 6 }, { 2, 0, 6 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_TRUE }, - { { { 2, 0, 0 }, { 3, 0, 0 }, { 0, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 3, 0, 0 }, { 2, 0, 0 }, { 3, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 0, 0, 0 }, { 0, 0, 0 }, { 5, 0, 7 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 2, 3, 6 }, { 2, 4, 5 }, { 2, 0, 5 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 0, 0, 0 }, { 0, 0, 0 }, { 2, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE }, - { { { 2, 0, 0 }, { 2, 0, 0 }, { 2, 0, 0 } }, ZYDIS_SIZE_HINT_ASZ, ZYAN_FALSE }, - { { { 0, 4, 7 }, { 0, 5, 6 }, { 0, 5, 6 } }, ZYDIS_SIZE_HINT_OSZ, ZYAN_FALSE }, + { { { 0, 3, 6 }, { 0, 4, 5 }, { 0, 0, 5 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_TRUE }, + { { { 2, 4, 7 }, { 2, 5, 6 }, { 2, 0, 6 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_TRUE, ZYAN_TRUE }, + { { { 2, 0, 0 }, { 3, 0, 0 }, { 0, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_FALSE }, + { { { 3, 0, 0 }, { 2, 0, 0 }, { 3, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_FALSE }, + { { { 0, 0, 0 }, { 0, 0, 0 }, { 5, 0, 7 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_FALSE }, + { { { 2, 3, 6 }, { 2, 4, 5 }, { 2, 0, 5 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_TRUE }, + { { { 0, 0, 0 }, { 0, 0, 0 }, { 2, 0, 0 } }, ZYDIS_SIZE_HINT_NONE, ZYAN_FALSE, ZYAN_FALSE }, + { { { 2, 0, 0 }, { 2, 0, 0 }, { 2, 0, 0 } }, ZYDIS_SIZE_HINT_ASZ, ZYAN_FALSE, ZYAN_FALSE }, + { { { 0, 4, 7 }, { 0, 5, 6 }, { 0, 5, 6 } }, ZYDIS_SIZE_HINT_OSZ, ZYAN_FALSE, ZYAN_FALSE }, }; switch (mnemonic) diff --git a/tools/ZydisTestEncoderAbsolute.c b/tools/ZydisTestEncoderAbsolute.c index 82889c2b..af7745a7 100644 --- a/tools/ZydisTestEncoderAbsolute.c +++ b/tools/ZydisTestEncoderAbsolute.c @@ -225,12 +225,14 @@ static ZyanBool RunBranchingTests(void) 0, ZYDIS_ATTRIB_HAS_BRANCH_TAKEN, ZYDIS_ATTRIB_HAS_BND, + ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | ZYDIS_ATTRIB_HAS_BND, }; static const char *str_prefixes[] = { "P00", "PBT", - "PBN", + "PBD", + "PBN+PBD", }; static const ZydisAddressSizeHint address_hints[] = { @@ -285,7 +287,12 @@ static ZyanBool RunBranchingTests(void) const ZydisEncoderRelInfo *rel_info = ZydisGetRelInfo(mnemonic); ZYAN_ASSERT(rel_info); - if (!rel_info->accepts_branch_hints && iter_branches[5].value != 0) + if ((!rel_info->accepts_branch_hints) && (prefix & (ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | + ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN))) + { + continue; + } + if ((!rel_info->accepts_bound) && (prefix & ZYDIS_ATTRIB_HAS_BND)) { continue; }