tor-browser

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

FormatterATT.c (16849B)


      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/FormatterATT.h"
     28 
     29 /* ============================================================================================== */
     30 /* Constants                                                                                      */
     31 /* ============================================================================================== */
     32 
     33 #include "zydis/Zydis/Generated/FormatterStrings.inc"
     34 
     35 /* ============================================================================================== */
     36 /* Formatter functions                                                                            */
     37 /* ============================================================================================== */
     38 
     39 /* ---------------------------------------------------------------------------------------------- */
     40 /* Instruction                                                                                    */
     41 /* ---------------------------------------------------------------------------------------------- */
     42 
     43 ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
     44    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
     45 {
     46    ZYAN_ASSERT(formatter);
     47    ZYAN_ASSERT(buffer);
     48    ZYAN_ASSERT(context);
     49    ZYAN_ASSERT(context->instruction);
     50    ZYAN_ASSERT(context->operands);
     51 
     52    ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
     53    ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
     54 
     55    ZyanUPointer state_mnemonic;
     56    ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
     57 
     58    const ZyanI8 c = (ZyanI8)context->instruction->operand_count_visible - 1;
     59    for (ZyanI8 i = c; i >= 0; --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[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 /* ---------------------------------------------------------------------------------------------- */
    197 /* Operands                                                                                       */
    198 /* ---------------------------------------------------------------------------------------------- */
    199 
    200 ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter,
    201    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    202 {
    203    ZYAN_ASSERT(formatter);
    204    ZYAN_ASSERT(buffer);
    205    ZYAN_ASSERT(context);
    206 
    207    ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
    208 
    209    const ZyanBool absolute = !formatter->force_relative_riprel &&
    210        (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
    211    if (absolute && context->operand->mem.disp.has_displacement &&
    212        (context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
    213       ((context->operand->mem.base  == ZYDIS_REGISTER_NONE) ||
    214        (context->operand->mem.base  == ZYDIS_REGISTER_EIP ) ||
    215        (context->operand->mem.base  == ZYDIS_REGISTER_RIP )))
    216    {
    217        // EIP/RIP-relative or absolute-displacement address operand
    218        ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
    219    } else
    220    {
    221        const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
    222        const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
    223        const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
    224 
    225        // Regular memory operand
    226        if (neither_reg_nor_idx)
    227        {
    228            ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
    229        } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value)
    230        {
    231            ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
    232        }
    233 
    234        if (neither_reg_nor_idx)
    235        {
    236            return ZYAN_STATUS_SUCCESS;
    237        }
    238 
    239        ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_ATT);
    240 
    241        if (should_print_reg)
    242        {
    243            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
    244                context->operand->mem.base));
    245        }
    246        if (should_print_idx)
    247        {
    248            ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY);
    249            ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
    250                context->operand->mem.index));
    251            if (context->operand->mem.scale &&
    252                (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
    253                ((context->operand->mem.scale > 1) || formatter->force_memory_scale))
    254            {
    255                ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DELIMITER);
    256                ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY);
    257                ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
    258                ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
    259                    ZYAN_NULL, ZYAN_NULL));
    260            }
    261        }
    262 
    263        ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_ATT);
    264        return ZYAN_STATUS_SUCCESS;
    265    }
    266 
    267    return ZYAN_STATUS_SUCCESS;
    268 }
    269 
    270 /* ---------------------------------------------------------------------------------------------- */
    271 /* Elemental tokens                                                                               */
    272 /* ---------------------------------------------------------------------------------------------- */
    273 
    274 ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter,
    275    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    276 {
    277    ZYAN_ASSERT(formatter);
    278    ZYAN_ASSERT(buffer);
    279    ZYAN_ASSERT(context);
    280    ZYAN_ASSERT(context->instruction);
    281    ZYAN_ASSERT(context->operands);
    282 
    283    const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
    284        context->instruction->mnemonic);
    285    if (!mnemonic)
    286    {
    287        ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
    288        return ZYAN_STATUS_SUCCESS;
    289    }
    290 
    291    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
    292    if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
    293    {
    294        ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_FAR_ATT,
    295            formatter->case_mnemonic));
    296    }
    297    ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
    298 
    299    // Append operand-size suffix
    300    ZyanU32 size = 0;
    301    for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
    302    {
    303        const ZydisDecodedOperand* const operand = &context->operands[i];
    304        if ((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) &&
    305            ((operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
    306             (operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)))
    307        {
    308            size = ZydisFormatterHelperGetExplicitSize(formatter, context, operand);
    309            break;
    310        }
    311    }
    312 
    313    switch (size)
    314    {
    315    case   8: ZydisStringAppendShort(&buffer->string, &STR_SIZE_8_ATT  ); break;
    316    case  16: ZydisStringAppendShort(&buffer->string, &STR_SIZE_16_ATT ); break;
    317    case  32: ZydisStringAppendShort(&buffer->string, &STR_SIZE_32_ATT ); break;
    318    case  64: ZydisStringAppendShort(&buffer->string, &STR_SIZE_64_ATT ); break;
    319    case 128: ZydisStringAppendShort(&buffer->string, &STR_SIZE_128_ATT); break;
    320    case 256: ZydisStringAppendShort(&buffer->string, &STR_SIZE_256_ATT); break;
    321    case 512: ZydisStringAppendShort(&buffer->string, &STR_SIZE_512_ATT); break;
    322    default:
    323        break;
    324    }
    325 
    326    if (formatter->print_branch_size)
    327    {
    328        switch (context->instruction->meta.branch_type)
    329        {
    330        case ZYDIS_BRANCH_TYPE_NONE:
    331            break;
    332        case ZYDIS_BRANCH_TYPE_SHORT:
    333            return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
    334                formatter->case_mnemonic);
    335        case ZYDIS_BRANCH_TYPE_NEAR:
    336            return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
    337                formatter->case_mnemonic);
    338        default:
    339            return ZYAN_STATUS_INVALID_ARGUMENT;
    340        }
    341    }
    342 
    343    return ZYAN_STATUS_SUCCESS;
    344 }
    345 
    346 ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter,
    347    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
    348 {
    349    ZYAN_UNUSED(context);
    350 
    351    ZYAN_ASSERT(formatter);
    352    ZYAN_ASSERT(buffer);
    353    ZYAN_ASSERT(context);
    354 
    355    ZYDIS_BUFFER_APPEND(buffer, REGISTER);
    356    const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
    357    if (!str)
    358    {
    359        return ZydisStringAppendShortCase(&buffer->string, &STR_INVALID_REG,
    360            formatter->case_registers);
    361    }
    362    return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
    363 }
    364 
    365 ZyanStatus ZydisFormatterATTPrintAddressABS(const ZydisFormatter* formatter,
    366    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    367 {
    368    ZYAN_ASSERT(formatter);
    369    ZYAN_ASSERT(buffer);
    370    ZYAN_ASSERT(context);
    371 
    372    if ((context->instruction->meta.branch_type != ZYDIS_BRANCH_TYPE_NONE) &&
    373        (context->operand->type == ZYDIS_OPERAND_TYPE_MEMORY))
    374    {
    375        ZYDIS_BUFFER_APPEND(buffer, MUL);
    376    }
    377 
    378    return ZydisFormatterBasePrintAddressABS(formatter, buffer, context);
    379 }
    380 
    381 ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter,
    382    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    383 {
    384    ZYAN_ASSERT(formatter);
    385    ZYAN_ASSERT(buffer);
    386    ZYAN_ASSERT(context);
    387 
    388    ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
    389    switch (formatter->disp_signedness)
    390    {
    391    case ZYDIS_SIGNEDNESS_AUTO:
    392    case ZYDIS_SIGNEDNESS_SIGNED:
    393        ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->disp_base, &buffer->string,
    394            context->operand->mem.disp.value, formatter->disp_padding, 
    395            formatter->hex_force_leading_number, ZYAN_FALSE);
    396        break;
    397    case ZYDIS_SIGNEDNESS_UNSIGNED:
    398        ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
    399            context->operand->mem.disp.value, formatter->disp_padding, 
    400            formatter->hex_force_leading_number);
    401        break;
    402    default:
    403        return ZYAN_STATUS_INVALID_ARGUMENT;
    404    }
    405 
    406    return ZYAN_STATUS_SUCCESS;
    407 }
    408 
    409 ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter,
    410    ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
    411 {
    412    ZYAN_ASSERT(formatter);
    413    ZYAN_ASSERT(buffer);
    414    ZYAN_ASSERT(context);
    415 
    416    ZYDIS_BUFFER_APPEND(buffer, IMMEDIATE);
    417    return ZydisFormatterBasePrintIMM(formatter, buffer, context);
    418 }
    419 
    420 /* ---------------------------------------------------------------------------------------------- */
    421 
    422 /* ============================================================================================== */