Zydis  v3.0.0
FormatterBase.h
Go to the documentation of this file.
1 /***************************************************************************************************
2 
3  Zyan Disassembler Library (Zydis)
4 
5  Original Author : Florian Bernd, Joel Hoener
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 
32 #ifndef ZYDIS_FORMATTER_BASE_H
33 #define ZYDIS_FORMATTER_BASE_H
34 
35 #include <Zydis/Formatter.h>
36 #include <Zydis/Internal/String.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /* ============================================================================================== */
43 /* Macros */
44 /* ============================================================================================== */
45 
46 /* ---------------------------------------------------------------------------------------------- */
47 /* String */
48 /* ---------------------------------------------------------------------------------------------- */
49 
59 #define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length) \
60  switch (base) \
61  { \
62  case ZYDIS_NUMERIC_BASE_DEC: \
63  ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \
64  (formatter)->number_format[base][0].string, \
65  (formatter)->number_format[base][1].string)); \
66  break; \
67  case ZYDIS_NUMERIC_BASE_HEX: \
68  ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, \
69  (formatter)->hex_uppercase, \
70  (formatter)->number_format[base][0].string, \
71  (formatter)->number_format[base][1].string)); \
72  break; \
73  default: \
74  return ZYAN_STATUS_INVALID_ARGUMENT; \
75  }
76 
87 #define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, force_sign) \
88  switch (base) \
89  { \
90  case ZYDIS_NUMERIC_BASE_DEC: \
91  ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \
92  (formatter)->number_format[base][0].string, \
93  (formatter)->number_format[base][1].string)); \
94  break; \
95  case ZYDIS_NUMERIC_BASE_HEX: \
96  ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, \
97  (formatter)->hex_uppercase, force_sign, \
98  (formatter)->number_format[base][0].string, \
99  (formatter)->number_format[base][1].string)); \
100  break; \
101  default: \
102  return ZYAN_STATUS_INVALID_ARGUMENT; \
103  }
104 
105 /* ---------------------------------------------------------------------------------------------- */
106 /* Buffer */
107 /* ---------------------------------------------------------------------------------------------- */
108 
119 #define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \
120  if ((buffer)->is_token_list) \
121  { \
122  ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \
123  }
124 
134 #define ZYDIS_BUFFER_REMEMBER(buffer, state) \
135  if ((buffer)->is_token_list) \
136  { \
137  (state) = (ZyanUPointer)(buffer)->string.vector.data; \
138  } else \
139  { \
140  (state) = (ZyanUPointer)(buffer)->string.vector.size; \
141  }
142 
149 #define ZYDIS_BUFFER_APPEND(buffer, name) \
150  if ((buffer)->is_token_list) \
151  { \
152  ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
153  } else \
154  { \
155  ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \
156  }
157 
158 // TODO: Implement `letter_case` for predefined tokens
159 
167 #define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \
168  if ((buffer)->is_token_list) \
169  { \
170  ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
171  } else \
172  { \
173  ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \
174  }
175 
176 /* ---------------------------------------------------------------------------------------------- */
177 
178 /* ============================================================================================== */
179 /* Helper functions */
180 /* ============================================================================================== */
181 
182 /* ---------------------------------------------------------------------------------------------- */
183 /* Buffer */
184 /* ---------------------------------------------------------------------------------------------- */
185 
186 // MSVC does not like the C99 flexible-array extension
187 #ifdef ZYAN_MSVC
188 # pragma warning(push)
189 # pragma warning(disable:4200)
190 #endif
191 
192 #pragma pack(push, 1)
193 
194 typedef struct ZydisPredefinedToken_
195 {
196  ZyanU8 size;
197  ZyanU8 next;
198  ZyanU8 data[];
200 
201 #pragma pack(pop)
202 
203 #ifdef ZYAN_MSVC
204 # pragma warning(pop)
205 #endif
206 
219  const ZydisPredefinedToken* data)
220 {
221  ZYAN_ASSERT(buffer);
222  ZYAN_ASSERT(data);
223 
224  const ZyanUSize len = buffer->string.vector.size;
225  ZYAN_ASSERT((len > 0) && (len < 256));
226  if (buffer->capacity <= len + data->size)
227  {
228  return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
229  }
230 
231  ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1;
232  last->next = (ZyanU8)len;
233 
234  ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size);
235 
236  const ZyanUSize delta = len + data->next;
237  buffer->capacity -= delta;
238  buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
239  buffer->string.vector.size = data->size - data->next;
240  buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
241 
242  return ZYAN_STATUS_SUCCESS;
243 }
244 
245 /* ---------------------------------------------------------------------------------------------- */
246 /* General */
247 /* ---------------------------------------------------------------------------------------------- */
248 
263  ZydisFormatterContext* context, ZyanU8 memop_id);
264 
265 /* ---------------------------------------------------------------------------------------------- */
266 
267 /* ============================================================================================== */
268 /* Formatter functions */
269 /* ============================================================================================== */
270 
271 /* ---------------------------------------------------------------------------------------------- */
272 /* Operands */
273 /* ---------------------------------------------------------------------------------------------- */
274 
276  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
277 
279  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
280 
282  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
283 
284 /* ---------------------------------------------------------------------------------------------- */
285 /* Elemental tokens */
286 /* ---------------------------------------------------------------------------------------------- */
287 
289  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
290 
292  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
293 
294 ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
295  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
296 
297 /* ---------------------------------------------------------------------------------------------- */
298 /* Optional tokens */
299 /* ---------------------------------------------------------------------------------------------- */
300 
301 ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
302  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
303 
305  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
306 
308  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator);
309 
310 /* ---------------------------------------------------------------------------------------------- */
311 
312 /* ============================================================================================== */
313 
314 #ifdef __cplusplus
315 }
316 #endif
317 
318 #endif // ZYDIS_FORMATTER_BASE_H
ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer *buffer, const ZydisPredefinedToken *data)
Appends a predefined token-list to the buffer.
Definition: FormatterBase.h:218
ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter *formatter, ZydisFormatterContext *context, ZyanU8 memop_id)
Returns the size to be used as explicit size suffix (AT&T) or explicit typecast (INTEL),...
struct ZydisPredefinedToken_ ZydisPredefinedToken
ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context, ZydisDecorator decorator)
ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter *formatter, ZydisFormatterBuffer *buffer, ZydisFormatterContext *context)
Functions for formatting instructions to human-readable text.
enum ZydisDecorator_ ZydisDecorator
Defines the ZydisDecorator enum.
Provides some internal, more performant, but unsafe helper functions for the ZyanString data-type.
Defines the ZydisFormatterBuffer struct.
Definition: FormatterBuffer.h:168
ZyanString string
The ZyanString instance that refers to the literal value of the most recently added token.
Definition: FormatterBuffer.h:182
ZyanUSize capacity
The remaining capacity of the buffer.
Definition: FormatterBuffer.h:177
Defines the ZydisFormatterContext struct.
Definition: Formatter.h:633
Defines the ZydisFormatterToken struct.
Definition: FormatterBuffer.h:139
ZyanU8 next
An offset to the next token, or 0.
Definition: FormatterBuffer.h:147
Defines the ZydisFormatter struct.
Definition: Formatter.h:747
Definition: FormatterBase.h:195
ZyanU8 size
Definition: FormatterBase.h:196
ZyanU8 next
Definition: FormatterBase.h:197
ZyanU8 data[]
Definition: FormatterBase.h:198