📄 gdb.c
字号:
strcpy( out_buf, "S05" ); break; case 'G' : /* * write 32 bit regs GXX..XX Each byte of register data * is described by two hex digits. * reply OK for success * ENN for an error */ rc = write_regs( in_buf, sizeof(UINT32) ); if( rc != GDB_OK ) return rc; strcpy( out_buf, "OK" ); break; case 'H' : /* * Set Thread (Hg | Hc) or "Write 64 bit regs" command. * * Set Thread request is ignored. * * Write 64 bit regs HXX..XX Each byte of register data * is described by two hex digits. * reply OK for success * ENN for an error */ if( (*in_buf == 'g') || (*in_buf == 'c') ) { /* Possibly "set thread" command */ if( strlen( in_buf ) <= 18 ) { *out_buf = '\0'; break; } } /* Write 64 bit regs command */ rc = write_regs( in_buf, sizeof(UINT64) ); if( rc != GDB_OK ) return rc; strcpy( out_buf, "OK" ); break; case 'g' : /* * read registers g[S] Registers of size S * reply XX....X Each byte of register data * is described by two hex digits. * Registers are in the internal order * for GDB, and the bytes in a register * are in the same order the machine uses. * or ENN for an error. */ if( *in_buf != '\0' ) { size = gethex( in_buf, &ptr, &rc, FALSE ); if( (rc != GDB_OK) || (*ptr != '\0') ) { return GDB_ERROR_GENERAL; } if( (size != sizeof(UINT32)) && (size != sizeof(UINT64)) ) { return GDB_ERROR_GENERAL; } } else size = sizeof(UINT32); read_regs( out_buf, size ); break; case 'r' : /* * Read single register (SDE extension) rNN[:S] Register NN * of size S */ reg = gethex( in_buf, &ptr, &rc, FALSE ); if( (rc != GDB_OK) || ( (*ptr != '\0') && (*ptr != ':') ) ) { return GDB_ERROR_GENERAL; } else { if( *ptr == ':' ) { ptr++; size = gethex( ptr, &ptr, &rc, FALSE ); if( (rc != GDB_OK) || (*ptr != '\0') ) { return GDB_ERROR_GENERAL; } if( (size != sizeof(UINT32)) && (size != sizeof(UINT64)) ) { return GDB_ERROR_GENERAL; } } else size = sizeof(UINT32); } setval( &out_buf, SYS_CPUREG(&appl_context, reg), size, TRUE ); *out_buf = '\0'; break; case 'R' : /* * Command depends on whether we are running extended * protocol (due to '!' command) or not. * * Normal : Identical to 'P', see below. * Extended : Restart (reinitialise registers) */ if(extended && (*in_buf == '\0') ) { init_data(); strcpy( out_buf, "OK" ); break; } /* Fallthrough !! */ case 'P' : /* * Write single register (SDE extension) PNN[:S]=XX Register NN * of size S */ reg = gethex( in_buf, &ptr, &rc, FALSE ); if( rc != GDB_OK ) return GDB_ERROR_GENERAL; size = sizeof(UINT32); /* Default */ switch( *ptr ) { case ':' : ptr++; size = gethex( ptr, &ptr, &rc, FALSE ); if( (rc != GDB_OK) || (size != sizeof(UINT32)) || (*ptr != '=') ) { return GDB_ERROR_GENERAL; } if( (size != sizeof(UINT32)) && (size != sizeof(UINT64)) ) { return GDB_ERROR_GENERAL; } /* FALL THROUGH ! */ case '=' : ptr++; val = gethex( ptr, &ptr, &rc, TRUE ); if( size == sizeof(UINT32) ) { /* Sign extend */ val = (INT64)((INT32)((UINT32)val)); } if( (rc != GDB_OK) || (*ptr != '\0') ) { return GDB_ERROR_GENERAL; } break; default : return GDB_ERROR_GENERAL; } SYS_CPUREG(&appl_context, reg) = val; strcpy( out_buf, "OK" ); break; case 'm' : /* * read mem mAA..AA,LLLL AA..AA is address, LLLL is length. * reply XX..XX XX..XX is mem contents * Can be fewer bytes than requested * if able to read only part of the data. * or ENN NN is errno */ /**** Fall through !! ****/ case 'M' : /* * write mem MAA..AA,LLLL:XX..XX * AA..AA is address, * LLLL is number of bytes, * XX..XX is data * reply OK for success * ENN for an error (this includes the case * where only part of the data was * written). */ /* Find the ',' */ ptr = strchr( in_buf, ',' ); if( ptr ) { *ptr = '\0'; ptr++; /* Get address */ address = gethex( in_buf, NULL, &rc, FALSE ); if( rc != GDB_OK ) return GDB_ERROR_GENERAL; /* Get count */ count = gethex( ptr, NULL, &rc, FALSE ); if( rc != GDB_OK ) return GDB_ERROR_GENERAL; } if( !ptr ) return GDB_ERROR_GENERAL; else { /* Validate range */ if( sys_validate_range( address, count, sizeof(UINT8), FALSE ) != OK ) { return GDB_ERROR_ADDRESS; } if( ch == 'm' ) { /* Read */ for( i=0; i<count; i++ ) { setval( &out_buf, (UINT64)REG8(address), sizeof(UINT8), FALSE ); address++; } } else { /* Write (M command) */ /* Find the ':' */ ptr = strchr( ptr, ':' ); if( !ptr ) return GDB_ERROR_GENERAL; else ptr++; for( i=0; i<count; i++ ) { rc = getval( &ptr, &val, 2*sizeof(UINT8), FALSE, FALSE ); if( rc != GDB_OK ) return rc; /* Convert to KSEG0 */ if( !sys_kseg0( address, &addr_kseg0 ) ) return GDB_ERROR_ADDRESS; REG8(addr_kseg0) = (UINT8)val; /* Flush D-cache in order to store data in * physical memory. * Invalidate I-cache since new instructions may * have been stored; */ sys_flush_cache_line( (void *)addr_kseg0 ); address++; } strcpy( out_buf, "OK" ); out_buf += 2; } *out_buf = '\0'; } break; case 'C' : /* * continue with Csig;AA..AA Continue with signal sig (hex signal * signal number). If ;AA..AA is omitted, * resume at same address. */ case 'S' : /* * step with Ssig;AA..AA Like 'C' but step not continue. * signal */ /* skip sig; sequence */ ptr = strchr( in_buf, ';' ); if( ptr ) in_buf = ptr + 1; /**** Fall through !! ****/ case 'c' : /* * continue cAA..AA AA..AA is address to resume * If AA..AA is omitted, * resume at same address. */ case 's' : /* * step sAA..AA AA..AA is address to resume * If AA..AA is omitted, * resume at same address. */ if( *in_buf != '\0' ) { /* Get address */ address = gethex( in_buf, NULL, &rc, FALSE ); if( rc != GDB_OK ) return GDB_ERROR_GENERAL; else { /* Store address in epc */ appl_context.cp0_epc = (INT64)((INT32)address); /* Clear ERL and set EXL so that EPC will be used upon eret */ appl_context.cp0_status &= ~(UINT64)M_StatusERL; appl_context.cp0_status |= (UINT64)M_StatusEXL; } } if( (ch == 's') || (ch =='S') ) { if( !setup_single_step() ) return GDB_ERROR_ADDRESS; *ss = TRUE; } return GDB_CONTINUE; case 'D' : /* detach D Reply OK. */ case 'k' : /* kill request k */ strcpy( out_buf, "OK" ); /* Reply ignored by GBD for kill */ return GDB_KILL; default : /* Other */ *out_buf = '\0'; break; } return GDB_OK;}/************************************************************************ * put_packet ************************************************************************/static voidput_packet( char *buf ){ UINT8 csum = 0; bool calc_csum = FALSE; char ch[2]; char *s = buf; while( *buf != '\0' ) { PUTCHAR( gdb_port, *buf ); if( calc_csum ) csum += (UINT8)(*buf); if( *buf == '$' ) calc_csum = TRUE; buf++; } if( calc_csum ) { ch[0] = hex2char( csum >> 4 ); ch[1] = hex2char( csum & 0xF ); PUTCHAR( gdb_port, '#' ); PUTCHAR( gdb_port, ch[0] ); PUTCHAR( gdb_port, ch[1] ); if( verbose ) { printf( "(To Host : %s#%c%c)", s, ch[0], ch[1] ); } } else { if( verbose ) { printf( "(To Host : %s)", s ); } }}/************************************************************************ * shell_get_epc ************************************************************************/static UINT64*shell_get_epc( t_gdb_regs *regs ){ return ( (UINT32)regs->cp0_status & M_StatusERL ) ? ®s->cp0_errorepc : ®s->cp0_epc;}/************************************************************************ * setup_single_step ************************************************************************/static boolsetup_single_step( void ){ UINT32 epc, instruction, opcode; UINT32 addr_kseg0; UINT32 i; bool branch; INT32 offset; UINT32 target; bool mips16e; bool extend; bool jump; UINT32 size; UINT32 reg; /* Read EPC (only support for 32 bit) */ epc = (UINT32)*shell_get_epc(&appl_context); /* Determine mips16e, then clear lsb */ mips16e = (epc & 1); epc &= ~1; size = mips16e ? sizeof(UINT16) : sizeof(UINT32); if( mips16e && !sys_mips16e ) return FALSE; /* Validate address */ if( sys_validate_range( epc, size, size, FALSE ) != OK ) { return FALSE; } /* Convert to KSEG0 */ if( !sys_kseg0( epc, &addr_kseg0 ) ) return FALSE; /* Read next instruction */ instruction = mips16e ? REG16( addr_kseg0 ) : REG32( addr_kseg0 ); /* Defaults */ branch = FALSE; extend = FALSE; ss_count = 1; ss_addr[0] = epc + size; /* Determine where to set BREAK(s) */ if( mips16e ) { opcode = MIPS16E_OPCODE(instruction); if( (opcode == MIPS16E_OPC_EXTEND) || (opcode == MIPS16E_OPC_JAL_X) ) { extend = TRUE; epc += sizeof(UINT16); ss_addr[0] += sizeof(UINT16); /* Validate address of second half of instruction */ if( sys_validate_range( epc, sizeof(UINT16), sizeof(UINT16), FALSE ) != OK ) { return FALSE; } /* Convert to KSEG0 */ if( !sys_kseg0( epc, &addr_kseg0 ) ) return FALSE; /* Read next instruction */ instruction = (instruction << 16) | REG16( addr_kseg0 ); if( opcode == MIPS16E_OPC_EXTEND ) opcode = MIPS16E_OPCODE(instruction); } /* Default break must be MIPS16e */ ss_addr[0] |= 1; switch( opcode ) { case MIPS16E_OPC_B : if( extend ) { offset = (((instruction >> 16) & 0x1f) << 11) | (((instruction >> 21) & 0x3f) << 5) | (((instruction >> 0) & 0x1f) << 0); offset <<= 1; /* Sign extend */ if( offset & 0x10000 ) offset |= 0xffff0000; } else { offset = (instruction & 0x7ff) << 1; /* Sign extend */ if( offset & 0x800 ) offset |= 0xfffff000; } ss_addr[0] = (UINT32)(offset + (INT32)(epc + 2)); ss_addr[0] |= 1; break; case MIPS16E_OPC_BEQZ : case MIPS16E_OPC_BNEZ : branch = TRUE; break; case MIPS16E_OPC_I8 : switch( MIPS16E_I8_FUNCTION( instruction ) ) { case MIPS16E_I8_FUNC_BTEQZ : case MIPS16E_I8_FUNC_BTNEZ : branch = TRUE; break; } break; case MIPS16E_OPC_JAL_X : /* JAL/JALX */ target = (((instruction >> 16) & 0x001f) << 21) | (((instruction >> 21) & 0x001f) << 16) | (((instruction >> 0) & 0xffff) << 0); target <<= 2; ss_addr[0] = ((epc + 2) & 0xf0000000) | target; if( MIPS16E_X( instruction ) != MIPS16E_X_JALX ) ss_addr[0] |= 1; break; case MIPS16E_OPC_RR : if( MIPS16E_RR_FUNCTION( instruction ) == MIPS16E_RR_FUNC_JALRC ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -