> 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:
@ -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
|
||||
|
15
nemu/Kconfig
15
nemu/Kconfig
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
114
nemu/src/monitor/elf.c
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user