📄 remote-mm.c
字号:
/* Get keyboard termio (to save to restore original modes) */#ifdef HAVE_TERMIO result = ioctl(0, TCGETA, &kbd_tbuf);#else result = ioctl(0, TIOCGETP, &kbd_tbuf);#endif if (result == -1) return (errno); /* Get keyboard TERMINAL (for modification) */#ifdef HAVE_TERMIO result = ioctl(0, TCGETA, &tbuf);#else result = ioctl(0, TIOCGETP, &tbuf);#endif if (result == -1) return (errno); /* Set up new parameters */#ifdef HAVE_TERMIO tbuf.c_iflag = tbuf.c_iflag & ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT); tbuf.c_lflag = tbuf.c_lflag & ~(ICANON | ISIG | ECHO); tbuf.c_cc[4] = 0; /* MIN */ tbuf.c_cc[5] = 0; /* TIME */#else /* FIXME: not sure if this is correct (matches HAVE_TERMIO). */ tbuf.sg_flags |= RAW; tbuf.sg_flags |= ANYP; tbuf.sg_flags &= ~ECHO;#endif /* Set keyboard termio to new mode (RAW) */#ifdef HAVE_TERMIO result = ioctl(0, TCSETAF, &tbuf);#else result = ioctl(0, TIOCSETP, &tbuf);#endif if (result == -1) return (errno); return (0);} /* end kbd_raw() *//***************************************************************** KBD_RESTORE** This function is used to put the keyboard back in the** mode it was in before kbk_raw was called. Note that** kbk_raw() must have been called at least once before** kbd_restore() is called.*/intkbd_restore() { int result; /* Set keyboard termio to original mode */#ifdef HAVE_TERMIO result = ioctl(0, TCSETAF, &kbd_tbuf);#else result = ioctl(0, TIOCGETP, &kbd_tbuf);#endif if (result == -1) return (errno); return(0);} /* end kbd_cooked() *//*****************************************************************************/ /* Fetch a single register indicatated by 'regno'. * Returns 0/-1 on success/failure. */static intfetch_register (regno) int regno;{ int result; out_msg_buf->read_req_msg.code= READ_REQ; out_msg_buf->read_req_msg.length = 4*3; out_msg_buf->read_req_msg.byte_count = 4; if (regno == GR1_REGNUM) { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG; out_msg_buf->read_req_msg.address = 1; } else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32) { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG; out_msg_buf->read_req_msg.address = (regno - GR96_REGNUM) + 96; }#if defined(GR64_REGNUM) else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 ) { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG; out_msg_buf->read_req_msg.address = (regno - GR64_REGNUM) + 64; }#endif /* GR64_REGNUM */ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128) { out_msg_buf->read_req_msg.memory_space = LOCAL_REG; out_msg_buf->read_req_msg.address = (regno - LR0_REGNUM); } else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM) { int val = -1; supply_register(160 + (regno - FPE_REGNUM),&val); return 0; /* Pretend Success */ } else { out_msg_buf->read_req_msg.memory_space = SPECIAL_REG; out_msg_buf->read_req_msg.address = regnum_to_srnum(regno); } msg_send_serial(out_msg_buf); if (expect_msg(READ_ACK,in_msg_buf,1)) { supply_register (regno, &(in_msg_buf->read_r_ack_msg.data[0])); result = 0; } else { result = -1; } return result;}/*****************************************************************************/ /* Store a single register indicated by 'regno'. * Returns 0/-1 on success/failure. */static intstore_register (regno) int regno;{ int result; out_msg_buf->write_req_msg.code= WRITE_REQ; out_msg_buf->write_req_msg.length = 4*4; out_msg_buf->write_req_msg.byte_count = 4; out_msg_buf->write_r_msg.data[0] = read_register (regno); if (regno == GR1_REGNUM) { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG; out_msg_buf->write_req_msg.address = 1; /* Setting GR1 changes the numbers of all the locals, so invalidate the * register cache. Do this *after* calling read_register, because we want * read_register to return the value that write_register has just stuffed * into the registers array, not the value of the register fetched from * the inferior. */ registers_changed (); }#if defined(GR64_REGNUM) else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 ) { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG; out_msg_buf->write_req_msg.address = (regno - GR64_REGNUM) + 64; }#endif /* GR64_REGNUM */ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32) { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG; out_msg_buf->write_req_msg.address = (regno - GR96_REGNUM) + 96; } else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128) { out_msg_buf->write_req_msg.memory_space = LOCAL_REG; out_msg_buf->write_req_msg.address = (regno - LR0_REGNUM); } else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM) { return 0; /* Pretend Success */ } else /* An unprotected or protected special register */ { out_msg_buf->write_req_msg.memory_space = SPECIAL_REG; out_msg_buf->write_req_msg.address = regnum_to_srnum(regno); } msg_send_serial(out_msg_buf); if (expect_msg(WRITE_ACK,in_msg_buf,1)) { result = 0; } else { result = -1; } return result;}/****************************************************************************//* * Convert a gdb special register number to a 29000 special register number. */static intregnum_to_srnum(regno)int regno;{ switch(regno) { case VAB_REGNUM: return(0); case OPS_REGNUM: return(1); case CPS_REGNUM: return(2); case CFG_REGNUM: return(3); case CHA_REGNUM: return(4); case CHD_REGNUM: return(5); case CHC_REGNUM: return(6); case RBP_REGNUM: return(7); case TMC_REGNUM: return(8); case TMR_REGNUM: return(9); case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10)); case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11)); case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12)); case MMU_REGNUM: return(13); case LRU_REGNUM: return(14); case IPC_REGNUM: return(128); case IPA_REGNUM: return(129); case IPB_REGNUM: return(130); case Q_REGNUM: return(131); case ALU_REGNUM: return(132); case BP_REGNUM: return(133); case FC_REGNUM: return(134); case CR_REGNUM: return(135); case FPE_REGNUM: return(160); case INTE_REGNUM: return(161); case FPS_REGNUM: return(162); case EXO_REGNUM:return(164); default: return(255); /* Failure ? */ }}/****************************************************************************//* * Initialize the target debugger (minimon only). */static voidinit_target_mm(tstart,tend,dstart,dend,entry,ms_size,rs_size,arg_start)ADDR32 tstart,tend,dstart,dend,entry;INT32 ms_size,rs_size;ADDR32 arg_start;{ out_msg_buf->init_msg.code = INIT; out_msg_buf->init_msg.length= sizeof(struct init_msg_t)-2*sizeof(INT32); out_msg_buf->init_msg.text_start = tstart; out_msg_buf->init_msg.text_end = tend; out_msg_buf->init_msg.data_start = dstart; out_msg_buf->init_msg.data_end = dend; out_msg_buf->init_msg.entry_point = entry; out_msg_buf->init_msg.mem_stack_size = ms_size; out_msg_buf->init_msg.reg_stack_size = rs_size; out_msg_buf->init_msg.arg_start = arg_start; msg_send_serial(out_msg_buf); expect_msg(INIT_ACK,in_msg_buf,1);}/****************************************************************************//* * Return a pointer to a string representing the given message code. * Not all messages are represented here, only the ones that we expect * to be called with. */static char*msg_str(code)INT32 code;{ static char cbuf[32]; switch (code) { case BKPT_SET_ACK: sprintf(cbuf,"%s (%d)","BKPT_SET_ACK",code); break; case BKPT_RM_ACK: sprintf(cbuf,"%s (%d)","BKPT_RM_ACK",code); break; case INIT_ACK: sprintf(cbuf,"%s (%d)","INIT_ACK",code); break; case READ_ACK: sprintf(cbuf,"%s (%d)","READ_ACK",code); break; case WRITE_ACK: sprintf(cbuf,"%s (%d)","WRITE_ACK",code); break; case ERROR: sprintf(cbuf,"%s (%d)","ERROR",code); break; case HALT: sprintf(cbuf,"%s (%d)","HALT",code); break; default: sprintf(cbuf,"UNKNOWN (%d)",code); break; } return(cbuf);}/****************************************************************************//* * Selected (not all of them) error codes that we might get. */static char* error_msg_str(code)INT32 code;{ static char cbuf[50]; switch (code) { case EMFAIL: return("EMFAIL: unrecoverable error"); case EMBADADDR: return("EMBADADDR: Illegal address"); case EMBADREG: return("EMBADREG: Illegal register "); case EMACCESS: return("EMACCESS: Could not access memory"); case EMBADMSG: return("EMBADMSG: Unknown message type"); case EMMSG2BIG: return("EMMSG2BIG: Message to large"); case EMNOSEND: return("EMNOSEND: Could not send message"); case EMNORECV: return("EMNORECV: Could not recv message"); case EMRESET: return("EMRESET: Could not RESET target"); case EMCONFIG: return("EMCONFIG: Could not get target CONFIG"); case EMSTATUS: return("EMSTATUS: Could not get target STATUS"); case EMREAD: return("EMREAD: Could not READ target memory"); case EMWRITE: return("EMWRITE: Could not WRITE target memory"); case EMBKPTSET: return("EMBKPTSET: Could not set breakpoint"); case EMBKPTRM: return("EMBKPTRM: Could not remove breakpoint"); case EMBKPTSTAT:return("EMBKPTSTAT: Could not get breakpoint status"); case EMBKPTNONE:return("EMBKPTNONE: All breakpoints in use"); case EMBKPTUSED:return("EMBKPTUSED: Breakpoints already in use"); case EMINIT: return("EMINIT: Could not init target memory"); case EMGO: return("EMGO: Could not start execution"); case EMSTEP: return("EMSTEP: Could not single step"); case EMBREAK: return("EMBREAK: Could not BREAK"); case EMCOMMERR: return("EMCOMMERR: Communication error"); default: sprintf(cbuf,"error number %d",code); break; } /* end switch */ return (cbuf);}/****************************************************************************//* * Receive a message and expect it to be of type msgcode. * Returns 0/1 on failure/success. */static intexpect_msg(msgcode,msg_buf,from_tty)INT32 msgcode; /* Msg code we expect */union msg_t *msg_buf; /* Where to put the message received */int from_tty; /* Print message on error if non-zero */{ int retries=0; while(msg_recv_serial(msg_buf) && (retries++<MAX_RETRIES)); if (retries >= MAX_RETRIES) { printf("Expected msg %s, ",msg_str(msgcode)); printf("no message received!\n"); return(0); /* Failure */ } if (msg_buf->generic_msg.code != msgcode) { if (from_tty) { printf("Expected msg %s, ",msg_str(msgcode)); printf("got msg %s\n",msg_str(msg_buf->generic_msg.code)); if (msg_buf->generic_msg.code == ERROR) printf("%s\n",error_msg_str(msg_buf->error_msg.error_code)); } return(0); /* Failure */ } return(1); /* Success */} /****************************************************************************//* * Determine the MiniMon memory space qualifier based on the addr. * FIXME: Can't distinguis I_ROM/D_ROM. * FIXME: Doesn't know anything about I_CACHE/D_CACHE. */static intmm_memory_space(addr)CORE_ADDR *addr;{ ADDR32 tstart = target_config.I_mem_start; ADDR32 tend = tstart + target_config.I_mem_size; ADDR32 dstart = target_config.D_mem_start; ADDR32 dend = tstart + target_config.D_mem_size; ADDR32 rstart = target_config.ROM_start; ADDR32 rend = tstart + target_config.ROM_size; if (((ADDR32)addr >= tstart) && ((ADDR32)addr < tend)) { return I_MEM; } else if (((ADDR32)addr >= dstart) && ((ADDR32)addr < dend)) { return D_MEM; } else if (((ADDR32)addr >= rstart) && ((ADDR32)addr < rend)) { /* FIXME: how do we determine between D_ROM and I_ROM */ return D_ROM; } else /* FIXME: what do me do now? */ return D_MEM; /* Hmmm! */}/****************************************************************************//* * Define the target subroutine names */struct target_ops mm_ops = { "minimon", "Remote AMD/Minimon target", "Remote debug an AMD 290*0 using the MiniMon dbg core on the target", mm_open, mm_close, mm_attach, mm_detach, mm_resume, mm_wait, mm_fetch_registers, mm_store_registers, mm_prepare_to_store, mm_xfer_inferior_memory, mm_files_info, mm_insert_breakpoint, mm_remove_breakpoint, /* Breakpoints */ 0, 0, 0, 0, 0, /* Terminal handling */ mm_kill, /* FIXME, kill */ mm_load, 0, /* lookup_symbol */ mm_create_inferior, /* create_inferior */ mm_mourn, /* mourn_inferior FIXME */ 0, /* can_run */ 0, /* notice_signals */ process_stratum, 0, /* next */ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0,0, /* sections, sections_end */ OPS_MAGIC, /* Always the last thing */};void_initialize_remote_mm(){ add_target (&mm_ops);}#ifdef NO_HIF_SUPPORTservice_HIF(msg)union msg_t *msg;{ return(0); /* Emulate a failure */}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -