home *** CD-ROM | disk | FTP | other *** search
- #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;
- static BOOL retrying = NO;
-
- 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) return NULL;
-
- if (!reloc->rFlags.readIn) {
- if (![self readInReloc: reloc]) {
- /* If there was an error during a read of this reloc, it could be that
- * this reloc is just stale. Refresh the relocs and retry once.
- */
- if (!retrying) {
- retrying = YES;
- [self invalidate];
- reloc = [self relocFor:pointer];
- retrying = NO;
- }
- else
- reloc = NULL;
- }
- }
-
- if (reloc)
- lastReloc = reloc;
- return reloc;
- }
- }
-
- -(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
-