diff options
| author | Leslie Zhai <zhaixiang@loongson.cn> | 2024-12-26 21:43:19 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-26 14:43:19 +0100 |
| commit | 89713993cb86a51cfe8c65d581351ea57459445e (patch) | |
| tree | 8880a9dc01fb17fe5e1c094f6e2246084da6e022 /src | |
| parent | cf24eaf9d2bcb739aaec5b4c75d6bb09b4b902ae (diff) | |
| download | box64-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.c | 29 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_functions.c | 5 | ||||
| -rw-r--r-- | src/dynarec/dynarec_native.c | 10 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_functions.c | 8 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_functions.c | 5 | ||||
| -rw-r--r-- | src/include/debug.h | 2 | ||||
| -rw-r--r-- | src/include/dynarec_native.h | 4 |
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_ |