Subversion Repositories Kolibri OS

Rev

Rev 4874 | Rev 5190 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | 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. static void send_dbg_msg(void *msg)
  521. {
  522.     __asm__ __volatile__(
  523.     "int $0x40"
  524.     ::"a"(69),
  525.       "b"(10),
  526.       "S"(msg));
  527. };
  528.  
  529.  
  530. int link_app()
  531. {
  532.     struct app_hdr *header = NULL;
  533.     PIMAGE_IMPORT_DESCRIPTOR imp;
  534.  
  535.     imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start;
  536.  
  537.     if(link_image(NULL, imp))
  538.     {
  539.  
  540. #ifdef DEBUG_INFO
  541.         struct
  542.         {
  543.             void     *start;
  544.             uint32_t  end;
  545.             char      name[24];
  546.         } dbg_msg;
  547.  
  548.         module_t *mod = &libc_dll;
  549.  
  550.         do
  551.         {
  552.             printf("%s %x - %x\n",
  553.                    mod->img_name, mod->start, mod->end);
  554.  
  555. //            asm volatile("int3");
  556.  
  557.             dbg_msg.start = mod->start;
  558.             dbg_msg.end   = mod->end;
  559.             strcpy(dbg_msg.name, mod->img_name);
  560.             send_dbg_msg(&dbg_msg);
  561.             mod = (module_t*)mod->list.next;
  562.         }while(mod != &libc_dll);
  563. #endif
  564.  
  565.         return 1;
  566.     };
  567.  
  568.     return 0;
  569. }
  570.  
  571.  
  572. void* get_entry_point(void *raw)
  573. {
  574.     PIMAGE_DOS_HEADER     dos;
  575.     PIMAGE_NT_HEADERS32   nt;
  576.  
  577.     dos = (PIMAGE_DOS_HEADER)raw;
  578.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  579.  
  580.     return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
  581. };
  582.  
  583.  
  584. void *get_proc_address(module_t *module, char *proc_name)
  585. {
  586.  
  587.     PIMAGE_DOS_HEADER        expdos;
  588.     PIMAGE_NT_HEADERS32      expnt;
  589.     PIMAGE_EXPORT_DIRECTORY  exp;
  590.  
  591.     uint32_t   *exp_functions;
  592.     uint16_t   *exp_ordinals;
  593.     char      **exp_names;
  594.  
  595.     int minn, maxn;
  596.     char *export_name;
  597.     uint16_t   ordinal;
  598.     void *function=NULL;
  599.  
  600.     exp = module->img_exp;
  601.  
  602.     exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,module->start);
  603.     exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,module->start);
  604.     exp_names = MakePtr(char**, exp->AddressOfNames,module->start);
  605.  
  606.     minn = 0;
  607.     maxn = exp->NumberOfNames - 1;
  608.     while (minn <= maxn)
  609.     {
  610.         int mid;
  611.         int res;
  612.  
  613.         mid = (minn + maxn) / 2;
  614.  
  615.         export_name = MakePtr(char*,exp_names[mid],module->start);
  616.  
  617.         res = strcmp(export_name, proc_name);
  618.         if (res == 0)
  619.         {
  620.             ordinal  = exp_ordinals[mid];
  621.             function = MakePtr(void*,exp_functions[ordinal], module->start);
  622.  
  623.             if((uint32_t)function >= (uint32_t)exp)
  624.             {
  625.                 printf("forward %s\n", function);
  626.             }
  627.             else
  628.             {
  629.                 DBG(" \t\tat %x\n", function);
  630.             };
  631.             break;
  632.         }
  633.         else if (minn == maxn)
  634.         {
  635.             DBG(" unresolved %s\n",proc_name);
  636.             break;
  637.         }
  638.         else if (res > 0)
  639.         {
  640.             maxn = mid - 1;
  641.         }
  642.         else
  643.         {
  644.             minn = mid + 1;
  645.         }
  646.     };
  647.  
  648.     return function;
  649. };
  650.  
  651. static void *load_lib_internal(const char *path)
  652. {
  653.     PIMAGE_DOS_HEADER        dos;
  654.     PIMAGE_NT_HEADERS32      nt;
  655.     PIMAGE_EXPORT_DIRECTORY  exp;
  656.  
  657.     ufile_t   uf;
  658.     void     *raw_img;
  659.     size_t    raw_size;
  660.     void     *img_base = NULL;
  661.  
  662.     uf = load_file(path);
  663.     raw_img  = uf.data;
  664.     raw_size = uf.size;
  665.  
  666.     if(raw_img == NULL)
  667.         return NULL;
  668.  
  669.     if( validate_pe(raw_img, raw_size, 0) == 0)
  670.     {
  671.         printf("invalide module %s\n", path);
  672.         user_free(raw_img);
  673.         return NULL;
  674.     };
  675.  
  676.     img_base = create_image(raw_img);
  677.     user_free(raw_img);
  678.  
  679.     if( unlikely(img_base == NULL) )
  680.         printf("cannot create image %s\n",path);
  681.  
  682.     return img_base;
  683. }
  684.  
  685. module_t* load_library(const char *name)
  686. {
  687.     PIMAGE_DOS_HEADER        dos;
  688.     PIMAGE_NT_HEADERS32      nt;
  689.     PIMAGE_EXPORT_DIRECTORY  exp;
  690.  
  691.     module_t    *module, *mod = &libc_dll;
  692.     dll_path_t  *dllpath;
  693.     char        *path;
  694.     int          len;
  695.     char        *libname, *tmp;
  696.     void        *img_base;
  697.  
  698.  
  699. /*  check for already loaded libraries  */
  700.  
  701.     tmp = strrchr(name, '/');
  702.     libname = path = tmp != NULL ? tmp+1 : (char*)name;
  703.  
  704. //    printf("path %s\n", path);
  705.  
  706.     do
  707.     {
  708.         if( !strncmp(path, mod->img_name, 16))
  709.             return mod;
  710.         mod = (module_t*)mod->list.next;
  711.     }while(mod != &libc_dll);
  712.  
  713.     if(name[0] == '/')
  714.     {
  715.         path = (char*)name;
  716.         img_base = load_lib_internal(path);
  717.     }
  718.     else
  719.     {
  720.         len = strlen(libname);
  721.         list_for_each_entry(dllpath, &path_list, list)
  722.         {
  723.             path = alloca(len+dllpath->path_len+1);
  724.             memcpy(path, dllpath->path, dllpath->path_len);
  725.  
  726.             memcpy(path+dllpath->path_len, libname, len);
  727.             path[len+dllpath->path_len]=0;
  728.  
  729. //            printf("%s\n", path);
  730.  
  731.             img_base = load_lib_internal(path);
  732.  
  733.             if( unlikely(img_base == NULL) )
  734.                 continue;
  735.         };
  736.     }
  737.  
  738.     if( unlikely(img_base == NULL) )
  739.     {
  740.         printf("unable to load %s\n", name);
  741.         return NULL;
  742.     };
  743.  
  744.     module = (module_t*)malloc(sizeof(module_t));
  745.  
  746.     if(unlikely(module == NULL))
  747.     {
  748.         printf("%s epic fail: no enough memory\n",__FUNCTION__);
  749.         goto err1;
  750.     }
  751.  
  752.     INIT_LIST_HEAD(&module->list);
  753.  
  754.     module->img_name = strdup(libname);
  755.     module->img_path = strdup(path);
  756.     module->start    = img_base;
  757.     module->entry    = get_entry_point(img_base);
  758.     module->refcount = 1;
  759.  
  760.     dos =  (PIMAGE_DOS_HEADER)img_base;
  761.     nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  762.     exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  763.                nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  764.  
  765.     module->end   = MakePtr(uint32_t,img_base, nt->OptionalHeader.SizeOfImage);
  766.  
  767.     module->img_hdr  = nt;
  768.     module->img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
  769.     module->img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  770.                        nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  771.  
  772.     list_add_tail(&module->list, &libc_dll.list);
  773.  
  774.     if(nt->OptionalHeader.DataDirectory[1].Size)
  775.     {
  776.         PIMAGE_IMPORT_DESCRIPTOR imp;
  777.         int (*dll_startup)(module_t *mod, uint32_t reason);
  778.  
  779.         imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
  780.                     nt->OptionalHeader.DataDirectory[1].VirtualAddress);
  781.  
  782.         if(link_image(img_base, imp) == 0)
  783.             goto err2;
  784.  
  785.         dll_startup = get_proc_address(module, "DllStartup");
  786.         if( dll_startup )
  787.         {
  788.             if( 0 == dll_startup(module, 1))
  789.                 goto err2;
  790.         }
  791.     };
  792.  
  793. //    printf("module %s %p - %p\n", name, module->start, module->end);
  794.  
  795.     return module;
  796.  
  797. err2:
  798.     list_del(&module->list);
  799.     free(module->img_name);
  800.     free(module->img_path);
  801.     free(module);
  802. err1:
  803.     user_free(img_base);
  804.     return NULL;
  805.  
  806. };
  807.  
  808.  
  809.