|
|
1.1 ! root 1: #import "RegionManager.h" ! 2: #import <stdlib.h> ! 3: #import <string.h> ! 4: #import <mach/mach.h> ! 5: #import <mach-o/loader.h> ! 6: #import <mach/vm_param.h> ! 7: ! 8: kern_return_t static inline vmRegion(task_t task, ! 9: vm_address_t address, ! 10: Region *region) ! 11: { ! 12: vm_offset_t offset; ! 13: vm_prot_t maxProtection; ! 14: vm_inherit_t inheritance; ! 15: boolean_t shared; ! 16: port_t objectName; ! 17: region->reloc.address = address; ! 18: return vm_region(task, ! 19: ®ion->reloc.address, ! 20: ®ion->reloc.size, ! 21: ®ion->protection, ! 22: &maxProtection, ! 23: &inheritance, ! 24: &shared, ! 25: &objectName, ! 26: &offset); ! 27: } ! 28: ! 29: @implementation RegionManager ! 30: ! 31: -initTask: (vm_task_t)theTask readInRegions: (BOOL)readInRegions ! 32: { ! 33: vm_statistics_data_t vm_stats; ! 34: ! 35: task = theTask; ! 36: vm_statistics(theTask, &vm_stats); ! 37: pageSize = vm_stats.pagesize; ! 38: relocSize = sizeof(Region); ! 39: rmFlags.shouldSortRelocs = NO; ! 40: if (readInRegions) ! 41: [self readInAllRelocs]; ! 42: else ! 43: rmFlags.invalid = YES; ! 44: return self; ! 45: } ! 46: ! 47: -(BOOL)isTask ! 48: { ! 49: struct task_basic_info taskInfo; ! 50: unsigned int taskInfoCount; ! 51: BOOL ret; ! 52: ! 53: taskInfoCount = TASK_BASIC_INFO_COUNT; ! 54: ret = (task_info(task, ! 55: TASK_BASIC_INFO, ! 56: (task_info_t)&taskInfo, ! 57: &taskInfoCount) == KERN_SUCCESS) ? YES : NO; ! 58: if (!ret && taskGoneCallBack) ! 59: (*taskGoneCallBack)(); ! 60: return ret; ! 61: } ! 62: ! 63: -(void)setTaskGoneCallBack: (TaskGoneCallBack)theCallBack ! 64: { ! 65: taskGoneCallBack = theCallBack; ! 66: } ! 67: ! 68: +newTask: (vm_task_t)theTask ! 69: { ! 70: return [[super new] initTask: theTask readInRegions: YES]; ! 71: } ! 72: ! 73: +newTask: (vm_task_t)theTask readInRegions: (BOOL)readInRegions ! 74: { ! 75: return [[super new] initTask: theTask readInRegions: readInRegions]; ! 76: } ! 77: ! 78: -invalidate ! 79: { ! 80: if (rmFlags.invalid) ! 81: return self; ! 82: else { ! 83: Region *region; ! 84: int count; ! 85: if (relocs) { ! 86: for (count = numRelocs, region = (Region *)relocs; ! 87: count; ! 88: count--, region++) { ! 89: if (region->reloc.rFlags.readIn) ! 90: vm_deallocate(task_self(), ! 91: region->reloc.data, ! 92: region->reloc.size); ! 93: } ! 94: } ! 95: if (pages) { ! 96: free(pages); ! 97: pages = NULL; ! 98: } ! 99: return [super invalidate]; ! 100: } ! 101: } ! 102: ! 103: -(void)getStartPage: (void **)startPage andSize: (int *)sizePage ! 104: forPointer: (void *)start andSize: (int)numBytes ! 105: { ! 106: vm_address_t offset = ((vm_address_t)start % pageSize); ! 107: vm_address_t s = numBytes + offset; ! 108: ! 109: *startPage = start - offset; ! 110: *sizePage = (s - (s % pageSize)) + pageSize; ! 111: } ! 112: ! 113: -(void)protectDataAt: (const void *)start for: (int)numBytes ! 114: { ! 115: vm_address_t offset = ((vm_address_t)start % pageSize); ! 116: vm_address_t startPage = (vm_address_t)start - offset; ! 117: size_t sizePage = numBytes + offset; ! 118: ! 119: vm_protect(task, startPage, pageSize, NO, VM_PROT_READ); ! 120: } ! 121: ! 122: -(void)unProtectDataAt: (const void *)start for: (int)numBytes ! 123: { ! 124: vm_address_t offset = ((vm_address_t)start % pageSize); ! 125: vm_address_t startPage = (vm_address_t)start - offset; ! 126: size_t sizePage = numBytes + offset; ! 127: ! 128: vm_protect(task, startPage, pageSize, NO, VM_PROT_READ | VM_PROT_WRITE); ! 129: } ! 130: ! 131: -(int)writeDataAt: (const void *)start for: (int)numBytes reloc: (Region *)region markOnly: (BOOL)markOnly ! 132: { ! 133: vm_address_t offset = ((vm_address_t)start % pageSize); ! 134: vm_address_t startPage = (vm_address_t)start - offset; ! 135: size_t sizePage = numBytes + offset; ! 136: pointer_t startData; ! 137: kern_return_t ret = 0; ! 138: unsigned char *pPage; ! 139: ! 140: if (markOnly) { ! 141: if (!region->pagesInvalid) ! 142: regionsInvalid++; ! 143: } ! 144: for (sizePage += (pageSize - (sizePage % pageSize)), ! 145: startData = region->reloc.data ! 146: + ((pointer_t)startPage - region->reloc.address), ! 147: pPage = region->pages ! 148: + (((pointer_t)startPage - region->reloc.address) / pageSize); ! 149: sizePage && !ret; ! 150: sizePage -= pageSize, startData += pageSize, startPage += pageSize, ! 151: pPage++) { ! 152: if (markOnly) { ! 153: if (!(*pPage & PAGEINVALID)) { ! 154: *pPage |= PAGEINVALID; ! 155: region->pagesInvalid++; ! 156: } ! 157: } else { ! 158: *pPage &= ~PAGEINVALID; ! 159: if (*pPage & VM_PROT_WRITE) ! 160: ret = vm_write(task, startPage, startData, pageSize); ! 161: else { ! 162: vm_protect(task, startPage, pageSize, NO, VM_PROT_WRITE); ! 163: ret = vm_write(task, startPage, startData, pageSize); ! 164: vm_protect(task, startPage, pageSize, NO, ! 165: (vm_prot_t)(*pPage & 0x7)); ! 166: } ! 167: } ! 168: } ! 169: if (ret == KERN_SUCCESS) ! 170: return numBytes; ! 171: else { ! 172: [self isTask]; ! 173: return 0; ! 174: } ! 175: } ! 176: ! 177: -(int)writeDataAt: (const void *)start for: (int)numBytes reloc: (Region *)region ! 178: { ! 179: return [self writeDataAt: start for: numBytes reloc: region markOnly: NO]; ! 180: } ! 181: ! 182: -(int)putDataAt: (void *)start for: (int)numBytes from: (const void *)data markOnly: (BOOL)markOnly ! 183: { ! 184: int numBytesInRegion; ! 185: Reloc *reloc = [self relocFor: start]; ! 186: if (reloc) { ! 187: numBytesInRegion = reloc->maxAddress - (int)start; ! 188: if (numBytes > numBytesInRegion) ! 189: numBytes = numBytesInRegion; ! 190: if (numBytes == 1) ! 191: *(char *)(reloc->data + ((pointer_t)start - reloc->address)) ! 192: = *(char *)data; ! 193: else ! 194: memcpy((void *)(reloc->data + ((pointer_t)start - reloc->address)), ! 195: data, ! 196: numBytes); ! 197: return [self writeDataAt: start for: numBytes reloc: (Region *)reloc markOnly: markOnly]; ! 198: } else ! 199: return 0; ! 200: } ! 201: ! 202: -(int)putDataAt: (void *)start for: (int)numBytes from: (const void *)data ! 203: { ! 204: return [self putDataAt: start for: numBytes from: data markOnly: NO]; ! 205: } ! 206: ! 207: -(void)flushMarkedPages ! 208: { ! 209: int ret = 0; ! 210: while (regionsInvalid) { ! 211: int i; ! 212: Region *region; ! 213: ! 214: for (i = 0, region = (Region *)relocs; ! 215: i < numRelocs; ! 216: i++, ((void *)region) += relocSize) { ! 217: if (region->pagesInvalid) { ! 218: unsigned char *p = region->pages; ! 219: while (region->pagesInvalid) { ! 220: if (*p & PAGEINVALID) { ! 221: int numPage = p - region->pages; ! 222: pointer_t startPage, startData; ! 223: ! 224: startPage ! 225: = region->reloc.address + (numPage * pageSize); ! 226: startData ! 227: = region->reloc.data + (numPage * pageSize); ! 228: *p &= ~PAGEINVALID; ! 229: region->pagesInvalid--; ! 230: if (*p & VM_PROT_WRITE) ! 231: ret = vm_write(task, startPage, startData, pageSize); ! 232: else { ! 233: vm_protect(task, startPage, pageSize, NO, VM_PROT_WRITE); ! 234: ret = vm_write(task, startPage, startData, pageSize); ! 235: vm_protect(task, startPage, pageSize, NO, ! 236: (vm_prot_t)(*p & 0x7)); ! 237: } ! 238: } ! 239: p++; ! 240: } ! 241: regionsInvalid--; ! 242: } ! 243: } ! 244: } ! 245: if (ret) ! 246: [self isTask]; ! 247: } ! 248: ! 249: -(int)writeDataAt: (const void *)start for: (int)numBytes; ! 250: { ! 251: Reloc *reloc = [self relocFor: start]; ! 252: if (reloc) ! 253: return [self writeDataAt: start for: numBytes reloc: (Region *)reloc]; ! 254: else ! 255: return NO; ! 256: } ! 257: ! 258: -(BOOL)readInReloc: (Reloc *)reloc ! 259: { ! 260: kern_return_t ret; ! 261: unsigned int nData; ! 262: if (reloc->rFlags.readIn) { ! 263: return YES; ! 264: } else { ! 265: ret = vm_read(task, reloc->address, reloc->size, &reloc->data, &nData); ! 266: if (ret == KERN_SUCCESS) { ! 267: reloc->maxData = reloc->data + reloc->size; ! 268: reloc->displacement = reloc->data - reloc->address; ! 269: reloc->rFlags.readIn = YES; ! 270: return YES; ! 271: } else { ! 272: [self isTask]; ! 273: return NO; ! 274: } ! 275: } ! 276: } ! 277: ! 278: -(void)combineRegions: (BOOL)combineRegions ! 279: { dontCombineRegions = !combineRegions;} ! 280: ! 281: -(void)_readInAllRelocs ! 282: { ! 283: kern_return_t error = 0; ! 284: vm_address_t address = VM_MIN_ADDRESS; ! 285: Region *theRegion, *regions, *newRegion, *nextRegion, *lastRegion; ! 286: int count = 0, numPages = 0, numAlloced = 16, nPages; ! 287: unsigned char *thePage; ! 288: ! 289: if ([self isTask]) { ! 290: theRegion = regions = malloc(numAlloced * sizeof(Region)); ! 291: bzero(regions, numAlloced * sizeof(Region)); ! 292: while (!error) { ! 293: error = vmRegion(task, address, theRegion); ! 294: address = theRegion->reloc.address + theRegion->reloc.size; ! 295: if (!error) { ! 296: if (theRegion->protection & VM_PROT_READ) { ! 297: count++; ! 298: numPages += theRegion->reloc.size / pageSize; ! 299: if (count < numAlloced) ! 300: theRegion++; ! 301: else { ! 302: numAlloced *= 2; ! 303: regions = realloc(regions, ! 304: numAlloced * sizeof(Region)); ! 305: theRegion = regions + count; ! 306: bzero(theRegion, count * sizeof(Region)); ! 307: } ! 308: } ! 309: if (address < theRegion->reloc.address) ! 310: error = KERN_NO_SPACE; ! 311: } ! 312: } ! 313: if (error == KERN_NO_SPACE) { ! 314: lastRegion = theRegion; ! 315: ! 316: pages = malloc(numPages); ! 317: for (theRegion = regions, thePage = pages; ! 318: theRegion < lastRegion; ! 319: theRegion++) { ! 320: theRegion->pages = thePage; ! 321: nPages = theRegion->reloc.size / pageSize; ! 322: while(nPages--) ! 323: *(thePage++) = (unsigned char)theRegion->protection; ! 324: } ! 325: ! 326: if (dontCombineRegions) { ! 327: for (theRegion = regions; theRegion < lastRegion; theRegion++) ! 328: theRegion->reloc.maxAddress ! 329: = theRegion->reloc.address + theRegion->reloc.size; ! 330: relocs = regions; ! 331: numRelocs = count; ! 332: } else { ! 333: relocs = malloc(count * sizeof(Region)); ! 334: bzero(relocs, count * sizeof(Region)); ! 335: for (theRegion = regions, newRegion = relocs; ! 336: theRegion < lastRegion; ! 337: theRegion = nextRegion, newRegion++) { ! 338: for (nextRegion = theRegion + 1; ! 339: (nextRegion < lastRegion ! 340: && ((theRegion->reloc.address + theRegion->reloc.size) ! 341: == nextRegion->reloc.address)); ! 342: nextRegion++) { ! 343: theRegion->reloc.size += nextRegion->reloc.size; ! 344: } ! 345: *newRegion = *theRegion; ! 346: newRegion->reloc.maxAddress ! 347: = newRegion->reloc.address + newRegion->reloc.size; ! 348: } ! 349: numRelocs = newRegion - (Region *)relocs; ! 350: relocs = realloc(relocs, numRelocs * sizeof(Region)); ! 351: free(regions); ! 352: } ! 353: rmFlags.invalid = NO; ! 354: } else ! 355: free(regions); ! 356: ! 357: if (error != KERN_NO_SPACE) ! 358: [self isTask]; ! 359: } ! 360: } ! 361: ! 362: -(struct mach_header *)getMachHeader ! 363: { ! 364: Reloc *reloc; ! 365: int count; ! 366: struct mach_header *header, *foundHeader; ! 367: ! 368: if (rmFlags.invalid) ! 369: [self readInAllRelocs]; ! 370: reloc = relocs; ! 371: for (foundHeader = NULL, count = 0; ! 372: !foundHeader && count < numRelocs; ! 373: count++) { ! 374: [self readInReloc: reloc]; ! 375: header = [self pointerFor: (void *)reloc->address ! 376: withSize: sizeof(*header)]; ! 377: if (header ! 378: && (header->magic == MH_MAGIC) ! 379: && ([self pointerFor: (void *)reloc->address ! 380: withSize: header->sizeofcmds])) ! 381: foundHeader = header; ! 382: else ! 383: ((void *)reloc) += relocSize; ! 384: } ! 385: return foundHeader; ! 386: } ! 387: ! 388: -(int)getNumMachHeaders ! 389: { ! 390: struct mach_header *myHeader; ! 391: int numHeaders, i; ! 392: struct fvmlib_command *loadCmd; ! 393: if (myHeader = [self getMachHeader]) { ! 394: numHeaders = 1; ! 395: for (i = 0, loadCmd = (struct fvmlib_command *)(myHeader + 1); ! 396: i < myHeader->ncmds; ! 397: i++, ! 398: loadCmd = ((void *)loadCmd + loadCmd->cmdsize)) { ! 399: if (loadCmd->cmd == LC_LOADFVMLIB) ! 400: numHeaders++; ! 401: } ! 402: } else ! 403: numHeaders = 0; ! 404: return numHeaders; ! 405: } ! 406: ! 407: -(struct mach_header **)getMachHeadersWithNames: (char ***)names ! 408: { ! 409: struct mach_header *myHeader, **headers, *header; ! 410: char **theNames = NULL; ! 411: struct fvmlib_command *loadCmd; ! 412: int numHeaders, headerIndex; ! 413: numHeaders = [self getNumMachHeaders]; ! 414: myHeader = [self getMachHeader]; ! 415: headers = malloc((numHeaders + 1) * sizeof(*headers)); ! 416: if (names) { ! 417: *names = theNames = malloc((numHeaders + 1) * sizeof(*theNames)); ! 418: theNames[0] = NULL; ! 419: } ! 420: headers[0] = myHeader; ! 421: for (headerIndex = 1, loadCmd = (struct fvmlib_command *)(myHeader + 1); ! 422: headerIndex < numHeaders; ! 423: loadCmd = ((void *)loadCmd + loadCmd->cmdsize)) { ! 424: if (loadCmd->cmd == LC_LOADFVMLIB) { ! 425: header = [self pointerFor: (void *)(loadCmd->fvmlib.header_addr) ! 426: withSize: sizeof(*header)]; ! 427: if (header) ! 428: headers[headerIndex] ! 429: = [self pointerFor: (void *)(loadCmd->fvmlib.header_addr) ! 430: withSize: header->sizeofcmds]; ! 431: if (names) ! 432: theNames[headerIndex] ! 433: = (char *)loadCmd ! 434: + ((struct fvmlib_command *)loadCmd) ! 435: ->fvmlib.name.offset; ! 436: headerIndex++; ! 437: } ! 438: } ! 439: headers[numHeaders] = NULL; ! 440: if (names) ! 441: theNames[numHeaders] = NULL; ! 442: return headers; ! 443: } ! 444: ! 445: -(struct mach_header **)getMachHeaders ! 446: { ! 447: return [self getMachHeadersWithNames: NULL]; ! 448: } ! 449: ! 450: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.