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