Zydis  master
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 
61 #define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length, \
62  force_leading_number) \
63  switch (base) \
64  { \
65  case ZYDIS_NUMERIC_BASE_DEC: \
66  ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \
67  (formatter)->number_format[base][0].string, \
68  (formatter)->number_format[base][1].string)); \
69  break; \
70  case ZYDIS_NUMERIC_BASE_HEX: \
71  ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, force_leading_number, \
72  (formatter)->hex_uppercase, \
73  (formatter)->number_format[base][0].string, \
74  (formatter)->number_format[base][1].string)); \
75  break; \
76  default: \
77  return ZYAN_STATUS_INVALID_ARGUMENT; \
78  }
79 
92 #define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, \
93  force_leading_number, force_sign) \
94  switch (base) \
95  { \
96  case ZYDIS_NUMERIC_BASE_DEC: \
97  ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \
98  (formatter)->number_format[base][0].string, \
99  (formatter)->number_format[base][1].string)); \
100  break; \
101  case ZYDIS_NUMERIC_BASE_HEX: \
102  ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, force_leading_number, \
103  (formatter)->hex_uppercase, force_sign, \
104  (formatter)->number_format[base][0].string, \
105  (formatter)->number_format[base][1].string)); \
106  break; \
107  default: \
108  return ZYAN_STATUS_INVALID_ARGUMENT; \
109  }
110 
111 /* ---------------------------------------------------------------------------------------------- */
112 /* Buffer */
113 /* ---------------------------------------------------------------------------------------------- */
114 
125 #define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \
126  if ((buffer)->is_token_list) \
127  { \
128  ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \
129  }
130 
140 #define ZYDIS_BUFFER_REMEMBER(buffer, state) \
141  if ((buffer)->is_token_list) \
142  { \
143  (state) = (ZyanUPointer)(buffer)->string.vector.data; \
144  } else \
145  { \
146  (state) = (ZyanUPointer)(buffer)->string.vector.size; \
147  }
148 
155 #define ZYDIS_BUFFER_APPEND(buffer, name) \
156  if ((buffer)->is_token_list) \
157  { \
158  ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
159  } else \
160  { \
161  ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \
162  }
163 
164 // TODO: Implement `letter_case` for predefined tokens
165 
173 #define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \
174  if ((buffer)->is_token_list) \
175  { \
176  ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \
177  } else \
178  { \
179  ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \
180  }
181 
182 /* ---------------------------------------------------------------------------------------------- */
183 
184 /* ============================================================================================== */
185 /* Helper functions */
186 /* ============================================================================================== */
187 
188 /* ---------------------------------------------------------------------------------------------- */
189 /* Buffer */
190 /* ---------------------------------------------------------------------------------------------- */
191 
192 // MSVC does not like the C99 flexible-array extension
193 #ifdef ZYAN_MSVC
194 # pragma warning(push)
195 # pragma warning(disable:4200)
196 #endif
197 
198 #pragma pack(push, 1)
199 
200 typedef struct ZydisPredefinedToken_
201 {
202  ZyanU8 size;
203  ZyanU8 next;
204  ZyanU8 data[];
206 
207 #pragma pack(pop)
208 
209 #ifdef ZYAN_MSVC
210 # pragma warning(pop)
211 #endif
212 
225  const ZydisPredefinedToken* data)
226 {
227  ZYAN_ASSERT(buffer);
228  ZYAN_ASSERT(data);
229 
230  const ZyanUSize len = buffer->string.vector.size;
231  ZYAN_ASSERT((len > 0) && (len < 256));
232  if (buffer->capacity <= len + data->size)
233  {
234  return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
235  }
236 
237  ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1;
238  last->next = (ZyanU8)len;
239 
240  ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size);
241 
242  const ZyanUSize delta = len + data->next;
243  buffer->capacity -= delta;
244  buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
245  buffer->string.vector.size = data->size - data->next;
246  buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
247 
248  return ZYAN_STATUS_SUCCESS;
249 }
250 
251 /* ---------------------------------------------------------------------------------------------- */
252 /* General */
253 /* ---------------------------------------------------------------------------------------------- */
254 
269  ZydisFormatterContext* context, const ZydisDecodedOperand* operand);
270 
271 /* ---------------------------------------------------------------------------------------------- */
272 
273 /* ============================================================================================== */
274 /* Formatter functions */
275 /* ============================================================================================== */
276 
277 /* ---------------------------------------------------------------------------------------------- */
278 /* Operands */
279 /* ---------------------------------------------------------------------------------------------- */
280 
282  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
283 
285  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
286 
288  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
289 
290 /* ---------------------------------------------------------------------------------------------- */
291 /* Elemental tokens */
292 /* ---------------------------------------------------------------------------------------------- */
293 
295  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
296 
298  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
299 
300 ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter,
301  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
302 
303 /* ---------------------------------------------------------------------------------------------- */
304 /* Optional tokens */
305 /* ---------------------------------------------------------------------------------------------- */
306 
307 ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter,
308  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
309 
311  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
312 
314  ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator);
315 
316 /* ---------------------------------------------------------------------------------------------- */
317 
318 /* ============================================================================================== */
319 
320 #ifdef __cplusplus
321 }
322 #endif
323 
324 #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:224
ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter *formatter, ZydisFormatterContext *context, const ZydisDecodedOperand *operand)
Returns the size to be used as explicit size suffix (AT&T) or explicit typecast (INTEL),...
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)
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
Enum of all decorator types.
Provides some internal, more performant, but unsafe helper functions for the ZyanString data-type.
Defines the ZydisDecodedOperand struct.
Definition: DecoderTypes.h:214
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
Context structure that that is passed to all formatter.
Definition: Formatter.h:652
Defines the ZydisFormatterToken struct.
Definition: FormatterBuffer.h:139
ZyanU8 next
An offset to the next token, or 0.
Definition: FormatterBuffer.h:147
Context structure keeping track of internal state of the formatter.
Definition: Formatter.h:773
Definition: FormatterBase.h:201
ZyanU8 size
Definition: FormatterBase.h:202
ZyanU8 next
Definition: FormatterBase.h:203
ZyanU8 data[]
Definition: FormatterBase.h:204