This is RelocManager.m in view mode; [Download] [Up]
#import "RelocManager.h" #import <stdlib.h> #import <string.h> #import <mach-o/loader.h> #import <libc.h> int slideWarpM = 0; @implementation RelocManager -init { rmFlags.invalid = YES; rmFlags.shouldSortRelocs = YES; return self; } -free { [self invalidate]; return [super free]; } int compareRelocsSort(const void *v1, const void *v2) { const Reloc *r1 = v1, *r2 = v2; pointer_t a1 = r1->address, a2 = r2->address; return a1 < a2 ? -1 : (a1 == a2 ? 0 : 1); } int compareRelocsSearch(const void *v1, const void *v2) { const Reloc *r1 = v1, *r2 = v2; pointer_t address = r1->address; return address < r2->address ? -1 : (address >= r2->maxAddress ? 1 : 0); } -(Reloc *)relocFor: (const void *)pointer { Reloc *reloc; int count; BOOL found, tooFar; if (rmFlags.invalid) [self readInAllRelocs]; if (lastReloc && (lastReloc->address <= (pointer_t)pointer) && ((pointer_t)pointer < (lastReloc->maxAddress))) return lastReloc; else { #if 1 Reloc keyReloc; keyReloc.address = (pointer_t)pointer; if (reloc = bsearch(&keyReloc, relocs, numRelocs, relocSize, compareRelocsSearch)) found = YES; else found = NO; #else reloc = relocs; for (count = numRelocs, found = NO, tooFar = NO; count && !found && !tooFar; count--) { if ((pointer_t)pointer < (reloc->maxAddress)) { if (reloc->address <= (pointer_t)pointer) found = YES; else tooFar = YES; } else ((void *)reloc) += relocSize; } #endif if (found && (reloc->rFlags.readIn || [self readInReloc: reloc])) { lastReloc = reloc; return reloc; } else return NULL; } } -(BOOL)readInReloc: (Reloc *)reloc { [self subclassResponsibility: _cmd]; return NO; } -(void)_readInAllRelocs { [self subclassResponsibility: _cmd]; } -(void)readInAllRelocs { [self _readInAllRelocs]; if (rmFlags.shouldSortRelocs) qsort(relocs, numRelocs, relocSize, compareRelocsSort); } -invalidate { if (rmFlags.invalid) return self; else { if (relocs) { free(relocs); relocs = NULL; } numRelocs = 0; lastReloc = NULL; rmFlags.invalid = YES; return self; } } -(Reloc *)oldRelocFor: (const void *)pointer { int count; BOOL found; Reloc *reloc; if (lastReloc && (lastReloc->data <= (pointer_t)pointer) && ((pointer_t)pointer < lastReloc->maxData)) return lastReloc; else { reloc = relocs; for (count = numRelocs, found = NO; count && !found; count--) { if (reloc->rFlags.readIn && (reloc->data <= (pointer_t)pointer) && ((pointer_t)pointer < reloc->maxData)) found = YES; else ((void *)reloc) += relocSize; } if (found) { lastReloc = reloc; return reloc; } else return NULL; } } -(void *)originalPointerFor: (const void *)pointer { Reloc *reloc = [self oldRelocFor: pointer]; if (reloc) return (void *)(reloc->address + (pointer - reloc->data)); else return NULL; } -(void *)pointerFor: (const void *)pointer { Reloc *reloc; if (pointer && (reloc = [self relocFor: pointer])) return (void *)((pointer_t)pointer + reloc->displacement); else return NULL; } -(char *)pointerForString: (const char *)pointer isNullTerminated: (BOOL *)isNT { char *retPointer; Reloc *reloc; char *string; if (pointer && (reloc = [self relocFor: pointer])) { retPointer = (char *)((pointer_t)pointer + reloc->displacement); for (string = retPointer; *string && ((pointer_t)string < reloc->maxData); string++); *isNT = *string ? NO : YES; return retPointer; } else{ *isNT = NO; return NULL; } } -(char *)pointerForString: (const char *)string { BOOL isNT; char *retPointer; if ((retPointer = [self pointerForString: string isNullTerminated: &isNT]) && isNT) return retPointer; else return NULL; } -(void *)pointerFor: (const void *)pointer withSize: (int)size { Reloc *reloc; pointer_t newPointer; if (pointer && (reloc = [self relocFor: pointer])) { newPointer = (pointer_t)pointer + reloc->displacement; if ((newPointer + size) <= reloc->maxData) return (void *)newPointer; else return NULL; } else return NULL; } -pointerForID: (const id)pointer { Class theClass; struct _ObjectID { @defs(Object) } *newID; if (pointer && (newID = [self pointerFor: pointer withSize: sizeof(id)]) && (theClass = [self pointerFor: newID->isa withSize: sizeof(Class)]) && (newID = [self pointerFor: pointer withSize: theClass->instance_size])) return (id)newID; else return nil; } -(int)getDataAt: (const void *)start for: (int)numBytes into: (void *)data { Reloc *reloc = [self relocFor: start]; int numBytesInReloc; if (reloc) { numBytesInReloc = reloc->maxAddress - (int)start; if (numBytes > numBytesInReloc) numBytes = numBytesInReloc; memcpy(data, (void *)(reloc->data + ((pointer_t)start - reloc->address)), numBytes); return numBytes; } else return 0; } -(struct mach_header *)getMachHeader { [self subclassResponsibility: _cmd]; return NULL; } -(unsigned)getSlide { [self subclassResponsibility: _cmd]; return 0; } -(int)getNumMachHeaders { [self subclassResponsibility: _cmd]; return 0; } -(struct mach_header **)getMachHeaders { [self subclassResponsibility: _cmd]; return NULL; } -(unsigned*)getSlides { [self subclassResponsibility: _cmd]; return NULL; } -(struct mach_header **)getMachHeadersWithNames: (char ***)names { [self subclassResponsibility: _cmd]; return NULL; } -(unsigned*)getSlidesWithNames: (char ***)names { [self subclassResponsibility: _cmd]; return NULL; } -(void *)getSectData: (STR)segName section: (STR)sectName size: (int *)pSize forHeader: (struct mach_header *)header withSlide: (unsigned)slide { void *data = getsectdatafromheader(header, segName, sectName, pSize); return [self pointerFor: (void*) ((char*) data + slide) withSize: *pSize]; } -(void *)getSectData: (STR)segName section: (STR)sectName size: (int *)pSize { return [self getSectData: segName section: sectName size: pSize forHeader: [self getMachHeader] withSlide: [self getSlide]]; } -(const struct section *)getSeg: (STR)segName sect: (STR)sectName { return getsectbynamefromheader([self getMachHeader], segName, sectName); } -(const struct section *)firstSection { struct mach_header *header = [self getMachHeader]; int i; struct load_command *loadCmd; for (i = 0, loadCmd = (struct load_command *)(header + 1); i < header->ncmds; i++, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_SEGMENT) { struct segment_command *segCmd = (struct segment_command *)loadCmd; if (segCmd->nsects) return (struct section *)(segCmd + 1); } } return NULL; } -(unsigned)getMaximumAddressForHeader: (struct mach_header *)header withSlide:(unsigned)slide { int i; struct load_command *loadCmd; unsigned maxAddr = 0; for (i = 0, loadCmd = (struct load_command *)(header + 1); i < header->ncmds; i++, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_SEGMENT) { struct segment_command *segCmd = (struct segment_command *)loadCmd; if ((segCmd->vmaddr + segCmd->vmsize + slide) > maxAddr) maxAddr = segCmd->vmaddr + segCmd->vmsize; } } return maxAddr; } -(struct segment_command *)getSegment: (const char *)segName { int i; struct load_command *loadCmd; struct segment_command *foundSeg = NULL; struct mach_header *header = [self getMachHeader]; for (i = 0, loadCmd = (struct load_command *)(header + 1); i < header->ncmds && !foundSeg; i++, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_SEGMENT) { struct segment_command *segCmd = (struct segment_command *)loadCmd; if (strcmp(segName, segCmd->segname) == 0) foundSeg = segCmd; } } return foundSeg; } -(unsigned)getMaximumAddressForSegment: (const char *)segName { int i; struct load_command *loadCmd; unsigned maxAddr = 0; struct mach_header *header = [self getMachHeader]; unsigned int slide = [self getSlide]; for (i = 0, loadCmd = (struct load_command *)(header + 1); i < header->ncmds; i++, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_SEGMENT) { struct segment_command *segCmd = (struct segment_command *)loadCmd; struct section *section; int nSects; for (nSects = segCmd->nsects, section = (struct section *)(segCmd + 1); nSects; nSects--, section++) { if (strcmp(section->segname, segName) == 0) { if ((section->addr + section->size + slide) > maxAddr) maxAddr = (section->addr + section->size + slide); } } } } return maxAddr; } -(unsigned)getMaximumAddress { return [self getMaximumAddressForHeader: [self getMachHeader] withSlide: [self getSlide]]; } -(unsigned)getMinimumAddressForSegment: (const char*)segName { int i; struct load_command *loadCmd; unsigned minAddr = 0xffffffffU; struct mach_header *header = [self getMachHeader]; unsigned int slide = [self getSlide]; for (i = 0, loadCmd = (struct load_command *)(header + 1); i < header->ncmds; i++, ((void *)loadCmd) += loadCmd->cmdsize) { if (loadCmd->cmd == LC_SEGMENT) { struct segment_command *segCmd = (struct segment_command *)loadCmd; struct section *section; int nSects; for (nSects = segCmd->nsects, section = (struct section *)(segCmd + 1); nSects; nSects--, section++) { if (strcmp(section->segname, segName) == 0) { if ((section->addr + slide) < minAddr) minAddr = (section->addr + slide); } } } } return minAddr; } -(unsigned)getMaximumTextAddress { return [self getMaximumAddressForSegment: "__TEXT"]; } -(unsigned)getMaximumDataAddress { return [self getMaximumAddressForSegment: "__DATA"]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.