Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve ZydisRegisterGetLargestEnclosing #456

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/Zydis/Register.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, Zyd
* @param reg The register.
*
* @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the
* register is invalid for the active machine-mode or does not have an enclosing-register.
* register is invalid for the active machine-mode.
*/
ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode,
ZydisRegister reg);
Expand Down
85 changes: 68 additions & 17 deletions src/Register.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,67 @@ ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegis
return ZYDIS_REGISTER_NONE;
}

if (mode > ZYDIS_MACHINE_MODE_MAX_VALUE)
{
return ZYDIS_REGISTER_NONE;
}

const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;

if ((reg_class == ZYDIS_REGCLASS_INVALID) ||
((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))
{
return ZYDIS_REGISTER_NONE;
}

static const ZydisRegister STATIC_MAPPING[ZYDIS_REGCLASS_MAX_VALUE + 1][3] =
{
/* 16 */ /* 32 */ /* 64 * /
/* INVALID */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* GPR8 */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* GPR16 */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* GPR32 */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* GPR64 */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* X87 */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* MMX */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* XMM */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* YMM */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* ZMM */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* TMM */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* FLAGS */ { ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_RFLAGS },
/* IP */ { ZYDIS_REGISTER_IP , ZYDIS_REGISTER_EIP , ZYDIS_REGISTER_RIP },
/* SEGMENT */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* TABLE */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* TEST */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* CONTROL */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* DEBUG */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* MASK */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE },
/* BOUND */ { ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE , ZYDIS_REGISTER_NONE }
flobernd marked this conversation as resolved.
Show resolved Hide resolved
};
ZYAN_ASSERT(reg_class < ZYAN_ARRAY_LENGTH(STATIC_MAPPING));

ZyanU8 mode_bits;
switch (mode)
{
case ZYDIS_MACHINE_MODE_LONG_64:
mode_bits = 2;
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
mode_bits = 1;
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
mode_bits = 0;
flobernd marked this conversation as resolved.
Show resolved Hide resolved
default:
ZYAN_UNREACHABLE;
}

const ZydisRegister static_reg = STATIC_MAPPING[reg_class][mode_bits];
if (static_reg != ZYDIS_REGISTER_NONE)
{
return static_reg;
}

static const ZyanU8 GPR8_MAPPING[20] =
{
/* AL */ 0,
Expand All @@ -177,16 +238,9 @@ ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegis
/* R12B */ 12,
/* R13B */ 13,
/* R14B */ 14,
/* R15B */ 15,
/* R15B */ 15
};

const ZydisRegisterClass reg_class = REG_LOOKUP[reg].class;
if ((reg_class == ZYDIS_REGCLASS_INVALID) ||
((reg_class == ZYDIS_REGCLASS_GPR64) && (mode != ZYDIS_MACHINE_MODE_LONG_64)))
{
return ZYDIS_REGISTER_NONE;
}

ZyanU8 reg_id = REG_LOOKUP[reg].id;
switch (reg_class)
{
Expand All @@ -196,19 +250,16 @@ ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegis
case ZYDIS_REGCLASS_GPR16:
case ZYDIS_REGCLASS_GPR32:
case ZYDIS_REGCLASS_GPR64:
switch (mode)
switch (mode_bits)
{
case ZYDIS_MACHINE_MODE_LONG_64:
case 2:
return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR64].lo + reg_id;
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
case 1:
return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR32].lo + reg_id;
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
case 0:
return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_GPR16].lo + reg_id;
default:
return ZYDIS_REGISTER_NONE;
ZYAN_UNREACHABLE;
}
case ZYDIS_REGCLASS_XMM:
case ZYDIS_REGCLASS_YMM:
Expand All @@ -219,7 +270,7 @@ ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, ZydisRegis
return REG_CLASS_LOOKUP[ZYDIS_REGCLASS_ZMM].lo + reg_id;
#endif
default:
return ZYDIS_REGISTER_NONE;
return reg;
}
}

Expand Down