about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorLeslie Zhai <zhaixiang@loongson.cn>2024-12-26 21:43:19 +0800
committerGitHub <noreply@github.com>2024-12-26 14:43:19 +0100
commit89713993cb86a51cfe8c65d581351ea57459445e (patch)
tree8880a9dc01fb17fe5e1c094f6e2246084da6e022 /src
parentcf24eaf9d2bcb739aaec5b4c75d6bb09b4b902ae (diff)
downloadbox64-89713993cb86a51cfe8c65d581351ea57459445e.tar.gz
box64-89713993cb86a51cfe8c65d581351ea57459445e.zip
[DYNAREC] Implement perf map (#2212)
* [DYNAREC] Implement perf map

* [DYNAREC] Use function name as the Symbol
Diffstat (limited to 'src')
-rw-r--r--src/core.c29
-rw-r--r--src/dynarec/arm64/dynarec_arm64_functions.c5
-rw-r--r--src/dynarec/dynarec_native.c10
-rw-r--r--src/dynarec/la64/dynarec_la64_functions.c8
-rw-r--r--src/dynarec/rv64/dynarec_rv64_functions.c5
-rw-r--r--src/include/debug.h2
-rw-r--r--src/include/dynarec_native.h4
7 files changed, 58 insertions, 5 deletions
diff --git a/src/core.c b/src/core.c
index c7e6bd2c..36393235 100644
--- a/src/core.c
+++ b/src/core.c
@@ -17,6 +17,9 @@
 #include <linux/auxvec.h>
 #include <asm/hwcap.h>
 #endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #endif
 
 #include "build_info.h"
@@ -99,6 +102,8 @@ uintptr_t box64_dynarec_test_start = 0;
 uintptr_t box64_dynarec_test_end = 0;
 int box64_dynarec_gdbjit = 0;
 int box64_dynarec_df = 1;
+int box64_dynarec_perf_map = 0;
+int box64_dynarec_perf_map_fd = -1;
 #ifdef ARM64
 int arm64_asimd = 0;
 int arm64_aes = 0;
@@ -912,6 +917,15 @@ void LoadLogEnv()
         if (box64_dynarec_gdbjit)
             printf_log(LOG_INFO, "Dynarec will generate debuginfo for gdbjit\n");
     }
+    p = getenv("BOX64_DYNAREC_PERFMAP");
+    if (p) {
+        if (strlen(p) == 1) {
+            if (p[0] >= '0' && p[0] <= '1')
+                box64_dynarec_perf_map = p[0] - '0';
+        }
+        if (box64_dynarec_perf_map)
+            printf_log(LOG_INFO, "Dynarec will generate map file for Linux perf tool\n");
+    }
     p = getenv("BOX64_DYNAREC_DF");
     if(p) {
         if(strlen(p)==1) {
@@ -2526,6 +2540,14 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
 
     *emulator = emu;
 
+#ifdef DYNAREC
+    if (box64_dynarec_perf_map) {
+        char pathname[32];
+        snprintf(pathname, sizeof(pathname), "/tmp/perf-%d.map", getpid());
+        box64_dynarec_perf_map_fd = open(pathname, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR);
+    }
+#endif
+
     return 0;
 }
 
@@ -2565,5 +2587,12 @@ int emulate(x64emu_t* emu, elfheader_t* elf_header)
     }
 #endif
 
+#ifdef DYNAREC
+    if (box64_dynarec_perf_map && box64_dynarec_perf_map_fd != -1) {
+        close(box64_dynarec_perf_map_fd);
+        box64_dynarec_perf_map_fd = -1;
+    }
+#endif
+
     return ret;
 }
diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c
index 020341d5..ba31f91b 100644
--- a/src/dynarec/arm64/dynarec_arm64_functions.c
+++ b/src/dynarec/arm64/dynarec_arm64_functions.c
@@ -734,7 +734,7 @@ static register_mapping_t register_mappings[] = {
 
 void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
 {
-    if (!box64_dynarec_dump && !box64_dynarec_gdbjit) return;
+    if (!box64_dynarec_dump && !box64_dynarec_gdbjit && !box64_dynarec_perf_map) return;
 
     static char buf[512];
     int length = sprintf(buf, "barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
@@ -849,6 +849,9 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
         }
         dyn->gdbjit_block = GdbJITBlockAddLine(dyn->gdbjit_block, (dyn->native_start + dyn->insts[ninst].address), inst_name);
     }
+    if (box64_dynarec_perf_map && box64_dynarec_perf_map_fd != -1) {
+        writePerfMap(dyn->insts[ninst].x64.addr, dyn->native_start + dyn->insts[ninst].address, dyn->insts[ninst].size / 4);
+    }
 }
 
 void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
diff --git a/src/dynarec/dynarec_native.c b/src/dynarec/dynarec_native.c
index 5abbb9ef..47c1c99e 100644
--- a/src/dynarec/dynarec_native.c
+++ b/src/dynarec/dynarec_native.c
@@ -841,3 +841,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
     //block->done = 1;
     return (void*)block;
 }
+
+void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size)
+{
+    char pbuf[128];
+    uint64_t sz = 0;
+    uintptr_t start = 0;
+    const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, func_addr), (void*)func_addr, &start, &sz);
+    snprintf(pbuf, sizeof(pbuf), "0x%lx %ld %s\n", code_addr, code_size, symbname);
+    write(box64_dynarec_perf_map_fd, pbuf, strlen(pbuf));
+}
diff --git a/src/dynarec/la64/dynarec_la64_functions.c b/src/dynarec/la64/dynarec_la64_functions.c
index b12bf69d..cf3c43d4 100644
--- a/src/dynarec/la64/dynarec_la64_functions.c
+++ b/src/dynarec/la64/dynarec_la64_functions.c
@@ -26,6 +26,7 @@
 #include "custommem.h"
 #include "bridge.h"
 #include "gdbjit.h"
+#include "elfloader.h"
 
 #define XMM0 0
 #define XMM8 16
@@ -331,7 +332,7 @@ static register_mapping_t register_mappings[] = {
 
 void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
 {
-    if (!box64_dynarec_dump && !box64_dynarec_gdbjit) return;
+    if (!box64_dynarec_dump && !box64_dynarec_gdbjit && !box64_dynarec_perf_map) return;
 
     static char buf[512];
     int length = sprintf(buf, "barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, fuse=%d, sm=%d(%d/%d)",
@@ -397,6 +398,9 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
         }
         dyn->gdbjit_block = GdbJITBlockAddLine(dyn->gdbjit_block, (dyn->native_start + dyn->insts[ninst].address), inst_name);
     }
+    if (box64_dynarec_perf_map && box64_dynarec_perf_map_fd != -1) {
+        writePerfMap(dyn->insts[ninst].x64.addr, dyn->native_start + dyn->insts[ninst].address, dyn->insts[ninst].size / 4);
+    }
 }
 
 // will go badly if address is unaligned
@@ -522,4 +526,4 @@ void get_free_scratch(dynarec_la64_t* dyn, int ninst, uint8_t* tmp1, uint8_t* tm
     *tmp1 = tmp[0];
     *tmp2 = tmp[1];
     *tmp3 = tmp[2];
-}
\ No newline at end of file
+}
diff --git a/src/dynarec/rv64/dynarec_rv64_functions.c b/src/dynarec/rv64/dynarec_rv64_functions.c
index b26b2aad..08dec929 100644
--- a/src/dynarec/rv64/dynarec_rv64_functions.c
+++ b/src/dynarec/rv64/dynarec_rv64_functions.c
@@ -698,7 +698,7 @@ static register_mapping_t register_mappings[] = {
 
 void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
 {
-    if (!box64_dynarec_dump && !box64_dynarec_gdbjit) return;
+    if (!box64_dynarec_dump && !box64_dynarec_gdbjit && !box64_dynarec_perf_map) return;
 
     static char buf[512];
     int length = sprintf(buf, "barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, fuse=%d, sm=%d(%d/%d), sew@entry=%d, sew@exit=%d",
@@ -772,6 +772,9 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
         }
         dyn->gdbjit_block = GdbJITBlockAddLine(dyn->gdbjit_block, (dyn->native_start + dyn->insts[ninst].address), inst_name);
     }
+    if (box64_dynarec_perf_map && box64_dynarec_perf_map_fd != -1) {
+        writePerfMap(dyn->insts[ninst].x64.addr, dyn->native_start + dyn->insts[ninst].address, dyn->insts[ninst].size / 4);
+    }
 }
 
 void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
diff --git a/src/include/debug.h b/src/include/debug.h
index 14e062d5..563011e0 100644
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -43,6 +43,8 @@ extern int box64_dynarec_missing;
 extern int box64_dynarec_aligned_atomics;
 extern int box64_dynarec_nativeflags;
 extern int box64_dynarec_df;
+extern int box64_dynarec_perf_map;
+extern int box64_dynarec_perf_map_fd;
 #ifdef ARM64
 extern int arm64_asimd;
 extern int arm64_aes;
diff --git a/src/include/dynarec_native.h b/src/include/dynarec_native.h
index dd5218f6..4a5219a7 100644
--- a/src/include/dynarec_native.h
+++ b/src/include/dynarec_native.h
@@ -26,4 +26,6 @@ void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size);
 void CancelBlock64(int need_lock);
 void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits);
 
-#endif //__DYNAREC_ARM_H_
\ No newline at end of file
+void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size);
+
+#endif //__DYNAREC_ARM_H_