The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/mach_header.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   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 (umeshv@NeXT.com)
   32  *      Added getsegdatafromheader();
   33  *
   34  * 29-Jan-92  Mike DeMoney (mike@next.com)
   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 #include <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 #if FIXME  /* [ */
   75 struct mach_header **
   76 getmachheaders(void)
   77 {
   78         extern struct mach_header _mh_execute_header;
   79         struct mach_header **tl;
   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 #endif  /* FIXME ] */
   86 
   87 /*
   88  * This routine returns the a pointer to the data for the named section in the
   89  * named segment if it exist in the mach header passed to it.  Also it returns
   90  * the size of the section data indirectly through the pointer size.  Otherwise
   91  *  it returns zero for the pointer and the size.
   92  */
   93 void *
   94 getsectdatafromheader(
   95     struct mach_header *mhp,
   96     char *segname,
   97     char *sectname,
   98     int *size)
   99 {               
  100         const struct section *sp;
  101         void *result;
  102 
  103         sp = getsectbynamefromheader(mhp, segname, sectname);
  104         if(sp == (struct section *)0){
  105             *size = 0;
  106             return((char *)0);
  107         }
  108         *size = sp->size;
  109         result = (void *)sp->addr;
  110         return result;
  111 }
  112 
  113 /*
  114  * This routine returns the a pointer to the data for the named segment
  115  * if it exist in the mach header passed to it.  Also it returns
  116  * the size of the segment data indirectly through the pointer size.
  117  * Otherwise it returns zero for the pointer and the size.
  118  */
  119 void *
  120 getsegdatafromheader(
  121     struct mach_header *mhp,
  122         char *segname,
  123         int *size)
  124 {
  125         const struct segment_command *sc;
  126         void *result;
  127 
  128         sc = getsegbynamefromheader(mhp, segname);
  129         if(sc == (struct segment_command *)0){
  130             *size = 0;
  131             return((char *)0);
  132         }
  133         *size = sc->vmsize;
  134         result = (void *)sc->vmaddr;
  135         return result;
  136 }
  137 
  138 /*
  139  * This routine returns the section structure for the named section in the
  140  * named segment for the mach_header pointer passed to it if it exist.
  141  * Otherwise it returns zero.
  142  */
  143 struct section *
  144 getsectbynamefromheader(
  145     struct mach_header *mhp,
  146     char *segname,
  147     char *sectname)
  148 {
  149         struct segment_command *sgp;
  150         struct section *sp;
  151         long i, j;
  152 
  153         sgp = (struct segment_command *)
  154               ((char *)mhp + sizeof(struct mach_header));
  155         for(i = 0; i < mhp->ncmds; i++){
  156             if(sgp->cmd == LC_SEGMENT)
  157                 if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
  158                    mhp->filetype == MH_OBJECT){
  159                     sp = (struct section *)((char *)sgp +
  160                          sizeof(struct segment_command));
  161                     for(j = 0; j < sgp->nsects; j++){
  162                         if(strncmp(sp->sectname, sectname,
  163                            sizeof(sp->sectname)) == 0 &&
  164                            strncmp(sp->segname, segname,
  165                            sizeof(sp->segname)) == 0)
  166                             return(sp);
  167                         sp = (struct section *)((char *)sp +
  168                              sizeof(struct section));
  169                     }
  170                 }
  171             sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  172         }
  173         return((struct section *)0);
  174 }
  175 
  176 struct segment_command *getsegbynamefromheader(
  177         struct mach_header      *header,
  178         char                    *seg_name)
  179 {
  180         struct segment_command *sgp;
  181         int i;
  182 
  183         sgp = (struct segment_command *)
  184                 ((char *)header + sizeof(struct mach_header));
  185         for (i = 0; i < header->ncmds; i++){
  186                 if (   sgp->cmd == LC_SEGMENT
  187                     && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
  188                         return sgp;
  189                 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  190         }
  191         return (struct segment_command *)0;
  192 }
  193 
  194 
  195 /*
  196  * For now at least, all the rest of this seems unused.
  197  * NOTE: The constant in here for segment alignment is machine-dependent,
  198  * so if you include this, define a machine dependent constant for it's
  199  * value.
  200  */
  201 static struct {
  202         struct segment_command  seg;
  203         struct section          sect;
  204 } fvm_data = {
  205         {
  206                 LC_SEGMENT,             // cmd
  207                 sizeof(fvm_data),       // cmdsize
  208                 "__USER",               // segname
  209                 0,                      // vmaddr
  210                 0,                      // vmsize
  211                 0,                      // fileoff
  212                 0,                      // filesize
  213                 VM_PROT_READ,           // maxprot
  214                 VM_PROT_READ,           // initprot,
  215                 1,                      // nsects
  216                 0                       // flags
  217         },
  218         {
  219                 "",                     // sectname
  220                 "__USER",               // segname
  221                 0,                      // addr
  222                 0,                      // size
  223                 0,                      // offset
  224                 4,                      // align
  225                 0,                      // reloff
  226                 0,                      // nreloc
  227                 0                       // flags
  228         }
  229 };
  230 
  231 struct segment_command *fvm_seg;
  232 
  233 static struct fvmfile_command *fvmfilefromheader(struct mach_header *header);
  234 static vm_offset_t getsizeofmacho(struct mach_header *header);
  235 
  236 /*
  237  * Return the first segment_command in the header.
  238  */
  239 struct segment_command *firstseg(void)
  240 {
  241         return firstsegfromheader(&_mh_execute_header);
  242 }
  243 
  244 struct segment_command *firstsegfromheader(struct mach_header *header)
  245 {
  246         struct segment_command *sgp;
  247         int i;
  248 
  249         sgp = (struct segment_command *)
  250                 ((char *)header + sizeof(struct mach_header));
  251         for (i = 0; i < header->ncmds; i++){
  252                 if (sgp->cmd == LC_SEGMENT)
  253                         return sgp;
  254                 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  255         }
  256         return (struct segment_command *)0;
  257 }
  258 
  259 struct segment_command *nextseg(struct segment_command *sgp)
  260 {
  261         struct segment_command *this;
  262 
  263         this = nextsegfromheader(&_mh_execute_header, sgp);
  264 
  265         /*
  266          * For the kernel's header add on the faked segment for the
  267          * USER boot code identified by a FVMFILE_COMMAND in the mach header.
  268          */
  269         if (!this && sgp != fvm_seg)
  270                 this = fvm_seg;
  271 
  272         return this;
  273 }
  274 
  275 struct segment_command *nextsegfromheader(
  276         struct mach_header      *header,
  277         struct segment_command  *seg)
  278 {
  279         struct segment_command *sgp;
  280         int i;
  281 
  282         sgp = (struct segment_command *)
  283                 ((char *)header + sizeof(struct mach_header));
  284         for (i = 0; i < header->ncmds; i++) {
  285                 if (sgp == seg)
  286                         break;
  287                 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  288         }
  289 
  290         if (i == header->ncmds)
  291                 return (struct segment_command *)0;
  292 
  293         sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  294         for (; i < header->ncmds; i++) {
  295                 if (sgp->cmd == LC_SEGMENT)
  296                         return sgp;
  297                 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
  298         }
  299 
  300         return (struct segment_command *)0;
  301 }
  302 
  303 
  304 /*
  305  * Return the address of the named Mach-O segment, or NULL.
  306  */
  307 struct segment_command *getsegbyname(char *seg_name)
  308 {
  309         struct segment_command *this;
  310 
  311         this = getsegbynamefromheader(&_mh_execute_header, seg_name);
  312 
  313         /*
  314          * For the kernel's header add on the faked segment for the
  315          * USER boot code identified by a FVMFILE_COMMAND in the mach header.
  316          */
  317         if (!this && strcmp(seg_name, fvm_seg->segname) == 0)
  318                 this = fvm_seg;
  319 
  320         return this;
  321 }
  322 
  323 /*
  324  * This routine returns the a pointer the section structure of the named
  325  * section in the named segment if it exist in the mach executable it is
  326  * linked into.  Otherwise it returns zero.
  327  */
  328 struct section *
  329 getsectbyname(
  330     char *segname,
  331     char *sectname)
  332 {
  333         return(getsectbynamefromheader(
  334                 (struct mach_header *)&_mh_execute_header, segname, sectname));
  335 }
  336 
  337 struct section *firstsect(struct segment_command *sgp)
  338 {
  339         struct section *sp;
  340 
  341         if (!sgp || sgp->nsects == 0)
  342                 return (struct section *)0;
  343 
  344         return (struct section *)(sgp+1);
  345 }
  346 
  347 struct section *nextsect(struct segment_command *sgp, struct section *sp)
  348 {
  349         struct section *fsp = firstsect(sgp);
  350 
  351         if (sp - fsp >= sgp->nsects-1)
  352                 return (struct section *)0;
  353 
  354         return sp+1;
  355 }
  356 
  357 static struct fvmfile_command *fvmfilefromheader(struct mach_header *header)
  358 {
  359         struct fvmfile_command *fvp;
  360         int i;
  361 
  362         fvp = (struct fvmfile_command *)
  363                 ((char *)header + sizeof(struct mach_header));
  364         for (i = 0; i < header->ncmds; i++){
  365                 if (fvp->cmd == LC_FVMFILE)
  366                         return fvp;
  367                 fvp = (struct fvmfile_command *)((char *)fvp + fvp->cmdsize);
  368         }
  369         return (struct fvmfile_command *)0;
  370 }
  371 
  372 /*
  373  * Create a fake USER seg if a fvmfile_command is present.
  374  */
  375 struct segment_command *getfakefvmseg(void)
  376 {
  377         struct segment_command *sgp = getsegbyname("__USER");
  378         struct fvmfile_command *fvp = fvmfilefromheader(&_mh_execute_header);
  379         struct section *sp;
  380 
  381         if (sgp)
  382                 return sgp;
  383 
  384         if (!fvp)
  385                 return (struct segment_command *)0;
  386 
  387         fvm_seg = &fvm_data.seg;
  388         sgp = fvm_seg;
  389         sp = &fvm_data.sect;
  390 
  391         sgp->vmaddr = fvp->header_addr;
  392         sgp->vmsize = getsizeofmacho((struct mach_header *)(sgp->vmaddr));
  393 
  394         strcpy(sp->sectname, fvp->name.ptr);
  395         sp->addr = sgp->vmaddr;
  396         sp->size = sgp->vmsize;
  397 
  398 #if     DEBUG
  399         printf("fake fvm seg __USER/\"%s\" at 0x%x, size 0x%x\n",
  400                 sp->sectname, sp->addr, sp->size);
  401 #endif  /* DEBUG */
  402 }
  403 
  404 /*
  405  * Figure out the size the size of the data associated with a
  406  * loaded mach_header.
  407  */
  408 static vm_offset_t getsizeofmacho(struct mach_header *header)
  409 {
  410         struct segment_command  *sgp;
  411         struct section          *sp;
  412         vm_offset_t             last_addr;
  413 
  414         last_addr = 0;
  415         for (  sgp = firstsegfromheader(header)
  416             ; sgp
  417             ; sgp = nextsegfromheader(header, sgp))
  418         {
  419                 if (sgp->fileoff + sgp->filesize > last_addr)
  420                         last_addr = sgp->fileoff + sgp->filesize;
  421         }
  422 
  423         return last_addr;
  424 }
  425 #endif  /* !defined(KERNEL_PRELOAD) */

Cache object: 7ee4b06424ea9f171362e26e610ea73a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.