tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FormatterBase.h (13734B)


      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 
     27 /**
     28 * @file
     29 * Provides formatter functions that are shared between the different formatters.
     30 */
     31 
     32 #ifndef ZYDIS_FORMATTER_BASE_H
     33 #define ZYDIS_FORMATTER_BASE_H
     34 
     35 #include "zydis/Zydis/Formatter.h"
     36 #include "zydis/Zydis/Internal/String.h"
     37 
     38 #ifdef __cplusplus
     39 extern "C" {
     40 #endif
     41 
     42 /* ============================================================================================== */
     43 /* Macros                                                                                         */
     44 /* ============================================================================================== */
     45 
     46 /* ---------------------------------------------------------------------------------------------- */
     47 /* String                                                                                         */
     48 /* ---------------------------------------------------------------------------------------------- */
     49 
     50 /**
     51 * Appends an unsigned numeric value to the given string.
     52 *
     53 * @param   formatter               A pointer to the `ZydisFormatter` instance.
     54 * @param   base                    The numeric base.
     55 * @param   str                     The destination string.
     56 * @param   value                   The value to append.
     57 * @param   padding_length          The padding length.
     58 * @param   force_leading_number    Enable this option to prepend a leading `0` if the first
     59 *                                  character is non-numeric.
     60 */
     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 
     80 /**
     81 * Appends a signed numeric value to the given string.
     82 *
     83 * @param   formatter               A pointer to the `ZydisFormatter` instance.
     84 * @param   base                    The numeric base.
     85 * @param   str                     The destination string.
     86 * @param   value                   The value to append.
     87 * @param   padding_length          The padding length.
     88 * @param   force_leading_number    Enable this option to prepend a leading `0`, if the first
     89 *                                  character is non-numeric.
     90 * @param   force_sign              Enable to print the '+' sign for positive numbers.
     91 */
     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 
    115 /**
    116 * Invokes the `ZydisFormatterBufferAppend` routine, if tokenization is enabled for the
    117 * current pass.
    118 *
    119 * @param   buffer  A pointer to the `ZydisFormatterBuffer` struct.
    120 * @param   type    The token type.
    121 *
    122 * Using this macro instead of direct calls to `ZydisFormatterBufferAppend` greatly improves the
    123 * performance for non-tokenizing passes.
    124 */
    125 #define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \
    126    if ((buffer)->is_token_list) \
    127    { \
    128        ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \
    129    }
    130 
    131 /**
    132 * Returns a snapshot of the buffer-state.
    133 *
    134 * @param   buffer  A pointer to the `ZydisFormatterBuffer` struct.
    135 * @param   state   Receives a snapshot of the buffer-state.
    136 *
    137 * Using this macro instead of direct calls to `ZydisFormatterBufferRemember` improves the
    138 * performance for non-tokenizing passes.
    139 */
    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 
    149 /**
    150 * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
    151 *
    152 * @param   buffer  A pointer to the `ZydisFormatterBuffer` struct.
    153 * @param   name    The base name (without prefix) of the string- or token.
    154 */
    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 
    166 /**
    167 * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
    168 *
    169 * @param   buffer      A pointer to the `ZydisFormatterBuffer` struct.
    170 * @param   name        The base name (without prefix) of the string- or token.
    171 * @param   letter_case The desired letter-case.
    172 */
    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[];
    205 } ZydisPredefinedToken;
    206 
    207 #pragma pack(pop)
    208 
    209 #ifdef ZYAN_MSVC
    210 #   pragma warning(pop)
    211 #endif
    212 
    213 /**
    214 * Appends a predefined token-list to the `buffer`.
    215 *
    216 * @param   buffer  A pointer to the `ZydisFormatterBuffer` struct.
    217 * @param   data    A pointer to the `ZydisPredefinedToken` struct.
    218 *
    219 * @return  A zycore status code.
    220 *
    221 * This function is internally used to improve performance while adding static strings or multiple
    222 * tokens at once.
    223 */
    224 ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer* buffer,
    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 
    255 /**
    256 * Returns the size to be used as explicit size suffix (`AT&T`) or explicit typecast
    257 * (`INTEL`), if required.
    258 *
    259 * @param   formatter   A pointer to the `ZydisFormatter` instance.
    260 * @param   context     A pointer to the `ZydisFormatterContext` struct.
    261 * @param   operand     The instructions first memory operand.
    262 *
    263 * @return  Returns the explicit size, if required, or `0`, if not needed.
    264 *
    265 * This function always returns a size different to `0`, if the `ZYDIS_FORMATTER_PROP_FORCE_SIZE`
    266 * is set to `ZYAN_TRUE`.
    267 */
    268 ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter,
    269    ZydisFormatterContext* context, const ZydisDecodedOperand* operand);
    270 
    271 /* ---------------------------------------------------------------------------------------------- */
    272 
    273 /* ============================================================================================== */
    274 /* Formatter functions                                                                            */
    275 /* ============================================================================================== */
    276 
    277 /* ---------------------------------------------------------------------------------------------- */
    278 /* Operands                                                                                       */
    279 /* ---------------------------------------------------------------------------------------------- */
    280 
    281 ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter,
    282    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
    283 
    284 ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter,
    285    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
    286 
    287 ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter,
    288    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
    289 
    290 /* ---------------------------------------------------------------------------------------------- */
    291 /* Elemental tokens                                                                               */
    292 /* ---------------------------------------------------------------------------------------------- */
    293 
    294 ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter,
    295    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
    296 
    297 ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter,
    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 
    310 ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter,
    311    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);
    312 
    313 ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter,
    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