Subversion Repositories Kolibri OS

Rev

Rev 3900 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <alloca.h>
  6. #include <malloc.h>
  7. #include <setjmp.h>
  8. #include <envz.h>
  9.  
  10. #include <kos32sys.h>
  11.  
  12. #include "list.h"
  13. #include "pe.h"
  14.  
  15. #define unlikely(x)     __builtin_expect(!!(x), 0)
  16.  
  17. //#define DBG(format,...) printf(format,##__VA_ARGS__)
  18.  
  19. #define DBG(format,...)
  20.  
  21.  
  22. void    init_loader(void *libc_image);
  23. void*   create_image(void *raw);
  24. int     link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp);
  25.  
  26. extern char* __appenv;
  27. extern int   __appenv_size;
  28.  
  29. typedef struct tag_module module_t;
  30.  
  31. struct app_hdr
  32. {
  33.     char  banner[8];
  34.     int   version;
  35.     int   start;
  36.     int   iend;
  37.     int   memsize;
  38.     int   stacktop;
  39.     char  *cmdline;
  40.     char  *path;
  41.     int    reserved;
  42.     void  *__idata_start;
  43.     void  *__idata_end;
  44.     void  (*main)(int argc, char **argv, char **envp);
  45. };
  46.  
  47. struct tag_module
  48. {
  49.     struct list_head list;
  50.  
  51.     char       *img_name;
  52.     char       *img_path;
  53.  
  54.     uint32_t    refcount;
  55.  
  56.     void       *start;
  57.     uint32_t    end;
  58.  
  59.     void       *entry;
  60.  
  61.     PIMAGE_NT_HEADERS32      img_hdr;
  62.     PIMAGE_SECTION_HEADER    img_sec;
  63.     PIMAGE_EXPORT_DIRECTORY  img_exp;
  64. };
  65.  
  66. typedef struct
  67. {
  68.     struct list_head list;
  69.     char *path;
  70.     int   path_len;
  71. }dll_path_t;
  72.  
  73. module_t* load_library(const char *name);
  74.  
  75. LIST_HEAD(path_list);
  76.  
  77. static module_t libc_dll;
  78. static char libc_name[] = "libc.dll";
  79. static char libc_path[] = "/KolibriOS/lib/libc.dll";
  80.  
  81. static inline int IsPowerOf2(uint32_t val)
  82. {
  83.     if(val == 0)
  84.         return 0;
  85.     return (val & (val - 1)) == 0;
  86. }
  87.  
  88.  
  89. int validate_pe(void *raw, size_t raw_size, int is_exec)
  90. {
  91.     PIMAGE_DOS_HEADER     dos;
  92.     PIMAGE_NT_HEADERS32   nt;
  93.  
  94.     dos = (PIMAGE_DOS_HEADER)raw;
  95.  
  96.     if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
  97.         return 0;
  98.  
  99.     if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
  100.         return 0;
  101.  
  102.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  103.  
  104.     if( (uint32_t)nt < (uint32_t)raw)
  105.         return 0;
  106.  
  107.     if(nt->Signature != IMAGE_NT_SIGNATURE)
  108.         return 0;
  109.  
  110.     if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
  111.         return 0;
  112.  
  113.     if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
  114.         return 0;
  115.  
  116.     if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  117.         return 0;
  118.  
  119.     if( is_exec && nt->OptionalHeader.ImageBase != 0)
  120.         return 0;
  121.  
  122.     if(nt->OptionalHeader.SectionAlignment < 4096)
  123.     {
  124.         if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
  125.             return 0;
  126.     }
  127.     else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
  128.         return 0;
  129.  
  130.     if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
  131.        !IsPowerOf2(nt->OptionalHeader.FileAlignment))
  132.         return 0;
  133.  
  134.     if(nt->FileHeader.NumberOfSections > 96)
  135.         return 0;
  136.  
  137.     return 1;
  138. }
  139.  
  140.  
  141. void init_loader(void *libc_image)
  142. {
  143.  
  144.     PIMAGE_DOS_HEADER        dos;
  145.     PIMAGE_NT_HEADERS32      nt;
  146.     PIMAGE_EXPORT_DIRECTORY  exp;
  147.  
  148.     struct app_hdr  *header = NULL;
  149.     dll_path_t      *path;
  150.     int             len;
  151.     char            *p;
  152.  
  153. #if 0
  154.  
  155.     if(__appenv_size)
  156.     {
  157.         char *env;
  158.         env = envz_get(__appenv, __appenv_size, "PATH");
  159.         if( env )
  160.         {
  161.             while( *env )
  162.             {
  163.                 p = env;
  164.                 while(*p)
  165.                 {
  166.                     if( *p == 0x0D)
  167.                         break;
  168.                     else if( *p == 0x0A)
  169.                         break;
  170.                     else if( *p == ':')
  171.                         break;
  172.                     p++;
  173.                 };
  174.                 len = p-env;
  175.                 if(len)
  176.                 {
  177.                     char *p1;
  178.  
  179.                     p1 = (char*)malloc(len+1);
  180.                     memcpy(p1, env, len);
  181.                     p1[len]=0;
  182.  
  183.                     path = (dll_path_t*)malloc(sizeof(dll_path_t));
  184.                     INIT_LIST_HEAD(&path->list);
  185.                     path->path = p1;
  186.                     path->path_len = len;
  187.                     DBG("add libraries path %s\n", path->path);
  188.                     list_add_tail(&path->list, &path_list);
  189.                 };
  190.                 if(*p == ':')
  191.                 {
  192.                     env = p+1;
  193.                     continue;
  194.                 }
  195.                 else break;
  196.             };
  197.         };
  198.     };
  199. #endif
  200.  
  201.     len = strrchr(header->path, '/') - header->path+1;
  202.     p = (char*)malloc(len+1);
  203.     memcpy(p, header->path, len);
  204.     p[len]=0;
  205.  
  206.     path = (dll_path_t*)malloc(sizeof(dll_path_t));
  207.     INIT_LIST_HEAD(&path->list);
  208.     path->path = p;
  209.     path->path_len = len;
  210.     DBG("add libraries path %s\n", path->path);
  211.     list_add_tail(&path->list, &path_list);
  212.  
  213.  
  214.     path = (dll_path_t*)malloc(sizeof(dll_path_t));
  215.     INIT_LIST_HEAD(&path->list);
  216.     path->path = "/kolibrios/lib/";
  217.     path->path_len = 15;                           /* FIXME */
  218.     DBG("add libraries path %s\n", path->path);
  219.     list_add_tail(&path->list, &path_list);
  220.  
  221.     INIT_LIST_HEAD(&libc_dll.list);
  222.  
  223.     libc_dll.img_name = libc_name;
  224.     libc_dll.img_path = libc_path;
  225.  
  226.     libc_dll.refcount = 1;
  227.  
  228.     dos =  (PIMAGE_DOS_HEADER)libc_image;
  229.     nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  230.     exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, libc_image,
  231.                    nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  232.  
  233.     libc_dll.start = libc_image;
  234.     libc_dll.end   = MakePtr(uint32_t,libc_image, nt->OptionalHeader.SizeOfImage);
  235.  
  236.     libc_dll.img_hdr  = nt;
  237.     libc_dll.img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
  238.     libc_dll.img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY,libc_image,
  239.                         nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  240.  
  241. };
  242.  
  243. static inline void sec_copy(void *dst, void *src, size_t len)
  244. {
  245.     __asm__ __volatile__ (
  246.     "shrl $2, %%ecx         \n\t"
  247.     "rep movsl"
  248.     :
  249.     :"c"(len),"S"(src),"D"(dst)
  250.     :"cc");
  251.     __asm__ __volatile__ (
  252.     ""
  253.     :::"ecx","esi","edi");
  254. };
  255.  
  256.  
  257. void* create_image(void *raw)
  258. {
  259.     PIMAGE_DOS_HEADER     dos;
  260.     PIMAGE_NT_HEADERS32   nt;
  261.     PIMAGE_SECTION_HEADER img_sec;
  262.  
  263.     void  *img_base;
  264.     uint32_t  sec_align;
  265.     int    i;
  266.  
  267.     dos = (PIMAGE_DOS_HEADER)raw;
  268.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  269.  
  270.     img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
  271.  
  272.     if(unlikely(img_base == NULL))
  273.         return 0;
  274.  
  275.     sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
  276.  
  277.     img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
  278.  
  279.     sec_align = nt->OptionalHeader.SectionAlignment;
  280.  
  281.     for(i=0; i< nt->FileHeader.NumberOfSections; i++)
  282.     {
  283.         void *src_ptr;
  284.         void *dest_ptr;
  285.         size_t   sec_size;
  286.  
  287.         if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
  288.         {
  289.             src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
  290.             dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
  291.             sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
  292.         };
  293.  
  294.         img_sec++;
  295.     };
  296.  
  297.     if(nt->OptionalHeader.DataDirectory[5].Size)
  298.     {
  299.         PIMAGE_BASE_RELOCATION reloc;
  300.  
  301.         uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
  302.  
  303.         reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
  304.                         nt->OptionalHeader.DataDirectory[5].VirtualAddress);
  305.  
  306.         while ( reloc->SizeOfBlock != 0 )
  307.         {
  308.             uint32_t  cnt;
  309.             uint16_t *entry;
  310.             uint16_t  reltype;
  311.             uint32_t  offs;
  312.  
  313.             cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
  314.             entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
  315.  
  316.             for ( i=0; i < cnt; i++ )
  317.             {
  318.                 uint16_t *p16;
  319.                 uint32_t *p32;
  320.  
  321.                 reltype = (*entry & 0xF000) >> 12;
  322.                 offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
  323.                 switch(reltype)
  324.                 {
  325.                     case 1:
  326.                         p16 = MakePtr(uint16_t*, img_base, offs);
  327.                         *p16+= (uint16_t)(delta>>16);
  328.                         break;
  329.                     case 2:
  330.                         p16 = MakePtr(uint16_t*, img_base, offs);
  331.                         *p16+= (uint16_t)delta;
  332.                         break;
  333.                     case 3:
  334.                         p32 = MakePtr(uint32_t*, img_base, offs);
  335.                         *p32+= delta;
  336.                 }
  337.                 entry++;
  338.             }
  339.             reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
  340.         }
  341.     };
  342.     return img_base;
  343. };
  344.  
  345. //static jmp_buf loader_env;
  346. //static loader_recursion;
  347.  
  348. int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp)
  349. {
  350.     static jmp_buf loader_env;
  351.     static recursion = -1;
  352.     int warn = 0;
  353.  
  354.     recursion++;
  355.     if( !recursion )
  356.     {
  357.         if( unlikely(setjmp(loader_env) != 0))
  358.         {
  359.             recursion = -1;
  360.             return 0;
  361.         };
  362.     };
  363.  
  364.     while ( imp->Name )
  365.     {
  366.         PIMAGE_DOS_HEADER        expdos;
  367.         PIMAGE_NT_HEADERS32      expnt;
  368.         PIMAGE_EXPORT_DIRECTORY  exp;
  369.         PIMAGE_THUNK_DATA32      thunk;
  370.  
  371.         void       **iat;
  372.         char       *libname;
  373.         uint32_t   *exp_functions;
  374.         uint16_t   *exp_ordinals;
  375.         char      **exp_names;
  376.  
  377.         const module_t *api;
  378.  
  379.         libname=MakePtr(char*,imp->Name, img_base);
  380.  
  381.         DBG("import from %s\n",libname);
  382.  
  383.         api = load_library(libname);
  384.         if(unlikely(api == NULL))
  385.         {
  386.             printf("library %s not found\n", libname);
  387.             longjmp(loader_env, 1);
  388.         }
  389.  
  390.         iat = MakePtr(void**,imp->FirstThunk, img_base);
  391.  
  392.         if(imp->OriginalFirstThunk !=0 )
  393.         {
  394.             thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base);
  395.         }
  396.         else
  397.         {
  398.             thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base);
  399.         };
  400.  
  401.         exp = api->img_exp;
  402.  
  403.         exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start);
  404.         exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,api->start);
  405.         exp_names = MakePtr(char**, exp->AddressOfNames,api->start);
  406.  
  407.         while ( thunk->u1.AddressOfData != 0 )
  408.         {
  409.             PIMAGE_IMPORT_BY_NAME imp_name;
  410.  
  411.             if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
  412.             {
  413. //                ordinal = (*func_list) & 0x7fffffff;
  414. //               *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
  415. //                if ((*ImportAddressList) == NULL)
  416. //                {
  417. //                    DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
  418. //                    RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
  419. //                    return STATUS_ENTRYPOINT_NOT_FOUND;
  420. //                }
  421.             }
  422.             else
  423.             {
  424.                 char *export_name;
  425.                 uint16_t   ordinal;
  426.                 void      *function;
  427.                 uint32_t   minn;
  428.                 uint32_t   maxn;
  429.  
  430.                 imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
  431.                               thunk->u1.AddressOfData, img_base);
  432.                 *iat = NULL;
  433.  
  434.                 DBG("import %s", imp_name->Name);
  435.  
  436.                 if(imp_name->Hint < exp->NumberOfNames)
  437.                 {
  438.                     export_name = MakePtr(char*,exp_names[imp_name->Hint],
  439.                                           api->start);
  440.                     if(strcmp(imp_name->Name, export_name) == 0)
  441.                     {
  442.                         ordinal = exp_ordinals[imp_name->Hint];
  443.                         function = MakePtr(void*,exp_functions[ordinal], api->start);
  444.                         if((uint32_t)function >= (uint32_t)exp)
  445.                         {
  446.                             printf("forward %s\n", function);
  447.                             warn=1;
  448.                         }
  449.                         else
  450.                         {
  451.                             DBG(" \t\tat %x\n", function);
  452.                             *iat = function;
  453.                         };
  454.                         thunk++;  // Advance to next thunk
  455.                         iat++;
  456.                         continue;
  457.                     };
  458.                 };
  459.  
  460.  
  461.                 minn = 0;
  462.                 maxn = exp->NumberOfNames - 1;
  463.                 while (minn <= maxn)
  464.                 {
  465.                     int mid;
  466.                     int res;
  467.  
  468.                     mid = (minn + maxn) / 2;
  469.  
  470.                     export_name = MakePtr(char*,exp_names[mid],api->start);
  471.  
  472.                     res = strcmp(export_name, imp_name->Name);
  473.                     if (res == 0)
  474.                     {
  475.                         ordinal  = exp_ordinals[mid];
  476.                         function = MakePtr(void*,exp_functions[ordinal], api->start);
  477.  
  478.                         if((uint32_t)function >= (uint32_t)exp)
  479.                         {
  480.                             printf("forward %s\n", function);
  481.                             warn=1;
  482.                         }
  483.                         else
  484.                         {
  485.                             DBG(" \t\tat %x\n", function);
  486.                             *iat = function;
  487.                         };
  488.                         break;
  489.                     }
  490.                     else if (minn == maxn)
  491.                     {
  492.                         printf(" unresolved %s\n",imp_name->Name);
  493.                         warn=1;
  494.                         break;
  495.                     }
  496.                     else if (res > 0)
  497.                     {
  498.                         maxn = mid - 1;
  499.                     }
  500.                     else
  501.                     {
  502.                         minn = mid + 1;
  503.                     }
  504.                 };
  505.             };
  506.             thunk++;            // Advance to next thunk
  507.             iat++;
  508.         }
  509.         imp++;  // advance to next IMAGE_IMPORT_DESCRIPTOR
  510.     };
  511.  
  512.     recursion--;
  513.  
  514.     if ( !warn )
  515.         return 1;
  516.     else
  517.         return 0;
  518. }
  519.  
  520. int link_app()
  521. {
  522.     struct app_hdr *header = NULL;
  523.     PIMAGE_IMPORT_DESCRIPTOR imp;
  524.  
  525.     imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start;
  526.  
  527.     return link_image(NULL, imp);
  528.  
  529. }
  530.  
  531.  
  532. void* get_entry_point(void *raw)
  533. {
  534.     PIMAGE_DOS_HEADER     dos;
  535.     PIMAGE_NT_HEADERS32   nt;
  536.  
  537.     dos = (PIMAGE_DOS_HEADER)raw;
  538.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  539.  
  540.     return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
  541. };
  542.  
  543.  
  544. void *get_proc_address(module_t *module, char *proc_name)
  545. {
  546.  
  547.     PIMAGE_DOS_HEADER        expdos;
  548.     PIMAGE_NT_HEADERS32      expnt;
  549.     PIMAGE_EXPORT_DIRECTORY  exp;
  550.  
  551.     uint32_t   *exp_functions;
  552.     uint16_t   *exp_ordinals;
  553.     char      **exp_names;
  554.  
  555.     int minn, maxn;
  556.     char *export_name;
  557.     uint16_t   ordinal;
  558.     void *function=NULL;
  559.  
  560.     exp = module->img_exp;
  561.  
  562.     exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,module->start);
  563.     exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,module->start);
  564.     exp_names = MakePtr(char**, exp->AddressOfNames,module->start);
  565.  
  566.     minn = 0;
  567.     maxn = exp->NumberOfNames - 1;
  568.     while (minn <= maxn)
  569.     {
  570.         int mid;
  571.         int res;
  572.  
  573.         mid = (minn + maxn) / 2;
  574.  
  575.         export_name = MakePtr(char*,exp_names[mid],module->start);
  576.  
  577.         res = strcmp(export_name, proc_name);
  578.         if (res == 0)
  579.         {
  580.             ordinal  = exp_ordinals[mid];
  581.             function = MakePtr(void*,exp_functions[ordinal], module->start);
  582.  
  583.             if((uint32_t)function >= (uint32_t)exp)
  584.             {
  585.                 printf("forward %s\n", function);
  586.             }
  587.             else
  588.             {
  589.                 DBG(" \t\tat %x\n", function);
  590.             };
  591.             break;
  592.         }
  593.         else if (minn == maxn)
  594.         {
  595.             DBG(" unresolved %s\n",proc_name);
  596.             break;
  597.         }
  598.         else if (res > 0)
  599.         {
  600.             maxn = mid - 1;
  601.         }
  602.         else
  603.         {
  604.             minn = mid + 1;
  605.         }
  606.     };
  607.  
  608.     return function;
  609. };
  610.  
  611. static void *load_lib_internal(const char *path)
  612. {
  613.     PIMAGE_DOS_HEADER        dos;
  614.     PIMAGE_NT_HEADERS32      nt;
  615.     PIMAGE_EXPORT_DIRECTORY  exp;
  616.  
  617.     ufile_t   uf;
  618.     void     *raw_img;
  619.     size_t    raw_size;
  620.     void     *img_base = NULL;
  621.  
  622.     uf = load_file(path);
  623.     raw_img  = uf.data;
  624.     raw_size = uf.size;
  625.  
  626.     if(raw_img == NULL)
  627.         return NULL;
  628.  
  629.     if( validate_pe(raw_img, raw_size, 0) == 0)
  630.     {
  631.         printf("invalide module %s\n", path);
  632.         user_free(raw_img);
  633.         return NULL;
  634.     };
  635.  
  636.     img_base = create_image(raw_img);
  637.     user_free(raw_img);
  638.  
  639.     if( unlikely(img_base == NULL) )
  640.         printf("cannot create image %s\n",path);
  641.  
  642.     return img_base;
  643. }
  644.  
  645. module_t* load_library(const char *name)
  646. {
  647.     PIMAGE_DOS_HEADER        dos;
  648.     PIMAGE_NT_HEADERS32      nt;
  649.     PIMAGE_EXPORT_DIRECTORY  exp;
  650.  
  651.     module_t    *module, *mod = &libc_dll;
  652.     dll_path_t  *dllpath;
  653.     char        *path;
  654.     int          len;
  655.     char        *libname, *tmp;
  656.     void        *img_base;
  657.  
  658.  
  659. /*  check for already loaded libraries  */
  660.  
  661.     tmp = strrchr(name, '/');
  662.     libname = path = tmp != NULL ? tmp+1 : (char*)name;
  663.  
  664. //    printf("path %s\n", path);
  665.  
  666.     do
  667.     {
  668.         if( !strncmp(path, mod->img_name, 16))
  669.             return mod;
  670.         mod = (module_t*)mod->list.next;
  671.     }while(mod != &libc_dll);
  672.  
  673.     if(name[0] == '/')
  674.     {
  675.         path = (char*)name;
  676.         img_base = load_lib_internal(path);
  677.     }
  678.     else
  679.     {
  680.         len = strlen(libname);
  681.         list_for_each_entry(dllpath, &path_list, list)
  682.         {
  683.             path = alloca(len+dllpath->path_len+1);
  684.             memcpy(path, dllpath->path, dllpath->path_len);
  685.  
  686.             memcpy(path+dllpath->path_len, libname, len);
  687.             path[len+dllpath->path_len]=0;
  688.  
  689. //            printf("%s\n", path);
  690.  
  691.             img_base = load_lib_internal(path);
  692.  
  693.             if( unlikely(img_base == NULL) )
  694.                 continue;
  695.         };
  696.     }
  697.  
  698.     if( unlikely(img_base == NULL) )
  699.     {
  700.         printf("unable to load %s\n", name);
  701.         return NULL;
  702.     };
  703.  
  704.     module = (module_t*)malloc(sizeof(module_t));
  705.  
  706.     if(unlikely(module == NULL))
  707.     {
  708.         printf("%s epic fail: no enough memory\n",__FUNCTION__);
  709.         goto err1;
  710.     }
  711.  
  712.     INIT_LIST_HEAD(&module->list);
  713.  
  714.     module->img_name = strdup(libname);
  715.     module->img_path = strdup(path);
  716.     module->start    = img_base;
  717.     module->entry    = get_entry_point(img_base);
  718.     module->refcount = 1;
  719.  
  720.     dos =  (PIMAGE_DOS_HEADER)img_base;
  721.     nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  722.     exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  723.                nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  724.  
  725.     module->end   = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage);
  726.  
  727.     module->img_hdr  = nt;
  728.     module->img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
  729.     module->img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  730.                        nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  731.  
  732.     list_add_tail(&module->list, &libc_dll.list);
  733.  
  734.     if(nt->OptionalHeader.DataDirectory[1].Size)
  735.     {
  736.         PIMAGE_IMPORT_DESCRIPTOR imp;
  737.         int (*dll_startup)(module_t *mod, uint32_t reason);
  738.  
  739.         imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
  740.                     nt->OptionalHeader.DataDirectory[1].VirtualAddress);
  741.  
  742.         if(link_image(img_base, imp) == 0)
  743.             goto err2;
  744.  
  745.         dll_startup = get_proc_address(module, "DllStartup");
  746.         if( dll_startup )
  747.         {
  748.             if( 0 == dll_startup(module, 1))
  749.                 goto err2;
  750.         }
  751.     };
  752.  
  753.     return module;
  754.  
  755. err2:
  756.     list_del(&module->list);
  757.     free(module->img_name);
  758.     free(module->img_path);
  759.     free(module);
  760. err1:
  761.     user_free(img_base);
  762.     return NULL;
  763.  
  764. };
  765.  
  766.  
  767.