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/compat/ndis/subr_pe.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) 2003
    3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Bill Paul.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 /*
   37  * This file contains routines for relocating and dynamically linking
   38  * executable object code files in the Windows(r) PE (Portable Executable)
   39  * format. In Windows, anything with a .EXE, .DLL or .SYS extention is
   40  * considered an executable, and all such files have some structures in
   41  * common. The PE format was apparently based largely on COFF but has
   42  * mutated significantly over time. We are mainly concerned with .SYS files,
   43  * so this module implements only enough routines to be able to parse the
   44  * headers and sections of a .SYS object file and perform the necessary
   45  * relocations and jump table patching to allow us to call into it
   46  * (and to have it call back to us). Note that while this module
   47  * can handle fixups for imported symbols, it knows nothing about
   48  * exporting them.
   49  */
   50 
   51 #include <sys/param.h>
   52 #include <sys/types.h>
   53 #include <sys/errno.h>
   54 #ifdef _KERNEL
   55 #include <sys/systm.h>
   56 #else
   57 #include <stdio.h>
   58 #include <stddef.h>
   59 #include <stdlib.h>
   60 #include <unistd.h>
   61 #include <string.h>
   62 #endif
   63 
   64 #include <compat/ndis/pe_var.h>
   65 
   66 static vm_offset_t pe_functbl_match(image_patch_table *, char *);
   67 
   68 /*
   69  * Check for an MS-DOS executable header. All Windows binaries
   70  * have a small MS-DOS executable prepended to them to print out
   71  * the "This program requires Windows" message. Even .SYS files
   72  * have this header, in spite of the fact that you're can't actually
   73  * run them directly.
   74  */
   75 
   76 int
   77 pe_get_dos_header(imgbase, hdr)
   78         vm_offset_t             imgbase;
   79         image_dos_header        *hdr;
   80 {
   81         uint16_t                signature;
   82 
   83         if (imgbase == 0 || hdr == NULL)
   84                 return (EINVAL);
   85 
   86         signature = *(uint16_t *)imgbase;
   87         if (signature != IMAGE_DOS_SIGNATURE)
   88                 return (ENOEXEC);
   89 
   90         bcopy ((char *)imgbase, (char *)hdr, sizeof(image_dos_header));
   91 
   92         return (0);
   93 }
   94 
   95 /*
   96  * Verify that this image has a Windows NT PE signature.
   97  */
   98 
   99 int
  100 pe_is_nt_image(imgbase)
  101         vm_offset_t             imgbase;
  102 {
  103         uint32_t                signature;
  104         image_dos_header        *dos_hdr;
  105 
  106         if (imgbase == 0)
  107                 return (EINVAL);
  108 
  109         signature = *(uint16_t *)imgbase;
  110         if (signature == IMAGE_DOS_SIGNATURE) {
  111                 dos_hdr = (image_dos_header *)imgbase;
  112                 signature = *(uint32_t *)(imgbase + dos_hdr->idh_lfanew);
  113                 if (signature == IMAGE_NT_SIGNATURE)
  114                         return (0);
  115         }
  116 
  117         return (ENOEXEC);
  118 }
  119 
  120 /*
  121  * Return a copy of the optional header. This contains the
  122  * executable entry point and the directory listing which we
  123  * need to find the relocations and imports later.
  124  */
  125 
  126 int
  127 pe_get_optional_header(imgbase, hdr)
  128         vm_offset_t             imgbase;
  129         image_optional_header   *hdr;
  130 {
  131         image_dos_header        *dos_hdr;
  132         image_nt_header         *nt_hdr;
  133 
  134         if (imgbase == 0 || hdr == NULL)
  135                 return (EINVAL);
  136 
  137         if (pe_is_nt_image(imgbase))
  138                 return (EINVAL);
  139 
  140         dos_hdr = (image_dos_header *)(imgbase);
  141         nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
  142 
  143         bcopy ((char *)&nt_hdr->inh_optionalhdr, (char *)hdr,
  144             nt_hdr->inh_filehdr.ifh_optionalhdrlen);
  145 
  146         return (0);
  147 }
  148 
  149 /*
  150  * Return a copy of the file header. Contains the number of
  151  * sections in this image.
  152  */
  153 
  154 int
  155 pe_get_file_header(imgbase, hdr)
  156         vm_offset_t             imgbase;
  157         image_file_header       *hdr;
  158 {
  159         image_dos_header        *dos_hdr;
  160         image_nt_header         *nt_hdr;
  161 
  162         if (imgbase == 0 || hdr == NULL)
  163                 return (EINVAL);
  164 
  165         if (pe_is_nt_image(imgbase))
  166                 return (EINVAL);
  167 
  168         dos_hdr = (image_dos_header *)imgbase;
  169         nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
  170 
  171         /*
  172          * Note: the size of the nt_header is variable since it
  173          * can contain optional fields, as indicated by ifh_optionalhdrlen.
  174          * However it happens we're only interested in fields in the
  175          * non-variant portion of the nt_header structure, so we don't
  176          * bother copying the optional parts here.
  177          */
  178 
  179         bcopy ((char *)&nt_hdr->inh_filehdr, (char *)hdr,
  180             sizeof(image_file_header));
  181 
  182         return (0);
  183 }
  184 
  185 /*
  186  * Return the header of the first section in this image (usually
  187  * .text).
  188  */
  189 
  190 int
  191 pe_get_section_header(imgbase, hdr)
  192         vm_offset_t             imgbase;
  193         image_section_header    *hdr;
  194 {
  195         image_dos_header        *dos_hdr;
  196         image_nt_header         *nt_hdr;
  197         image_section_header    *sect_hdr;
  198 
  199         if (imgbase == 0 || hdr == NULL)
  200                 return (EINVAL);
  201 
  202         if (pe_is_nt_image(imgbase))
  203                 return (EINVAL);
  204 
  205         dos_hdr = (image_dos_header *)imgbase;
  206         nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
  207         sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
  208 
  209         bcopy ((char *)sect_hdr, (char *)hdr, sizeof(image_section_header));
  210 
  211         return (0);
  212 }
  213 
  214 /*
  215  * Return the number of sections in this executable, or 0 on error.
  216  */
  217 
  218 int
  219 pe_numsections(imgbase)
  220         vm_offset_t             imgbase;
  221 {
  222         image_file_header       file_hdr;
  223 
  224         if (pe_get_file_header(imgbase, &file_hdr))
  225                 return (0);
  226 
  227         return (file_hdr.ifh_numsections);
  228 }
  229 
  230 /*
  231  * Return the base address that this image was linked for.
  232  * This helps us calculate relocation addresses later.
  233  */
  234 
  235 vm_offset_t
  236 pe_imagebase(imgbase)
  237         vm_offset_t             imgbase;
  238 {
  239         image_optional_header   optional_hdr;
  240 
  241         if (pe_get_optional_header(imgbase, &optional_hdr))
  242                 return (0);
  243 
  244         return (optional_hdr.ioh_imagebase);
  245 }
  246 
  247 /*
  248  * Return the offset of a given directory structure within the
  249  * image. Directories reside within sections.
  250  */
  251 
  252 vm_offset_t
  253 pe_directory_offset(imgbase, diridx)
  254         vm_offset_t             imgbase;
  255         uint32_t                diridx;
  256 {
  257         image_optional_header   opt_hdr;
  258         vm_offset_t             dir;
  259 
  260         if (pe_get_optional_header(imgbase, &opt_hdr))
  261                 return (0);
  262 
  263         if (diridx >= opt_hdr.ioh_rva_size_cnt)
  264                 return (0);
  265 
  266         dir = opt_hdr.ioh_datadir[diridx].idd_vaddr;
  267 
  268         return (pe_translate_addr(imgbase, dir));
  269 }
  270 
  271 vm_offset_t
  272 pe_translate_addr(imgbase, rva)
  273         vm_offset_t             imgbase;
  274         vm_offset_t             rva;
  275 {
  276         image_optional_header   opt_hdr;
  277         image_section_header    *sect_hdr;
  278         image_dos_header        *dos_hdr;
  279         image_nt_header         *nt_hdr;
  280         int                     i = 0, sections, fixedlen;
  281 
  282         if (pe_get_optional_header(imgbase, &opt_hdr))
  283                 return (0);
  284 
  285         sections = pe_numsections(imgbase);
  286 
  287         dos_hdr = (image_dos_header *)imgbase;
  288         nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
  289         sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
  290 
  291         /*
  292          * The test here is to see if the RVA falls somewhere
  293          * inside the section, based on the section's start RVA
  294          * and its length. However it seems sometimes the
  295          * virtual length isn't enough to cover the entire
  296          * area of the section. We fudge by taking into account
  297          * the section alignment and rounding the section length
  298          * up to a page boundary.
  299          */
  300         while (i++ < sections) {
  301                 fixedlen = sect_hdr->ish_misc.ish_vsize;
  302                 fixedlen += ((opt_hdr.ioh_sectalign - 1) -
  303                     sect_hdr->ish_misc.ish_vsize) &
  304                     (opt_hdr.ioh_sectalign - 1);
  305                 if (sect_hdr->ish_vaddr <= (uint32_t)rva &&
  306                     (sect_hdr->ish_vaddr + fixedlen) >
  307                     (uint32_t)rva)
  308                         break;
  309                 sect_hdr++;
  310         }
  311 
  312         if (i > sections)
  313                 return (0);
  314 
  315         return ((vm_offset_t)(imgbase + rva - sect_hdr->ish_vaddr +
  316             sect_hdr->ish_rawdataaddr));
  317 }
  318 
  319 /*
  320  * Get the section header for a particular section. Note that
  321  * section names can be anything, but there are some standard
  322  * ones (.text, .data, .rdata, .reloc).
  323  */
  324 
  325 int
  326 pe_get_section(imgbase, hdr, name)
  327         vm_offset_t             imgbase;
  328         image_section_header    *hdr;
  329         const char              *name;
  330 {
  331         image_dos_header        *dos_hdr;
  332         image_nt_header         *nt_hdr;
  333         image_section_header    *sect_hdr;
  334 
  335         int                     i, sections;
  336 
  337         if (imgbase == 0 || hdr == NULL)
  338                 return (EINVAL);
  339 
  340         if (pe_is_nt_image(imgbase))
  341                 return (EINVAL);
  342 
  343         sections = pe_numsections(imgbase);
  344 
  345         dos_hdr = (image_dos_header *)imgbase;
  346         nt_hdr = (image_nt_header *)(imgbase + dos_hdr->idh_lfanew);
  347         sect_hdr = IMAGE_FIRST_SECTION(nt_hdr);
  348 
  349         for (i = 0; i < sections; i++) {
  350                 if (!strcmp ((char *)&sect_hdr->ish_name, name)) {
  351                         bcopy((char *)sect_hdr, (char *)hdr,
  352                             sizeof(image_section_header));
  353                         return (0);
  354                 } else
  355                         sect_hdr++;
  356         }
  357 
  358         return (ENOEXEC);
  359 }
  360 
  361 /*
  362  * Apply the base relocations to this image. The relocation table
  363  * resides within the .reloc section. Relocations are specified in
  364  * blocks which refer to a particular page. We apply the relocations
  365  * one page block at a time.
  366  */
  367 
  368 int
  369 pe_relocate(imgbase)
  370         vm_offset_t             imgbase;
  371 {
  372         image_section_header    sect;
  373         image_base_reloc        *relhdr;
  374         uint16_t                rel, *sloc;
  375         vm_offset_t             base;
  376         vm_size_t               delta;
  377         uint32_t                *lloc;
  378         uint64_t                *qloc;
  379         int                     i, count;
  380         vm_offset_t             txt;
  381 
  382         base = pe_imagebase(imgbase);
  383         pe_get_section(imgbase, &sect, ".text");
  384         txt = pe_translate_addr(imgbase, sect.ish_vaddr);
  385         delta = (uint32_t)(txt) - base - sect.ish_vaddr;
  386 
  387         pe_get_section(imgbase, &sect, ".reloc");
  388 
  389         relhdr = (image_base_reloc *)(imgbase + sect.ish_rawdataaddr);
  390 
  391         do {
  392                 count = (relhdr->ibr_blocksize -
  393                     (sizeof(uint32_t) * 2)) / sizeof(uint16_t);
  394                 for (i = 0; i < count; i++) {
  395                         rel = relhdr->ibr_rel[i];
  396                         switch (IMR_RELTYPE(rel)) {
  397                         case IMAGE_REL_BASED_ABSOLUTE:
  398                                 break;
  399                         case IMAGE_REL_BASED_HIGHLOW:
  400                                 lloc = (uint32_t *)pe_translate_addr(imgbase,
  401                                     relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
  402                                 *lloc = pe_translate_addr(imgbase,
  403                                     (*lloc - base));
  404                                 break;
  405                         case IMAGE_REL_BASED_HIGH:
  406                                 sloc = (uint16_t *)pe_translate_addr(imgbase,
  407                                     relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
  408                                 *sloc += (delta & 0xFFFF0000) >> 16;
  409                                 break;
  410                         case IMAGE_REL_BASED_LOW:
  411                                 sloc = (uint16_t *)pe_translate_addr(imgbase,
  412                                     relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
  413                                 *sloc += (delta & 0xFFFF);
  414                                 break;
  415                         case IMAGE_REL_BASED_DIR64:
  416                                 qloc = (uint64_t *)pe_translate_addr(imgbase,
  417                                     relhdr->ibr_vaddr + IMR_RELOFFSET(rel));
  418                                 *qloc = pe_translate_addr(imgbase,
  419                                     (*qloc - base));
  420                                 break;
  421 
  422                         default:
  423                                 printf("[%d]reloc type: %d\n",i,
  424                                     IMR_RELTYPE(rel));
  425                                 break;
  426                         }
  427                 }
  428                 relhdr = (image_base_reloc *)((vm_offset_t)relhdr +
  429                     relhdr->ibr_blocksize);
  430         } while (relhdr->ibr_blocksize);
  431 
  432         return (0);
  433 }
  434 
  435 /*
  436  * Return the import descriptor for a particular module. An image
  437  * may be linked against several modules, typically HAL.dll, ntoskrnl.exe
  438  * and NDIS.SYS. For each module, there is a list of imported function
  439  * names and their addresses.
  440  *
  441  * Note: module names are case insensitive!
  442  */
  443 
  444 int
  445 pe_get_import_descriptor(imgbase, desc, module)
  446         vm_offset_t             imgbase;
  447         image_import_descriptor *desc;
  448         char                    *module;
  449 {
  450         vm_offset_t             offset;
  451         image_import_descriptor *imp_desc;
  452         char                    *modname;
  453 
  454         if (imgbase == 0 || module == NULL || desc == NULL)
  455                 return (EINVAL);
  456 
  457         offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_IMPORT);
  458         if (offset == 0)
  459                 return (ENOENT);
  460 
  461         imp_desc = (void *)offset;
  462 
  463         while (imp_desc->iid_nameaddr) {
  464                 modname = (char *)pe_translate_addr(imgbase,
  465                     imp_desc->iid_nameaddr);
  466                 if (!strncasecmp(module, modname, strlen(module))) {
  467                         bcopy((char *)imp_desc, (char *)desc,
  468                             sizeof(image_import_descriptor));
  469                         return (0);
  470                 }
  471                 imp_desc++;
  472         }
  473 
  474         return (ENOENT);
  475 }
  476 
  477 int
  478 pe_get_messagetable(imgbase, md)
  479         vm_offset_t             imgbase;
  480         message_resource_data   **md;
  481 {
  482         image_resource_directory        *rdir, *rtype;
  483         image_resource_directory_entry  *dent, *dent2;
  484         image_resource_data_entry       *rent;
  485         vm_offset_t             offset;
  486         int                     i;
  487 
  488         if (imgbase == 0)
  489                 return (EINVAL);
  490 
  491         offset = pe_directory_offset(imgbase, IMAGE_DIRECTORY_ENTRY_RESOURCE);
  492         if (offset == 0)
  493                 return (ENOENT);
  494 
  495         rdir = (image_resource_directory *)offset;
  496 
  497         dent = (image_resource_directory_entry *)(offset +
  498             sizeof(image_resource_directory));
  499 
  500         for (i = 0; i < rdir->ird_id_entries; i++){
  501                 if (dent->irde_name != RT_MESSAGETABLE) {
  502                         dent++;
  503                         continue;
  504                 }
  505                 dent2 = dent;
  506                 while (dent2->irde_dataoff & RESOURCE_DIR_FLAG) {
  507                         rtype = (image_resource_directory *)(offset +
  508                             (dent2->irde_dataoff & ~RESOURCE_DIR_FLAG));
  509                         dent2 = (image_resource_directory_entry *)
  510                             ((uintptr_t)rtype +
  511                              sizeof(image_resource_directory));
  512                 }
  513                 rent = (image_resource_data_entry *)(offset +
  514                     dent2->irde_dataoff);
  515                 *md = (message_resource_data *)pe_translate_addr(imgbase,
  516                     rent->irde_offset);
  517                 return (0);
  518         }
  519 
  520         return (ENOENT);
  521 }
  522 
  523 int
  524 pe_get_message(imgbase, id, str, len, flags)
  525         vm_offset_t             imgbase;
  526         uint32_t                id;
  527         char                    **str;
  528         int                     *len;
  529         uint16_t                *flags;
  530 {
  531         message_resource_data   *md = NULL;
  532         message_resource_block  *mb;
  533         message_resource_entry  *me;
  534         uint32_t                i;
  535 
  536         pe_get_messagetable(imgbase, &md);
  537 
  538         if (md == NULL)
  539                 return (ENOENT);
  540 
  541         mb = (message_resource_block *)((uintptr_t)md +
  542             sizeof(message_resource_data));
  543 
  544         for (i = 0; i < md->mrd_numblocks; i++) {
  545                 if (id >= mb->mrb_lowid && id <= mb->mrb_highid) {
  546                         me = (message_resource_entry *)((uintptr_t)md +
  547                             mb->mrb_entryoff);
  548                         for (i = id - mb->mrb_lowid; i > 0; i--)
  549                                 me = (message_resource_entry *)((uintptr_t)me +
  550                                     me->mre_len);
  551                         *str = me->mre_text;
  552                         *len = me->mre_len;
  553                         *flags = me->mre_flags;
  554                         return (0);
  555                 }
  556                 mb++;
  557         }
  558 
  559         return (ENOENT);
  560 }
  561 
  562 /*
  563  * Find the function that matches a particular name. This doesn't
  564  * need to be particularly speedy since it's only run when loading
  565  * a module for the first time.
  566  */
  567 
  568 static vm_offset_t
  569 pe_functbl_match(functbl, name)
  570         image_patch_table       *functbl;
  571         char                    *name;
  572 {
  573         image_patch_table       *p;
  574 
  575         if (functbl == NULL || name == NULL)
  576                 return (0);
  577 
  578         p = functbl;
  579 
  580         while (p->ipt_name != NULL) {
  581                 if (!strcmp(p->ipt_name, name))
  582                         return ((vm_offset_t)p->ipt_wrap);
  583                 p++;
  584         }
  585         printf("no match for %s\n", name);
  586 
  587         /*
  588          * Return the wrapper pointer for this routine.
  589          * For x86, this is the same as the funcptr.
  590          * For amd64, this points to a wrapper routine
  591          * that does calling convention translation and
  592          * then invokes the underlying routine.
  593          */
  594         return ((vm_offset_t)p->ipt_wrap);
  595 }
  596 
  597 /*
  598  * Patch the imported function addresses for a given module.
  599  * The caller must specify the module name and provide a table
  600  * of function pointers that will be patched into the jump table.
  601  * Note that there are actually two copies of the jump table: one
  602  * copy is left alone. In a .SYS file, the jump tables are usually
  603  * merged into the INIT segment.
  604  */
  605 
  606 int
  607 pe_patch_imports(imgbase, module, functbl)
  608         vm_offset_t             imgbase;
  609         char                    *module;
  610         image_patch_table       *functbl;
  611 {
  612         image_import_descriptor imp_desc;
  613         char                    *fname;
  614         vm_offset_t             *nptr, *fptr;
  615         vm_offset_t             func;
  616 
  617         if (imgbase == 0 || module == NULL || functbl == NULL)
  618                 return (EINVAL);
  619 
  620         if (pe_get_import_descriptor(imgbase, &imp_desc, module))
  621                 return (ENOEXEC);
  622 
  623         nptr = (vm_offset_t *)pe_translate_addr(imgbase,
  624             imp_desc.iid_import_name_table_addr);
  625         fptr = (vm_offset_t *)pe_translate_addr(imgbase,
  626             imp_desc.iid_import_address_table_addr);
  627 
  628         while (nptr != NULL && pe_translate_addr(imgbase, *nptr)) {
  629                 fname = (char *)pe_translate_addr(imgbase, (*nptr) + 2);
  630                 func = pe_functbl_match(functbl, fname);
  631                 if (func)
  632                         *fptr = func;
  633 #ifdef notdef
  634                 if (*fptr == 0)
  635                         return (ENOENT);
  636 #endif
  637                 nptr++;
  638                 fptr++;
  639         }
  640 
  641         return (0);
  642 }

Cache object: 91eb84af6a8f11bb041357d946947229


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