/*************************************************************************************** * Copyright (c) 2014-2022 Zihao Yu, Nanjing University * * NEMU is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * * See the Mulan PSL v2 for more details. ***************************************************************************************/ #include #include #include #include #include void init_rand(); void init_log(const char *log_file); void init_mem(); void init_difftest(char *ref_so_file, long img_size, int port); void init_device(); void init_disasm(const char *triple); int nemu_gdbstub_init(); static void welcome() { Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN), ANSI_FMT("OFF", ANSI_FG_RED))); IFDEF(CONFIG_TRACE, Log("If trace is enabled, a log file will be generated " "to record the trace. This may lead to a large log file. " "If it is not necessary, you can disable it in menuconfig")); Log("Build time: %s, %s", __TIME__, __DATE__); printf("Welcome to %s-NEMU!\n", ANSI_FMT(str(__GUEST_ISA__), ANSI_FG_YELLOW ANSI_BG_RED)); printf("For help, type \"help\"\n"); } #ifndef CONFIG_TARGET_AM #include static char *log_file = NULL; static char *elf_file = NULL; static char *diff_so_file = NULL; static char *img_file = NULL; static int difftest_port = 1234; static long load_img() { FILE *fp = NULL; size_t img_filename_len = strlen(img_file); if (img_file == NULL) { Log("No image is given. Use the default build-in image."); return 4096; // built-in image size } // Image file is searched from paths in environment variable NEMU_IMAGES_PATH if it's a relative path if (img_file[0] != '/') { char *search_paths = getenv("NEMU_IMAGES_PATH"); if(search_paths == NULL) search_paths = "./"; search_paths = strdup(search_paths); Trace("NEMU_IMAGES_PATH=%s", search_paths); char *paths_end = strchr(search_paths, '\0'); char *p_start = search_paths; do { char *p = strchr(p_start, ':'); if (p != NULL) *p = '\0'; else p = paths_end; char *file_path = malloc(p - p_start + img_filename_len + 2); strcpy(file_path, p_start); strcat(file_path, "/"); strcat(file_path, img_file); fp = fopen(file_path, "rb"); free(file_path); if (fp) { Log("Found '%s' in '%s'", img_file, p_start); break; } Assert(fp != NULL || errno == ENOENT, "Cannot open '%s'", img_file); p_start = p + 1; } while(p_start < paths_end); free(search_paths); Assert(fp, "Cannot find '%s'", img_file); } else { fp = fopen(img_file, "rb"); Assert(fp, "Cannot open '%s'", img_file); } fseek(fp, 0, SEEK_END); long size = ftell(fp); Log("The image is %s, size = %ld", img_file, size); fseek(fp, 0, SEEK_SET); int ret = fread(guest_to_host(RESET_VECTOR), size, 1, fp); assert(ret == 1); fclose(fp); return size; } static int parse_args(int argc, char *argv[]) { const struct option table[] = { {"batch", no_argument, NULL, 'b'}, {"log", required_argument, NULL, 'l'}, {"diff", required_argument, NULL, 'd'}, {"port", required_argument, NULL, 'p'}, {"elf", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {0, 0, NULL, 0}, }; int o; while ((o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) { switch (o) { case 'p': sscanf(optarg, "%d", &difftest_port); break; case 'l': log_file = optarg; break; case 'd': diff_so_file = optarg; break; case 'f': elf_file = optarg; break; case 1: img_file = optarg; return 0; default: printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]); printf("\t-b,--batch run with batch mode\n"); 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-f,--elf=FILE elf file with debug info\n"); printf("\n"); exit(0); } } return 0; } void init_monitor(int argc, char *argv[]) { /* Perform some global initialization. */ /* Parse arguments. */ parse_args(argc, argv); /* Set random seed. */ init_rand(); /* Open the log file. */ init_log(log_file); /* Initialize memory. */ init_mem(); /* Initialize devices. */ IFDEF(CONFIG_DEVICE, init_device()); /* Perform ISA dependent initialization. */ init_isa(); /* Load the image to memory. This will overwrite the built-in image. */ long img_size = load_img(); /* Initialize differential testing. */ init_difftest(diff_so_file, img_size, difftest_port); /* Initialize debugger */ if (nemu_gdbstub_init()) { Error("Failed to init"); exit(1); } // printf("elf_file: %s\n", elf_file); if (elf_file != NULL) { #ifdef CONFIG_FTRACE void init_elf(const char *path); init_elf(elf_file); #else Warning("Elf file provided, but ftrace not turned on. Ignoring elf file."); #endif } #ifndef CONFIG_ISA_loongarch32r IFDEF(CONFIG_ITRACE, init_disasm( MUXDEF(CONFIG_ISA_x86, "i686", MUXDEF(CONFIG_ISA_mips32, "mipsel", MUXDEF(CONFIG_ISA_riscv, MUXDEF(CONFIG_RV64, "riscv64", "riscv32"), "bad"))) "-pc-linux-gnu")); #endif /* Display welcome message. */ welcome(); } #else // CONFIG_TARGET_AM static long load_img() { extern char bin_start, bin_end; size_t size = &bin_end - &bin_start; Log("img size = %ld", size); memcpy(guest_to_host(RESET_VECTOR), &bin_start, size); return size; } void am_init_monitor() { init_rand(); init_mem(); init_isa(); load_img(); IFDEF(CONFIG_DEVICE, init_device()); welcome(); } #endif