|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * File: kern/mach_header.c
27: *
28: * Functions for accessing mach-o headers.
29: *
30: * HISTORY
31: * 27-MAR-97 Umesh Vaishampayan ([email protected])
32: * Added getsegdatafromheader();
33: *
34: * 29-Jan-92 Mike DeMoney ([email protected])
35: * Made into machine independent form from machdep/m68k/mach_header.c.
36: * Ifdef'ed out most of this since I couldn't find any references.
37: */
38:
39: #if !defined(KERNEL_PRELOAD)
40: #import <kern/mach_header.h>
41:
42: extern struct mach_header _mh_execute_header;
43:
44: struct section *getsectbynamefromheader(
45: struct mach_header *header,
46: char *seg_name,
47: char *sect_name);
48: struct segment_command *getsegbynamefromheader(
49: struct mach_header *header,
50: char *seg_name);
51:
52: /*
53: * return the last address (first avail)
54: */
55: vm_offset_t getlastaddr(void)
56: {
57: struct segment_command *sgp;
58: vm_offset_t last_addr = 0;
59: struct mach_header *header = &_mh_execute_header;
60: int i;
61:
62: sgp = (struct segment_command *)
63: ((char *)header + sizeof(struct mach_header));
64: for (i = 0; i < header->ncmds; i++){
65: if ( sgp->cmd == LC_SEGMENT) {
66: if (sgp->vmaddr + sgp->vmsize > last_addr)
67: last_addr = sgp->vmaddr + sgp->vmsize;
68: }
69: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
70: }
71: return last_addr;
72: }
73:
74: struct mach_header **
75: getmachheaders(void)
76: {
77: extern struct mach_header _mh_execute_header;
78: struct mach_header **tl;
79:
80: tl = (struct mach_header **)malloc(2*sizeof(struct mach_header *));
81: tl[0] = &_mh_execute_header;
82: tl[1] = (struct mach_header *)0;
83: return tl;
84: }
85:
86: /*
87: * This routine returns the a pointer to the data for the named section in the
88: * named segment if it exist in the mach header passed to it. Also it returns
89: * the size of the section data indirectly through the pointer size. Otherwise
90: * it returns zero for the pointer and the size.
91: */
92: void *
93: getsectdatafromheader(
94: struct mach_header *mhp,
95: char *segname,
96: char *sectname,
97: int *size)
98: {
99: const struct section *sp;
100: void *result;
101:
102: sp = getsectbynamefromheader(mhp, segname, sectname);
103: if(sp == (struct section *)0){
104: *size = 0;
105: return((char *)0);
106: }
107: *size = sp->size;
108: result = (void *)sp->addr;
109: return result;
110: }
111:
112: /*
113: * This routine returns the a pointer to the data for the named segment
114: * if it exist in the mach header passed to it. Also it returns
115: * the size of the segment data indirectly through the pointer size.
116: * Otherwise it returns zero for the pointer and the size.
117: */
118: void *
119: getsegdatafromheader(
120: struct mach_header *mhp,
121: char *segname,
122: int *size)
123: {
124: const struct segment_command *sc;
125: void *result;
126:
127: sc = getsegbynamefromheader(mhp, segname);
128: if(sc == (struct segment_command *)0){
129: *size = 0;
130: return((char *)0);
131: }
132: *size = sc->vmsize;
133: result = (void *)sc->vmaddr;
134: return result;
135: }
136:
137: /*
138: * This routine returns the section structure for the named section in the
139: * named segment for the mach_header pointer passed to it if it exist.
140: * Otherwise it returns zero.
141: */
142: struct section *
143: getsectbynamefromheader(
144: struct mach_header *mhp,
145: char *segname,
146: char *sectname)
147: {
148: struct segment_command *sgp;
149: struct section *sp;
150: long i, j;
151:
152: sgp = (struct segment_command *)
153: ((char *)mhp + sizeof(struct mach_header));
154: for(i = 0; i < mhp->ncmds; i++){
155: if(sgp->cmd == LC_SEGMENT)
156: if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
157: mhp->filetype == MH_OBJECT){
158: sp = (struct section *)((char *)sgp +
159: sizeof(struct segment_command));
160: for(j = 0; j < sgp->nsects; j++){
161: if(strncmp(sp->sectname, sectname,
162: sizeof(sp->sectname)) == 0 &&
163: strncmp(sp->segname, segname,
164: sizeof(sp->segname)) == 0)
165: return(sp);
166: sp = (struct section *)((char *)sp +
167: sizeof(struct section));
168: }
169: }
170: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
171: }
172: return((struct section *)0);
173: }
174:
175: struct segment_command *getsegbynamefromheader(
176: struct mach_header *header,
177: char *seg_name)
178: {
179: struct segment_command *sgp;
180: int i;
181:
182: sgp = (struct segment_command *)
183: ((char *)header + sizeof(struct mach_header));
184: for (i = 0; i < header->ncmds; i++){
185: if ( sgp->cmd == LC_SEGMENT
186: && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
187: return sgp;
188: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
189: }
190: return (struct segment_command *)0;
191: }
192:
193:
194: /*
195: * For now at least, all the rest of this seems unused.
196: * NOTE: The constant in here for segment alignment is machine-dependent,
197: * so if you include this, define a machine dependent constant for it's
198: * value.
199: */
200: static struct {
201: struct segment_command seg;
202: struct section sect;
203: } fvm_data = {
204: {
205: LC_SEGMENT, // cmd
206: sizeof(fvm_data), // cmdsize
207: "__USER", // segname
208: 0, // vmaddr
209: 0, // vmsize
210: 0, // fileoff
211: 0, // filesize
212: VM_PROT_READ, // maxprot
213: VM_PROT_READ, // initprot,
214: 1, // nsects
215: 0 // flags
216: },
217: {
218: "", // sectname
219: "__USER", // segname
220: 0, // addr
221: 0, // size
222: 0, // offset
223: 4, // align
224: 0, // reloff
225: 0, // nreloc
226: 0 // flags
227: }
228: };
229:
230: struct segment_command *fvm_seg;
231:
232: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
233: static vm_offset_t getsizeofmacho(struct mach_header *header);
234:
235: /*
236: * Return the first segment_command in the header.
237: */
238: struct segment_command *firstseg(void)
239: {
240: return firstsegfromheader(&_mh_execute_header);
241: }
242:
243: struct segment_command *firstsegfromheader(struct mach_header *header)
244: {
245: struct segment_command *sgp;
246: int i;
247:
248: sgp = (struct segment_command *)
249: ((char *)header + sizeof(struct mach_header));
250: for (i = 0; i < header->ncmds; i++){
251: if (sgp->cmd == LC_SEGMENT)
252: return sgp;
253: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
254: }
255: return (struct segment_command *)0;
256: }
257:
258: struct segment_command *nextseg(struct segment_command *sgp)
259: {
260: struct segment_command *this;
261:
262: this = nextsegfromheader(&_mh_execute_header, sgp);
263:
264: /*
265: * For the kernel's header add on the faked segment for the
266: * USER boot code identified by a FVMFILE_COMMAND in the mach header.
267: */
268: if (!this && sgp != fvm_seg)
269: this = fvm_seg;
270:
271: return this;
272: }
273:
274: struct segment_command *nextsegfromheader(
275: struct mach_header *header,
276: struct segment_command *seg)
277: {
278: struct segment_command *sgp;
279: int i;
280:
281: sgp = (struct segment_command *)
282: ((char *)header + sizeof(struct mach_header));
283: for (i = 0; i < header->ncmds; i++) {
284: if (sgp == seg)
285: break;
286: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
287: }
288:
289: if (i == header->ncmds)
290: return (struct segment_command *)0;
291:
292: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
293: for (; i < header->ncmds; i++) {
294: if (sgp->cmd == LC_SEGMENT)
295: return sgp;
296: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
297: }
298:
299: return (struct segment_command *)0;
300: }
301:
302:
303: /*
304: * Return the address of the named Mach-O segment, or NULL.
305: */
306: struct segment_command *getsegbyname(char *seg_name)
307: {
308: struct segment_command *this;
309:
310: this = getsegbynamefromheader(&_mh_execute_header, seg_name);
311:
312: /*
313: * For the kernel's header add on the faked segment for the
314: * USER boot code identified by a FVMFILE_COMMAND in the mach header.
315: */
316: if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
317: this = fvm_seg;
318:
319: return this;
320: }
321:
322: /*
323: * This routine returns the a pointer the section structure of the named
324: * section in the named segment if it exist in the mach executable it is
325: * linked into. Otherwise it returns zero.
326: */
327: struct section *
328: getsectbyname(
329: char *segname,
330: char *sectname)
331: {
332: return(getsectbynamefromheader(
333: (struct mach_header *)&_mh_execute_header, segname, sectname));
334: }
335:
336: struct section *firstsect(struct segment_command *sgp)
337: {
338: struct section *sp;
339:
340: if (!sgp || sgp->nsects == 0)
341: return (struct section *)0;
342:
343: return (struct section *)(sgp+1);
344: }
345:
346: struct section *nextsect(struct segment_command *sgp, struct section *sp)
347: {
348: struct section *fsp = firstsect(sgp);
349:
350: if (sp - fsp >= sgp->nsects-1)
351: return (struct section *)0;
352:
353: return sp+1;
354: }
355:
356: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
357: {
358: struct fvmfile_command *fvp;
359: int i;
360:
361: fvp = (struct fvmfile_command *)
362: ((char *)header + sizeof(struct mach_header));
363: for (i = 0; i < header->ncmds; i++){
364: if (fvp->cmd == LC_FVMFILE)
365: return fvp;
366: fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
367: }
368: return (struct fvmfile_command *)0;
369: }
370:
371: /*
372: * Create a fake USER seg if a fvmfile_command is present.
373: */
374: struct segment_command *getfakefvmseg(void)
375: {
376: struct segment_command *sgp = getsegbyname("__USER");
377: struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
378: struct section *sp;
379:
380: if (sgp)
381: return sgp;
382:
383: if (!fvp)
384: return (struct segment_command *)0;
385:
386: fvm_seg = &fvm_data.seg;
387: sgp = fvm_seg;
388: sp = &fvm_data.sect;
389:
390: sgp->vmaddr = fvp->header_addr;
391: sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
392:
393: strcpy(sp->sectname, fvp->name.ptr);
394: sp->addr = sgp->vmaddr;
395: sp->size = sgp->vmsize;
396:
397: #if DEBUG
398: printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
399: sp->sectname, sp->addr, sp->size);
400: #endif DEBUG
401: }
402:
403: /*
404: * Figure out the size the size of the data associated with a
405: * loaded mach_header.
406: */
407: static vm_offset_t getsizeofmacho(struct mach_header *header)
408: {
409: struct segment_command *sgp;
410: struct section *sp;
411: vm_offset_t last_addr;
412:
413: last_addr = 0;
414: for ( sgp = firstsegfromheader(header)
415: ; sgp
416: ; sgp = nextsegfromheader(header, sgp))
417: {
418: if (sgp->fileoff + sgp->filesize > last_addr)
419: last_addr = sgp->fileoff + sgp->filesize;
420: }
421:
422: return last_addr;
423: }
424: #endif /* !defined(KERNEL_PRELOAD) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.