📄 tracer.c
字号:
/* tracer.c - module to trace memory accesses and instruction execution
* in ARMulator.
* Copyright (c) 1996-1998 Advanced RISC Machines Limited. All Rights Reserved.
* Copyright (c) 1998-1999 ARM Limited. All Rights Reserved.
*
* RCS $Revision: 1.11.2.31.2.6 $
* Checkin $Date: 2004/10/25 15:27:43 $
* Revising $Author: clamb $
*/
#define MODEL_NAME Tracer
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h> /* for strcpy */
#include "hash.h"
/* needed for Conditional Instr evaluate */
#include "cvector.h"
#include "armul_cnf.h"
#include "minperip.h"
#include "rdi_prop.h" /* for RDIProperty_GetAsNumeric */
#include "armul_callbackid.h"
#define JAVA_EXT_MASK 0x1FF
#include "javadis.h" /* for disass_java */
#include "armjimm.h" /* for java internals */
#include "disass.h"
#ifdef ETRACE
#include "rdi_rti.h"
#endif
#ifdef SOCKETS
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include "armul_mem.h"
#ifndef NDEBUG
# if 1
# else
# define VERBOSE_INIT_CPREG_TRACE
# define VERBOSE_BUS
# define VERBOSE_RDI_LOG
# endif
#endif
typedef uint8 byte;
#define stringify1(x) #x
#define stringify(x) stringify1(x)
#define CURRENTMODE RDIMode_Curr
/* from armcnf.h */
#define ARMulCnf_TraceInstructions (tag_t)"TRACEINSTRUCTIONS"
#define ARMulCnf_TraceMemory (tag_t)"TRACEMEMORY"
#define ARMulCnf_TraceIdle (tag_t)"TRACEIDLE"
#define ARMulCnf_TraceNonAcc (tag_t)"TRACENONACCOUNTED"
#define ARMulCnf_TraceWaits (tag_t)"TRACEWAITS"
#define ARMulCnf_TraceEvents (tag_t)"TRACEEVENTS"
#define ARMulCnf_TraceRegisters (tag_t)"TRACEREGISTERS"
#define ARMulCnf_Disassemble (tag_t)"DISASSEMBLE"
#define ARMulCnf_Unbuffered (tag_t)"UNBUFFERED"
#define ARMulCnf_StartOn (tag_t)"STARTON"
#define ARMulCnf_File (tag_t)"FILE"
#define ARMulCnf_BinFile (tag_t)"BINFILE"
#define ARMulCnf_Port (tag_t)"PORT"
#define ARMulCnf_Host (tag_t)"HOST"
#define ARMulCnf_Pipe (tag_t)"PIPE"
#define ARMulCnf_EventMask (tag_t)"EVENTMASK"
#define ARMulCnf_Event (tag_t)"EVENT"
#define ARMulCnf_Range (tag_t)"RANGE"
#define ARMulCnf_Sample (tag_t)"SAMPLE"
#define ARMulCnf_TraceBus (tag_t)"TRACEBUS"
#define ARMulCnf_RDILog (tag_t)"RDILOG"
#define ARMulCnf_TimeStamp (tag_t)"TIMESTAMP"
#define ARMulCnf_OpcodeFetch (tag_t)"OPCODEFETCH"
#define ARMulCnf_Arch (tag_t)"TRACEEIS"
#define ARMulCnf_AccessHit (tag_t)"TRACEHITTYPE"
#define ARMulCnf_TraceJazelleFakeOpcodes (tag_t)"TRACE_JAZELLEFAKEOPCODES"
#define ARMulCnf_TraceInstrIf (tag_t)"TRACEINSTRIF"
/* --- used to be in tracer.h --- */
#define TRACE_INSTR 0x00000001
#define TRACE_MEM 0x00000002
#define TRACE_IDLE 0x00000004
#define TRACE_RANGE 0x00000008
#define TRACE_PIPE 0x00000010 /* use pclose to close */
#define TRACE_TEXT 0x00000020 /* stream is plain text */
#define TRACE_EVENT 0x00000040
#define TRACE_DISASS 0x00000080 /* disassemble instruction stream */
#define TRACE_BUS 0x00000100 /* trace at the bus/core */
#define TRACE_NONACC 0x00000200 /* trace non-accounted accesses */
#define TRACE_WAITS 0x00000400 /* show wait states returned */
#define TRACE_REGISTER 0x00000800 /* trace changes to register values */
#define TRACE_UNBUFF 0x00001000 /* unbuffered stream output */
/* !Todo: Allow timestamps of CoreCycles. */
#define TRACE_TIMESTAMP 0x00002000 /* prepend time-stamps. */
#define TRACE_OPCODEFETCH 0x00004000 /* Trace opcode fetches. */
#define TRACE_ARCH 0x00008000 /* "Architectural" trace */
#define TRACE_ACCESSHIT 0x00010000
#define TRACE_JAZELLEFAKEOPCODES 0x00020000
/* used for boolean lookup. Instead need to copy something like binfile which passes in a parameter */
#define TRACE_STARTON 0x80000000 /* tracing always on */
#define TRACE_VERBOSE 0x40000000
/* type of data stored in DataItem
This can be added to, but will need additional code elsewhere
It is linked directly to structs in the tracer code eg packet->instr, packet->pc etc
*/
enum DataItemType {
Value,
Instruction,
PC
};
/* Functions for standard "dispatch" */
typedef int Tracer_PrintfProc(void *handle, const char *format, ...);
typedef int Tracer_PutSProc(const char *string, void *handle);
typedef int Tracer_PutCProc(char c, void *handle);
typedef int Tracer_WriteProc(void *packet, int size, int n, void *handle);
typedef int Tracer_CloseProc(void *handle);
typedef int Tracer_FlushProc(void *handle);
/* A record describing one coprocessor-register being traced. */
struct CPregTrace {
unsigned32 mask; /* for asking the core */
unsigned reg, cpnum;
unsigned numwords;
ARMword *old, *new;
};
/* Conditional Execution Trace structures */
typedef struct TExpr1 *Expr1;
typedef struct {
unsigned32 addr;
ARMul_acc acc;
} Tracer_Pipeline;
enum EPacketType {
Trace_Instr, /* instruction execution */
Trace_MemAccess, /* memory cycles, includes idles */
Trace_BusAccess,
Trace_Event /* other misc events */
};
/* datatype used to track the kind of instruction stored. Eg Value (ie a real number),
Instruction, Program Counter. These allow the current instr or pc to be substituted
at run time */
typedef struct {
uint32 u32;
enum DataItemType Datatype;
void *v;
} Expr1DataItem;
enum INSTR_SET { ISET_ARM, ISET_THUMB, ISET_JAVA };
typedef struct {
enum EPacketType type;
union {
struct {
unsigned32 instr;
unsigned32 pc;
unsigned8 executed; /* 1 if executed, 0 otherwise */
enum INSTR_SET iset;
} instr;
struct {
ARMul_acc acc;
unsigned32 addr;
unsigned32 word1,word2;
int rv; /* return value from mem_access call */
Tracer_Pipeline predict;
} mem_access;
struct {
unsigned32 addr,addr2;
unsigned int type; /* see note in armdefs.h */
} event;
} u;
} Trace_Packet;
typedef void Expr1Func(Expr1, Expr1DataItem *, Trace_Packet *);
typedef struct {
char const *name;
int lpri,rpri;
Expr1Func *func;
Expr1DataItem data;
} Expr1Ident;
static Expr1Func push_u32_const_func; /*(Expr1 e1, Expr1DataItem * data);*/
static Expr1Func push_instr_const_func; /*(Expr1 e1);*/
static Expr1Func push_pc_const_func; /*(Expr1 e1);*/
static Expr1Ident NumericConstantID =
{
"#U32#", 0,0, push_u32_const_func, { 0, Value }
};
static Expr1Ident NumericConstantInstr =
{
"Instr", 0,0, push_instr_const_func, { 0, Instruction }
};
static Expr1Ident NumericConstantPC =
{
"PC", 0,0, push_pc_const_func, { 0, PC }
};
typedef struct {
Expr1Func *func;
Expr1DataItem data;
char const *name; /* DEBUG_ONLY*/
} Expr1Codon;
struct TExpr1 {
CVector idents;
CVector code;
CVector dataStack;
CVector parseStack;
} TExpr1;
/* We have one of these per MemInterface we trace on. */
typedef struct ATracer {
struct TracerState *ts;
/* Pipeline prediction checking */
Tracer_Pipeline current, advance;
Tracer_Pipeline dside_current, dside_advance;
Tracer_Pipeline iside_current, iside_advance;
unsigned32 memfeatures; /* features when displaying mem cycles */
ARMul_MemInterface bus_mem, child;
ARMul_MemInterfaceRef mem_ref;
enum EPacketType packet_type;
/* This one is 'const'. */
enum EPacketType as_TraceType;
/* For async2 memory-types */
int armiss_err;
/* For tracing times on an ARMul_Bus */
ARMul_Bus *p_ABus;
} ATracer;
typedef struct
{
uint32 eventnum;
/* void *killhandle; */
char const *name;
} TSEventNumberRecord;
BEGIN_STATE_DECL(Tracer)
unsigned int not_tracing; /* zero when RDILog_Trace is set */
unsigned int trace_opened; /* set to one once Tracer_Open called */
struct {
void *handle; /* usually a FILE * */
Tracer_PrintfProc *tprintf; /* fprintf -- ANSI C says we can't use symbol printf here */
Tracer_PutSProc *puts; /* fputs */
Tracer_PutCProc *putc; /* fputc */
Tracer_WriteProc *write; /* fwrite */
Tracer_CloseProc *close; /* fclose */
Tracer_FlushProc *flush; /* fflush */
} output;
unsigned32 prop;
uint32 initial_rdi_log;
char condexpr[512];
/* stores the parsed expression for evaluation at run time */
Expr1 parsedexpr;
ATracer Core_Tracer, Bus_Tracer;
unsigned32 prev_instr; /* Thumb 2-instr BL disassembly */
ARMword range_lo,range_hi;
unsigned long sample,sample_base;
unsigned int event_mask,event_set; /* masks for events */
void *hourglass_kh,*trace_event_kh; /* handles for ARMulator callbacks */
unsigned32 mainregister[16];
unsigned32 cpsrregister, spsrregister;
void *memcallback; /* so we can deregister it */
ARMTime LastTime;
unsigned line_number;
unsigned break_line;
CVector cpregs; /* For traceing coprocessor-registers. */
CVector ts_EventNumbers; /* of TSEventNumberRecord*/
HashTable *ts_EventNumHash;
uint32 ts_EventNumClasses;
void *ts_numberredEvent_kh;
bool_int ts_TraceJavaFakeCycles;
END_STATE_DECL(Tracer)
#define TRACE_MEMFEATURE_AMBA 0x1 /* use AMBA mnemonics */
#define TRACE_MEMFEATURE_PIPELINED 0x2 /* check next cycle info */
static struct {
tag_t option;
unsigned long flag;
char *print;
} TraceOption[] = {
{ ARMulCnf_TraceInstructions, TRACE_INSTR, "Instructions"},
{ ARMulCnf_TraceMemory, TRACE_MEM, "Memory accesses"},
{ ARMulCnf_TraceIdle, TRACE_IDLE, "Idle cycles"},
{ ARMulCnf_TraceEvents, TRACE_EVENT, "Events"},
{ ARMulCnf_Disassemble, TRACE_DISASS, "Disassemble"},
{ ARMulCnf_Unbuffered, TRACE_UNBUFF, "Unbuffered"},
{ ARMulCnf_StartOn, TRACE_STARTON, "Start on"},
{ ARMulCnf_TraceBus, TRACE_BUS, "Trace bus"},
{ ARMulCnf_TraceNonAcc, TRACE_NONACC, "Non-accounted"},
{ ARMulCnf_TraceWaits, TRACE_WAITS, "Waits"},
{ ARMulCnf_TraceRegisters, TRACE_REGISTER, "Trace registers"},
{ ARMulCnf_TimeStamp, TRACE_TIMESTAMP, "TimeStamp"},
{ ARMulCnf_OpcodeFetch, TRACE_OPCODEFETCH,"Opcode Fetch"},
{ ARMulCnf_Arch, TRACE_ARCH, "EIS-format"},
{ ARMulCnf_AccessHit, TRACE_ACCESSHIT, "Hit-type"},
{ ARMulCnf_TraceJazelleFakeOpcodes, TRACE_JAZELLEFAKEOPCODES, "Jazelle-FakeOps"},
{ NULL, 0, NULL}
};
/* other option fields */
/* Condition Instruction Trace Functions */
Expr1 Expr1_ParseString(char const *txt, char *errbuf, size_t errbuf_size);
Expr1 Expr1_AddVariableUint32(Expr1 e1, char const *name, uint32 *addr);
uint32 Expr1_EvalUint32(Expr1 e1, Trace_Packet *packet);
void Expr1_Destroy(Expr1 *p_e1);
static Expr1 Expr1_New(void)
{
Expr1 e1 = (Expr1) calloc(1,sizeof(TExpr1));
if (e1)
{
CVector_Init(&e1->idents, sizeof(Expr1Ident));
CVector_Init(&e1->code, sizeof(Expr1Codon));
CVector_Init(&e1->dataStack, sizeof(Expr1DataItem));
CVector_Init(&e1->parseStack, sizeof(Expr1Ident));
}
return e1;
}
static void push_uint32(Expr1 e1, uint32 v)
{
int retval;
Expr1DataItem d;
d.Datatype = Value;
d.u32 = v;
retval = CVector_Append(&e1->dataStack,&d);
}
static void push_instr(Expr1 e1)
{
int retval;
Expr1DataItem d;
d.u32 = 0;
d.Datatype = Instruction;
retval = CVector_Append(&e1->dataStack,&d);
}
static void push_pc(Expr1 e1)
{
int retval;
Expr1DataItem d;
d.u32 = 0;
d.Datatype = PC;
retval = CVector_Append(&e1->dataStack,&d);
}
static uint32 pop_uint32(Expr1 e1, Trace_Packet *packet)
{
Expr1DataItem d;
assert(CVector_Count(&e1->dataStack) > 0);
(void)CVector_Pop(&e1->dataStack,&d);
if (d.Datatype == Value){
#ifdef VERBOSE
printf("VALUE: %08x\n",(unsigned)d.u32);
#endif
return d.u32;
}
else if (d.Datatype == Instruction)
{
#ifdef VERBOSE
printf("INSTR: %08x\n",(unsigned)packet->u.instr.instr);
#endif
return packet->u.instr.instr;
}
else if (d.Datatype == PC)
{
#ifdef VERBOSE
printf("PC: %08x\n",(unsigned)packet->u.instr.pc);
#endif
return packet->u.instr.pc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -