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

Cache object: 21b006b651e28f90ee12150550ddea6c


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