|
|
1.1 root 1: #import "SegmentManager.h"
2: #import <stdlib.h>
3: #import <string.h>
4: #import <mach-o/loader.h>
5: #import <sys/types.h>
6: #import <sys/stat.h>
7: #import <mach-o/ldsyms.h>
8: #import <libc.h>
9: #import <objc/maptable.h>
10: #import <mach-o/fat.h>
11:
12: #define REALLY_SWAP_LONG(a) ( ((a) << 24) | \
13: (((a) << 8) & 0x00ff0000) | \
14: (((a) >> 8) & 0x0000ff00) | \
15: ((unsigned long)(a) >> 24) )
16:
17: #define SWAP_LONG(a) (shouldSwap ? REALLY_SWAP_LONG(a) : (a))
18:
19: @implementation SegmentManager
20:
21: static NXMapTable *managers = NULL;
22:
23: +initialize
24: {
25: static BOOL beenHere = NO;
26:
27: if (!beenHere) {
28: beenHere = YES;
29: managers = NXCreateMapTable(NXStrValueMapPrototype, 0);
30: }
31: return self;
32: }
33:
34: -init
35: {
36: relocSize = sizeof(Segment);
37: rmFlags.shouldSortRelocs = YES;
38: [self readInAllRelocs];
39: lastReloc = NULL;
40: if (numRelocs) {
41: if (images[0].name)
42: NXMapInsert(managers, images[0].name, self);
43: return self;
44: } else {
45: [self free];
46: return nil;
47: }
48: }
49:
50: -(void)setCpuType: (cpu_type_t)type
51: {
52: static cpu_type_t defaultCpuType = 0;
53: if (type)
54: cpuType = type;
55: else {
56: if (!defaultCpuType) {
57: struct host_basic_info host_basic_info;
58: unsigned int count = HOST_BASIC_INFO_COUNT;
59:
60: if (host_info(host_self(), HOST_BASIC_INFO,
61: (host_info_t)(&host_basic_info),
62: &count) == KERN_SUCCESS)
63: defaultCpuType = host_basic_info.cpu_type;
64: }
65: cpuType = defaultCpuType;
66: }
67: }
68:
69: -initFile: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
70: {
71: SegmentManager *oldManager;
72: if (oldManager = NXMapGet(managers, theName)) {
73: close(desc);
74: [self free];
75: return oldManager;
76: } else {
77: name = malloc(strlen(theName) + 1);
78: strcpy(name, theName);
79: skipShlibs = shouldSkipShlibs;
80: imageFd = desc;
81: [self setCpuType: type];
82: [self getImages];
83: return [self init];
84: }
85: }
86:
87: static const char loadedName[] = "loaded file";
88:
89: -(struct mach_header *)headerFromStart: (void *)start
90: {
91: struct mach_header *header = start;
92: if (header->magic == MH_MAGIC && header->cputype == cpuType)
93: return header;
94: else {
95: struct fat_header *fatHeader = start;
96: if ((fatHeader->magic == FAT_MAGIC)
97: || (fatHeader->magic == REALLY_SWAP_LONG(FAT_MAGIC))) {
98: BOOL shouldSwap = !(fatHeader->magic == FAT_MAGIC);
99: unsigned int nArches;
100: struct fat_arch *fatArch, *foundArch;
101:
102: for (nArches = SWAP_LONG(fatHeader->nfat_arch),
103: fatArch = (struct fat_arch *)(fatHeader + 1),
104: foundArch = NULL;
105: nArches && !foundArch;
106: fatArch++, nArches--) {
107: if (cpuType == SWAP_LONG(fatArch->cputype))
108: foundArch = fatArch;
109: }
110: if (foundArch)
111: return start + SWAP_LONG(foundArch->offset);
112: else
113: return NULL;
114: } else
115: return NULL;
116: }
117: }
118:
119: -initHeader: (struct mach_header *)header withSize: (int)size
120: {
121: numImages = 1;
122: [self setCpuType: 0];
123: images = malloc(sizeof(*images));
124: images->header = [self headerFromStart: header];
125: images->size = size;
126: images->name = NULL;
127: images->mtime = 0;
128: name = malloc(sizeof(loadedName));
129: strcpy(name, loadedName);
130: return [self init];
131: }
132:
133: -initFile: (STR)theName
134: {
135: return [self initFile: theName skipShlibs: NO withDesc: -1 cpuType: 0];
136: }
137:
138: +newExecutable: (STR)theName skipShlibs: (BOOL)shouldSkipShlibs withDesc: (int)desc cpuType: (cpu_type_t)type
139: {
140: SegmentManager *sm = [[super alloc] initFile: (STR)theName
141: skipShlibs: shouldSkipShlibs
142: withDesc: desc
143: cpuType: type];
144: if (sm && [sm isExecutable])
145: return sm;
146: else {
147: [sm free];
148: return nil;
149: }
150: }
151:
152: +newExecutable: (STR)theName
153: {
154: return [self newExecutable: theName skipShlibs: NO withDesc: -1 cpuType: 0];
155: }
156:
157: +newCore: (STR)theName
158: {
159: SegmentManager *sm = [[super alloc] initFile: (STR)theName];
160: if (sm && [sm isCore])
161: return sm;
162: else {
163: [sm free];
164: return nil;
165: }
166: }
167:
168: +newFile: (STR)theName
169: {
170: return [[super alloc] initFile: (STR)theName];
171: }
172:
173: +newShlib: (STR)theName cpuType: (cpu_type_t)type
174: {
175: SegmentManager *sm = [[super alloc] initFile: (STR)theName
176: skipShlibs: YES
177: withDesc: -1
178: cpuType: type];
179: if (sm && [sm isShlib])
180: return sm;
181: else {
182: [sm free];
183: return nil;
184: }
185: }
186:
187: +newShlib: (STR)theName
188: {
189: return [self newShlib: theName cpuType: 0];
190: }
191:
192: +newHeader: (struct mach_header *)header withSize: (int)size
193: {
194: return [[super alloc] initHeader: header withSize: size];
195: }
196:
197: -(STR)executableName
198: {
199: return name;
200: }
201:
202: -(long)mtime
203: {
204: return images[0].mtime;
205: }
206:
207: -free
208: {
209: NXMapRemove(managers, name);
210: free(name); name = NULL;
211: return [super free];
212: }
213:
214: -invalidate
215: {
216: int count;
217: Image *image;
218:
219: if (images) {
220: for (count = numImages, image = images; count; count--, image++) {
221: if (image->deallocate)
222: vm_deallocate(task_self(),
223: (vm_address_t)image->header,
224: image->size);
225: }
226: free(images); images = NULL;
227: numImages = 0;
228: }
229: return [super invalidate];
230: }
231:
232: -(void)getImages
233: {
234: struct stat imageStat;
235: struct load_command *loadCmd;
236: struct fvmlib_command *fvmCmd;
237: struct mach_header *header;
238: int i;
239: Image *image;
240: numImages = 0;
241: if (imageFd < 0)
242: imageFd = open(name, O_RDONLY, 0);
243: if (imageFd >= 0) {
244: fstat(imageFd, &imageStat);
245: if (map_fd(imageFd,
246: 0,
247: (vm_address_t *)&header,
248: YES,
249: imageStat.st_size) == 0) {
250: // printf("Map_fp successfull.\n");
251: header = [self headerFromStart: header];
252: if (header) {
253: // printf("Got header.\n");
254: numImages = 1;
255: if (skipShlibs) {
256: images = malloc(sizeof(Image));
257: images->name = name;
258: images->header = header;
259: images->size = imageStat.st_size;
260: images->deallocate = YES;
261: images->mtime = imageStat.st_mtime;
262: } else {
263: for (i = 0, loadCmd = (struct load_command *)(header + 1);
264: i < header->ncmds;
265: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
266: if (loadCmd->cmd == LC_LOADFVMLIB)
267: numImages++;
268: }
269: image
270: = images
271: = calloc(numImages, sizeof(Image));
272: image->name = name;
273: image->header = header;
274: image->size = imageStat.st_size;
275: image->deallocate = YES;
276: image->mtime = imageStat.st_mtime;
277: image++;
278: for (i = 0, loadCmd = (struct load_command *)(header + 1);
279: i < header->ncmds;
280: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
281: int shlibFd;
282: if (loadCmd->cmd == LC_LOADFVMLIB) {
283: fvmCmd = (struct fvmlib_command *)loadCmd;
284: image->name
285: = (void *)fvmCmd + fvmCmd->fvmlib.name.offset;
286: shlibFd = open(image->name, O_RDONLY, 0);
287: if (shlibFd >= 0) {
288: fstat(shlibFd, &imageStat);
289: image->size = imageStat.st_size;
290: image->mtime = imageStat.st_mtime;
291: if (map_fd(shlibFd,
292: 0,
293: (vm_address_t *)&image->header,
294: YES,
295: image->size)
296: == 0) {
297: image->header
298: = [self headerFromStart: image->header];
299: image->deallocate = YES;
300: image++;
301: } else
302: numImages--;
303: close(shlibFd);
304: } else
305: numImages--;
306: }
307: }
308: }
309: } else {
310: return;
311: }
312: } else {
313: extern int errno;
314: // printf("Map_fd failed, errno = %d.\n", errno);
315: }
316: close(imageFd);
317: imageFd = -1;
318: }
319: }
320:
321: -(int)numSegments
322: {
323: int count, numSegs = 0, i;
324: Image *image;
325: struct load_command *loadCmd;
326: struct mach_header *header;
327: for (count = numImages,
328: image = images;
329: count;
330: count--, image++) {
331: header = image->header;
332: for (i = 0, loadCmd = (struct load_command *)(header + 1);
333: i < header->ncmds;
334: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
335: if (loadCmd->cmd == LC_SEGMENT)
336: numSegs++;
337: }
338: }
339: return numSegs;
340: }
341:
342: -(BOOL)validate
343: {
344: int nImages, i;
345: Image *image;
346: struct mach_header *header;
347: struct load_command *loadCmd;
348: struct segment_command *segCmd;
349: BOOL allOK = YES;
350: for (nImages = numImages,
351: image = images;
352: allOK && nImages;
353: nImages--, image++) {
354: header = image->header;
355: for (i = 0, loadCmd = (struct load_command *)(header + 1);
356: allOK && i < header->ncmds;
357: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
358: if (loadCmd->cmd == LC_SEGMENT) {
359: segCmd = (struct segment_command *)loadCmd;
360: if ((segCmd->fileoff + segCmd->vmsize) > image->size)
361: allOK = NO;
362: }
363: if (!loadCmd->cmdsize)
364: allOK = NO;
365: }
366: }
367: return allOK;
368: }
369:
370: -(void)readInSegments
371: {
372: int nImages, i;
373: Image *image;
374: struct mach_header *header;
375: struct load_command *loadCmd;
376: struct segment_command *segCmd;
377: Segment *segment = relocs;
378: for (nImages = numImages,
379: image = images;
380: nImages;
381: nImages--, image++) {
382: header = image->header;
383: for (i = 0, loadCmd = (struct load_command *)(header + 1);
384: i < header->ncmds;
385: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
386: if (loadCmd->cmd == LC_SEGMENT) {
387: segCmd = (struct segment_command *)loadCmd;
388: segment->address = segCmd->vmaddr;
389: segment->size = segCmd->vmsize;
390: segment->data = (vm_address_t)header + segCmd->fileoff;
391: segment->maxAddress = segment->address + segment->size;
392: segment->displacement = segment->data - segment->address;
393: segment->maxData = segment->data + segment->size;
394: segment->segName = segCmd->segname;
395: segment->rFlags.readIn = YES;
396: ((void *)segment) += relocSize;
397: }
398: }
399: }
400: }
401:
402: -(void)_readInAllRelocs
403: {
404: numRelocs = [self numSegments];
405: relocs = calloc(numRelocs, relocSize);
406: [self readInSegments];
407: rmFlags.invalid = NO;
408: }
409:
410: -(struct mach_header *)getMachHeader
411: {
412: if (numImages)
413: return images[0].header;
414: else
415: return NULL;
416: }
417:
418: -(int)getNumMachHeaders
419: {
420: return numImages;
421: }
422:
423: -(struct mach_header **)getMachHeaders
424: {
425: struct mach_header **headers;
426: int headerIndex;
427: headers = malloc((numImages + 1) * sizeof(*headers));
428: for (headerIndex = 0; headerIndex < numImages; headerIndex++)
429: headers[headerIndex] = images[headerIndex].header;
430: headers[numImages] = NULL;
431: return headers;
432: }
433:
434: -(struct mach_header **)getMachHeadersWithNames: (char ***)names
435: {
436: struct mach_header **headers;
437: char **theNames;
438: int headerIndex;
439: headers = malloc((numImages + 1) * sizeof(*headers));
440: *names = theNames = malloc((numImages + 1) * sizeof(*theNames));
441: for (headerIndex = 0; headerIndex < numImages; headerIndex++) {
442: headers[headerIndex] = images[headerIndex].header;
443: theNames[headerIndex] = images[headerIndex].name;
444: }
445: headers[numImages] = NULL;
446: theNames[numImages] = NULL;
447: return headers;
448: }
449:
450: -(struct load_command *)findLoadCommand: (unsigned long)command
451: forHeader: (struct mach_header *)header
452: {
453: int i;
454: struct load_command *loadCmd, *foundCmd = NULL;
455: for (i = 0, loadCmd = (struct load_command *)(header + 1);
456: i < header->ncmds && !foundCmd;
457: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
458: if (loadCmd->cmd == command)
459: foundCmd = loadCmd;
460: }
461: return foundCmd;
462: }
463:
464: -(int)numCommands: (unsigned long)command
465: forHeader: (struct mach_header *)header
466: {
467: int i, nCommands = 0;
468: struct load_command *loadCmd;
469: for (i = 0, loadCmd = (struct load_command *)(header + 1);
470: i < header->ncmds;
471: i++, ((void *)loadCmd) += loadCmd->cmdsize) {
472: if (loadCmd->cmd == command)
473: nCommands++;
474: }
475: return nCommands;
476: }
477:
478: -(struct symtab_command *)symCmd
479: {
480: return (struct symtab_command *)
481: [self findLoadCommand: LC_SYMTAB
482: forHeader: images[0].header];
483: }
484:
485: -(char *)stringTable
486: {
487: struct symtab_command *symCmd = [self symCmd];
488: return (char *)(images[0].header) + symCmd->stroff;
489: }
490:
491: -(BOOL)isCore
492: {
493: return images && images[0].header->filetype == MH_CORE;
494: }
495:
496: -(BOOL)isShlib
497: {
498: return images && images[0].header->filetype == MH_FVMLIB;
499: }
500:
501: -(BOOL)isExecutable
502: {
503: BOOL ret = images && ((images[0].header->filetype == MH_EXECUTE)
504: || (images[0].header->filetype == MH_OBJECT)
505: || (images[0].header->filetype == MH_PRELOAD));
506: // if (ret)
507: // printf("Is executable.\n");
508: // else
509: // printf("Isn't executable.\n");
510: return ret;
511: }
512:
513: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.