📄 gdb.c
字号:
jump = TRUE; switch( MIPS16E_RY( instruction ) ) { case MIPS16E_RR_RY_JRRX : case MIPS16E_RR_RY_JALR : case MIPS16E_RR_RY_JRCRX : case MIPS16E_RR_RY_JALRC : switch( (instruction >> 8) & 0x7 ) { case 0 : reg = SYS_CPUREG_S0; break; case 1 : reg = SYS_CPUREG_S1; break; case 2 : reg = SYS_CPUREG_V0; break; case 3 : reg = SYS_CPUREG_V1; break; case 4 : reg = SYS_CPUREG_A0; break; case 5 : reg = SYS_CPUREG_A1; break; case 6 : reg = SYS_CPUREG_A2; break; case 7 : reg = SYS_CPUREG_A3; break; } break; case MIPS16E_RR_RY_JRRA : case MIPS16E_RR_RY_JRCRA : reg = SYS_CPUREG_RA; break; default : jump = FALSE; break; } if( jump ) ss_addr[0] = (UINT32)SYS_CPUREG(&appl_context, reg); } break; } if( branch ) { /* We need to set two breakpoints, one if the branch is * taken, and one if it is not taken. */ 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 & 0xff) << 1; /* Sign extend */ if( offset & 0x100 ) offset |= 0xffffff00; } ss_addr[0] = epc + 2; ss_addr[1] = (UINT32)(offset + (INT32)( epc + 2 )); ss_addr[0] |= 1; ss_addr[1] |= 1; if( ss_addr[0] != ss_addr[1] ) ss_count = 2; } } else { opcode = MIPS_OPCODE(instruction); switch( opcode ) { case OPC_SPECIAL : switch( MIPS_FUNCTION( instruction ) ) { case FUNC_JR : case FUNC_JALR : ss_addr[0] = (UINT32)SYS_CPUREG(&appl_context, MIPS_RS(instruction)); break; } break; case OPC_REGIM : switch( MIPS_RT( instruction ) ) { case RT_BLTZ : case RT_BGEZ : case RT_BLTZL : case RT_BGEZL : case RT_BLTZAL : case RT_BGEZAL : case RT_BLTZALL : case RT_BGEZALL : branch = TRUE; break; } break; case OPC_BEQ : case OPC_BNE : case OPC_BLEZ : case OPC_BGTZ : case OPC_BEQL : case OPC_BNEL : case OPC_BLEZL : case OPC_BGTZL : branch = TRUE; break; case OPC_J : case OPC_JAL : case OPC_JALX : ss_addr[0] = ((epc + 4) & (MSK(4) << 28)) | (MIPS_TARGET( instruction ) << 2); if( opcode == OPC_JALX ) ss_addr[0] |= 1; break; case OPC_COP1 : if( sys_fpu ) { switch( MIPS_RS(instruction) ) { case RS_BC1 : /* Floating point branch */ branch = TRUE; break; } } break; } if( branch ) { /* We need to set two breakpoints, one if the branch is * taken, and one if it is not taken. */ offset = (INT32)((INT16)MIPS_OFFSET(instruction)) * 4; ss_addr[0] = epc + 2*4; /* Instruction after branch delay slot */ ss_addr[1] = (UINT32)(offset + (INT32)( epc + 4 )); if( ss_addr[0] != ss_addr[1] ) ss_count = 2; } } /* Set BREAK(s) */ for( i=0; i < ss_count; i++ ) { mips16e = (ss_addr[i] & 1); ss_addr[i] &= ~1; size = mips16e ? sizeof(UINT16) : sizeof(UINT32); /* Validate address */ if( sys_validate_range( ss_addr[i], size, size, TRUE ) != OK ) { return FALSE; } /* Convert to KSEG0 */ if( !sys_kseg0( ss_addr[i], &addr_kseg0 ) ) return FALSE; /* Store original instruction and insert break */ if( mips16e ) { ss_instr[i] = REG16( addr_kseg0 ); REG16( addr_kseg0 ) = MIPS16E_OPCODE_BREAK; } else { ss_instr[i] = REG32( addr_kseg0 ); REG32( addr_kseg0 ) = OPCODE_BREAK; } /* 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 ); if( mips16e ) ss_addr[i] |= 1; } return TRUE;}/************************************************************************ * cleanup_single_step ************************************************************************/static boolcleanup_single_step( void ){ UINT32 i; UINT32 addr_kseg0; bool mips16e; UINT32 size; /* Write back original instruction(s) */ for( i=0; i<ss_count; i++) { mips16e = (ss_addr[i] & 1); ss_addr[i] &= ~1; size = mips16e ? sizeof(UINT16) : sizeof(UINT32); if( mips16e && !sys_mips16e ) return FALSE; /* Validate address */ if( sys_validate_range( ss_addr[i], size, size, TRUE ) != OK ) { return FALSE; } /* Convert to KSEG0 */ if( !sys_kseg0( ss_addr[i], &addr_kseg0 ) ) return FALSE; if( mips16e ) REG16( addr_kseg0 ) = ss_instr[i]; else REG32( addr_kseg0 ) = ss_instr[i]; /* 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 ); } return TRUE;}/************************************************************************ * get_char ************************************************************************/static charget_char( bool *ctrl_c ){ char ch; do { *ctrl_c = GETCHAR_CTRLC( DEFAULT_PORT ); } while( !(*ctrl_c) && !GETCHAR( gdb_port, &ch ) ); return ch;}/************************************************************************ * valid_hex ************************************************************************/static boolvalid_hex( char ch ){ if( (ch >= '0') && (ch <= '9') ) return TRUE; ch = tolower( ch ); if( (ch >= 'a') && (ch <= 'f') ) return TRUE; return FALSE;} /************************************************************************ * char2hex ************************************************************************/static UINT8char2hex( char ch ){ if( (ch >= '0') && (ch <= '9') ) return ch - '0'; ch = tolower( ch ); if( (ch >= 'a') && (ch <= 'f') ) return ch - 'a' + 10; return 0;}/************************************************************************ * hex2char ************************************************************************/static charhex2char( UINT8 val ){ if( val < 10 ) return '0' + val; else return val - 10 + 'a';}/************************************************************************ * getval ************************************************************************/static UINT32getval( char **in_buf, UINT64 *val, UINT8 nibble_count, bool strict, bool endian_swap ){ UINT32 i; bool valid; *val = 0; valid = FALSE; for( i=0; i < nibble_count; i++ ) { if( !valid_hex( **in_buf ) ) { if( strict ) return GDB_ERROR_GENERAL; else { break; } } else { valid = TRUE; *val <<= 4; *val += char2hex(**in_buf); (*in_buf)++; } } if( !valid ) return GDB_ERROR_GENERAL; else {#ifdef EL if( endian_swap ) { if( nibble_count == 2*sizeof(UINT32) ) *val = SWAPEND32( (UINT32)(*val) ); if( nibble_count == 2*sizeof(UINT64) ) *val = SWAPEND64( *val ); }#endif return GDB_OK; }}/************************************************************************ * setval ************************************************************************/static voidsetval( char **out_buf, UINT64 val, UINT8 size, bool endian_swap ){ UINT32 i;#ifdef EL if( endian_swap ) { if( size == sizeof(UINT32) ) val = SWAPEND32( (UINT32)val ); if( size == sizeof(UINT64) ) val = SWAPEND64( val ); }#endif for( i = 2*size; i > 0; i-- ) { (*out_buf)[i-1] = hex2char(val & 0xF); val >>= 4; } (*out_buf) += size * 2;}/************************************************************************ * write_regs ************************************************************************/static UINT32write_regs( char *in_buf, UINT32 size ){ UINT64 *regs; UINT64 val; UINT32 i; UINT32 rc; regs = (UINT64 *)&appl_context; for( i=0; i<GDB_REG_COUNT; i++ ) { rc = getval( &in_buf, &val, 2*size, TRUE, TRUE ); if( rc != GDB_OK ) return rc; else { if( size == sizeof(UINT32) ) { /* Sign extend */ val = (INT64)((INT32)((UINT32)val)); } regs[i] = val; } } return GDB_OK;}/************************************************************************ * read_regs ************************************************************************/static voidread_regs( char *out_buf, UINT32 size ){ UINT64 *regs; UINT32 i; regs = (UINT64 *)&appl_context; for( i=0; i<GDB_REG_COUNT; i++ ) { setval( &out_buf, regs[i], size, TRUE ); } *out_buf = '\0';}/************************************************************************ * gethex ************************************************************************/static UINT64gethex( char *in_buf, char **ptr, UINT32 *rc, bool endian_swap ){ UINT64 val, tmp; UINT32 nibble_count; if( rc ) *rc = GDB_ERROR_GENERAL; /* Default */ val = 0; nibble_count = 0; while( valid_hex( *in_buf ) ) { /* We have at least one valid nibble */ if( rc ) *rc = GDB_OK; getval( &in_buf, &tmp, 1, FALSE, FALSE ); val <<= 4; val += tmp; nibble_count++; }#ifdef EL if( endian_swap ) { if( nibble_count == 2*sizeof(UINT32) ) val = SWAPEND32( (UINT32)(val) ); if( nibble_count == 2*sizeof(UINT64) ) val = SWAPEND64( val ); }#endif if( ptr ) *ptr = in_buf; return val;}/* Command definition for help */static t_cmd cmd_def ={ "gdb", gdb, "gdb [-v][-c] [. <args>]", "Setup connection to GDB debugger on port ttyx.\n" "\n" "The Standard GDB remote protocol is used.\n" "\n" "If the user application is not currently running, and Ctrl-C\n" "is typed at the console, YAMON will leave GDB mode and\n" "return to the command prompt.\n" "\n" "<args> is broken up in substrings and passed to the application.\n" "The list of arguments to be passed must begin with a '.'.\n" "The '.' is not passed as an argument. The first argument (argv[0])\n" "will be the string 'gdb'.\n" "\n" "a0 is set to the number of substrings (argc).\n" "a1 is set to the address of an array of pointers to the substrings (argv).\n" "a2 is set to the address of the environment table.\n" "a3 is set to the memory size.\n" "ra holds the return address to YAMON.\n" "\n" "The application may return to YAMON by jumping to the address\n" "specified in ra or by calling the exit(rc) function supplied by YAMON.\n" "\n" "The verbose (-v) option will cause the commands from the\n" "GDB host and the responses from YAMON to be displayed on the\n" "console.\n" "\n" "The checksum off (-c) option will disable validation of\n" "the cheksum used in GDB commands. This is useful in case\n" "the user wishes to enter commands manually. Two checksum\n" "characters should still be used in the commands, but the\n" "values are don't care.", options, OPTION_COUNT, FALSE};/************************************************************************ * Implementation : Public functions ************************************************************************//************************************************************************ * * shell_gdb_init * Description : * ------------- * * Initialise command * * Return values : * --------------- * * void * ************************************************************************/t_cmd *shell_gdb_init( void ){ UINT8 uart_count; char *ch; /* Determine the number of serial ports */ SYSCON_read( SYSCON_BOARD_UART_COUNT_ID, (void *)&uart_count, sizeof(UINT8) ); /* Select the port to use for GDB */ gdb_port = (uart_count > 1) ? DEFAULT_GDB_PORT : PORT_TTY0; /* Setup port in help text */ ch = strstr( cmd_def.descr, "ttyx" ); if( ch ) ch[3] = ( (gdb_port == PORT_TTY0) ? '0' : '1' ); return &cmd_def;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -