Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/Segment.c
4212 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/Segment.h>
29
30
/* ============================================================================================== */
31
/* Exported functions */
32
/* ============================================================================================== */
33
34
ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction,
35
ZydisInstructionSegments* segments)
36
{
37
if (!instruction || !segments)
38
{
39
return ZYAN_STATUS_INVALID_ARGUMENT;
40
}
41
42
ZYAN_MEMSET(segments, 0, sizeof(*segments));
43
44
// Legacy prefixes and `REX`
45
if (instruction->raw.prefix_count)
46
{
47
const ZyanU8 rex_offset = (instruction->attributes & ZYDIS_ATTRIB_HAS_REX) ? 1 : 0;
48
if (!rex_offset || (instruction->raw.prefix_count > 1))
49
{
50
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_PREFIXES;
51
segments->segments[segments->count ].offset = 0;
52
segments->segments[segments->count++].size =
53
instruction->raw.prefix_count - rex_offset;
54
}
55
if (rex_offset)
56
{
57
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_REX;
58
segments->segments[segments->count ].offset =
59
instruction->raw.prefix_count - rex_offset;
60
segments->segments[segments->count++].size = 1;
61
}
62
}
63
64
// Encoding prefixes
65
ZydisInstructionSegment segment_type = ZYDIS_INSTR_SEGMENT_NONE;
66
ZyanU8 segment_offset = 0;
67
ZyanU8 segment_size = 0;
68
switch (instruction->encoding)
69
{
70
case ZYDIS_INSTRUCTION_ENCODING_XOP:
71
segment_type = ZYDIS_INSTR_SEGMENT_XOP;
72
segment_offset = instruction->raw.xop.offset;
73
segment_size = 3;
74
break;
75
case ZYDIS_INSTRUCTION_ENCODING_VEX:
76
segment_type = ZYDIS_INSTR_SEGMENT_VEX;
77
segment_offset = instruction->raw.vex.offset;
78
segment_size = instruction->raw.vex.size;
79
break;
80
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
81
segment_type = ZYDIS_INSTR_SEGMENT_EVEX;
82
segment_offset = instruction->raw.evex.offset;
83
segment_size = 4;
84
break;
85
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
86
segment_type = ZYDIS_INSTR_SEGMENT_MVEX;
87
segment_offset = instruction->raw.mvex.offset;
88
segment_size = 4;
89
break;
90
default:
91
break;
92
}
93
if (segment_type)
94
{
95
segments->segments[segments->count ].type = segment_type;
96
segments->segments[segments->count ].offset = segment_offset;
97
segments->segments[segments->count++].size = segment_size;
98
}
99
100
// Opcode
101
segment_size = 1;
102
if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_LEGACY) ||
103
(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW))
104
{
105
switch (instruction->opcode_map)
106
{
107
case ZYDIS_OPCODE_MAP_DEFAULT:
108
break;
109
case ZYDIS_OPCODE_MAP_0F:
110
ZYAN_FALLTHROUGH;
111
case ZYDIS_OPCODE_MAP_0F0F:
112
segment_size = 2;
113
break;
114
case ZYDIS_OPCODE_MAP_0F38:
115
ZYAN_FALLTHROUGH;
116
case ZYDIS_OPCODE_MAP_0F3A:
117
segment_size = 3;
118
break;
119
default:
120
ZYAN_UNREACHABLE;
121
}
122
}
123
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_OPCODE;
124
if (segments->count)
125
{
126
segments->segments[segments->count].offset =
127
segments->segments[segments->count - 1].offset +
128
segments->segments[segments->count - 1].size;
129
} else
130
{
131
segments->segments[segments->count].offset = 0;
132
}
133
segments->segments[segments->count++].size = segment_size;
134
135
// ModRM
136
if (instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM)
137
{
138
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_MODRM;
139
segments->segments[segments->count ].offset = instruction->raw.modrm.offset;
140
segments->segments[segments->count++].size = 1;
141
}
142
143
// SIB
144
if (instruction->attributes & ZYDIS_ATTRIB_HAS_SIB)
145
{
146
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_SIB;
147
segments->segments[segments->count ].offset = instruction->raw.sib.offset;
148
segments->segments[segments->count++].size = 1;
149
}
150
151
// Displacement
152
if (instruction->raw.disp.size)
153
{
154
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_DISPLACEMENT;
155
segments->segments[segments->count ].offset = instruction->raw.disp.offset;
156
segments->segments[segments->count++].size = instruction->raw.disp.size / 8;
157
}
158
159
// Immediates
160
for (ZyanU8 i = 0; i < 2; ++i)
161
{
162
if (instruction->raw.imm[i].size)
163
{
164
segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_IMMEDIATE;
165
segments->segments[segments->count ].offset = instruction->raw.imm[i].offset;
166
segments->segments[segments->count++].size = instruction->raw.imm[i].size / 8;
167
}
168
}
169
170
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
171
{
172
segments->segments[segments->count].type = ZYDIS_INSTR_SEGMENT_OPCODE;
173
segments->segments[segments->count].offset = instruction->length -1;
174
segments->segments[segments->count++].size = 1;
175
}
176
177
return ZYAN_STATUS_SUCCESS;
178
}
179
180
/* ---------------------------------------------------------------------------------------------- */
181
182
/* ============================================================================================== */
183
184