]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/mach_header.c
xnu-792.6.61.tar.gz
[apple/xnu.git] / bsd / kern / mach_header.c
index 2510daa92a8132b16477d193de79ac24783e93b4..9071eaa48c8ef54be5d73b40fef3e0543631f45a 100644 (file)
@@ -1,24 +1,21 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * 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. 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
+ * This 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
  *
  *     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));
@@ -72,10 +73,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;
@@ -89,12 +92,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;
@@ -115,11 +120,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;
@@ -139,16 +146,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));
@@ -173,12 +182,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));
@@ -224,7 +237,9 @@ static struct {
                4,                      // align
                0,                      // reloff
                0,                      // nreloc
-               0                       // flags
+               0,                      // flags
+               0,                      // reserved1
+               0                       // reserved2
        }
 };
 
@@ -235,16 +250,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));
@@ -256,7 +280,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;
 
@@ -272,12 +303,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));
@@ -302,9 +339,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;
 
@@ -322,42 +361,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));
@@ -371,8 +428,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);
@@ -398,17 +458,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;