|
|
1.1 ! root 1: #import "LazyRegionManager.h" ! 2: ! 3: #import <string.h> ! 4: ! 5: #define VM_PROT_VOLATILE ((vm_prot_t) 0x08) // not cacheable ! 6: #define VM_PROT_SPARSE ((vm_prot_t) 0x10) // sparse addr space ! 7: ! 8: @implementation LazyRegionManager ! 9: ! 10: -(BOOL)readInReloc: (Reloc *)reloc ! 11: { ! 12: kern_return_t ret; ! 13: ! 14: if (!reloc->rFlags.readIn) { ! 15: ret = vm_allocate(task_self(), &reloc->data, reloc->size, YES); ! 16: if (ret == KERN_SUCCESS) { ! 17: reloc->maxData = reloc->data + reloc->size; ! 18: reloc->displacement = reloc->data - reloc->address; ! 19: reloc->rFlags.readIn = YES; ! 20: } ! 21: } ! 22: return reloc->rFlags.readIn ? YES : NO; ! 23: } ! 24: ! 25: -(int)pageFor: (const void *)pointer inRegion: (Region *)region ! 26: { ! 27: return (((unsigned int)pointer - region->reloc.address) / pageSize); ! 28: } ! 29: ! 30: -(BOOL)readInDataFor: (const void *)pointer into: (void *)data withSize: (int)size ! 31: { ! 32: unsigned int error = 0, nData; ! 33: pointer_t readPage; ! 34: ! 35: error = vm_read(task, (vm_address_t)pointer, size, &readPage, &nData); ! 36: if (!error) { ! 37: bcopy((void *)readPage, data, size); ! 38: vm_deallocate(task_self(), readPage, nData); ! 39: } else ! 40: [self isTask]; ! 41: return error ? NO : YES; ! 42: } ! 43: ! 44: -(BOOL)readInPage: (unsigned char *)page ! 45: for: (void *)pointer ! 46: into: (void *)data ! 47: { ! 48: unsigned int error = 0, nData; ! 49: pointer_t readPage; ! 50: ! 51: if (!(*page & PAGEREADIN)) { ! 52: // printf("Reading in page at %p.\n", pointer); ! 53: error = vm_read(task, (vm_address_t)pointer, pageSize, &readPage, ! 54: &nData); ! 55: if (!error) { ! 56: bcopy((void *)readPage, data, pageSize); ! 57: vm_deallocate(task_self(), readPage, nData); ! 58: if (!(*page & VM_PROT_VOLATILE)) ! 59: *page |= PAGEREADIN; ! 60: } else ! 61: [self isTask]; ! 62: } ! 63: return error ? NO : YES; ! 64: } ! 65: ! 66: -(BOOL)readInPagesFor: (const void *)pointer withSize: (int)size inRegion: (Region *)region ! 67: { ! 68: int nPage, offset; ! 69: unsigned char *page, *endPage; ! 70: void *data, *address; ! 71: int ok = YES; ! 72: ! 73: // printf("Getting data at: %p for %d bytes.\n", pointer, size); ! 74: ! 75: nPage = [self pageFor: pointer inRegion: region]; ! 76: offset = nPage * pageSize; ! 77: page = region->pages + nPage; ! 78: if (*page & VM_PROT_SPARSE) ! 79: ok = [self readInDataFor: pointer ! 80: into: (void *)pointer + region->reloc.displacement ! 81: withSize: size]; ! 82: else { ! 83: endPage = region->pages ! 84: + [self pageFor: pointer + size inRegion: region]; ! 85: data = (void *)(region->reloc.data + offset); ! 86: address = (void *)(region->reloc.address + offset); ! 87: while (ok && page <= endPage) { ! 88: ok = [self readInPage: page for: address into: data]; ! 89: address += pageSize; ! 90: data += pageSize; ! 91: page++; ! 92: } ! 93: } ! 94: return ok; ! 95: } ! 96: ! 97: -(void *)pointerFor: (const void *)pointer withSize: (int)size ! 98: { ! 99: Region *region; ! 100: pointer_t newPointer; ! 101: if (pointer && (region = (Region *)[self relocFor: pointer])) { ! 102: newPointer = (pointer_t)pointer + region->reloc.displacement; ! 103: if (((newPointer + size) <= region->reloc.maxData) ! 104: && [self readInPagesFor: pointer withSize: size inRegion: region]) ! 105: return (void *)newPointer; ! 106: else ! 107: return NULL; ! 108: } else ! 109: return NULL; ! 110: } ! 111: ! 112: -(int)getDataAt: (const void *)start for: (int)numBytes into: (void *)data ! 113: { ! 114: Reloc *reloc = [self relocFor: start]; ! 115: int numBytesInRegion; ! 116: ! 117: // printf("Getting data at: %p for %d bytes.\n", start, numBytes); ! 118: ! 119: if (reloc) { ! 120: numBytesInRegion = reloc->maxAddress - (int)start; ! 121: if (numBytes > numBytesInRegion) ! 122: numBytes = numBytesInRegion; ! 123: if ([self readInPagesFor: start ! 124: withSize: numBytes ! 125: inRegion: (Region *)reloc]) { ! 126: memcpy(data, ! 127: (void *)(reloc->data ! 128: + ((pointer_t)start - reloc->address)), ! 129: numBytes); ! 130: return numBytes; ! 131: } else ! 132: return 0; ! 133: } else ! 134: return 0; ! 135: } ! 136: ! 137: -(int)putDataAt: (void *)start for: (int)numBytes from: (const void *)data ! 138: { ! 139: int numBytesInRegion; ! 140: Reloc *reloc = [self relocFor: start]; ! 141: ! 142: // printf("Putting data at: %p for %d bytes.\n", start, numBytes); ! 143: ! 144: if (reloc) { ! 145: numBytesInRegion = reloc->maxAddress - (int)start; ! 146: if (numBytes > numBytesInRegion) ! 147: numBytes = numBytesInRegion; ! 148: if ([self readInPagesFor: start ! 149: withSize: numBytes ! 150: inRegion: (Region *)reloc]) { ! 151: memcpy((void *)(reloc->data + ((pointer_t)start - reloc->address)), ! 152: data, ! 153: numBytes); ! 154: return [self writeDataAt: start for: numBytes ! 155: reloc: (Region *)reloc]; ! 156: } else ! 157: return 0; ! 158: } else ! 159: return 0; ! 160: } ! 161: ! 162: -(char *)pointerForString: (const char *)pointer isNullTerminated: (BOOL *)isNT ! 163: { ! 164: char *retPointer; ! 165: Region *region; ! 166: char *string; ! 167: int nPage, offset; ! 168: unsigned char *page; ! 169: void *data, *address; ! 170: BOOL ok; ! 171: ! 172: if (pointer && (region = (Region *)[self relocFor: pointer])) { ! 173: retPointer = (char *)((pointer_t)pointer + region->reloc.displacement); ! 174: nPage = [self pageFor: pointer inRegion: region]; ! 175: page = region->pages + nPage; ! 176: offset = nPage * pageSize; ! 177: data = (void *)(region->reloc.data + offset); ! 178: address = (void *)(region->reloc.address + offset); ! 179: string = retPointer; ! 180: do { ! 181: ok = [self readInPage: page for: address into: data]; ! 182: if (ok) { ! 183: page++; ! 184: address += pageSize; ! 185: data += pageSize; ! 186: while (*string && (string < (char *)data)) ! 187: string++; ! 188: } ! 189: } while (ok && *string && (data < (void *)region->reloc.maxData)); ! 190: *isNT = *string ? NO : YES; ! 191: return retPointer; ! 192: } else{ ! 193: *isNT = NO; ! 194: return NULL; ! 195: } ! 196: } ! 197: ! 198: -(int)writeDataAt: (const void *)start for: (int)numBytes reloc: (Region *)region ! 199: { ! 200: char *page = pages + [self pageFor: start inRegion: region]; ! 201: kern_return_t ret; ! 202: ! 203: if (*page & VM_PROT_SPARSE) { ! 204: ret = vm_write(task, ! 205: (vm_address_t)start, ! 206: (pointer_t)(start + region->reloc.displacement), ! 207: numBytes); ! 208: if (ret == KERN_SUCCESS) ! 209: return numBytes; ! 210: else { ! 211: [self isTask]; ! 212: return 0; ! 213: } ! 214: } else ! 215: return [super writeDataAt: start for: numBytes reloc: region]; ! 216: } ! 217: ! 218: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.