Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/zydis/Zydis/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 24 kB image not shown  

Quelle  Formatter.c   Sprache: C

 
/***************************************************************************************************

  Zyan Disassembler Library (Zydis)

  Original Author : Florian Bernd, Joel Hoener

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.

***************************************************************************************************/


#include "zydis/Zycore/LibC.h"
#include "zydis/Zydis/Formatter.h"
#include "zydis/Zydis/Internal/FormatterATT.h"
#include "zydis/Zydis/Internal/FormatterIntel.h"
#include "zydis/Zydis/Internal/String.h"

/* ============================================================================================== */
/* Constants                                                                                      */
/* ============================================================================================== */

/* ---------------------------------------------------------------------------------------------- */
/* Formatter presets                                                                              */
/* ---------------------------------------------------------------------------------------------- */

static const ZydisFormatter* const FORMATTER_PRESETS[ZYDIS_FORMATTER_STYLE_MAX_VALUE + 1] =
{
    &FORMATTER_ATT,
    &FORMATTER_INTEL,
    &FORMATTER_INTEL_MASM
};

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
/* Internal functions                                                                             */
/* ============================================================================================== */

/* ---------------------------------------------------------------------------------------------- */
/* Helper functions                                                                               */
/* ---------------------------------------------------------------------------------------------- */

static void ZydisFormatterBufferInit(ZydisFormatterBuffer* buffer, char* user_buffer,
    ZyanUSize length)
{
    ZYAN_ASSERT(buffer);
    ZYAN_ASSERT(user_buffer);
    ZYAN_ASSERT(length);

    buffer->is_token_list                   = ZYAN_FALSE;
    buffer->capacity                        = 0;
    buffer->string.flags                    = ZYAN_STRING_HAS_FIXED_CAPACITY;
    buffer->string.vector.allocator         = ZYAN_NULL;
    buffer->string.vector.growth_factor     = 1;
    buffer->string.vector.shrink_threshold  = 0;
    buffer->string.vector.destructor        = ZYAN_NULL;
    buffer->string.vector.element_size      = sizeof(char);
    buffer->string.vector.size              = 1;
    buffer->string.vector.capacity          = length;
    buffer->string.vector.data              = user_buffer;

    *user_buffer = '\0';
}

static void ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer* buffer,
    ZydisFormatterToken** first_token, void* user_buffer, ZyanUSize length)
{
    ZYAN_ASSERT(buffer);
    ZYAN_ASSERT(first_token);
    ZYAN_ASSERT(user_buffer);
    ZYAN_ASSERT(length);

    *first_token = user_buffer;
    (*first_token)->type = ZYDIS_TOKEN_INVALID;
    (*first_token)->next = 0;

    user_buffer = (ZyanU8*)user_buffer + sizeof(ZydisFormatterToken);
    length -= sizeof(ZydisFormatterToken);

    buffer->is_token_list                  = ZYAN_TRUE;
    buffer->capacity                       = length;
    buffer->string.flags                   = ZYAN_STRING_HAS_FIXED_CAPACITY;
    buffer->string.vector.allocator        = ZYAN_NULL;
    buffer->string.vector.growth_factor    = 1;
    buffer->string.vector.shrink_threshold = 0;
    buffer->string.vector.destructor       = ZYAN_NULL;
    buffer->string.vector.element_size     = sizeof(char);
    buffer->string.vector.size             = 1;
    buffer->string.vector.capacity         = length;
    buffer->string.vector.data             = user_buffer;

    *(char*)user_buffer = '\0';
}

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
/* Exported functions                                                                             */
/* ============================================================================================== */

/* ---------------------------------------------------------------------------------------------- */
/* Initialization                                                                                 */
/* ---------------------------------------------------------------------------------------------- */

ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style)
{
    if (!formatter || ((ZyanUSize)style > ZYDIS_FORMATTER_STYLE_MAX_VALUE))
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZYAN_MEMCPY(formatter, FORMATTER_PRESETS[style], sizeof(*formatter));

    return ZYAN_STATUS_SUCCESS;
}

/* ---------------------------------------------------------------------------------------------- */
/* Setter                                                                                         */
/* ---------------------------------------------------------------------------------------------- */

ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, ZydisFormatterProperty property,
    ZyanUPointer value)
{
    if (!formatter)
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZydisNumericBase base = (ZydisNumericBase)(-1);
    ZyanU8 index = 0xFF;

    switch (property)
    {
    case ZYDIS_FORMATTER_PROP_FORCE_SIZE:
    {
        formatter->force_memory_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_FORCE_SEGMENT:
    {
        formatter->force_memory_segment = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE:
    {
        formatter->force_memory_scale = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES:
    {
        formatter->force_relative_branches = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL:
    {
        formatter->force_relative_riprel = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE:
    {
        formatter->print_branch_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES:
    {
        formatter->detailed_prefixes = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_ADDR_BASE:
    {
        if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->addr_base = (ZydisNumericBase)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS:
    {
        if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->addr_signedness = (ZydisSignedness)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE:
    {
        if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) &&
            (value > 0xFF))
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->addr_padding_absolute = (ZydisPadding)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE:
    {
        if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) &&
            (value > 0xFF))
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->addr_padding_relative = (ZydisPadding)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DISP_BASE:
    {
        if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->disp_base = (ZydisNumericBase)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS:
    {
        if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->disp_signedness = (ZydisSignedness)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DISP_PADDING:
    {
        if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
        {
            if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
            {
                return ZYAN_STATUS_INVALID_ARGUMENT;
            }
            formatter->disp_padding = FORMATTER_PRESETS[formatter->style]->disp_padding;
        }
        else if (value > 0xFF)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->disp_padding = (ZydisPadding)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_IMM_BASE:
    {
        if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->imm_base = (ZydisNumericBase)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS:
    {
        if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->imm_signedness  = (ZydisSignedness)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_IMM_PADDING:
    {
        if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
        {
            if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
            {
                return ZYAN_STATUS_INVALID_ARGUMENT;
            }
            formatter->imm_padding = FORMATTER_PRESETS[formatter->style]->imm_padding;
        }
        else if (value > 0xFF)
        {
            return ZYAN_STATUS_INVALID_ARGUMENT;
        }
        formatter->imm_padding = (ZydisPadding)value;
        break;
    }
    case ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES:
    {
        formatter->case_prefixes = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
        break;
    }
    case ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC:
    {
        formatter->case_mnemonic = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
        break;
    }
    case ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS:
    {
        formatter->case_registers = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
        break;
    }
    case ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS:
    {
        formatter->case_typecasts = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
        break;
    }
    case ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS:
    {
        formatter->case_decorators = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DEC_PREFIX:
    {
        base  = ZYDIS_NUMERIC_BASE_DEC;
        index = 0;
        break;
    }
    case ZYDIS_FORMATTER_PROP_DEC_SUFFIX:
    {
        base  = ZYDIS_NUMERIC_BASE_DEC;
        index = 1;
        break;
    }
    case ZYDIS_FORMATTER_PROP_HEX_UPPERCASE:
    {
        formatter->hex_uppercase = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_HEX_FORCE_LEADING_NUMBER:
    {
        formatter->hex_force_leading_number = (value) ? ZYAN_TRUE : ZYAN_FALSE;
        break;
    }
    case ZYDIS_FORMATTER_PROP_HEX_PREFIX:
    {
        base  = ZYDIS_NUMERIC_BASE_HEX;
        index = 0;
        break;
    }
    case ZYDIS_FORMATTER_PROP_HEX_SUFFIX:
    {
        base  = ZYDIS_NUMERIC_BASE_HEX;
        index = 1;
        break;
    }
    default:
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    // Set prefix or suffix
    if (base != (ZydisNumericBase)(-1))
    {
        if (value)
        {
            const ZyanUSize len = ZYAN_STRLEN((char*)value);
            if (len > 10)
            {
                return ZYAN_STATUS_INVALID_ARGUMENT;
            }
            ZYAN_MEMCPY(formatter->number_format[base][index].buffer, (void*)value, len);
            formatter->number_format[base][index].buffer[len] = '\0';
            formatter->number_format[base][index].string_data.string.vector.data =
                formatter->number_format[base][index].buffer;
            formatter->number_format[base][index].string_data.string.vector.size = len + 1;
            formatter->number_format[base][index].string =
                &formatter->number_format[base][index].string_data;
        } else
        {
            formatter->number_format[base][index].string = ZYAN_NULL;
        }
    }

    return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type,
    const void** callback)
{
    if (!formatter || !callback || ((ZyanUSize)type > ZYDIS_FORMATTER_FUNC_MAX_VALUE))
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    const voidconst temp = *callback;

    // The following code relies on the order of the enum values and the function fields inside
    // the `ZydisFormatter` struct

#ifdef ZYAN_DEBUG
    const ZyanUPointer* test = (ZyanUPointer*)(&formatter->func_pre_instruction + type);
    switch (type)
    {
    case ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_instruction   ); break;
    case ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_instruction  ); break;
    case ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_instruction); break;
    case ZYDIS_FORMATTER_FUNC_PRE_OPERAND:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_operand       ); break;
    case ZYDIS_FORMATTER_FUNC_POST_OPERAND:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_operand      ); break;
    case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_reg); break;
    case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_mem); break;
    case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_ptr); break;
    case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_imm); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_mnemonic    ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_REGISTER:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_register    ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_abs ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_rel ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_DISP:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_disp        ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_IMM:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_imm         ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_typecast    ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_segment     ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_prefixes    ); break;
    case ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR:
        ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_decorator   ); break;
    default:
        ZYAN_UNREACHABLE;
    }
#endif

    *callback = *(const void**)(&formatter->func_pre_instruction + type);
    if (!temp)
    {
        return ZYAN_STATUS_SUCCESS;
    }
    ZYAN_MEMCPY(&formatter->func_pre_instruction + type, &temp, sizeof(ZyanUPointer));

    return ZYAN_STATUS_SUCCESS;
}

/* ---------------------------------------------------------------------------------------------- */
/* Formatting                                                                                     */
/* ---------------------------------------------------------------------------------------------- */

ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter,
    const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands,
    ZyanU8 operand_count, char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data)
{
    if (!formatter || !instruction || (operand_count && !operands) ||
        (operand_count > ZYDIS_MAX_OPERAND_COUNT) ||
        (operand_count < instruction->operand_count_visible) || !buffer || (length == 0))
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZydisFormatterBuffer formatter_buffer;
    ZydisFormatterBufferInit(&formatter_buffer, buffer, length);

    ZydisFormatterContext context;
    context.instruction     = instruction;
    context.operands        = operands;
    context.runtime_address = runtime_address;
    context.operand         = ZYAN_NULL;
    context.user_data       = user_data;

    if (formatter->func_pre_instruction)
    {
        ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
    }

    ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));

    if (formatter->func_post_instruction)
    {
        ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
    }

    return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
    const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand,
    char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data)
{
    if (!formatter || !instruction || !operand || !buffer || (length == 0))
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZydisFormatterBuffer formatter_buffer;
    ZydisFormatterBufferInit(&formatter_buffer, buffer, length);

    ZydisFormatterContext context;
    context.instruction     = instruction;
    context.operands        = ZYAN_NULL;
    context.runtime_address = runtime_address;
    context.operand         = operand;
    context.user_data       = user_data;

    // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
    // to skip the only operand printed by this function

    if (formatter->func_pre_operand)
    {
        ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
    }

    switch (context.operand->type)
    {
    case ZYDIS_OPERAND_TYPE_REGISTER:
        ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_MEMORY:
        ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_IMMEDIATE:
        ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_POINTER:
        ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
        break;
    default:
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    if (formatter->func_post_operand)
    {
        ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
    }

    return ZYAN_STATUS_SUCCESS;
}

/* ---------------------------------------------------------------------------------------------- */
/* Tokenizing                                                                                     */
/* ---------------------------------------------------------------------------------------------- */

ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter,
    const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands,
    ZyanU8 operand_count, void* buffer, ZyanUSize length, ZyanU64 runtime_address,
    ZydisFormatterTokenConst** token, void* user_data)
{
    if (!formatter || !instruction || (operand_count && !operands) ||
        (operand_count > ZYDIS_MAX_OPERAND_COUNT) || 
        (operand_count < instruction->operand_count_visible) || !buffer ||
        (length <= sizeof(ZydisFormatterToken)) || !token)
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZydisFormatterBuffer formatter_buffer;
    ZydisFormatterToken* first_token;
    ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);

    ZydisFormatterContext context;
    context.instruction     = instruction;
    context.operands        = operands;
    context.runtime_address = runtime_address;
    context.operand         = ZYAN_NULL;
    context.user_data       = user_data;

    if (formatter->func_pre_instruction)
    {
        ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
    }

    ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));

    if (formatter->func_post_instruction)
    {
        ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
    }

    if (first_token->next)
    {
        *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
            first_token->next);
        return ZYAN_STATUS_SUCCESS;
    }

    *token = first_token;
    return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter,
    const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand,
    void* buffer, ZyanUSize length, ZyanU64 runtime_address, ZydisFormatterTokenConst** token,
    void* user_data)
{
    if (!formatter || !instruction || !operand || !buffer ||
        (length <= sizeof(ZydisFormatterToken)) || !token)
    {
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    ZydisFormatterToken* first_token;
    ZydisFormatterBuffer formatter_buffer;
    ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);

    ZydisFormatterContext context;
    context.instruction     = instruction;
    context.operands        = ZYAN_NULL;
    context.runtime_address = runtime_address;
    context.operand         = operand;
    context.user_data       = user_data;

    // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
    // to skip the only operand printed by this function

    if (formatter->func_pre_operand)
    {
        ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
    }

    switch (context.operand->type)
    {
    case ZYDIS_OPERAND_TYPE_REGISTER:
        ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_MEMORY:
        ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_IMMEDIATE:
        ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
        break;
    case ZYDIS_OPERAND_TYPE_POINTER:
        ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
        break;
    default:
        return ZYAN_STATUS_INVALID_ARGUMENT;
    }

    if (formatter->func_post_operand)
    {
        ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
    }

    if (first_token->next)
    {
        *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
            first_token->next);
        return ZYAN_STATUS_SUCCESS;
    }

    *token = first_token;
    return ZYAN_STATUS_SUCCESS;
}

/* ============================================================================================== */

/* ============================================================================================== */

Messung V0.5
C=95 H=100 G=97

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.