]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/mach_header.c
xnu-792.21.3.tar.gz
[apple/xnu.git] / bsd / kern / mach_header.c
index fe3c023123da810b5ae289f616c31e026448f3cb..76408fab52ae4937bf95d222f101d4718da92ea3 100644 (file)
@@ -1,29 +1,43 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  *     File: kern/mach_header.c
  *
  *     Functions for accessing mach-o headers.
  *
+ * NOTE:       This file supports only 32 bit mach headers at the present
+ *             time; it's primary use is by kld, and all externally
+ *             referenced routines at the present time operate against
+ *             the 32 bit mach header _mh_execute_header, which is the
+ *             header for the currently executing kernel.  Adding support
+ *             for 64 bit kernels is possible, but is not necessary at the
+ *             present time.
+ *
  * HISTORY
  * 27-MAR-97  Umesh Vaishampayan (umeshv@NeXT.com)
  *     Added getsegdatafromheader();
 
 #if !defined(KERNEL_PRELOAD)
 #include <kern/mach_header.h>
+#include <string.h>            // from libsa
 
 extern struct mach_header _mh_execute_header;
 
-struct section *getsectbynamefromheader(
-       struct mach_header      *header,
-       char                    *seg_name,
-       char                    *sect_name);
-struct segment_command *getsegbynamefromheader(
-       struct mach_header      *header,
-       char                    *seg_name);
-
 /*
  * return the last address (first avail)
+ *
+ * This routine operates against the currently executing kernel only
  */
-vm_offset_t getlastaddr(void)
+vm_offset_t
+getlastaddr(void)
 {
        struct segment_command  *sgp;
        vm_offset_t             last_addr = 0;
        struct mach_header *header = &_mh_execute_header;
-       int i;
+       unsigned long i;
 
        sgp = (struct segment_command *)
                ((char *)header + sizeof(struct mach_header));
@@ -69,10 +79,12 @@ vm_offset_t getlastaddr(void)
 }
 
 #if FIXME  /* [ */
+/*
+ * This routine operates against the currently executing kernel only
+ */
 struct mach_header **
 getmachheaders(void)
 {
-       extern struct mach_header _mh_execute_header;
        struct mach_header **tl;
        tl = (struct mach_header **)malloc(2*sizeof(struct mach_header *));
        tl[0] = &_mh_execute_header;
@@ -86,12 +98,14 @@ getmachheaders(void)
  * named segment if it exist in the mach header passed to it.  Also it returns
  * the size of the section data indirectly through the pointer size.  Otherwise
  *  it returns zero for the pointer and the size.
+ *
+ * This routine can operate against any 32 bit mach header.
  */
 void *
 getsectdatafromheader(
     struct mach_header *mhp,
-    char *segname,
-    char *sectname,
+    const char *segname,
+    const char *sectname,
     int *size)
 {              
        const struct section *sp;
@@ -112,11 +126,13 @@ getsectdatafromheader(
  * if it exist in the mach header passed to it.  Also it returns
  * the size of the segment data indirectly through the pointer size.
  * Otherwise it returns zero for the pointer and the size.
+ *
+ * This routine can operate against any 32 bit mach header.
  */
 void *
 getsegdatafromheader(
-    struct mach_header *mhp,
-       char *segname,
+       struct mach_header *mhp,
+       const char *segname,
        int *size)
 {
        const struct segment_command *sc;
@@ -136,16 +152,18 @@ getsegdatafromheader(
  * This routine returns the section structure for the named section in the
  * named segment for the mach_header pointer passed to it if it exist.
  * Otherwise it returns zero.
+ *
+ * This routine can operate against any 32 bit mach header.
  */
 struct section *
 getsectbynamefromheader(
     struct mach_header *mhp,
-    char *segname,
-    char *sectname)
+    const char *segname,
+    const char *sectname)
 {
        struct segment_command *sgp;
        struct section *sp;
-       long i, j;
+       unsigned long i, j;
 
        sgp = (struct segment_command *)
              ((char *)mhp + sizeof(struct mach_header));
@@ -170,12 +188,16 @@ getsectbynamefromheader(
        return((struct section *)0);
 }
 
-struct segment_command *getsegbynamefromheader(
+/*
+ * This routine can operate against any 32 bit mach header.
+ */
+struct segment_command *
+getsegbynamefromheader(
        struct mach_header      *header,
-       char                    *seg_name)
+       const char              *seg_name)
 {
        struct segment_command *sgp;
-       int i;
+       unsigned long i;
 
        sgp = (struct segment_command *)
                ((char *)header + sizeof(struct mach_header));
@@ -221,7 +243,9 @@ static struct {
                4,                      // align
                0,                      // reloff
                0,                      // nreloc
-               0                       // flags
+               0,                      // flags
+               0,                      // reserved1
+               0                       // reserved2
        }
 };
 
@@ -232,16 +256,25 @@ static vm_offset_t getsizeofmacho(struct mach_header *header);
 
 /*
  * Return the first segment_command in the header.
+ *
+ * This routine operates against the currently executing kernel only
  */
-struct segment_command *firstseg(void)
+struct segment_command *
+firstseg(void)
 {
        return firstsegfromheader(&_mh_execute_header);
 }
 
-struct segment_command *firstsegfromheader(struct mach_header *header)
+/*
+ * This routine can operate against any 32 bit mach header, and returns a
+ * pointer to a 32 bit segment_command structure from the file prefixed by
+ * the header it is passed as its argument.
+ */
+struct segment_command *
+firstsegfromheader(struct mach_header *header)
 {
        struct segment_command *sgp;
-       int i;
+       unsigned long i;
 
        sgp = (struct segment_command *)
                ((char *)header + sizeof(struct mach_header));
@@ -253,7 +286,14 @@ struct segment_command *firstsegfromheader(struct mach_header *header)
        return (struct segment_command *)0;
 }
 
-struct segment_command *nextseg(struct segment_command *sgp)
+/*
+ * This routine operates against a 32 bit mach segment_command structure
+ * pointer from the currently executing kernel only, to obtain the
+ * sequentially next segment_command structure in the currently executing
+ * kernel
+ */
+struct segment_command *
+nextseg(struct segment_command *sgp)
 {
        struct segment_command *this;
 
@@ -269,12 +309,18 @@ struct segment_command *nextseg(struct segment_command *sgp)
        return this;
 }
 
-struct segment_command *nextsegfromheader(
+/*
+ * This routine operates against any 32 bit mach segment_command structure
+ * pointer and the provided 32 bit header, to obtain the sequentially next
+ * segment_command structure in that header.
+ */
+struct segment_command *
+nextsegfromheader(
        struct mach_header      *header,
        struct segment_command  *seg)
 {
        struct segment_command *sgp;
-       int i;
+       unsigned long i;
 
        sgp = (struct segment_command *)
                ((char *)header + sizeof(struct mach_header));
@@ -299,9 +345,11 @@ struct segment_command *nextsegfromheader(
 
 
 /*
- * Return the address of the named Mach-O segment, or NULL.
+ * Return the address of the named Mach-O segment from the currently
+ * executing 32 bit kernel, or NULL.
  */
-struct segment_command *getsegbyname(char *seg_name)
+struct segment_command *
+getsegbyname(const char *seg_name)
 {
        struct segment_command *this;
 
@@ -319,42 +367,60 @@ struct segment_command *getsegbyname(char *seg_name)
 
 /*
  * This routine returns the a pointer the section structure of the named
- * section in the named segment if it exist in the mach executable it is
- * linked into.  Otherwise it returns zero.
+ * section in the named segment if it exists in the currently executing
+ * kernel, which it is presumed to be linked into.  Otherwise it returns NULL.
  */
 struct section *
 getsectbyname(
-    char *segname,
-    char *sectname)
+    const char *segname,
+    const char *sectname)
 {
        return(getsectbynamefromheader(
                (struct mach_header *)&_mh_execute_header, segname, sectname));
 }
 
-struct section *firstsect(struct segment_command *sgp)
+/*
+ * This routine can operate against any 32 bit segment_command structure to
+ * return the first 32 bit section immediately following that structure.  If
+ * there are no sections associated with the segment_command structure, it
+ * returns NULL.
+ */
+struct section *
+firstsect(struct segment_command *sgp)
 {
-       struct section *sp;
-
        if (!sgp || sgp->nsects == 0)
                return (struct section *)0;
 
        return (struct section *)(sgp+1);
 }
 
-struct section *nextsect(struct segment_command *sgp, struct section *sp)
+/*
+ * This routine can operate against any 32 bit segment_command structure and
+ * 32 bit section to return the next consecutive  32 bit section immediately
+ * following the 32 bit section provided.  If there are no sections following
+ * the provided section, it returns NULL.
+ */
+struct section *
+nextsect(struct segment_command *sgp, struct section *sp)
 {
        struct section *fsp = firstsect(sgp);
 
-       if (sp - fsp >= sgp->nsects-1)
+       if (((unsigned long)(sp - fsp) + 1) >= sgp->nsects)
                return (struct section *)0;
 
        return sp+1;
 }
 
-static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
+/*
+ * This routine can operate against any 32 bit mach header to return the
+ * first occurring 32 bit fvmfile_command section.  If one is not present,
+ * it returns NULL.
+ */
+static struct fvmfile_command *
+fvmfilefromheader(struct mach_header *header)
 {
        struct fvmfile_command *fvp;
-       int i;
+       unsigned long i;
 
        fvp = (struct fvmfile_command *)
                ((char *)header + sizeof(struct mach_header));
@@ -368,8 +434,11 @@ static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
 
 /*
  * Create a fake USER seg if a fvmfile_command is present.
+ *
+ * This routine operates against the currently executing kernel only
  */
-struct segment_command *getfakefvmseg(void)
+struct segment_command *
+getfakefvmseg(void)
 {
        struct segment_command *sgp = getsegbyname("__USER");
        struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
@@ -395,17 +464,21 @@ struct segment_command *getfakefvmseg(void)
 #if    DEBUG
        printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
                sp->sectname, sp->addr, sp->size);
-#endif DEBUG
+#endif /* DEBUG */
+
+       return sgp;
 }
 
 /*
  * Figure out the size the size of the data associated with a
  * loaded mach_header.
+ *
+ * This routine can operate against any 32 bit mach header.
  */
-static vm_offset_t getsizeofmacho(struct mach_header *header)
+static vm_offset_t
+getsizeofmacho(struct mach_header *header)
 {
        struct segment_command  *sgp;
-       struct section          *sp;
        vm_offset_t             last_addr;
 
        last_addr = 0;