|
|
1.1 ! root 1: #import "SegmentManager.h" ! 2: #import <stdlib.h> ! 3: #import <string.h> ! 4: #import <mach-o/loader.h> ! 5: #import <sys/types.h> ! 6: #import <sys/stat.h> ! 7: #import <mach-o/ldsyms.h> ! 8: #import <libc.h> ! 9: #import <objc/maptable.h> ! 10: #import <mach-o/fat.h> ! 11: ! 12: #define REALLY_SWAP_LONG(a) ( ((a) << 24) | \ ! 13: (((a) << 8) & 0x00ff0000) | \ ! 14: (((a) >> 8) & 0x0000ff00) | \ ! 15: ((unsigned long)(a) >> 24) ) ! 16: ! 17: #define SWAP_LONG(a) (shouldSwap ? REALLY_SWAP_LONG(a) : (a)) ! 18: ! 19: @implementation SegmentManager ! 20: ! 21: static NXMapTable *managers = NULL; ! 22: ! 23: +initialize ! 24: { ! 25: static BOOL beenHere = NO; ! 26: ! 27: if (!beenHere) { ! 28: beenHere = YES; ! 29: managers = NXCreateMapTable(NXStrValueMapPrototype, 0); ! 30: } ! 31: return self; ! 32: } ! 33: ! 34: -init ! 35: { ! 36: relocSize = sizeof(Segment); ! 37: rmFlags.shouldSortRelocs = YES; ! 38: [self readInAllRelocs]; ! 39: lastReloc = NULL; ! 40: if (numRelocs) { ! 41: if (images[0].name) ! 42: NXMapInsert(managers, images[0].name, self); ! 43: return self; ! 44: } else { ! 45: [self free]; ! 46: return nil; ! 47: } ! 48: } ! 49: ! 50: -(void)setCpuType: (cpu_type_t)type ! 51: { ! 52: static cpu_type_t defaultCpuType = 0; ! 53: if (type) ! 54: cpuType = type; ! 55: else { ! 56: if (!defaultCpuType) { ! 57: struct host_basic_info host_basic_info; ! 58: unsigned int count = HOST_BASIC_INFO_COUNT; ! 59: ! 60: if (host_info(host_self(), HOST_BASIC_INFO, ! 61: (host_info_t)(&host_basic_info), ! 62: &count) == KERN_SUCCESS) ! 63: defaultCpuType = host_basic_info.cpu_type; ! 64: } ! 65: cpuType = defaultCpuType; ! 66: } ! 67: } ! 68: ! 69: -initFile: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type ! 70: { ! 71: SegmentManager *oldManager; ! 72: if (oldManager = NXMapGet(managers, theName)) { ! 73: close(desc); ! 74: [self free]; ! 75: return oldManager; ! 76: } else { ! 77: name = malloc(strlen(theName) + 1); ! 78: strcpy(name, theName); ! 79: skipShlibs = shouldSkipShlibs; ! 80: imageFd = desc; ! 81: [self setCpuType: type]; ! 82: [self getImages]; ! 83: return [self init]; ! 84: } ! 85: } ! 86: ! 87: static const char loadedName[] = "loaded file"; ! 88: ! 89: -(struct mach_header *)headerFromStart: (void *)start ! 90: { ! 91: struct mach_header *header = start; ! 92: if (header->magic == MH_MAGIC && header->cputype == cpuType) ! 93: return header; ! 94: else { ! 95: struct fat_header *fatHeader = start; ! 96: if ((fatHeader->magic == FAT_MAGIC) ! 97: || (fatHeader->magic == REALLY_SWAP_LONG(FAT_MAGIC))) { ! 98: BOOL shouldSwap = !(fatHeader->magic == FAT_MAGIC); ! 99: unsigned int nArches; ! 100: struct fat_arch *fatArch, *foundArch; ! 101: ! 102: for (nArches = SWAP_LONG(fatHeader->nfat_arch), ! 103: fatArch = (struct fat_arch *)(fatHeader + 1), ! 104: foundArch = NULL; ! 105: nArches && !foundArch; ! 106: fatArch++, nArches--) { ! 107: if (cpuType == SWAP_LONG(fatArch->cputype)) ! 108: foundArch = fatArch; ! 109: } ! 110: if (foundArch) ! 111: return start + SWAP_LONG(foundArch->offset); ! 112: else ! 113: return NULL; ! 114: } else ! 115: return NULL; ! 116: } ! 117: } ! 118: ! 119: -initHeader: (struct mach_header *)header withSize: (int)size ! 120: { ! 121: numImages = 1; ! 122: [self setCpuType: 0]; ! 123: images = malloc(sizeof(*images)); ! 124: images->header = [self headerFromStart: header]; ! 125: images->size = size; ! 126: images->name = NULL; ! 127: images->mtime = 0; ! 128: name = malloc(sizeof(loadedName)); ! 129: strcpy(name, loadedName); ! 130: return [self init]; ! 131: } ! 132: ! 133: -initFile: (STR)theName ! 134: { ! 135: return [self initFile: theName skipShlibs: NO withDesc: -1 cpuType: 0]; ! 136: } ! 137: ! 138: +newExecutable: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type ! 139: { ! 140: SegmentManager *sm = [[super alloc] initFile: (STR)theName ! 141: skipShlibs: shouldSkipShlibs ! 142: withDesc: desc ! 143: cpuType: type]; ! 144: if (sm && [sm isExecutable]) ! 145: return sm; ! 146: else { ! 147: [sm free]; ! 148: return nil; ! 149: } ! 150: } ! 151: ! 152: +newExecutable: (STR)theName ! 153: { ! 154: return [self newExecutable: theName skipShlibs: NO withDesc: -1 cpuType: 0]; ! 155: } ! 156: ! 157: +newCore: (STR)theName ! 158: { ! 159: SegmentManager *sm = [[super alloc] initFile: (STR)theName]; ! 160: if (sm && [sm isCore]) ! 161: return sm; ! 162: else { ! 163: [sm free]; ! 164: return nil; ! 165: } ! 166: } ! 167: ! 168: +newFile: (STR)theName ! 169: { ! 170: return [[super alloc] initFile: (STR)theName]; ! 171: } ! 172: ! 173: +newShlib: (STR)theName cpuType: (cpu_type_t)type ! 174: { ! 175: SegmentManager *sm = [[super alloc] initFile: (STR)theName ! 176: skipShlibs: YES ! 177: withDesc: -1 ! 178: cpuType: type]; ! 179: if (sm && [sm isShlib]) ! 180: return sm; ! 181: else { ! 182: [sm free]; ! 183: return nil; ! 184: } ! 185: } ! 186: ! 187: +newShlib: (STR)theName ! 188: { ! 189: return [self newShlib: theName cpuType: 0]; ! 190: } ! 191: ! 192: +newHeader: (struct mach_header *)header withSize: (int)size ! 193: { ! 194: return [[super alloc] initHeader: header withSize: size]; ! 195: } ! 196: ! 197: -(STR)executableName ! 198: { ! 199: return name; ! 200: } ! 201: ! 202: -(long)mtime ! 203: { ! 204: return images[0].mtime; ! 205: } ! 206: ! 207: -free ! 208: { ! 209: NXMapRemove(managers, name); ! 210: free(name); name = NULL; ! 211: return [super free]; ! 212: } ! 213: ! 214: -invalidate ! 215: { ! 216: int count; ! 217: Image *image; ! 218: ! 219: if (images) { ! 220: for (count = numImages, image = images; count; count--, image++) { ! 221: if (image->deallocate) ! 222: vm_deallocate(task_self(), ! 223: (vm_address_t)image->header, ! 224: image->size); ! 225: } ! 226: free(images); images = NULL; ! 227: numImages = 0; ! 228: } ! 229: return [super invalidate]; ! 230: } ! 231: ! 232: -(void)getImages ! 233: { ! 234: struct stat imageStat; ! 235: struct load_command *loadCmd; ! 236: struct fvmlib_command *fvmCmd; ! 237: struct mach_header *header; ! 238: int i; ! 239: Image *image; ! 240: numImages = 0; ! 241: if (imageFd < 0) ! 242: imageFd = open(name, O_RDONLY, 0); ! 243: if (imageFd >= 0) { ! 244: fstat(imageFd, &imageStat); ! 245: if (map_fd(imageFd, ! 246: 0, ! 247: (vm_address_t *)&header, ! 248: YES, ! 249: imageStat.st_size) == 0) { ! 250: // printf("Map_fp successfull.\n"); ! 251: header = [self headerFromStart: header]; ! 252: if (header) { ! 253: // printf("Got header.\n"); ! 254: numImages = 1; ! 255: if (skipShlibs) { ! 256: images = malloc(sizeof(Image)); ! 257: images->name = name; ! 258: images->header = header; ! 259: images->size = imageStat.st_size; ! 260: images->deallocate = YES; ! 261: images->mtime = imageStat.st_mtime; ! 262: } else { ! 263: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 264: i < header->ncmds; ! 265: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 266: if (loadCmd->cmd == LC_LOADFVMLIB) ! 267: numImages++; ! 268: } ! 269: image ! 270: = images ! 271: = calloc(numImages, sizeof(Image)); ! 272: image->name = name; ! 273: image->header = header; ! 274: image->size = imageStat.st_size; ! 275: image->deallocate = YES; ! 276: image->mtime = imageStat.st_mtime; ! 277: image++; ! 278: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 279: i < header->ncmds; ! 280: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 281: int shlibFd; ! 282: if (loadCmd->cmd == LC_LOADFVMLIB) { ! 283: fvmCmd = (struct fvmlib_command *)loadCmd; ! 284: image->name ! 285: = (void *)fvmCmd + fvmCmd->fvmlib.name.offset; ! 286: shlibFd = open(image->name, O_RDONLY, 0); ! 287: if (shlibFd >= 0) { ! 288: fstat(shlibFd, &imageStat); ! 289: image->size = imageStat.st_size; ! 290: image->mtime = imageStat.st_mtime; ! 291: if (map_fd(shlibFd, ! 292: 0, ! 293: (vm_address_t *)&image->header, ! 294: YES, ! 295: image->size) ! 296: == 0) { ! 297: image->header ! 298: = [self headerFromStart: image->header]; ! 299: image->deallocate = YES; ! 300: image++; ! 301: } else ! 302: numImages--; ! 303: close(shlibFd); ! 304: } else ! 305: numImages--; ! 306: } ! 307: } ! 308: } ! 309: } else { ! 310: return; ! 311: } ! 312: } else { ! 313: extern int errno; ! 314: // printf("Map_fd failed, errno = %d.\n", errno); ! 315: } ! 316: close(imageFd); ! 317: imageFd = -1; ! 318: } ! 319: } ! 320: ! 321: -(int)numSegments ! 322: { ! 323: int count, numSegs = 0, i; ! 324: Image *image; ! 325: struct load_command *loadCmd; ! 326: struct mach_header *header; ! 327: for (count = numImages, ! 328: image = images; ! 329: count; ! 330: count--, image++) { ! 331: header = image->header; ! 332: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 333: i < header->ncmds; ! 334: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 335: if (loadCmd->cmd == LC_SEGMENT) ! 336: numSegs++; ! 337: } ! 338: } ! 339: return numSegs; ! 340: } ! 341: ! 342: -(BOOL)validate ! 343: { ! 344: int nImages, i; ! 345: Image *image; ! 346: struct mach_header *header; ! 347: struct load_command *loadCmd; ! 348: struct segment_command *segCmd; ! 349: BOOL allOK = YES; ! 350: for (nImages = numImages, ! 351: image = images; ! 352: allOK && nImages; ! 353: nImages--, image++) { ! 354: header = image->header; ! 355: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 356: allOK && i < header->ncmds; ! 357: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 358: if (loadCmd->cmd == LC_SEGMENT) { ! 359: segCmd = (struct segment_command *)loadCmd; ! 360: if ((segCmd->fileoff + segCmd->vmsize) > image->size) ! 361: allOK = NO; ! 362: } ! 363: if (!loadCmd->cmdsize) ! 364: allOK = NO; ! 365: } ! 366: } ! 367: return allOK; ! 368: } ! 369: ! 370: -(void)readInSegments ! 371: { ! 372: int nImages, i; ! 373: Image *image; ! 374: struct mach_header *header; ! 375: struct load_command *loadCmd; ! 376: struct segment_command *segCmd; ! 377: Segment *segment = relocs; ! 378: for (nImages = numImages, ! 379: image = images; ! 380: nImages; ! 381: nImages--, image++) { ! 382: header = image->header; ! 383: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 384: i < header->ncmds; ! 385: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 386: if (loadCmd->cmd == LC_SEGMENT) { ! 387: segCmd = (struct segment_command *)loadCmd; ! 388: segment->address = segCmd->vmaddr; ! 389: segment->size = segCmd->vmsize; ! 390: segment->data = (vm_address_t)header + segCmd->fileoff; ! 391: segment->maxAddress = segment->address + segment->size; ! 392: segment->displacement = segment->data - segment->address; ! 393: segment->maxData = segment->data + segment->size; ! 394: segment->segName = segCmd->segname; ! 395: segment->rFlags.readIn = YES; ! 396: ((void *)segment) += relocSize; ! 397: } ! 398: } ! 399: } ! 400: } ! 401: ! 402: -(void)_readInAllRelocs ! 403: { ! 404: numRelocs = [self numSegments]; ! 405: relocs = calloc(numRelocs, relocSize); ! 406: [self readInSegments]; ! 407: rmFlags.invalid = NO; ! 408: } ! 409: ! 410: -(struct mach_header *)getMachHeader ! 411: { ! 412: if (numImages) ! 413: return images[0].header; ! 414: else ! 415: return NULL; ! 416: } ! 417: ! 418: -(int)getNumMachHeaders ! 419: { ! 420: return numImages; ! 421: } ! 422: ! 423: -(struct mach_header **)getMachHeaders ! 424: { ! 425: struct mach_header **headers; ! 426: int headerIndex; ! 427: headers = malloc((numImages + 1) * sizeof(*headers)); ! 428: for (headerIndex = 0; headerIndex < numImages; headerIndex++) ! 429: headers[headerIndex] = images[headerIndex].header; ! 430: headers[numImages] = NULL; ! 431: return headers; ! 432: } ! 433: ! 434: -(struct mach_header **)getMachHeadersWithNames: (char ***)names ! 435: { ! 436: struct mach_header **headers; ! 437: char **theNames; ! 438: int headerIndex; ! 439: headers = malloc((numImages + 1) * sizeof(*headers)); ! 440: *names = theNames = malloc((numImages + 1) * sizeof(*theNames)); ! 441: for (headerIndex = 0; headerIndex < numImages; headerIndex++) { ! 442: headers[headerIndex] = images[headerIndex].header; ! 443: theNames[headerIndex] = images[headerIndex].name; ! 444: } ! 445: headers[numImages] = NULL; ! 446: theNames[numImages] = NULL; ! 447: return headers; ! 448: } ! 449: ! 450: -(struct load_command *)findLoadCommand: (unsigned long)command ! 451: forHeader: (struct mach_header *)header ! 452: { ! 453: int i; ! 454: struct load_command *loadCmd, *foundCmd = NULL; ! 455: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 456: i < header->ncmds && !foundCmd; ! 457: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 458: if (loadCmd->cmd == command) ! 459: foundCmd = loadCmd; ! 460: } ! 461: return foundCmd; ! 462: } ! 463: ! 464: -(int)numCommands: (unsigned long)command ! 465: forHeader: (struct mach_header *)header ! 466: { ! 467: int i, nCommands = 0; ! 468: struct load_command *loadCmd; ! 469: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 470: i < header->ncmds; ! 471: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 472: if (loadCmd->cmd == command) ! 473: nCommands++; ! 474: } ! 475: return nCommands; ! 476: } ! 477: ! 478: -(struct symtab_command *)symCmd ! 479: { ! 480: return (struct symtab_command *) ! 481: [self findLoadCommand: LC_SYMTAB ! 482: forHeader: images[0].header]; ! 483: } ! 484: ! 485: -(char *)stringTable ! 486: { ! 487: struct symtab_command *symCmd = [self symCmd]; ! 488: return (char *)(images[0].header) + symCmd->stroff; ! 489: } ! 490: ! 491: -(BOOL)isCore ! 492: { ! 493: return images && images[0].header->filetype == MH_CORE; ! 494: } ! 495: ! 496: -(BOOL)isShlib ! 497: { ! 498: return images && images[0].header->filetype == MH_FVMLIB; ! 499: } ! 500: ! 501: -(BOOL)isExecutable ! 502: { ! 503: BOOL ret = images && ((images[0].header->filetype == MH_EXECUTE) ! 504: || (images[0].header->filetype == MH_OBJECT) ! 505: || (images[0].header->filetype == MH_PRELOAD)); ! 506: // if (ret) ! 507: // printf("Is executable.\n"); ! 508: // else ! 509: // printf("Isn't executable.\n"); ! 510: return ret; ! 511: } ! 512: ! 513: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.