/
setpatch.c
122 lines (106 loc) · 2.67 KB
/
setpatch.c
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
/*
* $Id: setpatch.c,v 1.2 1996/07/17 16:01:56 grubba Exp $
*
* Patches compiled M68000 code with Sparc code.
*
* $Log: setpatch.c,v $
* Revision 1.1 1996/07/13 19:32:05 grubba
* Now defaults to very little debuginfo.
* Added (un|set)patch().
* Patches added to MakeLibrary(), MakeFunctions(), Abort() and AddLibrary().
*
*
*/
/*
* Includes
*/
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "recomp.h"
#include "m68k.h"
#include "codeinfo.h"
#include "setpatch.h"
#ifdef DEBUG
void breakme(void);
#else
#define breakme abort
#endif /* DEBUG */
/*
* Functions
*/
U32 (*setpatch(U32 maddr, U32 (*code)(struct m_registers *, void *)))(struct m_registers *, void *)
{
struct seg_info *seg;
struct code_info *ci;
#ifdef DEBUG
printf("Setpatch(0x%08x)\n", maddr);
#endif /* DEBUG */
if (maddr & 0xff000001) {
fprintf(stderr, "setpatch: Bad address 0x%08x\n", maddr);
return(NULL);
}
if ((!(seg = find_seg(code_tree, maddr))) ||
(!(ci = find_ci(&seg->codeinfo, maddr)))) {
U32 mend;
ci = new_codeinfo(maddr);
#ifdef DEBUG
if (debuglevel & DL_RUNTIME_TRACE) {
fprintf(stdout, "setpatch: Compiling 0x%08x...\n", maddr);
}
#endif /* DEBUG */
mend = compile(ci);
if (!seg) {
#ifdef DEBUG
if (debuglevel & DL_COMPILER_VERBOSE) {
fprintf(stdout, "Creating new segment, maddr: %08x, end: %08x\n",
maddr, mend);
}
#endif /* DEBUG */
seg = insert_seg(&code_tree, maddr, mend);
if (!seg) {
/* BUS ERROR? */
fprintf(stderr, "Out of memory?\n");
abort();
}
} else if (mend != seg->mend) {
fprintf(stderr, "Strange ending, orig:%08x, new:%08x\n", seg->mend, mend);
abort();
}
/* Link it first */
ci->next = seg->codeinfo;
seg->codeinfo = ci;
#ifdef DEBUG
if (debuglevel & DL_COMPILER_DISASSEMBLY) {
disassemble(maddr, mend);
}
#endif /* DEBUG */
}
/* Don't attempt to patch an already patched function */
if (ci->flags & CIF_PATCHED) {
return(NULL);
} else {
U32 (*retval)(struct m_registers *, void *);
/* Don't attempt to free a patched function in the garbage collector */
retval = ci->code;
if (retval) {
ci->flags |= CIF_LOCKED | CIF_PATCHED;
ci->code = code;
} else {
fprintf(stderr, "Setpatch(0x%08x): retval == NULL\n", maddr);
breakme();
}
return(retval);
}
}
void unpatch(U32 maddr, U32 (*code)(struct m_registers *, void *)) {
struct seg_info *seg;
struct code_info *ci;
if ((!(seg = find_seg(code_tree, maddr))) ||
(!(ci = find_ci(&seg->codeinfo, maddr))) ||
(!(ci->flags & CIF_PATCHED))) {
return;
}
ci->code = code;
ci->flags &= ~CIF_PATCHED;
}