|
|
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 __i386__ ! 30: #error "this is i386 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 "jmp *%eax@" 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 "jmp *%eax@" and the allocated space after ! 45: * it are: ! 46: * exitPoint1: jmp *%eax@ ! 47: * | replace with the following instructions ! 48: * pushl %eax ! 49: * pushl %eax ! 50: * pushl 8(%esp) ! 51: * call _moncount ! 52: * addl $8,%esp ! 53: * popl %eax ! 54: * jmp *%eax@ ! 55: */ ! 56: extern unsigned long objc_exitPoints[]; ! 57: ! 58: /* ! 59: * objc_entryPoints is a private_extern defined in the objective-C messager ! 60: * which is a zero terminated table of a list of text lables that should not ! 61: * have a call inserted to moncount in their shared library branch table slot. ! 62: */ ! 63: extern unsigned long objc_entryPoints[]; ! 64: ! 65: /* ! 66: * moninitobjc() is a machine dependent routine that causes objective-C ! 67: * messager to call moncount() for each message it sends. ! 68: */ ! 69: unsigned long * ! 70: moninitobjc( ! 71: unsigned long moncount_addr) ! 72: { ! 73: unsigned long i, min, max, addr; ! 74: char *p; ! 75: kern_return_t r; ! 76: ! 77: if(objc_exitPoints[0] == 0) ! 78: return(objc_entryPoints); ! 79: ! 80: /* ! 81: * Determine the area to vm_protect() for writing the code. ! 82: */ ! 83: min = 0xffffffff; ! 84: max = 0; ! 85: for(i = 0; objc_exitPoints[i] != 0; i++){ ! 86: if(objc_exitPoints[i] < min) ! 87: min = objc_exitPoints[i]; ! 88: if(objc_exitPoints[i] > max) ! 89: max = objc_exitPoints[i]; ! 90: } ! 91: max += 24; ! 92: ! 93: if((r = vm_protect(task_self(), (vm_address_t)min, (vm_size_t)(max-min), ! 94: FALSE, VM_PROT_READ | VM_PROT_WRITE | ! 95: VM_PROT_EXECUTE)) != KERN_SUCCESS) ! 96: return(objc_entryPoints); ! 97: ! 98: /* ! 99: * Write in the code to call moncount. ! 100: */ ! 101: for(i = 0; objc_exitPoints[i] != 0; i++){ ! 102: p = (char *)(objc_exitPoints[i]); ! 103: /* pushl %eax */ ! 104: *p++ = 0x50; ! 105: /* pushl %eax */ ! 106: *p++ = 0x50; ! 107: /* pushl 8(%esp) */ ! 108: *p++ = 0xff; ! 109: *p++ = 0x74; ! 110: *p++ = 0x24; ! 111: *p++ = 0x08; ! 112: /* call moncount */ ! 113: addr = moncount_addr - ((unsigned long)p + 5); ! 114: *p++ = 0xe8; ! 115: *p++ = (addr) & 0xff; ! 116: *p++ = (addr >> 8) & 0xff; ! 117: *p++ = (addr >> 16) & 0xff; ! 118: *p++ = (addr >> 24) & 0xff; ! 119: /* addl $0x08,%esp */ ! 120: *p++ = 0x83; ! 121: *p++ = 0xc4; ! 122: *p++ = 0x08; ! 123: /* popl %eax */ ! 124: *p++ = 0x58; ! 125: /* jmp *%eax@ */ ! 126: *p++ = 0xff; ! 127: *p++ = 0xe0; ! 128: } ! 129: /* ! 130: * The text cache for the this code now needs to be flushed since ! 131: * it was just written on so that future calls will get the new ! 132: * instructions. ! 133: cache_flush(min, max-min); ! 134: */ ! 135: asm("jmp 1f"); ! 136: asm("1: nop"); ! 137: ! 138: return(objc_entryPoints); ! 139: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.