/*
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * This plugin patches instructions matching a pattern to a different
 * instruction as they execute
 *
 */

#include "glib.h"
#include "glibconfig.h"

#include <qemu-plugin.h>
#include <string.h>
#include <stdio.h>

QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;

static bool use_hwaddr;
static GByteArray *target_data;
static GByteArray *patch_data;

/**
 * Parse a string of hexadecimal digits into a GByteArray. The string must be
 * even length
 */
static GByteArray *str_to_bytes(const char *str)
{
    size_t len = strlen(str);

    if (len == 0 || len % 2 != 0) {
        return NULL;
    }

    GByteArray *bytes = g_byte_array_new();
    char byte[3] = {0};
    guint8 value = 0;

    for (size_t i = 0; i < len; i += 2) {
        byte[0] = str[i];
        byte[1] = str[i + 1];
        value = (guint8)g_ascii_strtoull(byte, NULL, 16);
        g_byte_array_append(bytes, &value, 1);
    }

    return bytes;
}

static void patch_hwaddr(unsigned int vcpu_index, void *userdata)
{
    uintptr_t addr = (uintptr_t) userdata;
    g_autoptr(GString) str = g_string_new(NULL);
    g_string_printf(str, "patching: @0x%"
                    PRIxPTR "\n",
                    addr);
    qemu_plugin_outs(str->str);

    enum qemu_plugin_hwaddr_operation_result result =
        qemu_plugin_write_memory_hwaddr(addr, patch_data);


    if (result != QEMU_PLUGIN_HWADDR_OPERATION_OK) {
        g_autoptr(GString) errmsg = g_string_new(NULL);
        g_string_printf(errmsg, "Failed to write memory: %d\n", result);
        qemu_plugin_outs(errmsg->str);
        return;
    }

    g_autoptr(GByteArray) read_data = g_byte_array_new();

    result = qemu_plugin_read_memory_hwaddr(addr, read_data,
                                            patch_data->len);

    qemu_plugin_outs("Reading memory...\n");

    if (result != QEMU_PLUGIN_HWADDR_OPERATION_OK) {
        g_autoptr(GString) errmsg = g_string_new(NULL);
        g_string_printf(errmsg, "Failed to read memory: %d\n", result);
        qemu_plugin_outs(errmsg->str);
        return;
    }

    if (memcmp(patch_data->data, read_data->data, patch_data->len) != 0) {
        qemu_plugin_outs("Failed to read back written data\n");
    }

    qemu_plugin_outs("Success!\n");

    return;
}

static void patch_vaddr(unsigned int vcpu_index, void *userdata)
{
    uintptr_t addr = (uintptr_t) userdata;
    uint64_t hwaddr = 0;
    if (!qemu_plugin_translate_vaddr(addr, &hwaddr)) {
        qemu_plugin_outs("Failed to translate vaddr\n");
        return;
    }
    g_autoptr(GString) str = g_string_new(NULL);
    g_string_printf(str, "patching: @0x%"
                    PRIxPTR " hw: @0x%" PRIx64 "\n",
                    addr, hwaddr);
    qemu_plugin_outs(str->str);

    qemu_plugin_outs("Writing memory (vaddr)...\n");

    if (!qemu_plugin_write_memory_vaddr(addr, patch_data)) {
        qemu_plugin_outs("Failed to write memory\n");
        return;
    }

    qemu_plugin_outs("Reading memory (vaddr)...\n");

    g_autoptr(GByteArray) read_data = g_byte_array_new();

    if (!qemu_plugin_read_memory_vaddr(addr, read_data, patch_data->len)) {
        qemu_plugin_outs("Failed to read memory\n");
        return;
    }

    if (memcmp(patch_data->data, read_data->data, patch_data->len) != 0) {
        qemu_plugin_outs("Failed to read back written data\n");
    }

    qemu_plugin_outs("Success!\n");

    return;
}

/*
 * Callback on translation of a translation block.
 */
static void vcpu_tb_trans_cb(struct qemu_plugin_tb *tb, void *userdata)
{
    g_autoptr(GByteArray) insn_data = g_byte_array_new();
    uintptr_t addr = 0;

    for (size_t i = 0; i < qemu_plugin_tb_n_insns(tb); i++) {
        struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
        uint64_t vaddr = qemu_plugin_insn_vaddr(insn);

        if (use_hwaddr) {
            uint64_t hwaddr = 0;
            if (!qemu_plugin_translate_vaddr(vaddr, &hwaddr)) {
                qemu_plugin_outs("Failed to translate vaddr\n");
                continue;
            }
            /*
             * As we cannot emulate 64 bit systems on 32 bit hosts we
             * should never see the top bits set, hence we can safely
             * cast to uintptr_t.
             */
            g_assert(hwaddr <= UINTPTR_MAX);
            addr = (uintptr_t) hwaddr;
        } else {
            g_assert(vaddr <= UINTPTR_MAX);
            addr = (uintptr_t) vaddr;
        }

        g_byte_array_set_size(insn_data, qemu_plugin_insn_size(insn));
        qemu_plugin_insn_data(insn, insn_data->data, insn_data->len);

        if (insn_data->len >= target_data->len &&
            !memcmp(insn_data->data, target_data->data,
                    MIN(target_data->len, insn_data->len))) {
            if (use_hwaddr) {
                qemu_plugin_register_vcpu_tb_exec_cb(tb, patch_hwaddr,
                                                     QEMU_PLUGIN_CB_NO_REGS,
                                                     (void *) addr);
            } else {
                qemu_plugin_register_vcpu_tb_exec_cb(tb, patch_vaddr,
                                                     QEMU_PLUGIN_CB_NO_REGS,
                                                     (void *) addr);
            }
        }
    }
}

static void usage(void)
{
    fprintf(stderr, "Usage: <lib>,target=<bytes>,patch=<new_bytes>"
            "[,use_hwaddr=true|false]");
}

/*
 * Called when the plugin is installed
 */
QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
                                           const qemu_info_t *info, int argc,
                                           char **argv)
{

    use_hwaddr = true;
    target_data = NULL;
    patch_data = NULL;

    if (argc > 4) {
        usage();
        return -1;
    }

    for (size_t i = 0; i < argc; i++) {
        char *opt = argv[i];
        g_auto(GStrv) tokens = g_strsplit(opt, "=", 2);
        if (g_strcmp0(tokens[0], "use_hwaddr") == 0) {
            if (!qemu_plugin_bool_parse(tokens[0], tokens[1], &use_hwaddr)) {
                fprintf(stderr,
                        "Failed to parse boolean argument use_hwaddr\n");
                return -1;
            }
        } else if (g_strcmp0(tokens[0], "target") == 0) {
            target_data = str_to_bytes(tokens[1]);
            if (!target_data) {
                fprintf(stderr,
                         "Failed to parse target bytes.\n");
                return -1;
            }
        } else if (g_strcmp0(tokens[0], "patch") == 0) {
            patch_data = str_to_bytes(tokens[1]);
            if (!patch_data) {
                fprintf(stderr, "Failed to parse patch bytes.\n");
                return -1;
            }
        } else {
            fprintf(stderr, "Unknown argument: %s\n", tokens[0]);
            usage();
            return -1;
        }
    }

    if (!target_data) {
        fprintf(stderr, "target argument is required\n");
        usage();
        return -1;
    }

    if (!patch_data) {
        fprintf(stderr, "patch argument is required\n");
        usage();
        return -1;
    }

    if (target_data->len != patch_data->len) {
        fprintf(stderr, "Target and patch data must be the same length\n");
        return -1;
    }

    qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans_cb, NULL);

    return 0;
}
