📄 mips64.c
字号:
if (i == MIPS64_MAX_BREAKPOINTS) return(-1); mcpu->breakpoints[i] = pc; mcpu->breakpoints_enabled = TRUE; return(0);}/* Remove a virtual breakpoint */void mips64_remove_breakpoint(cpu_gen_t *cpu,m_uint64_t pc){ cpu_mips_t *mcpu = CPU_MIPS64(cpu); int i,j; for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) if (mcpu->breakpoints[i] == pc) { for(j=i;j<MIPS64_MAX_BREAKPOINTS-1;j++) mcpu->breakpoints[j] = mcpu->breakpoints[j+1]; mcpu->breakpoints[MIPS64_MAX_BREAKPOINTS-1] = 0; } for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++) if (mcpu->breakpoints[i] != 0) return; mcpu->breakpoints_enabled = FALSE;}/* Debugging for register-jump to address 0 */fastcall void mips64_debug_jr0(cpu_mips_t *cpu){ printf("MIPS64: cpu %p jumping to address 0...\n",cpu); mips64_dump_regs(cpu->gen);}/* Set a register */void mips64_reg_set(cpu_gen_t *cpu,u_int reg,m_uint64_t val){ if (reg < MIPS64_GPR_NR) CPU_MIPS64(cpu)->gpr[reg] = val;}/* Dump registers of a MIPS64 processor */void mips64_dump_regs(cpu_gen_t *cpu){ cpu_mips_t *mcpu = CPU_MIPS64(cpu); mips_insn_t *ptr,insn; char buffer[80]; int i; printf("MIPS64 Registers:\n"); for(i=0;i<MIPS64_GPR_NR/2;i++) { printf(" %s ($%2d) = 0x%16.16llx %s ($%2d) = 0x%16.16llx\n", mips64_gpr_reg_names[i*2], i*2, mcpu->gpr[i*2], mips64_gpr_reg_names[(i*2)+1], (i*2)+1, mcpu->gpr[(i*2)+1]); } printf(" lo = 0x%16.16llx, hi = 0x%16.16llx\n", mcpu->lo, mcpu->hi); printf(" pc = 0x%16.16llx, ll_bit = %u\n", mcpu->pc, mcpu->ll_bit); /* Fetch the current instruction */ ptr = mcpu->mem_op_lookup(mcpu,mcpu->pc); if (ptr) { insn = vmtoh32(*ptr); if (mips64_dump_insn(buffer,sizeof(buffer),1,mcpu->pc,insn) != -1) printf(" Instruction: %s\n",buffer); } printf("\nCP0 Registers:\n"); for(i=0;i<MIPS64_CP0_REG_NR/2;i++) { printf(" %-10s ($%2d) = 0x%16.16llx %-10s ($%2d) = 0x%16.16llx\n", mips64_cp0_reg_names[i*2], i*2, mips64_cp0_get_reg(mcpu,i*2), mips64_cp0_reg_names[(i*2)+1], (i*2)+1, mips64_cp0_get_reg(mcpu,(i*2)+1)); } printf("\n IRQ count: %llu, IRQ false positives: %llu, " "IRQ Pending: %u\n", mcpu->irq_count,mcpu->irq_fp_count,mcpu->irq_pending); printf(" Timer IRQ count: %llu, pending: %u, timer drift: %u\n\n", mcpu->timer_irq_count,mcpu->timer_irq_pending,mcpu->timer_drift); printf(" Device access count: %llu\n",cpu->dev_access_counter); printf("\n");}/* Dump a memory block */void mips64_dump_memory(cpu_mips_t *cpu,m_uint64_t vaddr,u_int count){ void *haddr; u_int i; for(i=0;i<count;i++,vaddr+=4) { if ((i & 3) == 0) printf("\n 0x%16.16llx: ",vaddr); haddr = cpu->mem_op_lookup(cpu,vaddr); if (haddr) printf("0x%8.8x ",htovm32(*(m_uint32_t *)haddr)); else printf("XXXXXXXXXX "); } printf("\n\n");}/* Dump the stack */void mips64_dump_stack(cpu_mips_t *cpu,u_int count){ printf("MIPS Stack Dump at 0x%16.16llx:",cpu->gpr[MIPS_GPR_SP]); mips64_dump_memory(cpu,cpu->gpr[MIPS_GPR_SP],count);}/* Save the CPU state into a file */int mips64_save_state(cpu_mips_t *cpu,char *filename){ FILE *fd; int i; if (!(fd = fopen(filename,"w"))) { perror("mips64_save_state: fopen"); return(-1); } /* pc, lo and hi */ fprintf(fd,"pc: %16.16llx\n",cpu->pc); fprintf(fd,"lo: %16.16llx\n",cpu->lo); fprintf(fd,"hi: %16.16llx\n",cpu->hi); /* general purpose registers */ for(i=0;i<MIPS64_GPR_NR;i++) fprintf(fd,"%s: %16.16llx\n", mips64_gpr_reg_names[i],cpu->gpr[i]); printf("\n"); /* cp0 registers */ for(i=0;i<MIPS64_CP0_REG_NR;i++) fprintf(fd,"%s: %16.16llx\n", mips64_cp0_reg_names[i],cpu->cp0.reg[i]); printf("\n"); /* cp1 registers */ for(i=0;i<MIPS64_CP1_REG_NR;i++) fprintf(fd,"fpu%d: %16.16llx\n",i,cpu->fpu.reg[i]); printf("\n"); /* tlb entries */ for(i=0;i<cpu->cp0.tlb_entries;i++) { fprintf(fd,"tlb%d_mask: %16.16llx\n",i,cpu->cp0.tlb[i].mask); fprintf(fd,"tlb%d_hi: %16.16llx\n",i,cpu->cp0.tlb[i].hi); fprintf(fd,"tlb%d_lo0: %16.16llx\n",i,cpu->cp0.tlb[i].lo0); fprintf(fd,"tlb%d_lo1: %16.16llx\n",i,cpu->cp0.tlb[i].lo1); } fclose(fd); return(0);}/* Read a 64-bit unsigned integer */static m_uint64_t mips64_hex_u64(char *str,int *err){ m_uint64_t res = 0; u_char c; /* remove leading spaces */ while((*str == ' ') || (*str == '\t')) str++; while(*str) { c = *str; if ((c >= '0') && (c <= '9')) res = (res << 4) + (c - '0'); if ((c >= 'a') && (c <= 'f')) res = (res << 4) + ((c - 'a') + 10); if ((c >= 'A') && (c <= 'F')) res = (res << 4) + ((c - 'A') + 10); str++; } return(res);}/* Restore the CPU state from a file */int mips64_restore_state(cpu_mips_t *cpu,char *filename){ char buffer[4096],*sep,*value,*ep,*field; size_t len; FILE *fd; int index; if (!(fd = fopen(filename,"r"))) { perror("mips64_restore_state: fopen"); return(-1); } while(!feof(fd)) { *buffer = 0; fgets(buffer,sizeof(buffer),fd); len = strlen(buffer); if (buffer[len-1] == '\n') buffer[len-1] = 0; sep = strchr(buffer,':'); if (!sep) continue; value = sep + 1; *sep = 0; /* gpr ? */ if ((index = mips64_get_reg_index(buffer)) != -1) { cpu->gpr[index] = mips64_hex_u64(value,NULL); continue; } /* cp0 register ? */ if ((index = mips64_cp0_get_reg_index(buffer)) != -1) { cpu->cp0.reg[index] = mips64_hex_u64(value,NULL); continue; } /* cp1 register ? */ if ((len > 3) && (!strncmp(buffer,"fpu",3))) { index = atoi(buffer+3); cpu->fpu.reg[index] = mips64_hex_u64(value,NULL); } /* tlb entry ? */ if ((len > 3) && (!strncmp(buffer,"tlb",3))) { ep = strchr(buffer,'_'); if (ep) { index = atoi(buffer+3); field = ep + 1; if (!strcmp(field,"mask")) { cpu->cp0.tlb[index].mask = mips64_hex_u64(value,NULL); continue; } if (!strcmp(field,"hi")) { cpu->cp0.tlb[index].hi = mips64_hex_u64(value,NULL); continue; } if (!strcmp(field,"lo0")) { cpu->cp0.tlb[index].lo0 = mips64_hex_u64(value,NULL); continue; } if (!strcmp(field,"lo1")) { cpu->cp0.tlb[index].lo1 = mips64_hex_u64(value,NULL); continue; } } } /* pc, lo, hi ? */ if (!strcmp(buffer,"pc")) { cpu->pc = mips64_hex_u64(value,NULL); continue; } if (!strcmp(buffer,"lo")) { cpu->lo = mips64_hex_u64(value,NULL); continue; } if (!strcmp(buffer,"hi")) { cpu->hi = mips64_hex_u64(value,NULL); continue; } } mips64_cp0_map_all_tlb_to_mts(cpu); mips64_dump_regs(cpu->gen); mips64_tlb_dump(cpu->gen); fclose(fd); return(0);}/* Load a raw image into the simulated memory */int mips64_load_raw_image(cpu_mips_t *cpu,char *filename,m_uint64_t vaddr){ struct stat file_info; size_t len,clen; m_uint32_t remain; void *haddr; FILE *bfd; if (!(bfd = fopen(filename,"r"))) { perror("fopen"); return(-1); } if (fstat(fileno(bfd),&file_info) == -1) { perror("stat"); return(-1); } len = file_info.st_size; printf("Loading RAW file '%s' at virtual address 0x%llx (size=%lu)\n", filename,vaddr,(u_long)len); while(len > 0) { haddr = cpu->mem_op_lookup(cpu,vaddr); if (!haddr) { fprintf(stderr,"load_raw_image: invalid load address 0x%llx\n", vaddr); return(-1); } if (len > MIPS_MIN_PAGE_SIZE) clen = MIPS_MIN_PAGE_SIZE; else clen = len; remain = MIPS_MIN_PAGE_SIZE; remain -= (vaddr - (vaddr & MIPS_MIN_PAGE_MASK)); clen = m_min(clen,remain); if (fread((u_char *)haddr,clen,1,bfd) != 1) break; vaddr += clen; len -= clen; } fclose(bfd); return(0);}/* Load an ELF image into the simulated memory */int mips64_load_elf_image(cpu_mips_t *cpu,char *filename,int skip_load, m_uint32_t *entry_point){ m_uint64_t vaddr; m_uint32_t remain; void *haddr; Elf32_Ehdr *ehdr; Elf32_Shdr *shdr; Elf_Scn *scn; Elf *img_elf; size_t len,clen; char *name; int i,fd; FILE *bfd; if (!filename) return(-1);#ifdef __CYGWIN__ fd = open(filename,O_RDONLY|O_BINARY);#else fd = open(filename,O_RDONLY);#endif if (fd == -1) { perror("load_elf_image: open"); return(-1); } if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr,"load_elf_image: library out of date\n"); return(-1); } if (!(img_elf = elf_begin(fd,ELF_C_READ,NULL))) { fprintf(stderr,"load_elf_image: elf_begin: %s\n", elf_errmsg(elf_errno())); return(-1); } if (!(ehdr = elf32_getehdr(img_elf))) { fprintf(stderr,"load_elf_image: invalid ELF file\n"); return(-1); } printf("Loading ELF file '%s'...\n",filename); bfd = fdopen(fd,"rb"); if (!bfd) { perror("load_elf_image: fdopen"); return(-1); } if (!skip_load) { for(i=0;i<ehdr->e_shnum;i++) { scn = elf_getscn(img_elf,i); shdr = elf32_getshdr(scn); name = elf_strptr(img_elf, ehdr->e_shstrndx, (size_t)shdr->sh_name); len = shdr->sh_size; if (!(shdr->sh_flags & SHF_ALLOC) || !len) continue; fseek(bfd,shdr->sh_offset,SEEK_SET); vaddr = sign_extend(shdr->sh_addr,32); if (cpu->vm->debug_level > 0) { printf(" * Adding section at virtual address 0x%8.8llx " "(len=0x%8.8lx)\n",vaddr & 0xFFFFFFFF,(u_long)len); } while(len > 0) { haddr = cpu->mem_op_lookup(cpu,vaddr); if (!haddr) { fprintf(stderr,"load_elf_image: invalid load address 0x%llx\n", vaddr); return(-1); } if (len > MIPS_MIN_PAGE_SIZE) clen = MIPS_MIN_PAGE_SIZE; else clen = len; remain = PPC32_MIN_PAGE_SIZE; remain -= (vaddr - (vaddr & PPC32_MIN_PAGE_MASK)); clen = m_min(clen,remain); if (fread((u_char *)haddr,clen,1,bfd) < 1) break; vaddr += clen; len -= clen; } } } else { printf("ELF loading skipped, using a ghost RAM file.\n"); } printf("ELF entry point: 0x%x\n",ehdr->e_entry); if (entry_point) *entry_point = ehdr->e_entry; elf_end(img_elf); fclose(bfd); return(0);}/* Symbol lookup */struct symbol *mips64_sym_lookup(cpu_mips_t *cpu,m_uint64_t addr){ return(rbtree_lookup(cpu->sym_tree,&addr));}/* Insert a new symbol */struct symbol *mips64_sym_insert(cpu_mips_t *cpu,char *name,m_uint64_t addr){ struct symbol *sym; size_t len; if (!cpu->sym_tree) return NULL; len = strlen(name); if (!(sym = malloc(len+1+sizeof(*sym)))) return NULL; memcpy(sym->name,name,len+1); sym->addr = addr; if (rbtree_insert(cpu->sym_tree,sym,sym) == -1) { free(sym); return NULL; } return sym;}/* Symbol comparison function */static int mips64_sym_compare(m_uint64_t *a1,struct symbol *sym){ if (*a1 > sym->addr) return(1); if (*a1 < sym->addr) return(-1); return(0);}/* Create the symbol tree */int mips64_sym_create_tree(cpu_mips_t *cpu){ cpu->sym_tree = rbtree_create((tree_fcompare)mips64_sym_compare,NULL); return(cpu->sym_tree ? 0 : -1);}/* Load a symbol file */int mips64_sym_load_file(cpu_mips_t *cpu,char *filename){ char buffer[4096],func_name[128]; m_uint64_t addr; char sym_type; FILE *fd; if (!cpu->sym_tree && (mips64_sym_create_tree(cpu) == -1)) { fprintf(stderr,"CPU%u: Unable to create symbol tree.\n",cpu->gen->id); return(-1); } if (!(fd = fopen(filename,"r"))) { perror("load_sym_file: fopen"); return(-1); } while(!feof(fd)) { fgets(buffer,sizeof(buffer),fd); if (sscanf(buffer,"%llx %c %s",&addr,&sym_type,func_name) == 3) { mips64_sym_insert(cpu,func_name,addr); } } fclose(fd); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -