File: DebugMgr.h

package info (click to toggle)
pose 3.0a3-3
  • links: PTS
  • area: contrib
  • in suites: potato
  • size: 15,500 kB
  • ctags: 20,548
  • sloc: ansic: 72,579; cpp: 50,198; perl: 1,336; python: 1,242; sh: 363; makefile: 290
file content (213 lines) | stat: -rw-r--r-- 7,315 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/* -*- mode: C++; tab-width: 4 -*- */
/* ================================================================================== */
/* Copyright (c) 1998-1999 3Com Corporation or its subsidiaries. All rights reserved. */
/* ================================================================================== */

#ifndef _DEBUGMGR_H_
#define _DEBUGMGR_H_

#include "CPU_REG.h"		// kException_Trace

// Types

#pragma mark Types

class SLP;
class CSocket;
class CTCPSocket;

typedef uae_u32 (*registerFun)(int num);
typedef Bool	(*compareFun)(DWord a, DWord b);

// Need to change the packing at this point for the Solaris platform.
// According to Frank Yellin <fy@eng.sun.com>:
//
//		This fixes a bug in the compiler.
//		
//		Without this pack/pop, the code in DebugMgr.cpp, all references to
//		     gDebuggerGlobals.bp[ii].addr
//		are compiled as if this were on a 4-byte boundary.  This is in spite of
//		the fact that the compiler knows that BreakPoint is packed, and that it
//		is 6-bytes long!
//		
//		Accesses to  gDebuggerGlobals.bp[ii].addr sometimes give a bus error.


#include "PalmPack.h"

typedef struct BreakpointCondition
// Breakpoint conditions are of the form
//				<register-expr>[<size>] <cond> <value>
// where:
// <register-expr> is either a 68000 register (e.g. "d5") or an indirect reference at a constant
// offset from a 68000 register (e.g. "8(a6)").  An indirect reference reads from memory; when
// you set up a breakpoint condition involving an indirect reference, you must be sure that
// the indirect reference will point to a valid memory address whenever the breakpoint is hit.
//
// <size> is either ".l" (long), ".w" (word) or ".b" (byte).  If no size is specified, the
// expression is assumed to be long.
// <cond> is a binary comparison operator: ==, !=, <=, >=, <, or >
// <value> is a 32-bit integer
// All comparisons are unsigned!
{
	registerFun regType;
	int 		regNum;
	Bool		indirect;
	uae_u32 	indirectOffset;
	int 		size;	/* number of bytes to compare: 4, 2, or 1 */

	compareFun	condition;
	uae_u32 	value;

	// The source text.  We keep this around so that, for example, a user can specify
	// a condition using either hex or decimal notation and they will see the same
	// notation the next time they edit the breakpoint.
	char*		source;

	Bool		Evaluate (void);
} BreakpointCondition;


struct DebugGlobalsType
{
	// Mode settings

	bool			inDebugger; 					// true if in debug mode
	bool			ignoreDbgBreaks;				// if true, ignore DbgBreak's
	bool			reEntered;						// true if we re-entered
	bool			firstEntrance;					// true first time we enter debugger
	bool			stepSpy;						// true if step spying.
	bool			breakingOnATrap;				// true if there are A-Traps to check
	bool			continueOverATrap;				// True if skipping over next system call
	bool			continueOverBP; 				// True if skipping over next breakpoint

	bool			checkTrapWordOnExit;
	uae_u16 		trapWord;
	uae_u16 		refNum;

	// Breakpoints and saved opcodes behind each one

	BreakpointType	bp[dbgTotalBreakpoints];
	uae_u16 		bpOpcode[dbgTotalBreakpoints];
	BreakpointCondition *bpCondition[dbgTotalBreakpoints];	// condition, or NULL if none

	// Current trap breaks

	Word			trapBreak[dbgTotalTrapBreaks];
	Word			trapParam[dbgTotalTrapBreaks];

	// Step spy support

	uaecptr 		ssAddr; 						// address to step spy on
	DWord			ssValue;						// saved value

	// Exception type

	uae_s32 		excType;						// why we entered debugger

	// (adam) Data breakpoint support.	This is similar to the step spy capability, but can monitor
	// an arbitrary range of addresses for writes, and doesn't require a saved value.

	bool			watchEnabled;
	uaecptr 		watchAddr;		// address to watch, or 0 if none
	DWord			watchBytes; 	// number of bytes to watch
};

#include "PalmPackPop.h"

// class Debug

#pragma mark class Debug

extern DebugGlobalsType 	gDebuggerGlobals;
extern Bool 				gFullDebuggerPackets;


class Debug
{
	public:
		static void 			Initialize				(void);
		static void 			Reset					(void);
		static void 			Save					(SessionFile&);
		static void 			Load					(SessionFile&);
		static void 			Dispose 				(void);

		static void 			Startup 				(void);
		static void 			Shutdown				(void);
		static Bool 			ConnectedToTCPDebugger	(void);
		static CTCPSocket*		GetTCPDebuggerSocket	(void);
		static CSocket*			GetDebuggerSocket		(void);

		static ErrCode			HandleNewPacket 		(SLP&);

		static Bool 			BreakIfConnected		(uae_s32 exceptionNumber, uaecptr oldpc);
		static Bool 			HandleTrap8 			(uae_s32 exceptionNumber, uaecptr oldpc);
		static Bool 			HandleSystemCall		(const SystemCallContext& context);
		static ErrCode			EnterDebugger			(uae_s32 reason, uaecptr oldpc, SLP*);
		static ErrCode			ExitDebugger			(void);
		static Bool 			InDebugger				(void);
		static void 			CheckStepSpy			(uaecptr writeAddress, int writeBytes);

		static void 			HandleCPUBreak			(void);
		static void 			InstallCPUBreaks		(void);
		static void 			RemoveCPUBreaks 		(void);

		static BreakpointCondition*
								NewBreakpointCondition	(const char* sourceString);
		static void 			SetBreakpoint			(int index, uaecptr addr, BreakpointCondition* c);
		static void 			ClearBreakpoint 		(int index);

	private:
		static void 	ConditionalBreak	(uaecptr oldpc);
		static Bool 	MustBreakOnTrapSystemCall
											(uae_u16 trapWord, uae_u16 refNum);

		static void 	EventCallback			(CSocket* s, int event);
		static void 	CreateListeningSockets	(void);
		static void 	DeleteListeningSockets	(void);
};


// This function is called from the RAM setter functions. Make it inline so
// that the common case where stepSpy == FALSE executes quickly.  Yes, this
// _does_ make a difference.

inline void Debug::CheckStepSpy (uaecptr writeAddress, int writeBytes)
{
	if (gDebuggerGlobals.stepSpy)
	{
		if (get_long (gDebuggerGlobals.ssAddr) != gDebuggerGlobals.ssValue)
		{
			// !!! Look into adam's comments below.
			Emulator::SetBreakReason (kException_Trace);
		}
	}
	if (gDebuggerGlobals.watchEnabled &&
		writeAddress < gDebuggerGlobals.watchAddr + gDebuggerGlobals.watchBytes &&
		writeAddress + writeBytes > gDebuggerGlobals.watchAddr)
	{
		// (adam) The step spy code above apparently thinks it can break into
		// the debugger by calling Emulator::SetBreakReason, but that won't work
		// (I tried it).  Software::ProcessException() will do everything we need
		// here; it calls Debug::BreakIfConnected(), which in turn calls
		// Debug::EnterDebugger().
		// We must first check whether we are already in the debugger,
		// because it's possible that a single instruction will trigger the
		// data breakpoint several times.  This can happen, for example, when we hit
		// a trap #15 calling the PalmOS system function MemMove.  In this case, for
		// efficiency, the debugger emulates the entire MemMove call - this happens
		// in the function Headpatch::MemMove.	A single MemMove can trigger the
		// data breakpoint many times, but we must call Debug::EnterDebugger() only once
		// or very bad things will happen.

		/* (adam) old code - this doesn't work because the PC hasn't been incremented yet
		 * if (!fgDebuggerGlobals.inDebugger)
		 *	Software::ProcessException (kException_Trace, m68k_getpc (), m68k_getpc ()); */

		regs.spcflags |= SPCFLAG_DOTRACE;	// break immediately
	}
}


#endif /* _DEBUGMGR_H_ */