📄 debug.c
字号:
/*
* debug.c: Debugging command functions
*
* Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@www.eletztrick.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ident "$Id: debug.c,v 1.9 2002/01/06 15:44:23 erikm Exp $"
/**********************************************************************
* Includes
*/
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/error.h>
#include <blob/types.h>
#include <blob/util.h>
#include <blob/serial.h>
#include <blob/command.h>
/**********************************************************************
* defines
*/
#define CHKMEM_DEBUG BLOB_DEBUG
/* this will send a cold shiver through erik's spine ... */
#define ERR( x ) { ret = x; goto DONE; }
/* more readable IMHO */
#define MEM( x ) (*((u32 *)x))
/**********************************************************************
* prototypes
*/
static void perror( int errno, char *func );
/*********************************************************************
* CmdMemcpy
*
* AUTOR: SELETZ
* REVISED:
*
* Command wrapper for memcpy utility function.
*
*/
static int CmdMemcpy( int argc, char *argv[] )
{
int ret = 0;
u32 src = 0L;
u32 dest = 0L;
u32 len = 0L;
if ( argc < 4 ) ERR( -EINVAL );
ret = strtou32( argv[1], &src );
if ( ret < 0 ) ERR( -EINVAL );
ret = strtou32( argv[2], &dest );
if ( ret < 0 ) ERR( -EINVAL );
ret = strtou32( argv[3], &len );
if ( ret < 0 ) ERR( -EINVAL );
/* check alignment of src and dest */
if((src & 0x03) || (dest & 0x03))
ERR(-EALIGN);
/* counted in words */
if ( len & 0x00000003 ) {
len = ( len >> 2 ) + 1;
} else {
len = len >> 2;
}
SerialOutputString("\n### Now copying 0x");
SerialOutputHex(len);
SerialOutputString(" words from 0x");
SerialOutputHex((int)src);
SerialOutputString(" to 0x");
SerialOutputHex((int)dest);
serial_write('\n');
MyMemCpy( (u32 *)dest, (const u32 *)src, len);
SerialOutputString(" done\n");
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char memcpyhelp[] = "memcpy src dst len\n"
"copy len bytes from src to dst\n";
__commandlist(CmdMemcpy, "memcpy", memcpyhelp);
/*********************************************************************
* Poke
*
* AUTOR: Stefan Eletzhofer
* REVISED:
*
* Poke values to memory
*
*/
static int Poke( int argc, char *argv[] )
{
int ret = 0;
u32 address;
u32 value;
char type = 'w';
if ( argc < 3 ) ERR( -EINVAL );
ret = strtou32(argv[1], &address);
if ( ret < 0 ) ERR( -EINVAL );
ret = strtou32(argv[2], &value);
if ( ret < 0 ) ERR( -EINVAL );
if ( argc >= 3 ) {
type = argv[3][0];
}
#if CHKMEM_DEBUG
SerialOutputString("adr=0x");
SerialOutputHex(address);
SerialOutputString(" val=0x");
SerialOutputHex(value);
SerialOutputString(" type=");
serial_write(type);
serial_write('\n');
#endif
/* check memory alignment */
switch(type | 0x20) {
case 'b':
/* bytes don't have alignment restrictions */
break;
case 'h':
/* half word accesses should be aligned on half words */
if(address & 0x01)
ERR(-EALIGN);
break;
case 'w':
/* word accesses should be aligned on word boundaries */
if(address & 0x03)
ERR(-EALIGN);
break;
default:
/* hmm, invalid type */
ERR( -EINVAL );
break;
}
/* write the value to memory */
switch( type | 0x20 ) {
case 'b':
*((u8 *)address) = (u8)(value & 0xff);
break;
case 'h':
*((u16 *)address) = (u16)(value & 0xffff);
break;
case 'w':
*((u32 *)address) = value;
break;
default:
/* this should not happen */
ERR( -EINVAL );
break;
}
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char pokehelp[] = "poke address value [b|h|w]\n"
"b = byte, h = half word, w = word (default is w)\n";
__commandlist(Poke, "poke", pokehelp );
/*********************************************************************
* Peek
*
* AUTHOR: Stefan Eletzhofer
* REVISED:
*
* Peeks values from memory
*
*/
static int Peek( int argc, char *argv[] )
{
int ret = 0;
u32 address;
u32 value;
char type = 'w';
if ( argc < 2 ) ERR( -EINVAL );
ret = strtou32(argv[1], &address);
if ( ret < 0 ) ERR( -EINVAL );
if ( argc >= 2 ) {
type = argv[2][0];
}
#if CHKMEM_DEBUG
SerialOutputString("adr=0x");
SerialOutputHex(address);
SerialOutputString(" type=");
serial_write(type);
serial_write('\n');
#endif
/* check memory alignment */
switch(type | 0x20) {
case 'b':
/* bytes don't have alignment restrictions */
break;
case 'h':
/* half word accesses should be aligned on half words */
if(address & 0x01)
ERR(-EALIGN);
break;
case 'w':
/* word accesses should be aligned on word boundaries */
if(address & 0x03)
ERR(-EALIGN);
break;
default:
/* hmm, invalid type */
ERR( -EINVAL );
break;
}
/* read value from memory */
switch( type | 0x20 ) {
case 'b':
value = (*((u8 *)address)) & 0xff;
break;
case 'h':
value = (*((u16 *)address))& 0xffff;
break;
case 'w':
value = (*((u32 *)address));
break;
default:
/* this should not happen */
ERR(-EINVAL);
break;
}
serial_write(type);
serial_write(' ');
SerialOutputHex(value);
SerialOutputString("\n");
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char peekhelp[] = "peek address [b|h|w]\n"
"b = byte, h = half word, w = word (default is w)\n";
__commandlist(Peek, "peek", peekhelp );
/*********************************************************************
* dump
*
* AUTHOR: Tim Riker
* REVISED:
*
* dumps memory
*
*/
static int dump( int argc, char *argv[] )
{
int ret = 0;
u32 address;
u32 endaddress;
u32 tmpaddress;
u32 value;
if ( argc < 2 )
ERR( -EINVAL );
ret = strtou32(argv[1], &address);
if ( ret < 0 )
ERR( -EINVAL );
if ( argc == 3 ) {
ret = strtou32(argv[2], &endaddress);
if ( ret < 0 )
ERR( -EINVAL );
} else
endaddress = address + 0x80;
/* check alignment of address and endaddress */
if((address & 0x03) || (endaddress & 0x03))
ERR(-EALIGN);
/* print it */
for ( ; address < endaddress; address += 0x10) {
SerialOutputHex(address);
SerialOutputString(": ");
for (tmpaddress = address; tmpaddress < address + 0x10; tmpaddress += 4) {
value = (*((u32 *)tmpaddress));
SerialOutputHex(value);
serial_write(' ');
}
for (tmpaddress = address; tmpaddress < address + 0x10; tmpaddress++) {
value = (*((u8 *)tmpaddress)) & 0xff;
if ((value >= ' ') && (value <= '~'))
serial_write(value);
else
serial_write('.');
}
serial_write('\n');
}
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char dumphelp[] = "dump address [endAddress]\n";
__commandlist(dump, "dump", dumphelp );
/*********************************************************************
* BitChange
*
* AUTOR: SELETZ
* REVISED:
*
* Modifies bits of an given memory location
*
*/
static int BitChange( int argc, char *argv[] )
{
int ret = 0;
u32 adr = 0L;
u32 value = 0L;
if ( argc < 4 ) ERR( -EINVAL );
ret = strtou32( argv[1], &adr );
if ( ret < 0 ) ERR( -EINVAL );
ret = strtou32( argv[2], &value );
if ( ret < 0 ) ERR( -EINVAL );
/* check memory alignment */
if(adr &= 0x03)
ERR(-EALIGN);
SerialOutputHex( MEM( adr ) );
switch ( argv[3][0] & (~0x20) ) {
case 'A':
MEM( adr ) &= value;
break;
case 'S':
case 'O':
MEM( adr ) |= value;
break;
case 'X':
MEM( adr ) ^= value;
break;
case 'C':
MEM( adr ) &= ~value;
break;
default:
ERR( -EINVAL );
break;
}
SerialOutputString( "->" );
SerialOutputHex( MEM( adr ) );
SerialOutputString( "\n" );
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char bitchghelp[] = "bitchg address value {and|or|xor|set|clear}\n";
__commandlist(BitChange, "bitchg", bitchghelp );
/*********************************************************************
* Call
*
* AUTHOR: Christopher Hoover <ch@hpl.hp.com>
* REVISED:
*
* Jumps to an arbitrary address.
*
*/
static int Call( int argc, char *argv[] )
{
int ret = 0;
u32 adr, a = 0, b = 0, c = 0, d = 0;
int (*called_fn)(u32, u32, u32, u32);
if ( argc < 2 || argc > 6 ) ERR( -EINVAL );
ret = strtou32( argv[1], &adr );
if ( ret < 0 ) ERR( -EINVAL );
if ( argc >= 3 ) {
ret = strtou32( argv[2], &a );
if ( ret < 0 ) ERR( -EINVAL );
}
if ( argc >= 4 ) {
ret = strtou32( argv[2], &b );
if ( ret < 0 ) ERR( -EINVAL );
}
if ( argc >= 5 ) {
ret = strtou32( argv[2], &c );
if ( ret < 0 ) ERR( -EINVAL );
}
if ( argc >= 6) {
ret = strtou32( argv[2], &d );
if ( ret < 0 ) ERR( -EINVAL );
}
SerialOutputString("Calling function at 0x");
SerialOutputHex(adr);
SerialOutputString(" ...\n");
serial_flush_output();
called_fn = (int (*)(u32, u32, u32, u32))adr;
ret = called_fn(a, b, c, d);
SerialOutputString("\nReturn value: 0x");
SerialOutputHex((u32)ret);
serial_write('\n');
ret = 0;
DONE:
if ( ret != 0 ) {
perror( ret, __FUNCTION__ );
}
return ret;
}
static char callhelp[] = "call address [arg0 [arg1 [arg2 [arg3]]]]\n"
"Call function at <address> with optional arguments\n";
__commandlist(Call, "call", callhelp);
/**********************************************************************
* static functions
*/
static void perror( int errno, char *func )
{
printerrprefix();
if ( errno < 0 )
errno = -errno;
if ( func != NULL) {
SerialOutputString(func);
SerialOutputString(": ");
}
SerialOutputString(strerror(errno));
serial_write('\n');
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -