|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.0 (the 'License'). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License."
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: #ifdef SHLIB
25: #import "shlib.h"
26: #undef moninitobjc
27: #endif
28:
29: #ifndef __ppc__
30: #error "this is ppc machine dependent"
31: #endif
32:
33: #include <mach/mach.h>
34:
35: /*
36: * objc_exitPoints is a private_extern defined in the objective-C messager
37: * which is a zero terminated table of a list of text lables to write
38: * instructions which will cause the objective-C messager to then call
39: * moncount for each message it dispatches. The instruction at each of these
40: * text lables is a "bctr" instruction. The objective-C messager has
41: * allocated space after each of these instructions for moninitobjc to write
42: * the instructions to call moncount for each message it dispatches.
43: *
44: * The instructions written over the "bctr" and the allocated space after
45: * it are:
46: * exitPoint1: bctr
47: * ; replace with the following instructions
48: * stw r3, 24(r1) ; save register parameters
49: * stw r4, 28(r1) ;
50: * stw r5, 32(r1) ;
51: * stw r6, 36(r1) ;
52: * stw r7, 40(r1) ;
53: * stw r8, 44(r1) ;
54: * stw r9, 48(r1) ;
55: * stw r10,52(r1) ;
56: * mflr r0 ; move LR to r0
57: * stw r0,8(r1) ; save LR (return addr)
58: * mfcr r12 ; move CTR to r12
59: * stw r12,4(r1) ; save CTR (imp)
60: * stwu r1,-64(r1) ; grow the stack
61: *
62: * ori r3,r0,0 ; first arg is frompc (return addr)
63: * ori r4,r12,0 ; second arg is selfpc (imp)
64: * bl _moncount
65: *
66: * lwz r1,0(r1) ; restore the stack pointer
67: * lwz r12,4(r1) ;
68: * mtctr r12 ; restore CTR (imp)
69: * lwz r0,8(r1) ;
70: * mtlr r0 ; restore LR (return addr)
71: * lwz r3, 24(r1) ;
72: * lwz r4, 28(r1) ;
73: * lwz r5, 32(r1) ;
74: * lwz r6, 36(r1) ;
75: * lwz r7, 40(r1) ;
76: * lwz r8, 44(r1) ;
77: * lwz r9, 48(r1) ;
78: * lwz r10,52(r1) ;
79: * bctr ; goto *imp;
80: */
81: extern unsigned long objc_exitPoints[];
82:
83: /*
84: * objc_entryPoints is a private_extern defined in the objective-C messager
85: * which is a zero terminated table of a list of text lables that should not
86: * have a call inserted to moncount in their shared library branch table slot.
87: */
88: extern unsigned long objc_entryPoints[];
89:
90: /*
91: * moninitobjc() is a machine dependent routine that causes objective-C
92: * messager to call moncount() for each message it sends.
93: */
94: unsigned long *
95: moninitobjc(
96: unsigned long moncount_addr)
97: {
98: unsigned long i, min, max;
99: unsigned long *p, disp;
100: kern_return_t r;
101:
102: if(objc_exitPoints[0] == 0)
103: return(objc_entryPoints);
104:
105: /*
106: * Determine the area to vm_protect() for writing the code.
107: */
108: min = 0xffffffff;
109: max = 0;
110: for(i = 0; objc_exitPoints[i] != 0; i++){
111: if(objc_exitPoints[i] < min)
112: min = objc_exitPoints[i];
113: if(objc_exitPoints[i] > max)
114: max = objc_exitPoints[i];
115: }
116: max += 116;
117:
118: if((r = vm_protect(task_self(), (vm_address_t)min, (vm_size_t)(max-min),
119: FALSE, VM_PROT_READ | VM_PROT_WRITE |
120: VM_PROT_EXECUTE)) != KERN_SUCCESS)
121: return(objc_entryPoints);
122:
123: /*
124: * Write in the code to call moncount.
125: */
126: for(i = 0; objc_exitPoints[i] != 0; i++){
127: p = (unsigned long *)(objc_exitPoints[i]);
128: /* stw r3,24(r1) */
129: *p++ = 0x90610018;
130: /* stw r4,28(r1) */
131: *p++ = 0x9081001c;
132: /* stw r5,32(r1) */
133: *p++ = 0x90a10020;
134: /* stw r6,36(r1) */
135: *p++ = 0x90c10024;
136: /* stw r7,40(r1) */
137: *p++ = 0x90e10028;
138: /* stw r8,44(r1) */
139: *p++ = 0x9101002c;
140: /* stw r9,48(r1) */
141: *p++ = 0x91210030;
142: /* stw r10,52(r1) */
143: *p++ = 0x91410034;
144: /* mflr r0 */
145: *p++ = 0x7c0802a6;
146: /* stw r0,8(r1) */
147: *p++ = 0x90010008;
148: /* mfcr r12 */
149: *p++ = 0x7d800026;
150: /* stw r12,4(r1) */
151: *p++ = 0x91810004;
152: /* stwu r1,-64(r1) */
153: *p++ = 0x9421ffc0;
154: /* ori r3,r0,0 */
155: *p++ = 0x60030000;
156: /* ori r4,r12,0 */
157: *p++ = 0x61840000;
158: /* bl _moncount */
159: disp = moncount_addr - (unsigned long)(p);
160: *p++ = 0x48000001 | (disp & 0x03fffffc);
161: /* lwz r1,0(r1) */
162: *p++ = 0x80210000;
163: /* lwz r12,4(r1) */
164: *p++ = 0x81810004;
165: /* mtctr r12 */
166: *p++ = 0x7d8903a6;
167: /* lwz r0,8(r1) */
168: *p++ = 0x80010008;
169: /* mtlr r0 */
170: *p++ = 0x7c0803a6;
171: /* lwz r3,24(r1) */
172: *p++ = 0x80610018;
173: /* lwz r4,28(r1) */
174: *p++ = 0x8081001c;
175: /* lwz r5,32(r1) */
176: *p++ = 0x80a10020;
177: /* lwz r6,36(r1) */
178: *p++ = 0x80c10024;
179: /* lwz r7,40(r1) */
180: *p++ = 0x80e10028;
181: /* lwz r8,44(r1) */
182: *p++ = 0x8101002c;
183: /* lwz r9,48(r1) */
184: *p++ = 0x81210030;
185: /* lwz r10,52(r1) */
186: *p++ = 0x81410034;
187: /* bctr */
188: *p++ = 0x4e800420;
189: }
190: /*
191: * The text cache for the this code now needs to be flushed since
192: * it was just written on so that future calls will get the new
193: * instructions.
194: */
195: user_cache_flush(min, max-min);
196:
197: return(objc_entryPoints);
198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.