2
* UAE - The Un*x Amiga Emulator
4
* Enforcer Like Support
6
* Copyright 2000-2003 Bernd Roesch and Sebastian Bauer
7
* Copyright 2004 Richard Drummond
14
#include "sysconfig.h"
24
#define console_out printf
26
#define console_out(...) do {;} while (0)
29
/* Configurable options */
30
#define ENFORCESIZE 1024
32
#define INSTRUCTIONLINES 17
34
#define ISILLEGAL(addr) (addr < 4 || (addr > 4 && addr < ENFORCESIZE))
36
extern uae_u32 natmem_offset;
39
static int enforcer_installed = 0;
40
static int enforcer_hit = 0; /* set to 1 if displaying the hit */
42
#define ENFORCER_BUF_SIZE 4096
43
static char enforcer_buf[ENFORCER_BUF_SIZE];
45
#define GET_PC m68k_getpc (®s)
47
static addrbank saved_dummy_bank;
48
static addrbank saved_chipmem_bank;
51
/*************************************************************
52
Returns the first node entry of an exec list or 0 if
54
*************************************************************/
55
static uae_u32 amiga_list_first (uae_u32 list)
57
uae_u32 node = get_long (list); /* lh_Head */
61
return 0; /* ln_Succ */
65
/*************************************************************
66
Returns the next node of an exec node or 0 if it was the
68
*************************************************************/
69
static uae_u32 amiga_node_next (uae_u32 node)
71
uae_u32 next = get_long (node); /* ln_Succ */
75
return 0; /* ln_Succ */
79
/*************************************************************
80
Converts an amiga address to a native one or NULL if this
81
is not possible, Size specified the number of bytes you
83
*************************************************************/
84
static uae_u8 *amiga2native (uae_u32 aptr, int size)
86
addrbank bank = get_mem_bank (aptr);
88
/* Check if the address can be translated to native */
89
if (bank.check (aptr,size)) {
90
return bank.xlateaddr (aptr);
95
/*************************************************************
96
Writes the Hunk and Offset of the given Address into buf
97
*************************************************************/
98
static int enforcer_decode_hunk_and_offset (char *buf, uae_u32 pc)
100
uae_u32 sysbase = get_long(4);
101
uae_u32 semaphore_list = sysbase + 532;
103
/* First step is searching for the SegTracker semaphore */
104
uae_u32 node = amiga_list_first (semaphore_list);
106
uae_u32 string = get_long (node + 10); /* ln_Name */
107
uae_u8 *native_string = amiga2native (string, 100);
110
if (!strcmp ((char *) native_string, "SegTracker"))
113
node = amiga_node_next (node);
117
/* We have found the segtracker semaphore. Soon after the
118
* public documented semaphore structure Segtracker holds
119
* an own list of all segements. We will use this list to
120
* find out the hunk and offset (simliar to segtracker).
122
* Source of segtracker can be found at:
123
* http://www.sinz.org/Michael.Sinz/Enforcer/SegTracker.c.html
125
uae_u32 seg_list = node + 46 + 4; /* sizeof(struct SignalSemaphore) + seg find */
127
node = amiga_list_first (seg_list);
129
uae_u32 seg_entry = node + 12;
130
uae_u32 address, size;
133
/* Go through all entries until an address is 0
134
* or the segment has been found */
135
while ((address = get_long (seg_entry))) {
136
size = get_long (seg_entry + 4);
138
if (pc >= address && pc < address + size) {
139
uae_u32 name, offset;
140
const char *native_name;
142
offset = pc - address - 4;
143
name = get_long (node + 8); /* ln_Name */
145
native_name = (char *) amiga2native (name, 100);
147
native_name = "Unknown";
149
native_name = "Unknown";
151
sprintf (buf, "----> %08lx - \"%s\" Hunk %04lx Offset %08lx\n", pc,
152
native_name, hunk, offset);
158
node = amiga_node_next (node);
164
/*************************************************************
165
Display the enforcer hit
166
*************************************************************/
167
static void enforcer_display_hit (const char *addressmode, uae_u32 pc, uaecptr addr)
173
const char *native_task_name;
175
static char buf[256], instrcode[256];
176
static char lines[INSTRUCTIONLINES/2][256];
177
static uaecptr bestpc_array[INSTRUCTIONLINES/2][5];
178
static int bestpc_idxs[INSTRUCTIONLINES/2];
179
char *enforcer_buf_ptr = enforcer_buf;
180
uaecptr bestpc, pospc, nextpc, temppc;
182
if (enforcer_hit) return; /* our function itself generated a hit ;), avoid endless loop */
185
if (!(sysbase = get_long (4)))
187
if (!(this_task = get_long (sysbase + 276)))
190
task_name = get_long (this_task + 10); /* ln_Name */
191
native_task_name = (char *) amiga2native (task_name, 100);
193
strcpy (enforcer_buf_ptr, "Enforcer Hit! Bad program\n");
194
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
196
sprintf (buf, "Illegal %s: %08lx", addressmode, addr);
197
sprintf (enforcer_buf_ptr,"%-48sPC: %0lx\n", buf, pc);
198
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
201
sprintf (enforcer_buf_ptr, "Data: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
202
m68k_dreg (®s, 0), m68k_dreg (®s, 1), m68k_dreg (®s, 2), m68k_dreg (®s, 3),
203
m68k_dreg (®s, 4), m68k_dreg (®s, 5), m68k_dreg (®s, 6), m68k_dreg (®s, 7));
204
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
206
/* Address registers */
207
sprintf (enforcer_buf_ptr, "Addr: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
208
m68k_areg (®s, 0), m68k_areg (®s, 1), m68k_areg (®s, 2), m68k_areg (®s, 3),
209
m68k_areg (®s, 4), m68k_areg (®s, 5), m68k_areg (®s, 6), m68k_areg (®s, 7));
210
enforcer_buf_ptr += strlen(enforcer_buf_ptr);
213
a7 = m68k_areg (®s, 7);
214
for (i = 0; i < 8 * STACKLINES; i++) {
217
strcpy (enforcer_buf_ptr,"Stck:");
218
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
220
sprintf (enforcer_buf_ptr," %08lx", get_long (a7));
221
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
224
*enforcer_buf_ptr++ = '\n';
227
/* Segtracker output */
228
a7 = m68k_areg (®s, 7);
229
if (get_long (a7-4) != pc) {
230
if (enforcer_decode_hunk_and_offset (buf, pc)) {
231
strcpy (enforcer_buf_ptr, buf);
232
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
236
for (i = 0; i < 8 * STACKLINES; i++) {
238
if (enforcer_decode_hunk_and_offset (buf, get_long (a7))) {
239
int l = strlen (buf);
241
if (ENFORCER_BUF_SIZE - (enforcer_buf_ptr - enforcer_buf) > l + 256) {
242
strcpy(enforcer_buf_ptr, buf);
243
enforcer_buf_ptr += l;
248
/* Decode the instructions around the pc where the enforcer hit was caused.
250
* At first, the area before the pc, this not always done correctly because
251
* it's done backwards */
254
memset (bestpc_array, 0, sizeof (bestpc_array));
255
for (i = 0; i < INSTRUCTIONLINES / 2; i++)
258
for (i = 0; i < INSTRUCTIONLINES / 2; i++) {
262
if (bestpc_idxs[i] == -1) {
263
for (j = 0; j < 5; j++) {
265
sm68k_disasm (buf, NULL, pospc, &nextpc);
266
if (nextpc == temppc) {
268
bestpc_array[i][j] = bestpc = pospc;
272
bestpc = bestpc_array[i][bestpc_idxs[i]];
276
/* there was no best pc found, so it is high probable that
277
* a former used best pc was wrong.
279
* We trace back and use the former best pc instead
291
former_idx = bestpc_idxs[i];
293
bestpc_array[i][former_idx] = 0;
295
for (j = former_idx - 1; j >= 0; j--) {
296
if (bestpc_array[i][j]) {
301
} while (bestpc_idxs[i] == -1);
305
temppc = bestpc_array[i-1][bestpc_idxs[i-1]];
307
i--; /* will be increased in after continue */
311
sm68k_disasm (buf, instrcode, bestpc, NULL);
312
sprintf (lines[i], "%08lx : %-20s %s\n", bestpc, instrcode, buf);
318
strcpy (enforcer_buf_ptr,lines[i]);
319
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
322
/* Now the instruction after the pc including the pc */
324
for (i=0; i < (INSTRUCTIONLINES+1) / 2; i++) {
325
sm68k_disasm (buf, instrcode, temppc, &nextpc);
326
sprintf (enforcer_buf_ptr, "%08lx : %s %-20s %s\n", temppc,
327
(i == 0 ? "*" : " "), instrcode, buf);
328
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
332
if (!native_task_name)
333
native_task_name = "Unknown";
334
sprintf (enforcer_buf_ptr, "Name: \"%s\"\n\n", native_task_name);
335
enforcer_buf_ptr += strlen (enforcer_buf_ptr);
337
console_out (enforcer_buf);
338
write_log (enforcer_buf);
345
* Replacement chipmem accessors
348
static uae_u32 chipmem_lget2 (uaecptr addr) REGPARAM;
349
static uae_u32 chipmem_wget2 (uaecptr addr) REGPARAM;
350
static uae_u32 chipmem_bget2 (uaecptr addr) REGPARAM;
351
static void chipmem_lput2 (uaecptr addr, uae_u32 l) REGPARAM;
352
static void chipmem_wput2 (uaecptr addr, uae_u32 w) REGPARAM;
353
static void chipmem_bput2 (uaecptr addr, uae_u32 b) REGPARAM;
354
static int chipmem_check2 (uaecptr addr, uae_u32 size) REGPARAM;
355
static uae_u8 * chipmem_xlate2 (uaecptr addr) REGPARAM;
357
static uae_u32 REGPARAM2 chipmem_lget2 (uaecptr addr)
361
addr -= chipmem_start & chipmem_mask;
362
addr &= chipmem_mask;
363
m = (uae_u32 *)(chipmemory + addr);
365
if (ISILLEGAL (addr))
366
enforcer_display_hit ("LONG READ from", GET_PC, addr);
368
return do_get_mem_long (m);
371
static uae_u32 REGPARAM2 chipmem_wget2 (uaecptr addr)
375
addr -= chipmem_start & chipmem_mask;
376
addr &= chipmem_mask;
377
m = (uae_u16 *)(chipmemory + addr);
379
if (ISILLEGAL (addr))
380
enforcer_display_hit ("WORD READ from", GET_PC, addr);
382
return do_get_mem_word (m);
385
static uae_u32 REGPARAM2 chipmem_bget2 (uaecptr addr)
387
addr -= chipmem_start & chipmem_mask;
388
addr &= chipmem_mask;
390
if (ISILLEGAL (addr))
391
enforcer_display_hit ("BYTE READ from", GET_PC, addr);
393
return chipmemory[addr];
396
static void REGPARAM2 chipmem_lput2 (uaecptr addr, uae_u32 l)
400
addr -= chipmem_start & chipmem_mask;
401
addr &= chipmem_mask;
402
m = (uae_u32 *)(chipmemory + addr);
404
if (ISILLEGAL (addr))
405
enforcer_display_hit ("LONG WRITE to", GET_PC, addr);
407
do_put_mem_long (m, l);
410
static void REGPARAM2 chipmem_wput2 (uaecptr addr, uae_u32 w)
414
addr -= chipmem_start & chipmem_mask;
415
addr &= chipmem_mask;
416
m = (uae_u16 *)(chipmemory + addr);
418
if (ISILLEGAL (addr))
419
enforcer_display_hit ("WORD WRITE to", GET_PC, addr);
421
do_put_mem_word (m, w);
424
static void REGPARAM2 chipmem_bput2 (uaecptr addr, uae_u32 b)
426
addr -= chipmem_start & chipmem_mask;
427
addr &= chipmem_mask;
429
if (ISILLEGAL (addr))
430
enforcer_display_hit ("BYTE WRITE to", GET_PC, addr);
431
chipmemory[addr] = b;
434
static int REGPARAM2 chipmem_check2 (uaecptr addr, uae_u32 size)
436
addr -= chipmem_start & chipmem_mask;
437
addr &= chipmem_mask;
438
return (addr + size) <= allocated_chipmem;
441
static uae_u8 * REGPARAM2 chipmem_xlate2 (uaecptr addr)
443
addr -= chipmem_start & chipmem_mask;
444
addr &= chipmem_mask;
445
return chipmemory + addr;
448
static const addrbank enforcer_chipmem_bank = {
449
chipmem_lget2, chipmem_wget2, chipmem_bget2,
450
chipmem_lput2, chipmem_wput2, chipmem_bput2,
451
chipmem_xlate2, chipmem_check2, NULL
455
* Replacement dummy memory accessors
457
static uae_u32 dummy_lget2 (uaecptr addr) REGPARAM;
458
static uae_u32 dummy_wget2 (uaecptr addr) REGPARAM;
459
static uae_u32 dummy_bget2 (uaecptr addr) REGPARAM;
460
static void dummy_lput2 (uaecptr addr, uae_u32 l) REGPARAM;
461
static void dummy_wput2 (uaecptr addr, uae_u32 w) REGPARAM;
462
static void dummy_bput2 (uaecptr addr, uae_u32 b) REGPARAM;
463
static int dummy_check2 (uaecptr addr, uae_u32 size) REGPARAM;
465
static uae_u32 REGPARAM2 dummy_lget2 (uaecptr addr)
468
special_mem |= SPECIAL_MEM_READ;
470
enforcer_display_hit ("LONG READ from", GET_PC, addr);
475
static int warned_JIT_0xF10000 = 0;
478
static uae_u32 REGPARAM2 dummy_wget2 (uaecptr addr)
481
special_mem |= SPECIAL_MEM_READ;
483
if (addr >= 0x00F10000 && addr <= 0x00F7FFFF) {
484
if (!warned_JIT_0xF10000) {
485
warned_JIT_0xF10000 = 1;
486
enforcer_display_hit ("LONG READ from", GET_PC, addr);
491
enforcer_display_hit ("WORD READ from", GET_PC, addr);
495
static uae_u32 REGPARAM2 dummy_bget2 (uaecptr addr)
498
special_mem |= SPECIAL_MEM_READ;
500
enforcer_display_hit ("BYTE READ from", GET_PC, addr);
504
static void REGPARAM2 dummy_lput2 (uaecptr addr, uae_u32 l)
507
special_mem |= SPECIAL_MEM_WRITE;
509
enforcer_display_hit ("LONG WRITE to", GET_PC, addr);
512
static void REGPARAM2 dummy_wput2 (uaecptr addr, uae_u32 w)
515
special_mem |= SPECIAL_MEM_WRITE;
517
enforcer_display_hit ("WORD WRITE to", GET_PC, addr);
520
static void REGPARAM2 dummy_bput2 (uaecptr addr, uae_u32 b)
523
special_mem |= SPECIAL_MEM_WRITE;
525
enforcer_display_hit ("BYTE WRITE to", GET_PC, addr);
528
static int REGPARAM2 dummy_check2 (uaecptr addr, uae_u32 size)
531
special_mem |= SPECIAL_MEM_READ;
533
enforcer_display_hit ("CHECK from ", GET_PC, addr);
537
const addrbank enforcer_dummy_bank = {
538
dummy_lget2, dummy_wget2, dummy_bget2,
539
dummy_lput2, dummy_wput2, dummy_bput2,
540
default_xlate, dummy_check2, NULL
543
/*************************************************************
544
enable the enforcer like support, maybe later this make MMU
545
exceptions so enforcer can use it. Returns 1 if enforcer
547
*************************************************************/
548
int enforcer_enable (void)
550
extern addrbank chipmem_bank, dummy_bank;
552
if (!enforcer_installed) {
553
saved_dummy_bank = dummy_bank;
554
saved_chipmem_bank = chipmem_bank;
556
dummy_bank = enforcer_dummy_bank;
557
chipmem_bank = enforcer_chipmem_bank;
559
enforcer_installed = 1;
561
write_log ("Enforcer enabled\n");
565
/*************************************************************
566
Disable Enforcer like support
567
*************************************************************/
568
int enforcer_disable (void)
570
if (enforcer_installed) {
571
dummy_bank = saved_dummy_bank;
572
chipmem_bank = saved_chipmem_bank;
574
enforcer_installed = 0;