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