|
|
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: #include <vm/vm_map.h>
37: #include <vm/vm_kern.h>
38: #include <mach-o/mach_header.h>
39:
40: #ifdef __MACHO__
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: #ifdef MACH_BSD
56: __private_extern__
57: #endif
58: vm_offset_t getlastaddr(void)
59: {
60: struct segment_command *sgp;
61: vm_offset_t last_addr = 0;
62: struct mach_header *header = &_mh_execute_header;
63: int i;
64:
65: sgp = (struct segment_command *)
66: ((char *)header + sizeof(struct mach_header));
67: for (i = 0; i < header->ncmds; i++){
68: if ( sgp->cmd == LC_SEGMENT) {
69: if (sgp->vmaddr + sgp->vmsize > last_addr)
70: last_addr = sgp->vmaddr + sgp->vmsize;
71: }
72: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
73: }
74: return last_addr;
75: }
76:
77: #ifdef XXX_MACH_BSD
78: __private_extern__
79: #endif
80: struct mach_header **
81: getmachheaders(void)
82: {
83: extern struct mach_header _mh_execute_header;
84: struct mach_header **tl;
85:
86: if (kmem_alloc(kernel_map, (vm_offset_t *) &tl, 2*sizeof(struct mach_header *)) != KERN_SUCCESS)
87: return NULL;
88:
89: tl[0] = &_mh_execute_header;
90: tl[1] = (struct mach_header *)0;
91: return tl;
92: }
93:
94: /*
95: * This routine returns the a pointer to the data for the named section in the
96: * named segment if it exist in the mach header passed to it. Also it returns
97: * the size of the section data indirectly through the pointer size. Otherwise
98: * it returns zero for the pointer and the size.
99: */
100: #ifdef MACH_BSD
101: __private_extern__
102: #endif
103: void *
104: getsectdatafromheader(
105: struct mach_header *mhp,
106: char *segname,
107: char *sectname,
108: int *size)
109: {
110: const struct section *sp;
111: void *result;
112:
113: sp = getsectbynamefromheader(mhp, segname, sectname);
114: if(sp == (struct section *)0){
115: *size = 0;
116: return((char *)0);
117: }
118: *size = sp->size;
119: result = (void *)sp->addr;
120: return result;
121: }
122:
123: /*
124: * This routine returns the a pointer to the data for the named segment
125: * if it exist in the mach header passed to it. Also it returns
126: * the size of the segment data indirectly through the pointer size.
127: * Otherwise it returns zero for the pointer and the size.
128: */
129: #ifdef MACH_BSD
130: __private_extern__
131: #endif
132: void *
133: getsegdatafromheader(
134: struct mach_header *mhp,
135: char *segname,
136: int *size)
137: {
138: const struct segment_command *sc;
139: void *result;
140:
141: sc = getsegbynamefromheader(mhp, segname);
142: if(sc == (struct segment_command *)0){
143: *size = 0;
144: return((char *)0);
145: }
146: *size = sc->vmsize;
147: result = (void *)sc->vmaddr;
148: return result;
149: }
150:
151: /*
152: * This routine returns the section structure for the named section in the
153: * named segment for the mach_header pointer passed to it if it exist.
154: * Otherwise it returns zero.
155: */
156: #ifdef MACH_BSD
157: __private_extern__
158: #endif
159: struct section *
160: getsectbynamefromheader(
161: struct mach_header *mhp,
162: char *segname,
163: char *sectname)
164: {
165: struct segment_command *sgp;
166: struct section *sp;
167: long i, j;
168:
169: sgp = (struct segment_command *)
170: ((char *)mhp + sizeof(struct mach_header));
171: for(i = 0; i < mhp->ncmds; i++){
172: if(sgp->cmd == LC_SEGMENT)
173: if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
174: mhp->filetype == MH_OBJECT){
175: sp = (struct section *)((char *)sgp +
176: sizeof(struct segment_command));
177: for(j = 0; j < sgp->nsects; j++){
178: if(strncmp(sp->sectname, sectname,
179: sizeof(sp->sectname)) == 0 &&
180: strncmp(sp->segname, segname,
181: sizeof(sp->segname)) == 0)
182: return(sp);
183: sp = (struct section *)((char *)sp +
184: sizeof(struct section));
185: }
186: }
187: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
188: }
189: return((struct section *)0);
190: }
191:
192: #ifdef MACH_BSD
193: __private_extern__
194: #endif
195: struct segment_command *getsegbynamefromheader(
196: struct mach_header *header,
197: char *seg_name)
198: {
199: struct segment_command *sgp;
200: int i;
201:
202: sgp = (struct segment_command *)
203: ((char *)header + sizeof(struct mach_header));
204: for (i = 0; i < header->ncmds; i++){
205: if ( sgp->cmd == LC_SEGMENT
206: && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
207: return sgp;
208: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
209: }
210: return (struct segment_command *)0;
211: }
212:
213:
214: /*
215: * For now at least, all the rest of this seems unused.
216: * NOTE: The constant in here for segment alignment is machine-dependent,
217: * so if you include this, define a machine dependent constant for it's
218: * value.
219: */
220: static struct {
221: struct segment_command seg;
222: struct section sect;
223: } fvm_data = {
224: {
225: LC_SEGMENT, // cmd
226: sizeof(fvm_data), // cmdsize
227: "__USER", // segname
228: 0, // vmaddr
229: 0, // vmsize
230: 0, // fileoff
231: 0, // filesize
232: VM_PROT_READ, // maxprot
233: VM_PROT_READ, // initprot,
234: 1, // nsects
235: 0 // flags
236: },
237: {
238: "", // sectname
239: "__USER", // segname
240: 0, // addr
241: 0, // size
242: 0, // offset
243: 4, // align
244: 0, // reloff
245: 0, // nreloc
246: 0 // flags
247: }
248: };
249:
250: #ifdef MACH_BSD
251: static
252: #endif
253: struct segment_command *fvm_seg;
254:
255: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
256: static vm_offset_t getsizeofmacho(struct mach_header *header);
257:
258: /*
259: * Return the first segment_command in the header.
260: */
261: #ifdef MACH_BSD
262: __private_extern__
263: #endif
264: struct segment_command *firstseg(void)
265: {
266: return firstsegfromheader(&_mh_execute_header);
267: }
268:
269: #ifdef MACH_BSD
270: __private_extern__
271: #endif
272: struct segment_command *firstsegfromheader(struct mach_header *header)
273: {
274: struct segment_command *sgp;
275: int i;
276:
277: sgp = (struct segment_command *)
278: ((char *)header + sizeof(struct mach_header));
279: for (i = 0; i < header->ncmds; i++){
280: if (sgp->cmd == LC_SEGMENT)
281: return sgp;
282: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
283: }
284: return (struct segment_command *)0;
285: }
286:
287: #ifdef MACH_BSD
288: __private_extern__
289: #endif
290: struct segment_command *nextseg(struct segment_command *sgp)
291: {
292: struct segment_command *this;
293:
294: this = nextsegfromheader(&_mh_execute_header, sgp);
295:
296: /*
297: * For the kernel's header add on the faked segment for the
298: * USER boot code identified by a FVMFILE_COMMAND in the mach header.
299: */
300: if (!this && sgp != fvm_seg)
301: this = fvm_seg;
302:
303: return this;
304: }
305:
306: #ifdef MACH_BSD
307: __private_extern__
308: #endif
309: struct segment_command *nextsegfromheader(
310: struct mach_header *header,
311: struct segment_command *seg)
312: {
313: struct segment_command *sgp;
314: int i;
315:
316: sgp = (struct segment_command *)
317: ((char *)header + sizeof(struct mach_header));
318: for (i = 0; i < header->ncmds; i++) {
319: if (sgp == seg)
320: break;
321: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
322: }
323:
324: if (i == header->ncmds)
325: return (struct segment_command *)0;
326:
327: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
328: for (; i < header->ncmds; i++) {
329: if (sgp->cmd == LC_SEGMENT)
330: return sgp;
331: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
332: }
333:
334: return (struct segment_command *)0;
335: }
336:
337:
338: /*
339: * Return the address of the named Mach-O segment, or NULL.
340: */
341: #ifdef MACH_BSD
342: __private_extern__
343: #endif
344: struct segment_command *getsegbyname(char *seg_name)
345: {
346: struct segment_command *this;
347:
348: this = getsegbynamefromheader(&_mh_execute_header, seg_name);
349:
350: /*
351: * For the kernel's header add on the faked segment for the
352: * USER boot code identified by a FVMFILE_COMMAND in the mach header.
353: */
354: if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
355: this = fvm_seg;
356:
357: return this;
358: }
359:
360: /*
361: * This routine returns the a pointer the section structure of the named
362: * section in the named segment if it exist in the mach executable it is
363: * linked into. Otherwise it returns zero.
364: */
365: #ifdef MACH_BSD
366: __private_extern__
367: #endif
368: struct section *
369: getsectbyname(
370: char *segname,
371: char *sectname)
372: {
373: return(getsectbynamefromheader(
374: (struct mach_header *)&_mh_execute_header, segname, sectname));
375: }
376:
377: #ifdef MACH_BSD
378: __private_extern__
379: #endif
380: struct section *firstsect(struct segment_command *sgp)
381: {
382: struct section *sp;
383:
384: if (!sgp || sgp->nsects == 0)
385: return (struct section *)0;
386:
387: return (struct section *)(sgp+1);
388: }
389:
390: #ifdef MACH_BSD
391: __private_extern__
392: #endif
393: struct section *nextsect(struct segment_command *sgp, struct section *sp)
394: {
395: struct section *fsp = firstsect(sgp);
396:
397: if (sp - fsp >= sgp->nsects-1)
398: return (struct section *)0;
399:
400: return sp+1;
401: }
402:
403: static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
404: {
405: struct fvmfile_command *fvp;
406: int i;
407:
408: fvp = (struct fvmfile_command *)
409: ((char *)header + sizeof(struct mach_header));
410: for (i = 0; i < header->ncmds; i++){
411: if (fvp->cmd == LC_FVMFILE)
412: return fvp;
413: fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
414: }
415: return (struct fvmfile_command *)0;
416: }
417:
418: /*
419: * Create a fake USER seg if a fvmfile_command is present.
420: */
421: #ifdef MACH_BSD
422: __private_extern__
423: #endif
424: struct segment_command *getfakefvmseg(void)
425: {
426: struct segment_command *sgp = getsegbyname("__USER");
427: struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
428: struct section *sp;
429:
430: if (sgp)
431: return sgp;
432:
433: if (!fvp)
434: return (struct segment_command *)0;
435:
436: fvm_seg = &fvm_data.seg;
437: sgp = fvm_seg;
438: sp = &fvm_data.sect;
439:
440: sgp->vmaddr = fvp->header_addr;
441: sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
442:
443: strcpy(sp->sectname, fvp->name.ptr);
444: sp->addr = sgp->vmaddr;
445: sp->size = sgp->vmsize;
446:
447: #if DEBUG
448: printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
449: sp->sectname, sp->addr, sp->size);
450: #endif /*DEBUG*/
451: return sgp;
452: }
453:
454: /*
455: * Figure out the size the size of the data associated with a
456: * loaded mach_header.
457: */
458: static vm_offset_t getsizeofmacho(struct mach_header *header)
459: {
460: struct segment_command *sgp;
461: struct section *sp;
462: vm_offset_t last_addr;
463:
464: last_addr = 0;
465: for ( sgp = firstsegfromheader(header)
466: ; sgp
467: ; sgp = nextsegfromheader(header, sgp))
468: {
469: if (sgp->fileoff + sgp->filesize > last_addr)
470: last_addr = sgp->fileoff + sgp->filesize;
471: }
472:
473: return last_addr;
474: }
475:
476: #ifdef MACH_KDB
477: /*
478: * This routine returns the section command for the symbol table in the
479: * named segment for the mach_header pointer passed to it if it exist.
480: * Otherwise it returns zero.
481: */
482: struct symtab_command *
483: getsectcmdsymtabfromheader(
484: struct mach_header *mhp)
485: {
486: struct segment_command *sgp;
487: struct section *sp;
488: long i;
489:
490: sgp = (struct segment_command *)
491: ((char *)mhp + sizeof(struct mach_header));
492: for(i = 0; i < mhp->ncmds; i++){
493: if(sgp->cmd == LC_SYMTAB)
494: return((struct symtab_command *)sgp);
495: sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
496: }
497: return(NULL);
498: }
499:
500: boolean_t getsymtab(struct mach_header *header,
501: vm_offset_t *symtab,
502: int *nsyms,
503: vm_offset_t *strtab,
504: vm_size_t *strtabsize)
505: {
506: struct segment_command *seglink_cmd;
507: struct symtab_command *symtab_cmd;
508:
509: seglink_cmd = NULL;
510:
511: if(header->magic != MH_MAGIC) { /* Check if this is a valid header format */
512: printf("Attempt to use invalid header (magic = %08X) to find symbol table\n",
513: header->magic); /* Tell them what's wrong */
514: return (FALSE); /* Bye y'all... */
515: }
516:
517: seglink_cmd = getsegbynamefromheader(header,"__LINKEDIT");
518: if (seglink_cmd == NULL) {
519: return(FALSE);
520: }
521:
522: symtab_cmd = NULL;
523: symtab_cmd = getsectcmdsymtabfromheader(header);
524: if (symtab_cmd == NULL)
525: return(FALSE);
526:
527: *nsyms = symtab_cmd->nsyms;
528: if(symtab_cmd->nsyms == 0) return (FALSE); /* No symbols */
529:
530: *strtabsize = symtab_cmd->strsize;
531: if(symtab_cmd->strsize == 0) return (FALSE); /* Symbol length is 0 */
532:
533: *symtab = seglink_cmd->vmaddr + symtab_cmd->symoff -
534: seglink_cmd->fileoff;
535:
536: *strtab = seglink_cmd->vmaddr + symtab_cmd->stroff -
537: seglink_cmd->fileoff;
538:
539: return(TRUE);
540: }
541: #endif
542:
543: #else
544:
545: void * getsegdatafromheader( struct mach_header *mhp, char *segname, int *size)
546: {
547: return 0;
548: }
549:
550: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.