about summary refs log tree commit diff stats
path: root/src/emu/x64trace.c
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-02 14:49:36 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-02 14:49:36 +0100
commit1b9d1dc6093028ceb0f2eeeccf9cfbc5610fcf30 (patch)
treea63aca8dd2f11ea86ef7dfe066c3942e8b5e2dfe /src/emu/x64trace.c
parenta6143f33ce443c16a773816c2255936a39aee129 (diff)
downloadbox64-1b9d1dc6093028ceb0f2eeeccf9cfbc5610fcf30.tar.gz
box64-1b9d1dc6093028ceb0f2eeeccf9cfbc5610fcf30.zip
Added Zydis lib support for Trace enabled build
Diffstat (limited to 'src/emu/x64trace.c')
-rwxr-xr-xsrc/emu/x64trace.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/emu/x64trace.c b/src/emu/x64trace.c
new file mode 100755
index 00000000..b2f52179
--- /dev/null
+++ b/src/emu/x64trace.c
@@ -0,0 +1,111 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include "debug.h"
+#include "x64trace.h"
+#include "box64context.h"
+#include "x86zydis.h"
+#include "x64emu_private.h"
+
+typedef ZyanStatus (*PFNZydisDecoderInit)(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
+    ZydisAddressWidth address_width);
+
+typedef ZyanStatus (*PFNZydisFormatterInit)(ZydisFormatter* formatter, ZydisFormatterStyle style);
+
+typedef ZyanStatus (*PFNZydisDecoderDecodeBuffer)(const ZydisDecoder* decoder,
+    const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction);
+
+typedef ZyanStatus (*PFNZydisFormatterFormatInstruction)(const ZydisFormatter* formatter,
+    const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length,
+    ZyanU64 runtime_address);
+
+typedef struct zydis_s {
+    void*                       lib;
+    PFNZydisDecoderInit         ZydisDecoderInit;
+    PFNZydisFormatterInit       ZydisFormatterInit;
+    PFNZydisDecoderDecodeBuffer ZydisDecoderDecodeBuffer;
+    PFNZydisFormatterFormatInstruction ZydisFormatterFormatInstruction;
+} zydis_t;
+
+typedef struct zydis_dec_s {
+    ZydisDecoder            decoder;
+    ZydisFormatter          formatter;
+    ZydisDecodedInstruction instruction;
+    PFNZydisDecoderDecodeBuffer ZydisDecoderDecodeBuffer;
+    PFNZydisFormatterFormatInstruction ZydisFormatterFormatInstruction;
+} zydis_dec_t;
+
+int InitX64Trace(box64context_t *context)
+{
+    if(context->zydis)
+        return 0;
+    context->zydis = (zydis_t*)calloc(1, sizeof(zydis_t));
+    if(!context->zydis)
+        return 1;
+    context->zydis->lib = dlopen("libZydis.so", RTLD_LAZY);
+    if(!context->zydis->lib) {
+        printf_log(LOG_INFO, "Failed to open libZydis: %s\n", dlerror());
+        return 1;
+    }
+    #define GO(f) context->zydis->f = (PFN##f)dlsym(context->zydis->lib, #f);\
+         if(!context->zydis->f) {printf_log(LOG_INFO, "Fail to load Zydis function %s\n", #f); dlclose(context->zydis->lib); context->zydis->lib=NULL; return 1;}
+
+    GO(ZydisDecoderInit);
+    GO(ZydisFormatterInit);
+    GO(ZydisDecoderDecodeBuffer);
+    GO(ZydisFormatterFormatInstruction);
+    #undef GO
+
+    context->dec = InitX64TraceDecoder(context);
+
+    return 0;
+}
+
+void DeleteX64Trace(box64context_t *context)
+{
+    if(!context->zydis)
+        return;
+    if(context->zydis->lib)
+        dlclose(context->zydis->lib);
+    free(context->zydis);
+    context->zydis = NULL;
+}
+
+zydis_dec_t* InitX64TraceDecoder(box64context_t *context)
+{
+    if(!context->zydis)
+        return NULL;
+    zydis_dec_t *dec = (zydis_dec_t*)calloc(1, sizeof(zydis_dec_t));
+    dec->ZydisDecoderDecodeBuffer = context->zydis->ZydisDecoderDecodeBuffer;
+    dec->ZydisFormatterFormatInstruction = context->zydis->ZydisFormatterFormatInstruction;
+    context->zydis->ZydisDecoderInit(&dec->decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64);
+    context->zydis->ZydisFormatterInit(&dec->formatter, ZYDIS_FORMATTER_STYLE_INTEL);
+
+    return dec;
+}
+void DeleteX64TraceDecoder(zydis_dec_t **dec)
+{
+    free(*dec);
+    *dec = NULL;
+}
+
+const char* DecodeX64Trace(zydis_dec_t *dec, uintptr_t p)
+{
+    static char buff[256];
+    if(ZYAN_SUCCESS(dec->ZydisDecoderDecodeBuffer(&dec->decoder, (char*)p, 15,
+        &dec->instruction))) {
+        char tmp[255];
+        buff[0]='\0';
+        for (int i=0; i<dec->instruction.length; ++i) {
+            sprintf(tmp, "%02X ", *((unsigned char*)p+i));
+            strcat(buff, tmp);
+        }
+        dec->ZydisFormatterFormatInstruction(&dec->formatter, &dec->instruction, tmp, sizeof(tmp),p);
+        strcat(buff, tmp);
+    } else {
+        sprintf(buff, "Decoder failed @%p", (void*)p);
+    }
+    return buff;
+}