Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/Utils.c
4211 views
1
/***************************************************************************************************
2
3
Zyan Disassembler Library (Zydis)
4
5
Original Author : Florian Bernd
6
7
* Permission is hereby granted, free of charge, to any person obtaining a copy
8
* of this software and associated documentation files (the "Software"), to deal
9
* in the Software without restriction, including without limitation the rights
10
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
* copies of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
13
*
14
* The above copyright notice and this permission notice shall be included in all
15
* copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
* SOFTWARE.
24
25
***************************************************************************************************/
26
27
#include <Zycore/LibC.h>
28
#include <Zydis/Utils.h>
29
30
/* ============================================================================================== */
31
/* Exported functions */
32
/* ============================================================================================== */
33
34
/* ---------------------------------------------------------------------------------------------- */
35
/* Address calculation */
36
/* ---------------------------------------------------------------------------------------------- */
37
38
// Signed integer overflow is expected behavior in this function, for wrapping around the
39
// instruction pointer on jumps right at the end of the address space.
40
ZYAN_NO_SANITIZE("signed-integer-overflow")
41
ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction,
42
const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address)
43
{
44
if (!instruction || !operand || !result_address)
45
{
46
return ZYAN_STATUS_INVALID_ARGUMENT;
47
}
48
49
switch (operand->type)
50
{
51
case ZYDIS_OPERAND_TYPE_MEMORY:
52
if (!operand->mem.disp.has_displacement)
53
{
54
return ZYAN_STATUS_INVALID_ARGUMENT;
55
}
56
if (operand->mem.base == ZYDIS_REGISTER_EIP)
57
{
58
*result_address = ((ZyanU32)runtime_address + instruction->length +
59
(ZyanU32)operand->mem.disp.value);
60
return ZYAN_STATUS_SUCCESS;
61
}
62
if (operand->mem.base == ZYDIS_REGISTER_RIP)
63
{
64
*result_address = (ZyanU64)(runtime_address + instruction->length +
65
operand->mem.disp.value);
66
return ZYAN_STATUS_SUCCESS;
67
}
68
if ((operand->mem.base == ZYDIS_REGISTER_NONE) &&
69
(operand->mem.index == ZYDIS_REGISTER_NONE))
70
{
71
switch (instruction->address_width)
72
{
73
case 16:
74
*result_address = (ZyanU64)operand->mem.disp.value & 0x000000000000FFFF;
75
return ZYAN_STATUS_SUCCESS;
76
case 32:
77
*result_address = (ZyanU64)operand->mem.disp.value & 0x00000000FFFFFFFF;
78
return ZYAN_STATUS_SUCCESS;
79
case 64:
80
*result_address = (ZyanU64)operand->mem.disp.value;
81
return ZYAN_STATUS_SUCCESS;
82
default:
83
return ZYAN_STATUS_INVALID_ARGUMENT;
84
}
85
}
86
break;
87
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
88
if (operand->imm.is_signed && operand->imm.is_relative)
89
{
90
*result_address = (ZyanU64)((ZyanI64)runtime_address + instruction->length +
91
operand->imm.value.s);
92
switch (instruction->machine_mode)
93
{
94
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
95
case ZYDIS_MACHINE_MODE_LEGACY_16:
96
case ZYDIS_MACHINE_MODE_REAL_16:
97
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
98
case ZYDIS_MACHINE_MODE_LEGACY_32:
99
// `XBEGIN` is a special case as it doesn't truncate computed address
100
// This behavior is documented by Intel (SDM Vol. 2C):
101
// Use of the 16-bit operand size does not cause this address to be truncated to
102
// 16 bits, unlike a near jump to a relative offset.
103
if ((instruction->operand_width == 16) &&
104
(instruction->mnemonic != ZYDIS_MNEMONIC_XBEGIN))
105
{
106
*result_address &= 0xFFFF;
107
}
108
break;
109
case ZYDIS_MACHINE_MODE_LONG_64:
110
break;
111
default:
112
return ZYAN_STATUS_INVALID_ARGUMENT;
113
}
114
return ZYAN_STATUS_SUCCESS;
115
}
116
break;
117
default:
118
break;
119
}
120
121
return ZYAN_STATUS_INVALID_ARGUMENT;
122
}
123
124
ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction,
125
const ZydisDecodedOperand* operand, ZyanU64 runtime_address,
126
const ZydisRegisterContext* register_context, ZyanU64* result_address)
127
{
128
// TODO: Test this with AGEN/MIB operands
129
// TODO: Add support for Gather/Scatter instructions
130
131
if (!instruction || !operand || !register_context || !result_address)
132
{
133
return ZYAN_STATUS_INVALID_ARGUMENT;
134
}
135
136
if ((operand->type != ZYDIS_OPERAND_TYPE_MEMORY) ||
137
((operand->mem.base == ZYDIS_REGISTER_NONE) &&
138
(operand->mem.index == ZYDIS_REGISTER_NONE)) ||
139
(operand->mem.base == ZYDIS_REGISTER_EIP) ||
140
(operand->mem.base == ZYDIS_REGISTER_RIP))
141
{
142
return ZydisCalcAbsoluteAddress(instruction, operand, runtime_address, result_address);
143
}
144
145
ZyanU64 value = operand->mem.disp.value;
146
if (operand->mem.base)
147
{
148
value += register_context->values[operand->mem.base];
149
}
150
if (operand->mem.index)
151
{
152
value += register_context->values[operand->mem.index] * operand->mem.scale;
153
}
154
155
switch (instruction->address_width)
156
{
157
case 16:
158
*result_address = value & 0x000000000000FFFF;
159
return ZYAN_STATUS_SUCCESS;
160
case 32:
161
*result_address = value & 0x00000000FFFFFFFF;
162
return ZYAN_STATUS_SUCCESS;
163
case 64:
164
*result_address = value;
165
return ZYAN_STATUS_SUCCESS;
166
default:
167
return ZYAN_STATUS_INVALID_ARGUMENT;
168
}
169
}
170
171
/* ============================================================================================== */
172
173