|
|
1.1 ! root 1: #import "RelocManager.h" ! 2: #import <stdlib.h> ! 3: #import <string.h> ! 4: #import <mach-o/loader.h> ! 5: #import <libc.h> ! 6: ! 7: @implementation RelocManager ! 8: ! 9: -init ! 10: { ! 11: rmFlags.invalid = YES; ! 12: rmFlags.shouldSortRelocs = YES; ! 13: return self; ! 14: } ! 15: ! 16: -free ! 17: { ! 18: [self invalidate]; ! 19: return [super free]; ! 20: } ! 21: ! 22: int compareRelocsSort(const void *v1, const void *v2) ! 23: { ! 24: const Reloc *r1 = v1, *r2 = v2; ! 25: pointer_t a1 = r1->address, a2 = r2->address; ! 26: return a1 < a2 ? -1 : (a1 == a2 ? 0 : 1); ! 27: } ! 28: ! 29: int compareRelocsSearch(const void *v1, const void *v2) ! 30: { ! 31: const Reloc *r1 = v1, *r2 = v2; ! 32: pointer_t address = r1->address; ! 33: return address < r2->address ? -1 : (address >= r2->maxAddress ? 1 : 0); ! 34: } ! 35: ! 36: -(Reloc *)relocFor: (const void *)pointer ! 37: { ! 38: Reloc *reloc; ! 39: int count; ! 40: BOOL found, tooFar; ! 41: if (rmFlags.invalid) ! 42: [self readInAllRelocs]; ! 43: if (lastReloc ! 44: && (lastReloc->address <= (pointer_t)pointer) ! 45: && ((pointer_t)pointer < (lastReloc->maxAddress))) ! 46: return lastReloc; ! 47: else { ! 48: #if 1 ! 49: Reloc keyReloc; ! 50: keyReloc.address = (pointer_t)pointer; ! 51: if (reloc = bsearch(&keyReloc, relocs, numRelocs, relocSize, compareRelocsSearch)) ! 52: found = YES; ! 53: else ! 54: found = NO; ! 55: #else ! 56: reloc = relocs; ! 57: for (count = numRelocs, found = NO, tooFar = NO; ! 58: count && !found && !tooFar; count--) { ! 59: if ((pointer_t)pointer < (reloc->maxAddress)) { ! 60: if (reloc->address <= (pointer_t)pointer) ! 61: found = YES; ! 62: else ! 63: tooFar = YES; ! 64: } else ! 65: ((void *)reloc) += relocSize; ! 66: } ! 67: #endif ! 68: if (found && (reloc->rFlags.readIn || [self readInReloc: reloc])) { ! 69: lastReloc = reloc; ! 70: return reloc; ! 71: } else ! 72: return NULL; ! 73: } ! 74: } ! 75: ! 76: -(BOOL)readInReloc: (Reloc *)reloc ! 77: { ! 78: [self subclassResponsibility: _cmd]; ! 79: return NO; ! 80: } ! 81: ! 82: -(void)_readInAllRelocs ! 83: { ! 84: [self subclassResponsibility: _cmd]; ! 85: } ! 86: ! 87: -(void)readInAllRelocs ! 88: { ! 89: [self _readInAllRelocs]; ! 90: if (rmFlags.shouldSortRelocs) ! 91: qsort(relocs, numRelocs, relocSize, compareRelocsSort); ! 92: } ! 93: ! 94: -invalidate ! 95: { ! 96: if (rmFlags.invalid) ! 97: return self; ! 98: else { ! 99: if (relocs) { ! 100: free(relocs); relocs = NULL; ! 101: } ! 102: numRelocs = 0; ! 103: lastReloc = NULL; ! 104: rmFlags.invalid = YES; ! 105: return self; ! 106: } ! 107: } ! 108: ! 109: -(Reloc *)oldRelocFor: (const void *)pointer ! 110: { ! 111: int count; ! 112: BOOL found; ! 113: Reloc *reloc; ! 114: if (lastReloc ! 115: && (lastReloc->data <= (pointer_t)pointer) ! 116: && ((pointer_t)pointer < lastReloc->maxData)) ! 117: return lastReloc; ! 118: else { ! 119: reloc = relocs; ! 120: for (count = numRelocs, found = NO; count && !found; count--) { ! 121: if (reloc->rFlags.readIn && (reloc->data <= (pointer_t)pointer) ! 122: && ((pointer_t)pointer < reloc->maxData)) ! 123: found = YES; ! 124: else ! 125: ((void *)reloc) += relocSize; ! 126: } ! 127: if (found) { ! 128: lastReloc = reloc; ! 129: return reloc; ! 130: } else ! 131: return NULL; ! 132: } ! 133: } ! 134: ! 135: -(void *)originalPointerFor: (const void *)pointer ! 136: { ! 137: Reloc *reloc = [self oldRelocFor: pointer]; ! 138: if (reloc) ! 139: return (void *)(reloc->address + (pointer - reloc->data)); ! 140: else ! 141: return NULL; ! 142: } ! 143: ! 144: -(void *)pointerFor: (const void *)pointer ! 145: { ! 146: Reloc *reloc; ! 147: if (pointer && (reloc = [self relocFor: pointer])) ! 148: return (void *)((pointer_t)pointer + reloc->displacement); ! 149: else ! 150: return NULL; ! 151: } ! 152: ! 153: -(char *)pointerForString: (const char *)pointer isNullTerminated: (BOOL *)isNT ! 154: { ! 155: char *retPointer; ! 156: Reloc *reloc; ! 157: char *string; ! 158: if (pointer && (reloc = [self relocFor: pointer])) { ! 159: retPointer = (char *)((pointer_t)pointer + reloc->displacement); ! 160: for (string = retPointer; ! 161: *string && ((pointer_t)string < reloc->maxData); ! 162: string++); ! 163: *isNT = *string ? NO : YES; ! 164: return retPointer; ! 165: } else{ ! 166: *isNT = NO; ! 167: return NULL; ! 168: } ! 169: } ! 170: ! 171: -(char *)pointerForString: (const char *)string ! 172: { ! 173: BOOL isNT; ! 174: char *retPointer; ! 175: if ((retPointer = [self pointerForString: string isNullTerminated: &isNT]) ! 176: && isNT) ! 177: return retPointer; ! 178: else ! 179: return NULL; ! 180: } ! 181: ! 182: -(void *)pointerFor: (const void *)pointer withSize: (int)size ! 183: { ! 184: Reloc *reloc; ! 185: pointer_t newPointer; ! 186: if (pointer && (reloc = [self relocFor: pointer])) { ! 187: newPointer = (pointer_t)pointer + reloc->displacement; ! 188: if ((newPointer + size) <= reloc->maxData) ! 189: return (void *)newPointer; ! 190: else ! 191: return NULL; ! 192: } else ! 193: return NULL; ! 194: } ! 195: ! 196: -(id)pointerForID: (const id)pointer ! 197: { ! 198: Class theClass; ! 199: struct _ObjectID { ! 200: @defs(Object) ! 201: } *newID; ! 202: ! 203: if (pointer ! 204: && (newID = [self pointerFor: pointer withSize: sizeof(id)]) ! 205: && (theClass = [self pointerFor: newID->isa ! 206: withSize: sizeof(Class)]) ! 207: && (newID ! 208: = [self pointerFor: pointer withSize: theClass->instance_size])) ! 209: return (id)newID; ! 210: else ! 211: return nil; ! 212: } ! 213: ! 214: -(int)getDataAt: (const void *)start for: (int)numBytes into: (void *)data ! 215: { ! 216: Reloc *reloc = [self relocFor: start]; ! 217: int numBytesInReloc; ! 218: ! 219: if (reloc) { ! 220: numBytesInReloc = reloc->maxAddress - (int)start; ! 221: if (numBytes > numBytesInReloc) ! 222: numBytes = numBytesInReloc; ! 223: memcpy(data, ! 224: (void *)(reloc->data + ((pointer_t)start - reloc->address)), ! 225: numBytes); ! 226: return numBytes; ! 227: } else ! 228: return 0; ! 229: } ! 230: ! 231: -(struct mach_header *)getMachHeader ! 232: { ! 233: [self subclassResponsibility: _cmd]; ! 234: return NULL; ! 235: } ! 236: ! 237: -(int)getNumMachHeaders ! 238: { ! 239: [self subclassResponsibility: _cmd]; ! 240: return 0; ! 241: } ! 242: ! 243: -(struct mach_header **)getMachHeaders ! 244: { ! 245: [self subclassResponsibility: _cmd]; ! 246: return NULL; ! 247: } ! 248: ! 249: -(struct mach_header **)getMachHeadersWithNames: (char ***)names ! 250: { ! 251: [self subclassResponsibility: _cmd]; ! 252: return NULL; ! 253: } ! 254: ! 255: -(void *)getSectData: (STR)segName ! 256: section: (STR)sectName ! 257: size: (int *)pSize ! 258: forHeader: (struct mach_header *)header ! 259: { ! 260: void *data = getsectdatafromheader(header, segName, sectName, pSize); ! 261: return [self pointerFor: data withSize: *pSize]; ! 262: } ! 263: ! 264: -(void *)getSectData: (STR)segName ! 265: section: (STR)sectName ! 266: size: (int *)pSize ! 267: { ! 268: return [self getSectData: segName ! 269: section: sectName ! 270: size: pSize ! 271: forHeader: [self getMachHeader]]; ! 272: } ! 273: ! 274: -(const struct section *)getSeg: (STR)segName sect: (STR)sectName ! 275: { ! 276: return getsectbynamefromheader([self getMachHeader], segName, sectName); ! 277: } ! 278: ! 279: -(const struct section *)firstSection ! 280: { ! 281: struct mach_header *header = [self getMachHeader]; ! 282: int i; ! 283: struct load_command *loadCmd; ! 284: ! 285: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 286: i < header->ncmds; ! 287: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 288: if (loadCmd->cmd == LC_SEGMENT) { ! 289: struct segment_command *segCmd = (struct segment_command *)loadCmd; ! 290: if (segCmd->nsects) ! 291: return (struct section *)(segCmd + 1); ! 292: } ! 293: } ! 294: return NULL; ! 295: } ! 296: ! 297: -(unsigned)getMaximumAddressForHeader: (struct mach_header *)header ! 298: { ! 299: int i; ! 300: struct load_command *loadCmd; ! 301: unsigned maxAddr = 0; ! 302: ! 303: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 304: i < header->ncmds; ! 305: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 306: if (loadCmd->cmd == LC_SEGMENT) { ! 307: struct segment_command *segCmd = (struct segment_command *)loadCmd; ! 308: if ((segCmd->vmaddr + segCmd->vmsize) > maxAddr) ! 309: maxAddr = segCmd->vmaddr + segCmd->vmsize; ! 310: } ! 311: } ! 312: return maxAddr; ! 313: } ! 314: ! 315: -(struct segment_command *)getSegment: (const char *)segName ! 316: { ! 317: int i; ! 318: struct load_command *loadCmd; ! 319: struct segment_command *foundSeg = NULL; ! 320: struct mach_header *header = [self getMachHeader]; ! 321: ! 322: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 323: i < header->ncmds && !foundSeg; ! 324: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 325: if (loadCmd->cmd == LC_SEGMENT) { ! 326: struct segment_command *segCmd = (struct segment_command *)loadCmd; ! 327: if (strcmp(segName, segCmd->segname) == 0) ! 328: foundSeg = segCmd; ! 329: } ! 330: } ! 331: return foundSeg; ! 332: } ! 333: ! 334: -(unsigned)getMaximumAddressForSegment: (const char *)segName ! 335: { ! 336: int i; ! 337: struct load_command *loadCmd; ! 338: unsigned maxAddr = 0; ! 339: struct mach_header *header = [self getMachHeader]; ! 340: ! 341: for (i = 0, loadCmd = (struct load_command *)(header + 1); ! 342: i < header->ncmds; ! 343: i++, ((void *)loadCmd) += loadCmd->cmdsize) { ! 344: if (loadCmd->cmd == LC_SEGMENT) { ! 345: struct segment_command *segCmd = (struct segment_command *)loadCmd; ! 346: struct section *section; ! 347: int nSects; ! 348: ! 349: for (nSects = segCmd->nsects, ! 350: section = (struct section *)(segCmd + 1); ! 351: nSects; ! 352: nSects--, section++) { ! 353: if (strcmp(section->segname, segName) == 0) { ! 354: if ((section->addr + section->size) > maxAddr) ! 355: maxAddr = (section->addr + section->size); ! 356: } ! 357: } ! 358: } ! 359: } ! 360: return maxAddr; ! 361: } ! 362: ! 363: -(unsigned)getMaximumAddress ! 364: { ! 365: return [self getMaximumAddressForHeader: [self getMachHeader]]; ! 366: } ! 367: ! 368: -(unsigned)getMaximumTextAddress ! 369: { ! 370: return [self getMaximumAddressForSegment: "__TEXT"]; ! 371: } ! 372: ! 373: -(unsigned)getMaximumDataAddress ! 374: { ! 375: return [self getMaximumAddressForSegment: "__DATA"]; ! 376: } ! 377: ! 378: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.