|
|
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.