/*
 * PRINT STATE instrumentation.
 */

/*
 * Prints the register state.
 *
 * EXAMPLE USAGE:
 *  $ e9compile state.c
 *  $ e9tool -M jmp -P 'entry(state,asm)@state' xterm
 *  $ ./a.out
 */

#include "stdlib.c"
// #include "string.h"

/*
 * The "state" data structure.
 */
struct STATE
{
    union
    {
        uint16_t rflags;
        uint64_t __padding;
    };
    union
    {
        int64_t r15;
        int32_t r15d;
        int16_t r15w;
        int8_t r15b;
    };
    union
    {
        int64_t r14;
        int32_t r14d;
        int16_t r14w;
        int8_t r14b;
    };
    union
    {
        int64_t r13;
        int32_t r13d;
        int16_t r13w;
        int8_t r13b;
    };
    union
    {
        int64_t r12;
        int32_t r12d;
        int16_t r12w;
        int8_t r12b;
    };
    union
    {
        int64_t r11;
        int32_t r11d;
        int16_t r11w;
        int8_t r11b;
    };
    union
    {
        int64_t r10;
        int32_t r10d;
        int16_t r10w;
        int8_t r10b;
    };
    union
    {
        int64_t r9;
        int32_t r9d;
        int16_t r9w;
        int8_t r9b;
    };
    union
    {
        int64_t r8;
        int32_t r8d;
        int16_t r8w;
        int8_t r8b;
    };
    union
    {
        int64_t rdi;
        int32_t edi;
        int16_t di;
        int8_t dil;
    };
    union
    {
        int64_t rsi;
        int32_t esi;
        int16_t si;
        int8_t sil;
    };
    union
    {
        int64_t rbp;
        int32_t ebp;
        int16_t bp;
        int8_t bpl;
    };
    union
    {
        int64_t rbx;
        int32_t ebx;
        int16_t bx;
        struct
        {
            int8_t bl;
            int8_t bh;
        };
    };
    union
    {
        int64_t rdx;
        int32_t edx;
        int16_t dx;
        struct
        {
            int8_t dl;
            int8_t dh;
        };
    };
    union
    {
        int64_t rcx;
        int32_t ecx;
        int16_t cx;
        struct
        {
            int8_t cl;
            int8_t ch;
        };
    };
    union
    {
        int64_t rax;
        int32_t eax;
        int16_t ax;
        struct
        {
            int8_t al;
            int8_t ah;
        };
    };
    union
    {
        int64_t rsp;
        int32_t esp;
        int16_t sp;
        int16_t spl;
    };
    const union
    {
        int64_t rip;
        int32_t eip;
        int16_t ip;
    };
};

/*
 * Flags.
 */
#define OF      0x0001
#define CF      0x0100
#define PF      0x0400
#define AF      0x1000
#define ZF      0x4000
#define SF      0x8000

/*
 * Colors.
 */
#define RED     "\33[31m"
#define GREEN   "\33[32m"
#define YELLOW  "\33[33m"
#define WHITE   "\33[0m"

FILE* log_fd=NULL;

/*
 * Entry point.
 */
void entry(const struct STATE *state, const char *_asm)
{
    // read function address
    printf("[*] entry-------------------------------------------------------\n");
    static mutex_t mutex = MUTEX_INITIALIZER;
    if (mutex_lock(&mutex) < 0)
        return;
    clearerr(stderr);
    fprintf(stderr, RED "%.16lx" WHITE ": " GREEN "%s" WHITE "\n",
        state->rip, _asm);

    // split and match call function by offset


    // pass the parameter by register value


    // load function

    fprintf(stderr, "\t%rax    = 0x%.16lx (%ld)\n", state->rax, state->rax);
    fprintf(stderr, "\t%rcx    = 0x%.16lx (%ld)\n", state->rcx, state->rcx);
    fprintf(stderr, "\t%rdx    = 0x%.16lx (%ld)\n", state->rdx, state->rdx);
    fprintf(stderr, "\t%rbx    = 0x%.16lx (%ld)\n", state->rbx, state->rbx);
    fprintf(stderr, "\t%rsp    = 0x%.16lx (%ld)\n", state->rsp, state->rsp);
    fprintf(stderr, "\t%rbp    = 0x%.16lx (%ld)\n", state->rbp, state->rbp);
    fprintf(stderr, "\t%rsi    = 0x%.16lx (%ld)\n", state->rsi, state->rsi);
    fprintf(stderr, "\t%rdi    = 0x%.16lx (%ld)\n", state->rdi, state->rdi);
    fprintf(stderr, "\t%r8     = 0x%.16lx (%ld)\n", state->r8 , state->r8);
    fprintf(stderr, "\t%r9     = 0x%.16lx (%ld)\n", state->r9 , state->r9);
    // fprintf(stderr, "\t%r10    = 0x%.16lx (%ld)\n", state->r10, state->r10);
    // fprintf(stderr, "\t%r11    = 0x%.16lx (%ld)\n", state->r11, state->r11);
    // fprintf(stderr, "\t%r12    = 0x%.16lx (%ld)\n", state->r12, state->r12);
    // fprintf(stderr, "\t%r13    = 0x%.16lx (%ld)\n", state->r13, state->r13);
    // fprintf(stderr, "\t%r14    = 0x%.16lx (%ld)\n", state->r14, state->r14);
    // fprintf(stderr, "\t%r15    = 0x%.16lx (%ld)\n", state->r15, state->r15);
    // fprintf(stderr, "\t%rflags = %c%c%c%c%c\n\n",
    //     (state->rflags & SF? 'S': '-'),
    //     (state->rflags & ZF? 'Z': '-'),
    //     (state->rflags & AF? 'A': '-'),
    //     (state->rflags & PF? 'P': '-'),
    //     (state->rflags & CF? 'C': '-'),
    //     (state->rflags & OF? 'O': '-'));
    fflush(stderr);
    mutex_unlock(&mutex);
}

/*
 * Init.
 */
void init(void)
{
    setvbuf(stderr, NULL, _IOFBF, 0);
}