tor-browser

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

FormatterIntel.c (18096B)


      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 #include "zydis/Zydis/Internal/FormatterIntel.h"
     28 #include "zydis/Zydis/Utils.h"
     29 #include "zydis/Zycore/Format.h"
     30 
     31 /* ============================================================================================== */
     32 /* Constants                                                                                      */
     33 /* ============================================================================================== */
     34 
     35 #include "zydis/Zydis/Generated/FormatterStrings.inc"
     36 
     37 /* ============================================================================================== */
     38 /* Formatter functions                                                                            */
     39 /* ============================================================================================== */
     40 
     41 /* ---------------------------------------------------------------------------------------------- */
     42 /* Intel                                                                                          */
     43 /* ---------------------------------------------------------------------------------------------- */
     44 
     45 ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
     46    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
     47 {
     48    ZYAN_ASSERT(formatter);
     49    ZYAN_ASSERT(buffer);
     50    ZYAN_ASSERT(context);
     51    ZYAN_ASSERT(context->instruction);
     52    ZYAN_ASSERT(context->operands);
     53 
     54    ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
     55    ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
     56 
     57    ZyanUPointer state_mnemonic;
     58    ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
     59    for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
     60    {
     61        const ZydisDecodedOperand* const operand = &context->operands[i];
     62 
     63        // Print embedded-mask registers as decorator instead of a regular operand
     64        if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) &&
     65            (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
     66        {
     67            continue;
     68        }
     69 
     70        ZyanUPointer buffer_state;
     71        ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);
     72 
     73        if (buffer_state != state_mnemonic)
     74        {
     75            ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
     76        } else
     77        {
     78            ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
     79        }
     80 
     81        // Set current operand
     82        context->operand = operand;
     83 
     84        ZyanStatus status;
     85        if (formatter->func_pre_operand)
     86        {
     87            status = formatter->func_pre_operand(formatter, buffer, context);
     88            if (status == ZYDIS_STATUS_SKIP_TOKEN)
     89            {
     90                ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
     91                continue;
     92            }
     93            if (!ZYAN_SUCCESS(status))
     94            {
     95                return status;
     96            }
     97        }
     98 
     99        switch (operand->type)
    100        {
    101        case ZYDIS_OPERAND_TYPE_REGISTER:
    102            status = formatter->func_format_operand_reg(formatter, buffer, context);
    103            break;
    104        case ZYDIS_OPERAND_TYPE_MEMORY:
    105            status = formatter->func_format_operand_mem(formatter, buffer, context);
    106            break;
    107        case ZYDIS_OPERAND_TYPE_POINTER:
    108            status = formatter->func_format_operand_ptr(formatter, buffer, context);
    109            break;
    110        case ZYDIS_OPERAND_TYPE_IMMEDIATE:
    111            status = formatter->func_format_operand_imm(formatter, buffer, context);
    112            break;
    113        default:
    114            return ZYAN_STATUS_INVALID_ARGUMENT;
    115        }
    116        if (status == ZYDIS_STATUS_SKIP_TOKEN)
    117        {
    118            ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
    119            continue;
    120        }
    121        if (!ZYAN_SUCCESS(status))
    122        {
    123            return status;
    124        }
    125 
    126        if (formatter->func_post_operand)
    127        {
    128            status = formatter->func_post_operand(formatter, buffer, context);
    129            if (status == ZYDIS_STATUS_SKIP_TOKEN)
    130            {
    131                ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
    132                continue;
    133            }
    134            if (ZYAN_SUCCESS(status))
    135            {
    136                return status;
    137            }
    138        }
    139 
    140 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
    141        if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
    142            (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
    143        {
    144            if  ((i == 0) &&
    145                 (context->instruction->operand_count_visible > 1) &&
    146                 (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
    147            {
    148                ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    149                    ZYDIS_DECORATOR_MASK));
    150            }
    151            if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
    152            {
    153                ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    154                    ZYDIS_DECORATOR_BC));
    155                if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
    156                {
    157                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    158                        ZYDIS_DECORATOR_CONVERSION));
    159                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    160                        ZYDIS_DECORATOR_EH));
    161                }
    162            } else
    163            {
    164                ZyanBool decorate_operand;
    165                if (i == (context->instruction->operand_count_visible - 1))
    166                {
    167                    decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE;
    168                }
    169                else
    170                {
    171                    decorate_operand =
    172                        (context->instruction->operand_count_visible > (i + 1)) &&
    173                        ((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
    174                        (context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN));
    175                }
    176                if (decorate_operand)
    177                {
    178                    if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
    179                    {
    180                        ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    181                            ZYDIS_DECORATOR_SWIZZLE));
    182                    }
    183                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    184                        ZYDIS_DECORATOR_RC));
    185                    ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
    186                        ZYDIS_DECORATOR_SAE));
    187                }
    188            }
    189        }
    190 #endif
    191    }
    192 
    193    return ZYAN_STATUS_SUCCESS;
    194 }
    195 
    196 ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
    197    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    198 {
    199    ZYAN_ASSERT(formatter);
    200    ZYAN_ASSERT(buffer);
    201    ZYAN_ASSERT(context);
    202 
    203    if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
    204        (context->operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) ||
    205        (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB))
    206    {
    207        ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context));
    208    }
    209    ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
    210 
    211    ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL);
    212 
    213    const ZyanBool absolute = !formatter->force_relative_riprel &&
    214        (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
    215    if (absolute && context->operand->mem.disp.has_displacement &&
    216        (context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
    217       ((context->operand->mem.base  == ZYDIS_REGISTER_NONE) ||
    218        (context->operand->mem.base  == ZYDIS_REGISTER_EIP ) ||
    219        (context->operand->mem.base  == ZYDIS_REGISTER_RIP )))
    220    {
    221        // EIP/RIP-relative or absolute-displacement address operand
    222        ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
    223    } else
    224    {
    225        const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
    226        const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
    227        const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
    228 
    229        // Regular memory operand
    230        if (should_print_reg)
    231        {
    232            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
    233                context->operand->mem.base));
    234        }
    235        if (should_print_idx)
    236        {
    237            if (context->operand->mem.base != ZYDIS_REGISTER_NONE)
    238            {
    239                ZYDIS_BUFFER_APPEND(buffer, ADD);
    240            }
    241            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
    242                context->operand->mem.index));
    243            if (context->operand->mem.scale &&
    244                (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
    245                ((context->operand->mem.scale > 1) || formatter->force_memory_scale))
    246            {
    247                ZYDIS_BUFFER_APPEND(buffer, MUL);
    248                ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
    249                ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
    250                    ZYAN_NULL, ZYAN_NULL));
    251            }
    252        }
    253        if (neither_reg_nor_idx)
    254        {
    255            ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
    256        } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value)
    257        {
    258            ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
    259        }
    260    }
    261 
    262    ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL);
    263    return ZYAN_STATUS_SUCCESS;
    264 }
    265 
    266 ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
    267    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    268 {
    269    ZYAN_ASSERT(formatter);
    270    ZYAN_ASSERT(buffer);
    271    ZYAN_ASSERT(context);
    272 
    273    const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
    274        context->instruction->mnemonic);
    275    if (!mnemonic)
    276    {
    277        ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
    278        return ZYAN_STATUS_SUCCESS;
    279    }
    280 
    281    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
    282    ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
    283    if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
    284    {
    285        return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic);
    286    }
    287    if (formatter->print_branch_size)
    288    {
    289        switch (context->instruction->meta.branch_type)
    290        {
    291        case ZYDIS_BRANCH_TYPE_NONE:
    292            break;
    293        case ZYDIS_BRANCH_TYPE_SHORT:
    294            return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
    295                formatter->case_mnemonic);
    296        case ZYDIS_BRANCH_TYPE_NEAR:
    297            return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
    298                formatter->case_mnemonic);
    299        default:
    300            return ZYAN_STATUS_INVALID_ARGUMENT;
    301        }
    302    }
    303 
    304    return ZYAN_STATUS_SUCCESS;
    305 }
    306 
    307 ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
    308    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
    309 {
    310    ZYAN_UNUSED(context);
    311 
    312    ZYAN_ASSERT(formatter);
    313    ZYAN_ASSERT(buffer);
    314    ZYAN_ASSERT(context);
    315 
    316    const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
    317    if (!str)
    318    {
    319        ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers);
    320        return ZYAN_STATUS_SUCCESS;
    321    }
    322 
    323    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER);
    324    return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
    325 }
    326 
    327 ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
    328    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    329 {
    330    ZYAN_ASSERT(formatter);
    331    ZYAN_ASSERT(buffer);
    332    ZYAN_ASSERT(context);
    333 
    334    switch (formatter->disp_signedness)
    335    {
    336    case ZYDIS_SIGNEDNESS_AUTO:
    337    case ZYDIS_SIGNEDNESS_SIGNED:
    338        if (context->operand->mem.disp.value < 0)
    339        {
    340            if ((context->operand->mem.base  != ZYDIS_REGISTER_NONE) ||
    341                (context->operand->mem.index != ZYDIS_REGISTER_NONE))
    342            {
    343                ZYDIS_BUFFER_APPEND(buffer, SUB);
    344            }
    345            ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
    346            ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
    347                ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding,
    348                formatter->hex_force_leading_number);
    349            break;
    350        }
    351        ZYAN_FALLTHROUGH;
    352    case ZYDIS_SIGNEDNESS_UNSIGNED:
    353        if ((context->operand->mem.base  != ZYDIS_REGISTER_NONE) ||
    354            (context->operand->mem.index != ZYDIS_REGISTER_NONE))
    355        {
    356            ZYDIS_BUFFER_APPEND(buffer, ADD);
    357        }
    358        ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
    359        ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
    360            context->operand->mem.disp.value, formatter->disp_padding,
    361            formatter->hex_force_leading_number);
    362        break;
    363    default:
    364        return ZYAN_STATUS_INVALID_ARGUMENT;
    365    }
    366 
    367    return ZYAN_STATUS_SUCCESS;
    368 }
    369 
    370 ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
    371    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    372 {
    373    ZYAN_ASSERT(formatter);
    374    ZYAN_ASSERT(buffer);
    375    ZYAN_ASSERT(context);
    376 
    377    switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand))
    378    {
    379    case   8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL  ); break;
    380    case  16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break;
    381    case  32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break;
    382    case  48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48       ); break;
    383    case  64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break;
    384    case  80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80       ); break;
    385    case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break;
    386    case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break;
    387    case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break;
    388    default:
    389        break;
    390    }
    391 
    392    return ZYAN_STATUS_SUCCESS;
    393 }
    394 
    395 /* ---------------------------------------------------------------------------------------------- */
    396 /* MASM                                                                                           */
    397 /* ---------------------------------------------------------------------------------------------- */
    398 
    399 ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
    400    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    401 {
    402    ZYAN_ASSERT(formatter);
    403    ZYAN_ASSERT(buffer);
    404    ZYAN_ASSERT(context);
    405 
    406    // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function.
    407    // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative
    408    // memory operands
    409    context->runtime_address = 0;
    410 
    411    return ZydisFormatterIntelFormatInstruction(formatter, buffer, context);
    412 }
    413 
    414 ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
    415    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    416 {
    417    ZYAN_ASSERT(formatter);
    418    ZYAN_ASSERT(buffer);
    419    ZYAN_ASSERT(context);
    420 
    421    ZyanU64 address;
    422    ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
    423 
    424    ZyanU8 padding = (formatter->addr_padding_relative ==
    425        ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
    426    if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
    427        (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
    428    {
    429        switch (context->instruction->address_width)
    430        {
    431        case 16:
    432            padding =  4;
    433            address = (ZyanU16)address;
    434            break;
    435        case 32:
    436            padding =  8;
    437            address = (ZyanU32)address;
    438            break;
    439        case 64:
    440            padding = 16;
    441            break;
    442        default:
    443            return ZYAN_STATUS_INVALID_ARGUMENT;
    444        }
    445    }
    446 
    447    ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE);
    448    ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding,
    449        formatter->hex_force_leading_number, ZYAN_TRUE);
    450 
    451    return ZYAN_STATUS_SUCCESS;
    452 }
    453 
    454 /* ---------------------------------------------------------------------------------------------- */
    455 
    456 /* ============================================================================================== */