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/libkern/kernel_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-2008 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*
   29  *      File: libkern/kernel_mach_header.c
   30  *
   31  *      Functions for accessing mach-o headers.
   32  *
   33  * NOTE:        This file supports only kernel mach headers at the present
   34  *              time; it's primary use is by kld, and all externally
   35  *              referenced routines at the present time operate against
   36  *              the kernel mach header _mh_execute_header, which is the
   37  *              header for the currently executing kernel. 
   38  *
   39  */
   40 
   41 #include <vm/vm_map.h>
   42 #include <vm/vm_kern.h>
   43 #include <libkern/kernel_mach_header.h>
   44 #include <string.h>             // from libsa
   45 
   46 /*
   47  * return the last address (first avail)
   48  *
   49  * This routine operates against the currently executing kernel only
   50  */
   51 vm_offset_t
   52 getlastaddr(void)
   53 {
   54         kernel_segment_command_t        *sgp;
   55         vm_offset_t             last_addr = 0;
   56         kernel_mach_header_t *header = &_mh_execute_header;
   57         unsigned long i;
   58 
   59         sgp = (kernel_segment_command_t *)
   60                 ((uintptr_t)header + sizeof(kernel_mach_header_t));
   61         for (i = 0; i < header->ncmds; i++){
   62                 if (sgp->cmd == LC_SEGMENT_KERNEL) {
   63                         if (sgp->vmaddr + sgp->vmsize > last_addr)
   64                                 last_addr = sgp->vmaddr + sgp->vmsize;
   65                 }
   66                 sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
   67         }
   68         return last_addr;
   69 }
   70 
   71 /*
   72  * Find the specified load command in the Mach-O headers, and return
   73  * the command. If there is no such load command, NULL is returned.
   74  */
   75 void *
   76 getcommandfromheader(kernel_mach_header_t *mhp, uint32_t cmd) {
   77         struct load_command *lcp;
   78         unsigned long i;
   79 
   80         lcp = (struct load_command *) (mhp + 1);
   81         for(i = 0; i < mhp->ncmds; i++){
   82                 if(lcp->cmd == cmd) {
   83                         return (void *)lcp;
   84                 }
   85 
   86                 lcp = (struct load_command *)((uintptr_t)lcp + lcp->cmdsize);
   87         }
   88 
   89         return NULL;
   90 }
   91 
   92 /*
   93  * Find the UUID load command in the Mach-O headers, and return
   94  * the address of the UUID blob and size in "*size". If the
   95  * Mach-O image is missing a UUID, NULL is returned.
   96  */
   97 void *
   98 getuuidfromheader(kernel_mach_header_t *mhp, unsigned long *size)
   99 {
  100     struct uuid_command *cmd = (struct uuid_command *)
  101         getcommandfromheader(mhp, LC_UUID);
  102 
  103     if (cmd != NULL) {
  104         if (size) {
  105             *size = sizeof(cmd->uuid);
  106         }
  107         return cmd->uuid;
  108     }
  109 
  110     return NULL;
  111 }
  112 
  113 /*
  114  * This routine returns the a pointer to the data for the named section in the
  115  * named segment if it exist in the mach header passed to it.  Also it returns
  116  * the size of the section data indirectly through the pointer size.  Otherwise
  117  *  it returns zero for the pointer and the size.
  118  *
  119  * This routine can operate against any kernel mach header.
  120  */
  121 void *
  122 getsectdatafromheader(
  123     kernel_mach_header_t *mhp,
  124     const char *segname,
  125     const char *sectname,
  126     unsigned long *size)
  127 {               
  128         const kernel_section_t *sp;
  129         void *result;
  130 
  131         sp = getsectbynamefromheader(mhp, segname, sectname);
  132         if(sp == (kernel_section_t *)0){
  133             *size = 0;
  134             return((char *)0);
  135         }
  136         *size = sp->size;
  137         result = (void *)sp->addr; 
  138         return result;
  139 }
  140 
  141 /*
  142  * This routine returns the a pointer to the data for the named segment
  143  * if it exist in the mach header passed to it.  Also it returns
  144  * the size of the segment data indirectly through the pointer size.
  145  * Otherwise it returns zero for the pointer and the size.
  146  */
  147 void *
  148 getsegdatafromheader(
  149     kernel_mach_header_t *mhp,
  150         const char *segname,
  151         unsigned long *size)
  152 {
  153         const kernel_segment_command_t *sc;
  154         void *result;
  155 
  156         sc = getsegbynamefromheader(mhp, segname);
  157         if(sc == (kernel_segment_command_t *)0){
  158             *size = 0;
  159             return((char *)0);
  160         }
  161         *size = sc->vmsize;
  162         result = (void *)sc->vmaddr;
  163         return result;
  164 }
  165 
  166 /*
  167  * This routine returns the section structure for the named section in the
  168  * named segment for the mach_header pointer passed to it if it exist.
  169  * Otherwise it returns zero.
  170  *
  171  * This routine can operate against any kernel mach header.
  172  */
  173 kernel_section_t *
  174 getsectbynamefromheader(
  175     kernel_mach_header_t *mhp,
  176     const char *segname,
  177     const char *sectname)
  178 {
  179         kernel_segment_command_t *sgp;
  180         kernel_section_t *sp;
  181         unsigned long i, j;
  182 
  183         sgp = (kernel_segment_command_t *)
  184               ((uintptr_t)mhp + sizeof(kernel_mach_header_t));
  185         for(i = 0; i < mhp->ncmds; i++){
  186             if(sgp->cmd == LC_SEGMENT_KERNEL)
  187                 if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 ||
  188                    mhp->filetype == MH_OBJECT){
  189                     sp = (kernel_section_t *)((uintptr_t)sgp +
  190                          sizeof(kernel_segment_command_t));
  191                     for(j = 0; j < sgp->nsects; j++){
  192                         if(strncmp(sp->sectname, sectname,
  193                            sizeof(sp->sectname)) == 0 &&
  194                            strncmp(sp->segname, segname,
  195                            sizeof(sp->segname)) == 0)
  196                             return(sp);
  197                         sp = (kernel_section_t *)((uintptr_t)sp +
  198                              sizeof(kernel_section_t));
  199                     }
  200                 }
  201             sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  202         }
  203         return((kernel_section_t *)NULL);
  204 }
  205 
  206 /*
  207  * This routine can operate against any kernel mach header.
  208  */
  209 kernel_segment_command_t *
  210 getsegbynamefromheader(
  211         kernel_mach_header_t    *header,
  212         const char              *seg_name)
  213 {
  214         kernel_segment_command_t *sgp;
  215         unsigned long i;
  216 
  217         sgp = (kernel_segment_command_t *)
  218                 ((uintptr_t)header + sizeof(kernel_mach_header_t));
  219         for (i = 0; i < header->ncmds; i++){
  220                 if (   sgp->cmd == LC_SEGMENT_KERNEL
  221                     && !strncmp(sgp->segname, seg_name, sizeof(sgp->segname)))
  222                         return sgp;
  223                 sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  224         }
  225         return (kernel_segment_command_t *)NULL;
  226 }
  227 
  228 /*
  229  * Return the first segment_command in the header.
  230  */
  231 kernel_segment_command_t *
  232 firstseg(void)
  233 {
  234     return firstsegfromheader(&_mh_execute_header);
  235 }
  236 
  237 kernel_segment_command_t *
  238 firstsegfromheader(kernel_mach_header_t *header)
  239 {
  240     u_int i = 0;
  241     kernel_segment_command_t *sgp = (kernel_segment_command_t *)
  242         ((uintptr_t)header + sizeof(*header));
  243 
  244     for (i = 0; i < header->ncmds; i++){
  245         if (sgp->cmd == LC_SEGMENT_KERNEL)
  246             return sgp;
  247         sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  248     }
  249     return (kernel_segment_command_t *)NULL;
  250 }
  251 
  252 /*
  253  * This routine operates against any kernel mach segment_command structure
  254  * pointer and the provided kernel header, to obtain the sequentially next
  255  * segment_command structure in that header.
  256  */
  257 kernel_segment_command_t *
  258 nextsegfromheader(
  259         kernel_mach_header_t    *header,
  260         kernel_segment_command_t        *seg)
  261 {
  262     u_int i = 0;
  263     kernel_segment_command_t *sgp = (kernel_segment_command_t *)
  264         ((uintptr_t)header + sizeof(*header));
  265 
  266     /* Find the index of the passed-in segment */
  267     for (i = 0; sgp != seg && i < header->ncmds; i++) {
  268         sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  269     }
  270 
  271     /* Increment to the next load command */
  272     i++;
  273     sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  274 
  275     /* Return the next segment command, if any */
  276     for (; i < header->ncmds; i++) {
  277         if (sgp->cmd == LC_SEGMENT_KERNEL) return sgp;
  278 
  279         sgp = (kernel_segment_command_t *)((uintptr_t)sgp + sgp->cmdsize);
  280     }
  281 
  282     return (kernel_segment_command_t *)NULL;
  283 }
  284 
  285 
  286 /*
  287  * Return the address of the named Mach-O segment from the currently
  288  * executing kernel kernel, or NULL.
  289  */
  290 kernel_segment_command_t *
  291 getsegbyname(const char *seg_name)
  292 {
  293         return(getsegbynamefromheader(&_mh_execute_header, seg_name));
  294 }
  295 
  296 /*
  297  * This routine returns the a pointer the section structure of the named
  298  * section in the named segment if it exists in the currently executing
  299  * kernel, which it is presumed to be linked into.  Otherwise it returns NULL.
  300  */
  301 kernel_section_t *
  302 getsectbyname(
  303     const char *segname,
  304     const char *sectname)
  305 {
  306         return(getsectbynamefromheader(
  307                 (kernel_mach_header_t *)&_mh_execute_header, segname, sectname));
  308 }
  309 
  310 /*
  311  * This routine can operate against any kernel segment_command structure to
  312  * return the first kernel section immediately following that structure.  If
  313  * there are no sections associated with the segment_command structure, it
  314  * returns NULL.
  315  */
  316 kernel_section_t *
  317 firstsect(kernel_segment_command_t *sgp)
  318 {
  319         if (!sgp || sgp->nsects == 0)
  320                 return (kernel_section_t *)NULL;
  321 
  322         return (kernel_section_t *)(sgp+1);
  323 }
  324 
  325 /*
  326  * This routine can operate against any kernel segment_command structure and
  327  * kernel section to return the next consecutive  kernel section immediately
  328  * following the kernel section provided.  If there are no sections following
  329  * the provided section, it returns NULL.
  330  */
  331 kernel_section_t *
  332 nextsect(kernel_segment_command_t *sgp, kernel_section_t *sp)
  333 {
  334         kernel_section_t *fsp = firstsect(sgp);
  335 
  336         if (((uintptr_t)(sp - fsp) + 1) >= sgp->nsects)
  337                 return (kernel_section_t *)NULL;
  338 
  339         return sp+1;
  340 }

Cache object: 371ff323ab1638edcf105ce5c656151c


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