> compile NEMU

221220000 张三
Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
 23:03:46 up 5 days, 11:12,  3 users,  load average: 0.50, 0.80, 0.64
This commit is contained in:
tracer-ics2023
2024-09-10 23:03:48 +08:00
committed by zzy
parent 1dc0306ede
commit abd1085a05
6 changed files with 166 additions and 25 deletions

View File

@ -11,7 +11,7 @@ CFLAGS += -fdata-sections -ffunction-sections
LDFLAGS += -T $(AM_HOME)/scripts/linker.ld \
--defsym=_pmem_start=0x80000000 --defsym=_entry_offset=0x0
LDFLAGS += --gc-sections -e _start
NEMUFLAGS += -l $(shell dirname $(IMAGE).elf)/nemu-log.txt
NEMUFLAGS += -l $(shell dirname $(IMAGE).elf)/nemu-log.txt -e $(IMAGE).elf
CFLAGS += -DMAINARGS=\"$(mainargs)\"
CFLAGS += -I$(AM_HOME)/am/src/platform/nemu/include

View File

@ -179,9 +179,14 @@ config IRINGBUF_LINENUM
int "Instruction ring buffer size"
default 16
config IRINGBUF_END
config IRINGBUF_ASSERT_DISPLAY
depends on IRINGBUF
bool "Enable to log in 'statistic'(must end of log file) otherwise just in assert failure to log"
bool "Enable to log when assert failure(Warning it may display twice in `IRINGBUF_DISPLAY`)"
default y
config IRINGBUF_DISPLAY
depends on IRINGBUF
bool "Enable to iringbuf log in 'statistic'(must end of log file) otherwise just in assert failure to log"
default n
@ -205,11 +210,17 @@ config MTRACE_READ
bool "Enable memory trace on read"
default y
config FTRACE
depends on TRACE && TARGET_NATIVE_ELF && ENGINE_INTERPRETER
bool "Enable function tracer"
default n
config FTRACE_DISPLAY
depends on FTRACE
bool "Enable to ftrace log in 'statistic'(must end of log file)"
default n
config DIFFTEST
depends on TARGET_NATIVE_ELF

View File

@ -54,6 +54,11 @@ static void iringbuf_display(void) {
}
#endif
#ifdef CONFIG_FTRACE
void ftrace_display();
#endif
static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
#ifdef CONFIG_ITRACE_COND
if (ITRACE_COND) { log_write("%s\n", _this->logbuf); }
@ -117,8 +122,11 @@ static void execute(uint64_t n) {
}
static void statistic() {
#ifdef CONFIG_IRINGBUF_END
#ifdef CONFIG_IRINGBUF_DISPLAY
iringbuf_display();
#endif
#ifdef CONFIG_FTRACE_DISPLAY
ftrace_display();
#endif
IFNDEF(CONFIG_TARGET_AM, setlocale(LC_NUMERIC, ""));
#define NUMBERIC_FMT MUXDEF(CONFIG_TARGET_AM, "%", "%'") PRIu64
@ -129,7 +137,7 @@ static void statistic() {
}
void assert_fail_msg() {
#if defined(CONFIG_IRINGBUF) && !defined(CONFIG_IRINGBUF_END)
#if defined(CONFIG_IRINGBUF) && defined(CONFIG_IRINGBUF_ASSERT_DISPLAY)
iringbuf_display();
#endif
isa_reg_display();

View File

@ -80,10 +80,10 @@ static int decode_exec(Decode *s) {
INSTPAT("??????? ????? ????? 000 ????? 11000 11", beq , B, s->dnpc = (src1 == src2) ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 001 ????? 11000 11", bne , B, s->dnpc = (src1 != src2) ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 100 ????? 11000 11", blt , B, s->dnpc = (int32_t) src1 < (int32_t) src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 101 ????? 11000 11", bge , B, s->dnpc = (int32_t) src1 >= (int32_t) src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 110 ????? 11000 11", bltu , B, s->dnpc = (uint32_t)src1 < (uint32_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 111 ????? 11000 11", bgeu , B, s->dnpc = (uint32_t)src1 >= (uint32_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 100 ????? 11000 11", blt , B, s->dnpc = (sword_t)src1 < (sword_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 101 ????? 11000 11", bge , B, s->dnpc = (sword_t)src1 >= (sword_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 110 ????? 11000 11", bltu , B, s->dnpc = ( word_t)src1 < ( word_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 111 ????? 11000 11", bgeu , B, s->dnpc = ( word_t)src1 >= ( word_t)src2 ? (s->pc + imm) : s->dnpc);
INSTPAT("??????? ????? ????? 000 ????? 00000 11", lb , I, R(rd) = SEXT(Mr(src1 + imm, 1), 8)); // never used
INSTPAT("??????? ????? ????? 001 ????? 00000 11", lh , I, R(rd) = SEXT(Mr(src1 + imm, 2), 16));
@ -96,37 +96,37 @@ static int decode_exec(Decode *s) {
INSTPAT("??????? ????? ????? 010 ????? 01000 11", sw , S, Mw(src1 + imm, 4, src2));
INSTPAT("??????? ????? ????? 000 ????? 00100 11", addi , I, R(rd) = src1 + imm);
INSTPAT("??????? ????? ????? 010 ????? 00100 11", slti , I, R(rd) = (int32_t)src1 < (int32_t)imm ? 1 : 0); // never used
INSTPAT("??????? ????? ????? 011 ????? 00100 11", sltiu , I, R(rd) = (uint32_t)src1 < (uint32_t)imm ? 1 : 0);
INSTPAT("??????? ????? ????? 010 ????? 00100 11", slti , I, R(rd) = (sword_t)src1 < (sword_t)imm ? 1 : 0); // never used
INSTPAT("??????? ????? ????? 011 ????? 00100 11", sltiu , I, R(rd) = ( word_t)src1 < ( word_t)imm ? 1 : 0);
INSTPAT("??????? ????? ????? 100 ????? 00100 11", xori , I, R(rd) = src1 ^ imm);
INSTPAT("??????? ????? ????? 110 ????? 00100 11", ori , I, R(rd) = src1 | imm); // never used
INSTPAT("??????? ????? ????? 111 ????? 00100 11", andi , I, R(rd) = src1 & imm);
INSTPAT("0000000 ????? ????? 001 ????? 00100 11", slli , I, R(rd) = src1 << imm);
INSTPAT("0000000 ????? ????? 101 ????? 00100 11", srli , I, R(rd) = (uint32_t)src1 >> imm);
INSTPAT("0100000 ????? ????? 101 ????? 00100 11", srai , I, R(rd) = (int32_t) src1 >> imm);
INSTPAT("0000000 ????? ????? 101 ????? 00100 11", srli , I, R(rd) = ( word_t)src1 >> imm);
INSTPAT("0100000 ????? ????? 101 ????? 00100 11", srai , I, R(rd) = (sword_t)src1 >> imm);
INSTPAT("0000000 ????? ????? 000 ????? 01100 11", add , R, R(rd) = src1 + src2);
INSTPAT("0100000 ????? ????? 000 ????? 01100 11", sub , R, R(rd) = src1 - src2);
INSTPAT("0000000 ????? ????? 001 ????? 01100 11", sll , R, R(rd) = src1 << src2);
INSTPAT("0000000 ????? ????? 010 ????? 01100 11", slt , R, R(rd) = (int32_t) src1 < (int32_t) src2 ? 1 : 0);
INSTPAT("0000000 ????? ????? 011 ????? 01100 11", sltu , R, R(rd) = (uint32_t)src1 < (uint32_t)src2 ? 1 : 0);
INSTPAT("0000000 ????? ????? 010 ????? 01100 11", slt , R, R(rd) = (sword_t)src1 < (sword_t) src2 ? 1 : 0);
INSTPAT("0000000 ????? ????? 011 ????? 01100 11", sltu , R, R(rd) = ( word_t)src1 < ( word_t)src2 ? 1 : 0);
INSTPAT("0000000 ????? ????? 100 ????? 01100 11", xor , R, R(rd) = src1 ^ src2);
INSTPAT("0000000 ????? ????? 101 ????? 01100 11", srl , R, R(rd) = (uint32_t)src1 >> src2);
INSTPAT("0100000 ????? ????? 101 ????? 01100 11", sra , R, R(rd) = (int32_t) src1 >> src2);
INSTPAT("0000000 ????? ????? 101 ????? 01100 11", srl , R, R(rd) = (word_t)src1 >> src2);
INSTPAT("0100000 ????? ????? 101 ????? 01100 11", sra , R, R(rd) = (sword_t)src1 >> src2);
INSTPAT("0000000 ????? ????? 110 ????? 01100 11", or , R, R(rd) = src1 | src2);
INSTPAT("0000000 ????? ????? 111 ????? 01100 11", and , R, R(rd) = src1 & src2);
// INSTPAT("0000000 00000 00000 000 00000 11100 11", ecall , N, );
INSTPAT("0000000 00001 00000 000 00000 11100 11", ebreak , N, NEMUTRAP(s->pc, R(10))); // R(10) is $a0
INSTPAT("0000001 ????? ????? 000 ????? 01100 11", mul , R, R(rd) = (int32_t) src1 * (int32_t) src2);
INSTPAT("0000001 ????? ????? 001 ????? 01100 11", mulh , R, R(rd) = ((int64_t)(int32_t) src1 * (int64_t)(int32_t) src2) >> 32);
INSTPAT("0000001 ????? ????? 010 ????? 01100 11", mulhsu , R, R(rd) = ((int64_t)(int32_t) src1 * (uint64_t)src2) >> 32); // never used
INSTPAT("0000001 ????? ????? 000 ????? 01100 11", mul , R, R(rd) = (sword_t)src1 * (sword_t)src2);
INSTPAT("0000001 ????? ????? 001 ????? 01100 11", mulh , R, R(rd) = ((int64_t)(sword_t) src1 * (int64_t)(word_t) src2) >> 32);
INSTPAT("0000001 ????? ????? 010 ????? 01100 11", mulhsu , R, R(rd) = ((int64_t)(sword_t) src1 * (uint64_t)src2) >> 32); // never used
INSTPAT("0000001 ????? ????? 011 ????? 01100 11", mulhu , R, R(rd) = ((uint64_t)src1 * (uint64_t)src2) >> 32); // never used
INSTPAT("0000001 ????? ????? 100 ????? 01100 11", div , R, R(rd) = (src1 == INT_MIN && src2 == -1) ? src1 : (src2 ? (int32_t) src1 / (int32_t) src2 : -1));
INSTPAT("0000001 ????? ????? 101 ????? 01100 11", divu , R, R(rd) = src2 ? (uint32_t)src1 /(uint32_t) src2 : -1);
INSTPAT("0000001 ????? ????? 110 ????? 01100 11", rem , R, R(rd) = (src1 == INT_MIN && src2 == -1) ? 0 : (src2 ? (int32_t) src1 % (int32_t) src2 : src1));
INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu , R, R(rd) = src2 ? (uint32_t)src1 %(uint32_t) src2 : src1);
INSTPAT("0000001 ????? ????? 100 ????? 01100 11", div , R, R(rd) = (src1 == INT_MIN && src2 == -1) ? src1 : (src2 ? (sword_t) src1 / (sword_t) src2 : -1));
INSTPAT("0000001 ????? ????? 101 ????? 01100 11", divu , R, R(rd) = src2 ? (word_t)src1 /(word_t) src2 : -1);
INSTPAT("0000001 ????? ????? 110 ????? 01100 11", rem , R, R(rd) = (src1 == INT_MIN && src2 == -1) ? 0 : (src2 ? (sword_t) src1 % (sword_t) src2 : src1));
INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu , R, R(rd) = src2 ? (word_t)src1 %(word_t) src2 : src1);
INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv , N, INV(s->pc));
INSTPAT_END();

114
nemu/src/monitor/elf.c Normal file
View File

@ -0,0 +1,114 @@
#include <common.h>
#include <elf.h>
typedef MUXDEF(CONFIG_ISA64, Elf64_Ehdr, Elf32_Ehdr) Elf_Ehdr;
typedef MUXDEF(CONFIG_ISA64, Elf64_Phdr, Elf32_Phdr) Elf_Phdr;
typedef MUXDEF(CONFIG_ISA64, Elf64_Shdr, Elf32_Shdr) Elf_Shdr;
typedef MUXDEF(CONFIG_ISA64, Elf64_Sym , Elf32_Sym ) Elf_Sym;
typedef struct {
word_t start;
word_t end;
word_t size;
char fname[32];
} Elf_Ftrace;
// [start, start + size) == [start, end]
static int elf_ftrace_size = 0;
static Elf_Ftrace elf_ftrace[32];
#ifdef CONFIG_FTRACE_DISPLAY
void ftrace_display() {
for (int i = 0; i < elf_ftrace_size; i ++) {
log_write("ftrace %d: ["FMT_WORD", "FMT_WORD"] %s\n", i, elf_ftrace[i].start, elf_ftrace[i].end, elf_ftrace[i].fname);
}
}
#else
void ftrace_display() {}
#endif
void init_elf(const char* elf_file) {
// open elf
if (elf_file == NULL) {
Log("No elf is given.");
return;
}
FILE *fp = fopen(elf_file, "rb");
Assert(fp, "Can not open '%s'", elf_file);
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
int ret;
Log("The elf is %s, size = %ld", elf_file, size);
// read elf header
unsigned char e_ident[EI_NIDENT];
fseek(fp, 0, SEEK_SET);
ret = fread(e_ident, sizeof(e_ident), 1, fp);
assert(ret == 1);
switch (e_ident[EI_CLASS]) {
case ELFCLASS32:
Log("ELF class: ELF32");
break;
case ELFCLASS64:
Log("ELF class: ELF64");
break;
default:
Assert(false, "Error: unknown or unsupported ELF class.");
return;
}
// get elf header
Elf_Ehdr ehdr;
fseek(fp, 0, SEEK_SET);
ret = fread(&ehdr, sizeof(Elf_Ehdr), 1, fp);
assert(ret == 1);
// get section header
assert(ehdr.e_shoff != 0);
Elf_Shdr shdr[ehdr.e_shnum];
ret = fseek(fp, ehdr.e_shoff, SEEK_SET);
ret = fread(&shdr, sizeof(shdr), 1, fp);
assert(ret == 1);
// get symbol table and string table
Elf_Sym *psymt = NULL;
char* pstrt = NULL;
size_t symt_sz = 0, strt_sz = 0;
for (int i = 0; i < ehdr.e_shnum; i++) {
if (shdr[i].sh_type == SHT_SYMTAB) {
fseek(fp, shdr[i].sh_offset, SEEK_SET);
assert(shdr[i].sh_size % sizeof(Elf_Sym) == 0);
symt_sz = shdr[i].sh_size;
Elf_Sym sym[symt_sz];
ret = fread(sym, symt_sz, 1, fp);
assert(ret == 1);
psymt = sym;
} else if (shdr[i].sh_type == SHT_STRTAB) {
strt_sz = shdr[i].sh_size;
fseek(fp, shdr[i].sh_offset, SEEK_SET);
char buffer[strt_sz];
ret = fread(buffer, strt_sz, 1, fp);
assert(ret == 1);
pstrt = buffer;
}
}
// filling ftrace
assert(pstrt != NULL && pstrt != NULL);
for (int i = 0; i < symt_sz; i ++) {
if (psymt[i].st_info & STT_FUNC) {
// Warning due to elf_ftrace is global variable so you don't need to set '\0' in the end
strncpy(elf_ftrace[elf_ftrace_size].fname, pstrt + psymt[i].st_name,
sizeof(elf_ftrace[0].fname) - 1);
elf_ftrace[elf_ftrace_size].start = psymt[i].st_value;
elf_ftrace[elf_ftrace_size].size = psymt[i].st_size;
elf_ftrace[elf_ftrace_size].end = psymt[i].st_value + psymt[i].st_size - 1;
elf_ftrace_size ++;
}
}
fclose(fp);
return;
}

View File

@ -23,6 +23,7 @@ void init_difftest(char *ref_so_file, long img_size, int port);
void init_device();
void init_sdb();
void init_disasm(const char *triple);
void init_elf(const char* elf_file);
static void welcome() {
Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN), ANSI_FMT("OFF", ANSI_FG_RED)));
@ -44,6 +45,7 @@ void sdb_set_batch_mode();
static char *log_file = NULL;
static char *diff_so_file = NULL;
static char *img_file = NULL;
static char *elf_file = NULL;
static int difftest_port = 1234;
static long load_img() {
@ -74,16 +76,18 @@ static int parse_args(int argc, char *argv[]) {
{"log" , required_argument, NULL, 'l'},
{"diff" , required_argument, NULL, 'd'},
{"port" , required_argument, NULL, 'p'},
{"elf" , required_argument, NULL, 'e'},
{"help" , no_argument , NULL, 'h'},
{0 , 0 , NULL, 0 },
};
int o;
while ( (o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) {
while ( (o = getopt_long(argc, argv, "-bhl:d:p:e:", table, NULL)) != -1) {
switch (o) {
case 'b': sdb_set_batch_mode(); break;
case 'p': sscanf(optarg, "%d", &difftest_port); break;
case 'l': log_file = optarg; break;
case 'd': diff_so_file = optarg; break;
case 'e': elf_file = optarg; break;
case 1: img_file = optarg; return 0;
default:
printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]);
@ -91,6 +95,7 @@ static int parse_args(int argc, char *argv[]) {
printf("\t-l,--log=FILE output log to FILE\n");
printf("\t-d,--diff=REF_SO run DiffTest with reference REF_SO\n");
printf("\t-p,--port=PORT run DiffTest with port PORT\n");
printf("\t-e,--elf=ELF_FILE run with ELF_FILE to use FTRACE\n");
printf("\n");
exit(0);
}
@ -122,6 +127,9 @@ void init_monitor(int argc, char *argv[]) {
/* Load the image to memory. This will overwrite the built-in image. */
long img_size = load_img();
/* Init elf file to start function trace (ftrace). */
init_elf(elf_file);
/* Initialize differential testing. */
init_difftest(diff_so_file, img_size, difftest_port);