Skip to content

Commit

Permalink
[DYNAREC] Implement perf map (#2212)
Browse files Browse the repository at this point in the history
* [DYNAREC] Implement perf map

* [DYNAREC] Use function name as the Symbol
  • Loading branch information
xiangzhai authored Dec 26, 2024
1 parent cf24eaf commit 8971399
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 5 deletions.
5 changes: 5 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ The GDBJIT debugging support, only available with the compilation option GDBJIT=
* 1 : Dynarec will generate GDBJIT debuginfo.
* 2 : Dynarec will generate detailed GDBJIT debuginfo with internal state.

#### BOX64_DYNAREC_PERFMAP *
Dynarec generate map file for Linux perf tool.
* 0 : Dynarec will not generate perf map. (Default)
* 1 : Dynarec will generate perf map.

#### BOX64_DYNAREC_MISSING *
Dynarec print the missing opcodes
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
Expand Down
7 changes: 7 additions & 0 deletions docs/box64.pod
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,13 @@ The GDBJIT debugging support, only available with the compilation option GDBJIT=
* 1 : Dynarec will generate GDBJIT debuginfo.
* 2 : Dynarec will generate detailed GDBJIT debuginfo with internal state.

=item B<BOX64_DYNAREC_PERFMAP>=I<0|1>

Dynarec generate map file for Linux perf tool.

* 0 : Dynarec will not generate perf map. (Default)
* 1 : Dynarec will generate perf map.

=item B<BOX64_SSE_FLUSHTO0>=I<0|1>

Handling of SSE Flush to 0 flags
Expand Down
29 changes: 29 additions & 0 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
5 changes: 4 additions & 1 deletion src/dynarec/arm64/dynarec_arm64_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions src/dynarec/dynarec_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
8 changes: 6 additions & 2 deletions src/dynarec/la64/dynarec_la64_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "custommem.h"
#include "bridge.h"
#include "gdbjit.h"
#include "elfloader.h"

#define XMM0 0
#define XMM8 16
Expand Down Expand Up @@ -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)",
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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];
}
}
5 changes: 4 additions & 1 deletion src/dynarec/rv64/dynarec_rv64_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/include/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion src/include/dynarec_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_
void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size);

#endif //__DYNAREC_ARM_H_

0 comments on commit 8971399

Please sign in to comment.