📄 tracer.c
字号:
{
/* !Todo: Allow the user to choose. */
#if 0
ARMTime t1 = ARMulif_Time(&ts->coredesc);
#else
ARMTime t1 = ARMulif_CoreCycles(&ts->coredesc);
#endif
if (t1 != ts->LastTime)
{
tprintf(f,"T %08lX ", (unsigned long)t1);
ts->LastTime = t1;
}
else
tprintf(f," ");
}
if (ts->prop & TRACE_ARCH)
switch (packet->type) {
case Trace_Instr:
/* if doing instruction trace, check if conditional. If conditional, do expression eval first */
/* ID of instruction access is "I[A|T|J][P|F]". */
{
uint32 result;
char id[4];
static char const iset2char[4]="ATJX";
id[0]='I';
id[1]=iset2char[packet->u.instr.iset];
id[2]=(char)(packet->u.instr.executed ? 'P' : 'F');
id[3]='\0';
if ((strlen(ts->condexpr) != 0) && (ts->condexpr != NULL))
{
result = Expr1_EvalUint32(ts->parsedexpr,packet);
if (result)
{
Hostif_ConsolePrint(ts->hostif,"Doing Trace, result (ARCH) = %d, instr:%08x, pc:%08x\n",result,packet->u.instr.instr, packet->u.instr.pc);
TraceAccess(ts,id,packet->u.instr.pc,
packet->u.instr.instr,
UNKNOWN_REG /* DESTReg not applicable */, packet);
/* Registers are handy! */
traceRegsAsText(ts);
}
}
else /*if no condition, do trace anyway */
{
TraceAccess(ts,id,packet->u.instr.pc,
packet->u.instr.instr,
UNKNOWN_REG /* DESTReg not applicable */, packet);
/* Registers are handy! */
traceRegsAsText(ts);
}
return;
}
case Trace_BusAccess:
case Trace_MemAccess:
/* ID of memory access is "M[R|W][1|2|4]" */
{
char id[4];
ARMul_acc acc=packet->u.mem_access.acc;
int rv=packet->u.mem_access.rv;
int width=1 << (acc & 15);
assert(rv != 0);
id[0]='M';
id[1]=(char)(acc_READ(acc) ? 'R' : 'W');
id[2]=(char)('0' + ((width > 32) ? 4 : (width / 8)));
id[3]='\0';
if (rv < 0 && (acc_CYCLE(acc) != acc_typeI)) {
id[0] = 'X';
}
TraceAccess(ts,id,packet->u.mem_access.addr,
packet->u.mem_access.word1,
UNKNOWN_REG /* DESTReg unknown */, packet);
if (width > 32)
TraceAccess(ts,id,packet->u.mem_access.addr+4,
packet->u.mem_access.word2,
UNKNOWN_REG /* DESTReg unknown */, packet);
}
default: return;
}
else /* not TRACE_ARCH */
switch (packet->type)
{
case Trace_Instr: {
/* true means do instr trace, flase means don't */
bool flag = TRUE;
uint32 result=0;
char buffer[256];
ARMword instr=packet->u.instr.instr,pc=packet->u.instr.pc;
unsigned executed=packet->u.instr.executed;
/* need conditional loop around whole case execution. If condition exists, check before debug,
if not set, trace anyway. Initially do this with a flag set depending on the condition eval.
More elegant would be to encapsulate the trace in a function. */
/* check the condition, set flag */
if ((strlen(ts->condexpr) != 0) && (ts->condexpr != NULL))
{
result = Expr1_EvalUint32(ts->parsedexpr,packet);
if (result)
{
Hostif_ConsolePrint(ts->hostif,"Doing Trace, result = %d, instr:%08x\n",result, packet->u.instr.instr);
flag = TRUE;
}
else
{ /* result != expression, don't do trace */
flag = FALSE;
}
}
else /*if no condition, do trace anyway */
{
flag = TRUE;
}
/* flag now set, do instr trace if it's set. */
if (flag)
{
/* T for Taken, S for Skipped, J for Java. */
tprintf(f,"I%c %08lX ", executed ?
((packet->u.instr.iset==ISET_JAVA)?'J':'T') : 'S', pc);
switch(packet->u.instr.iset)
{
case ISET_THUMB:
if(instr & 0xffff0000)
tprintf(f,"%08lx",instr);
else
tprintf(f, "%04lx", instr);
break;
case ISET_JAVA:
{ /* Kill the high bytes */
unsigned extrabytes = (instr >> 12) & 3; /* 0,1,2 */
static uint32 masks[4] =
{ 0x00000FFF, 0x00FF0FFF, 0xFFFF0FFF, 0xFFFF0FFF };
instr &= masks[extrabytes];
}
default:
tprintf(f, "%08lx", instr);
break;
}
if (ts->prop & TRACE_DISASS) {
tracer_disass(ts, packet, instr, pc, buffer);
if (!executed) {
char *p;
for (p=buffer; *p; p++)
if (isupper((int)*p)) *p=(char)tolower((int)*p);
}
tputc(' ', f);
tputs(buffer, f);
}
Tracer_newline(ts);
traceRegsAsText(ts);
}
} /*end flag */
break;
case Trace_BusAccess:
case Trace_MemAccess:
{
ARMul_acc acc=packet->u.mem_access.acc;
unsigned32 addr=packet->u.mem_access.addr;
int rv=packet->u.mem_access.rv;
int width;
/* all mem_access packets sent are to be displayed */
width=Tracer_Acc(as, acc, addr,packet->type); /* prints "M" etc */
if (acc_CYCLE(acc) != acc_typeI /* includes acc_Icycle */) {
if (rv != 0) {
tprintf(f," %0*.*lX", width, width, packet->u.mem_access.word1);
if (acc_WIDTH(acc)==BITS_64)
tprintf(f," %08lX", packet->u.mem_access.word2);
}
}
if (rv < 0) {
tputs(" (abort)", f);
} else if (rv == 0) {
tputs(" (wait)", f);
}
if (!acc_ACCOUNT(acc)) {
/* display non-accounted accesses */
if (acc_MREQ(acc))
tprintf(f, acc_READ(acc) ? " (peek)" : " (poke)");
}
Tracer_newline(ts);
}
break;
case Trace_Event: {
char const *eventname = (packet->u.event.type >= SignalEvent_RESET &&
packet->u.event.type <= SignalEvent_Stop) ?
eventSignalNames[packet->u.event.type - SignalEvent_RESET] : "";
char const * title = "";
if (packet->u.event.type >= CoreEvent_Reset &&
packet->u.event.type <= CoreEvent_Watchpoint)
{
eventname =
eventSignalNames[packet->u.event.type - CoreEvent_Reset];
title = "Core ";
}
tprintf(f,"E %08lX %08lX %x %s%s",
packet->u.event.addr,packet->u.event.addr2,
packet->u.event.type, title, eventname);
Tracer_newline(ts);
break;
}
}
} else {
Tracer_WriteProc *twrite = ts->output.write;
twrite(packet,sizeof(*packet),1,f);
fflush(f);
}
}
/*
* Veneers onto DebugPrint
*/
static int DebugPutS(const char *s, void *handle)
{
RDI_HostosInterface *hostif = (RDI_HostosInterface *)handle;
Hostif_DebugPrint(hostif, "%s", s);
return 0;
}
static int DebugPutC(char c, void *handle)
{
RDI_HostosInterface *hostif = (RDI_HostosInterface *)handle;
Hostif_DebugPrint(hostif, "%c", c);
return 0;
}
/*
* Open the trace stream.
* Returns 1 on failure.
*/
static int Banner(TracerState *ts)
{
time_t now=time(NULL);
void *f=ts->output.handle;
Tracer_PrintfProc *tprintf = ts->output.tprintf;
Tracer_PutSProc *tputs = ts->output.puts;
Tracer_PutCProc *tputc = ts->output.putc;
tprintf(f, "Date: %s", ctime(&now));
tprintf(f, "Source: Armul");
Tracer_newline(ts);
tputs("Options: ", f);
if (ts->prop & TRACE_INSTR) {
char nextch = '(';
tputs("Trace Instructions ", f);
if (ts->prop & TRACE_DISASS) {
tputc(nextch, f);
tputs("Disassemble", f);
nextch = ',';
}
if (ts->prop & TRACE_REGISTER) {
tputc(nextch, f);
tputs("Registers", f);
nextch = ',';
}
if (nextch != '(')
tputs(") ", f);
}
if (ts->prop & TRACE_MEM) {
char nextch = '(';
tputs("Trace Memory Cycles ", f);
if (ts->prop & TRACE_IDLE) {
tputc(nextch, f);
tputs("Idles", f);
nextch = ',';
}
if (ts->prop & TRACE_NONACC) {
tputc(nextch, f);
tputs("Non-accounted", f);
nextch = ',';
}
if (ts->prop & TRACE_WAITS) {
tputc(nextch, f);
tputs("Waits", f);
nextch = ',';
}
if (nextch != '(')
tputs(") ", f);
}
if (ts->prop & TRACE_EVENT) tputs("Trace Events ", f);
Tracer_newline(ts);
if (ts->prop & TRACE_RANGE)
{
tprintf(f, "Range: 0x%08lX -> 0x%08lX",
ts->range_lo, ts->range_hi);
Tracer_newline(ts);
}
if (ts->sample_base)
{
tprintf(f, "Sample: %ld", ts->sample_base);
Tracer_newline(ts);
}
Tracer_newline(ts);
return 0;
}
/* Returns 0:Ok, else error. */
static unsigned Tracer_Open(TracerState *ts)
{
const char *option;
unsigned verbose;
verbose=ts->prop & TRACE_VERBOSE;
if (ToolConf_DLookupBool(ts->config, ARMulCnf_RDILog, FALSE)) {
/* output to the rdi_log window */
/* talk directly, rather than via DebugPrint, as it should be faster,
* and DebugPrint checks rdi_log bit 1
*/
union { void const *c; void *v; } u;
u.c = ts->hostif;
ts->output.handle = u.v;
ts->output.tprintf = (Tracer_PrintfProc *)Hostif_DebugPrint;
ts->output.puts = DebugPutS;
ts->output.putc = DebugPutC;
ts->prop|=TRACE_TEXT;
return Banner(ts);
}
option=ToolConf_Lookup(ts->config, ARMulCnf_File);
if (option!=NULL && option[0]) {
FILE *f = fopen(option,"w");
if (f == NULL) {
fprintf(stderr,"Could not open trace file '%s' - abandoning trace.\n",
option);
return 1;
}
ts->output.handle = f;
ts->output.tprintf = (Tracer_PrintfProc *)fprintf;
ts->output.puts = (Tracer_PutSProc *)fputs;
ts->output.putc = (Tracer_PutCProc *)fputc;
ts->output.close = (Tracer_CloseProc *)fclose;
ts->output.flush = (Tracer_FlushProc *)fflush;
ts->prop|=TRACE_TEXT;
return Banner(ts);
}
option=ToolConf_Lookup(ts->config, ARMulCnf_BinFile);
if (option!=NULL && option[0]) {
FILE *f = fopen(option,"wb");
if (f == NULL) {
fprintf(stderr,"Could not open trace file '%s' - abandoning trace.\n",
option);
return 1;
}
ts->output.handle = f;
ts->output.write = (Tracer_WriteProc *)fwrite;
ts->output.close = (Tracer_CloseProc *)fclose;
ts->output.flush = (Tracer_FlushProc *)fflush;
return 0;
}
#ifdef SOCKETS
option=ToolConf_Lookup(ts->config, ARMulCnf_Port);
if (option) {
long port;
port=strtol(option,NULL,0);
option=ToolConf_Lookup(ts->config, ARMulCnf_Host);
if (option) {
struct hostent *host;
struct sockaddr_in con;
int sock;
host=gethostbyname(option);
if (host==NULL) {
Hostif_ConsolePrint(ts->hostif,"Could not resolve host '%s'\n",
option);
return 1;
}
if (verbose)
Hostif_ConsolePrint(ts->hostif,"Tracing to %s:%d\n",option,port);
sock=socket(AF_INET,SOCK_STREAM,0);
if (sock==-1) {
Hostif_ConsolePrint(ts->hostif,"Could not open trace port\n");
return 1;
}
memset(&con,'\0',sizeof(con));
con.sin_family=AF_INET;
memcpy(&con.sin_addr,host->h_addr,sizeof(con.sin_addr));
con.sin_port=htons(port & 0xffff);
if (connect(sock,(struct sockaddr *)&con, sizeof(con))!=0) {
close(sock);
Hostif_ConsolePrint(ts->hostif,"Failed to open socket\n");
return 1;
}
ts->output.handle=(void *)fdopen(sock,"wb");
if (ts->output.handle!=NULL) return 0;
ts->output.write = (Tracer_WriteProc *)fwrite;
ts->output.close = (Tracer_CloseProc *)fclose;
ts->output.flush = (Tracer_FlushProc *)fflush;
Hostif_ConsolePrint(ts->hostif,"Failed to fdopen socket.\n");
return 1;
}
Hostif_ConsolePrint(ts->hostif,"PORT configured with no HOST.\n");
return 1;
}
#endif
#ifdef PIPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -