⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdb.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************
 *
 *  gdb.c
 *
 *  Shell gdb command
 *
 *  gdb [-v][-c] [. <args>]
 *
 *
 * ######################################################################
 *
 * Copyright (c) 1999-2000 MIPS Technologies, Inc. All rights reserved.
 *
 * Unpublished rights reserved under the Copyright Laws of the United States of
 * America.
 *
 * This document contains information that is proprietary to MIPS Technologies,
 * Inc. ("MIPS Technologies"). Any copying, modifying or use of this information
 * (in whole or in part) which is not expressly permitted in writing by MIPS
 * Technologies or a contractually-authorized third party is strictly
 * prohibited. At a minimum, this information is protected under unfair
 * competition laws and the expression of the information contained herein is
 * protected under federal copyright laws. Violations thereof may result in
 * criminal penalties and fines.
 * MIPS Technologies or any contractually-authorized third party reserves the
 * right to change the information contained in this document to improve
 * function, design or otherwise. MIPS Technologies does not assume any
 * liability arising out of the application or use of this information. Any
 * license under patent rights or any other intellectual property rights owned
 * by MIPS Technologies or third parties shall be conveyed by MIPS Technologies
 * or any contractually-authorized third party in a separate license agreement
 * between the parties.
 * The information contained in this document constitutes one or more of the
 * following: commercial computer software, commercial computer software
 * documentation or other commercial items. If the user of this information, or
 * any related documentation of any kind, including related technical data or
 * manuals, is an agency, department, or other entity of the United States
 * government ("Government"), the use, duplication, reproduction, release,
 * modification, disclosure, or transfer of this information, or any related
 * documentation of any kind, is restricted in accordance with Federal
 * Acquisition Regulation 12.212 for civilian agencies and Defense Federal
 * Acquisition Regulation Supplement 227.7202 for military agencies. The use of
 * this information by the Government is further restricted in accordance with
 * the terms of the license agreement(s) and/or applicable contract terms and
 * conditions covering this information from MIPS Technologies or any
 * contractually-authorized third party.
 *
 ************************************************************************/


/************************************************************************
 *  Include files
 ************************************************************************/

#include <sysdefs.h>
#include <syserror.h>
#include <shell_api.h>
#include "shell.h"
#include <gdb_stub.h>
#include <string.h>
#include <mips.h>
#include <syscon_api.h>
#include <sys_api.h>
#include <ctype.h>
#include <stdio.h>
#include <mips.h>

/************************************************************************
 *  Definitions
 ************************************************************************/

#define GDB_OK			0
#define GDB_BREAK		1
#define GDB_ERROR_CSUM		2
#define GDB_CONTINUE		3
#define GDB_KILL		4
#define GDB_ERROR_GENERAL	5
#define GDB_ERROR_ADDRESS	6
#define GDB_APPL_DONE		7

/************************************************************************
 *  Public variables
 ************************************************************************/

/************************************************************************
 *  Static variables
 ************************************************************************/

#define DEBUG_PROTOCOL 1

/* OPTIONS */
static t_cmd_option options[] =
{
#define OPTION_VERBOSE	        0
  { "v",  "Display messages from and to GDB host" },
#define OPTION_CHECKSUM_OFF	1
  { "c",  "Disable check of GDB checksum" }
};
#define OPTION_COUNT	(sizeof(options)/sizeof(t_cmd_option))

/* Application context */
static t_gdb_regs   context;

/* Arguments for application */
static char   *gdb_string = "gdb";

/* Single stepping */
static UINT32	    ss_count;
static UINT32	    ss_addr[2];
static UINT32	    ss_instr[2];

/* Verbose or not */
static bool	    verbose;

/* Enable checksum verification */
static bool	    checksum_on;

/* Extended protocol */
static bool	    extended;

/* Error codes */
static char *msg_e01 = "$E01 : Illegal format.";
static char *msg_e02 = "$E02 : Illegal address.";
static char *msg_e03 = "$E03 : Structural error in GDB-stub.";

/************************************************************************
 *  Static function prototypes
 ************************************************************************/

/************************************************************************
 *  Implementation : Static functions
 ************************************************************************/

static UINT32
get_options(
    UINT32 argc,
    char   **argv );

static UINT32
get_packet(
   char *buf );

static void
init_data( void );

static UINT32
determine_reply(
    char *in_buf,
    char *out_buf,
    bool *ss );

static void
put_packet(
    char *buf );

static bool
setup_single_step( void );

static bool
cleanup_single_step( void );

static char
get_char(
    bool *ctrl_c );

static bool
valid_hex(
    char ch );

static UINT64
gethex(
    char   *in_buf,
    char   **ptr,
    UINT32 *rc );

static UINT32
getval(
    char   **in_buf,
    UINT64 *val,
    UINT8  size,
    bool   strict );

static void
setval(
    char   **out_buf,
    UINT64 val,
    UINT8  size );

static UINT8
char2hex(
    char ch );

static char
hex2char(
    UINT8 val );

static UINT32
write_regs(
    char   *in_buf,
    UINT32 size );

static void
read_regs(
    char   *out_buf,
    UINT32 size );

extern int printf3();

/************************************************************************
 *  				gdb
 ************************************************************************/
static MON_FUNC(gdb)
{
#define MAXBUF	2048
    char   input_buffer[MAXBUF];
    char   output_buffer[MAXBUF];
    bool   ss;
    UINT32 rc;

    extended = FALSE;

    rc = get_options( argc, argv );

    if( rc != OK )
        return rc;

    printf( "Press Ctrl-C ");
    printf("to return to YAMON\n" );

    /* Flush input UART fifo */
    while( GETCHAR( GDB_PORT, input_buffer ) );
    /*  Remote unit may have an output fifo, so
     *  give it a chance to empty it and flush again.
     */
    sys_wait_ms(100);
    while( GETCHAR( GDB_PORT, input_buffer ) );

    init_data();

    do
    {
        /* Get packet from GDB */
        rc = get_packet( input_buffer );

        //printf3("packet received, rc = %d\n",rc);

	switch( rc )
	{
	  case GDB_OK :

	    put_packet( "+" ); /* Transfer OK */
	    //printf3("ACK\n");

	    rc = determine_reply( input_buffer,
			          output_buffer,
			          &ss );

	    switch( rc )
	    {
	      case GDB_ERROR_GENERAL :
	        strcpy( output_buffer, msg_e01 );
	        //printf3("%s\n",msg_e01);
			break;
	      case GDB_ERROR_ADDRESS :
	        strcpy( output_buffer, msg_e02 );
	        //printf3("%s\n",msg_e02);
			break;
	      case GDB_KILL :
	      	//printf3("Kill\n");
	      case GDB_OK   :
	        /* output_buffer was written by determine_reply() */
	        break;
	      case GDB_CONTINUE :
	        /* Interrupts should be disabled */
	        //printf3("continue\n");
			(UINT32)context.cp0_status &= ~C0_STATUS_IE_BIT;

	        /* Shift to user context */

	        if( shell_shift_to_user( TRUE, &context ) )
			{
				/* Application ended */
				//printf3("Application exited\n");
				sprintf( output_buffer, "$W%02x",
					 (UINT8)SYS_CPUREG(&context, SYS_CPUREG_V0) );

				rc = GDB_APPL_DONE;
			}
			else
			{
				/* Exception */
				if( REGFIELD( (UINT32)context.cp0_cause, C0_CAUSE_CODE ) ==
						C0_CAUSE_CODE_BP )
				{
					/* Breakpoint */
					//printf3("At breakpoint.\n");
					strcpy( output_buffer, "$S05" );
				}
				else
				{
					/* Other exception */
					//printf3("at exception.\n");
					strcpy( output_buffer, "$X0f" );
				}
			}

			if( ss )
			{
				/* Break due to single step */
				if( !cleanup_single_step() )
				{
						strcpy( output_buffer, msg_e02 );
				}
			}

			break;
	      default : /* Should not happen */
	        strcpy( output_buffer, msg_e03 );
	        break;
	    }

	    break;

	  case GDB_ERROR_CSUM :
		//printf3("Checksum ");
	  case GDB_ERROR_GENERAL :
	  	//printf3("error\n");
	    strcpy( output_buffer, "-$" );
	    break;

	  case GDB_BREAK :
	  	//printf3("Break\n");
	  	break;

	  default :  /* Should not happen */
		//printf3("huh?\n");
	    break;
        }

	if( rc != GDB_BREAK )
	{
	    /* Write reply */
	    put_packet( output_buffer );
	}
    }
    while( (rc != GDB_BREAK) &&
	   (rc != GDB_KILL)  &&
	   (rc != GDB_APPL_DONE) );

    if( verbose )
        printf( "\n" );

    return OK;
}


/************************************************************************
 *                          get_options
 ************************************************************************/
static UINT32
get_options(
    UINT32 argc,
    char   **argv )
{
    UINT32   arg, i;
    bool     ok	 = TRUE;
    UINT32   error = SHELL_ERROR_SYNTAX;
    bool     args = FALSE;
    char     *token;

    /* Setup defaults */
    verbose            = FALSE;
    checksum_on        = TRUE;
    shell_argc_appl    = 1;
    shell_argv_appl[0] = gdb_string;

    for( arg = 1;
	          ok &&
	          (arg < argc) &&
		  (token = argv[arg]);
         arg++ )
    {
        if( args )
	{
	    if( shell_argc_appl == SHELL_APPL_MAX_ARGS )
	    {
	        return SHELL_ERROR_ARGV;
	    }
	    else
	    {
	        shell_argv_appl[shell_argc_appl] = token;
	        shell_argc_appl++;
	    }
        }
	else
	{
	    if( strcmp( token, "-v" ) == 0 )
	    {
		verbose = TRUE;
            }
	    else if( strcmp( token, "-c" ) == 0 )
	    {
		checksum_on = FALSE;
            }
	    else if( *token == '-' )
	    {
	        error		 = SHELL_ERROR_OPTION;
		shell_error_data = token;
		ok		 = FALSE;
	    }
            else if( strcmp( token, "." ) == 0 )
	    {
	        args = TRUE;
	    }
	    else
	        ok = FALSE;
        }
    }

    return ok ? OK : error;
}

/************************************************************************
 *                          init_data
 ************************************************************************/
static void
init_data( void )
{
    /*  Setup initial context including EPC */
    shell_setup_default_cpu( &context,
			     shell_load_addr_valid ?
			         (UINT32)shell_load_addr :
				 0 );
}


/************************************************************************
 *                          get_packet
 ************************************************************************/
static UINT32
get_packet(
    char *buf )
{
    char   ch[2];
    char   *rcv;
    UINT8  csum_calc, csum_rcv;
    UINT8  i;
    bool   ctrl_c;
    UINT32 rc = GDB_OK;

    /* Wait for '$' */
    do
    {
        ch[0] = get_char( &ctrl_c );

	if( ctrl_c )
	{
	    rc = GDB_BREAK;
	    break;
	}
    }
    while( (ch[0] != '$') );

    /* Get packet contents, excluding cheksum bytes */
    if( rc == GDB_OK )
    {
        rcv       = buf;
        csum_calc = 0;

        do
        {
            ch[0] = get_char( &ctrl_c );

	    if( ctrl_c )
	    {
	        rc = GDB_BREAK;
		break;
	    }

	    switch( ch[0] )
	    {
	      case '$' :
	        /* Start again */
	        rcv       = buf;
	        csum_calc = 0;
	        break;
	      case '#' :
	        /* End */
	        *rcv = '\0';
	        break;
	      default :
	        /* Packet */
	        *rcv      = ch[0];
	        csum_calc += (UINT8)ch[0];
    	        rcv++;
	        break;
            }
        }
        while( ch[0] != '#' );
    }

    /* Get checksum bytes */
    if( rc == GDB_OK )
    {
	for(i=0; i<2; i++)
	{
            ch[i] = get_char( &ctrl_c );

	    if( ctrl_c )
	    {
	        rc = GDB_BREAK;
		break;
	    }
	}
    }

    /* Validate checksum (if not disabled by the -c command option) */
    if( (rc == GDB_OK) && checksum_on )
    {
        csum_rcv = 0;

        for(i=0; i<2; i++)
        {
            csum_rcv <<= 4;

	    if( !valid_hex( ch[i] ) )
	    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -