Пример #1
0
void PrintLabel( const char *labelName, const char *format, va_list *args ) {
   Str *label = StrNew( labelName );
   Str *formatString = StrNew( format );
   Str *messageString = StrConcat( label, formatString );

   Print( messageString->value, args );

   StrDel( label );
   StrDel( formatString );
   StrDel( messageString );
}
Пример #2
0
bool ParseInstString(XEDPARSE* Parse, Inst* Instruction)
{
    // Copy a buffer to edit
    char buf[XEDPARSE_MAXBUFSIZE];
    strcpy(buf, Parse->instr);

    // Find near/far modifiers
    Instruction->Near  = StrDel(buf, "near", ' ');
    Instruction->Far   = StrDel(buf, "far", ' ');
    Instruction->Short = StrDel(buf, "short", ' ');

    // Limit the number of possible modifiers to 1 at a time
    if(((int)Instruction->Near + (int)Instruction->Far + (int)Instruction->Short) > 1)
    {
        strcpy(Parse->error, "Instruction cannot have multiple modifiers (short, near, far)");
        return false;
    }

    // Parse into tokens
    char tokens[8][64];
    memset(tokens, 0, sizeof(tokens));

    int tokenIndex = 0;
    int tokenCount = InstructionToTokens(buf, tokens);

    if(tokenCount <= 0)
    {
        strcpy(Parse->error, "Malformed or invalid instruction");
        return false;
    }

    // Prefix
    Instruction->Prefix = PrefixFromString(tokens[tokenIndex]);

    if(Instruction->Prefix != PREFIX_NONE)
        tokenIndex++;

    // Mnemonic
    strcpy(Instruction->Mnemonic, tokens[tokenIndex++]);

    // Operands
    for(int i = tokenIndex; i < tokenCount; i++)
    {
        if(!AnalyzeOperand(Parse, tokens[i], &Instruction->Operands[Instruction->OperandCount++]))
            return false;
    }

    if(Instruction->OperandCount > 4)
    {
        strcpy(Parse->error, "Instruction has more than 4 operands");
        return false;
    }

    // Verify and translate the mnemonic this time
    Instruction->Class = str2xed_iclass_enum_t(MnemonicInstToXed(Parse, Instruction));

    if(Instruction->Class == XED_ICLASS_INVALID)
    {
        sprintf(Parse->error, "Unknown instruction mnemonic '%s'", Instruction->Mnemonic);
        return false;
    }

    return true;
}
Пример #3
0
bool HandleMemoryOperand(XEDPARSE* Parse, const char* Value, InstOperand* Operand)
{
    // Copy the prefix into a buffer
    char prefix[64];

    strcpy(prefix, Value);
    *strchr(prefix, '[') = '\0';

    // Copy the calculation into a buffer (strrchr is intentional)
    char calc[64];

    if(strrchr(Value, '[') > strrchr(Value, ']'))
    {
        // Someone tried using a closing bracket before the opening
        strcpy(Parse->error, "Invalid memory bracket open/close pair");
        return false;
    }

    strcpy(calc, strrchr(Value, '[') + 1);
    *strchr(calc, ']') = '\0';

    // Gather any information & check the prefix validity
    if(strlen(prefix) > 0)
    {
        // Prefix must be lowercase
        _strlwr(prefix);

        // Remove 'ptr' if it exists and remove colons
        StrDel(prefix, "ptr", '\0');
        StrDel(prefix, ":", '\0');

        // Check if the segment can be used
        size_t len = strlen(prefix);

        if(len >= 2)
        {
            // Move backwards in order to get the segment (SIZE-SEG[CALC])
            char* segPtr = (prefix + (len - 2));

            // See if the segment is actually valid
            REG segment = RegFromString(segPtr);

            if(segment != REG_INVALID)
            {
                // Set the new segment
                Operand->Segment = segment;

                // End the string here
                *segPtr = '\0';
            }
        }

        // Determine the prefix size
        Operand->Size = OpsizeFromString(prefix);

        // If the size is UNSET and there's still chars left in the string,
        // it is an invalid identifier
        if(Operand->Size == SIZE_UNSET && strlen(prefix) > 0)
        {
            sprintf(Parse->error, "Unknown identifier in '%s'", Value);
            return false;
        }

        // Update the effective operand size for Xed
        Operand->XedEOSZ = OpsizeToEosz(Operand->Size);
    }

    // Begin determining the calculation
    // [Base + (Index * Scale) + Displacement] -- IN ANY ORDER
    if(strlen(calc) <= 0)
    {
        strcpy(Parse->error, "Invalid memory calculation");
        return false;
    }

    char temp[32];
    char* ptr    = calc;
    char* base   = temp;
    bool mulFlag = false;

    for(;; ptr++)
    {
        *base = '\0';

        switch(*ptr)
        {
        case '\0':
        case '+':
        case '-':
            if(mulFlag)
                SetMemoryIndexOrScale(Parse, temp, Operand);
            else
                SetMemoryDisplacementOrBase(Parse, temp, Operand);

            base    = temp;
            mulFlag = false;

            if(*ptr == '-')
                *base++ = '-';
            break;

        case '*':
            SetMemoryIndexOrScale(Parse, temp, Operand);

            base    = temp;
            mulFlag = true;
            break;

        default:
            *base++ = *ptr;
            break;
        }

        if(*ptr == '\0')
            break;
    }

    // Fix up the operand segment
    if(Operand->Segment == REG_INVALID)
    {
        if((Operand->Mem.BaseVal == REG_ESP || Operand->Mem.BaseVal == REG_EBP) && !Parse->x64)
        {
            // If the segment isn't set and the base is ESP or EBP,
            // auto-set the segment to SS
            Operand->Segment = REG_SS;
        }
        else
        {
            // Default to DS
            // 64-bit also doesn't have true segments except for FS/GS/DS
            Operand->Segment = REG_DS;
        }
    }

    if(Operand->Mem.Disp)
    {
        // If the base isn't set, the displacement must be at least 32 bits
        if(!Operand->Mem.Base)
            Operand->Mem.DispWidth = max(Operand->Mem.DispWidth, SIZE_DWORD);

        // Use RIP-relative addressing per default when on x64 and when the displacement is set
        // and when the segment is SEG_DS
        if(Parse->x64 && Operand->Segment == REG_DS)
        {
            if(!Operand->Mem.Base && !Operand->Mem.Index && !Operand->Mem.Scale)
            {
                // If a 32-bit address was given, don't apply RIP-relative addressing
                if(true || Operand->Mem.DispWidth != SIZE_DWORD) //removed this because rip-relative instructions are smaller
                {
                    LONGLONG newDisp = TranslateRelativeCip(Parse, Operand->Mem.DispVal, true);
                    ULONGLONG masked = newDisp & 0xFFFFFFFF00000000;

                    // Check if the mask fits into a 32-bit variable (taking sign-extension into account)
                    if(masked == 0 || masked == 0xFFFFFFFF00000000)
                    {
                        Operand->Mem.DispVal     = newDisp;
                        Operand->Mem.DispWidth   = SIZE_DWORD;
                        Operand->Mem.Base        = true;
                        Operand->Mem.BaseVal     = REG_RIP;
                        Operand->Mem.ImplicitRip = true;
                    }
                    else
                        Operand->Mem.DispWidth = SIZE_QWORD;
                }
            }
        }
    }
    else if(!Operand->Mem.Base && Operand->Mem.Index && Operand->Mem.Scale)
    {
        // Handle when only an index register and scale are set
        // Ex: MOV EAX, [ECX * 8]
        Operand->Mem.Disp      = true;
        Operand->Mem.DispVal   = 0;
        Operand->Mem.DispWidth = SIZE_DWORD;
    }

    return true;
}