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