Subversion Repositories Kolibri OS

Rev

Rev 6536 | 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 <sys/ksys.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. void*   load_library(const char *name);
  26.  
  27. extern char* __appenv;
  28. extern int   __appenv_size;
  29.  
  30. typedef struct tag_module module_t;
  31.  
  32. struct app_hdr
  33. {
  34.     char  banner[8];
  35.     int   version;
  36.     int   start;
  37.     int   iend;
  38.     int   memsize;
  39.     int   stacktop;
  40.     char  *cmdline;
  41.     char  *path;
  42.     int    reserved;
  43.     void  *__idata_start;
  44.     void  *__idata_end;
  45.     void  (*main)(int argc, char **argv, char **envp);
  46. };
  47.  
  48. struct tag_module
  49. {
  50.     struct list_head list;
  51.  
  52.     char       *img_name;
  53.     char       *img_path;
  54.  
  55.     uint32_t    refcount;
  56.  
  57.     char       *start;
  58.     char       *end;
  59.  
  60.     void       *entry;
  61.  
  62.     PIMAGE_NT_HEADERS32      img_hdr;
  63.     PIMAGE_SECTION_HEADER    img_sec;
  64.     PIMAGE_EXPORT_DIRECTORY  img_exp;
  65. };
  66.  
  67. typedef struct
  68. {
  69.     struct list_head list;
  70.     char *path;
  71.     int   path_len;
  72. }dll_path_t;
  73.  
  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(char*,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 = _ksys_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.  
  346. int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp)
  347. {
  348.     static jmp_buf loader_env;
  349.     static int recursion = -1;
  350.     int warn = 0;
  351.  
  352.     recursion++;
  353.     if( !recursion )
  354.     {
  355.         if( unlikely(setjmp(loader_env) != 0))
  356.         {
  357.             recursion = -1;
  358.             return 0;
  359.         };
  360.     };
  361.  
  362.     while ( imp->Name )
  363.     {
  364.         PIMAGE_DOS_HEADER        expdos;
  365.         PIMAGE_NT_HEADERS32      expnt;
  366.         PIMAGE_EXPORT_DIRECTORY  exp;
  367.         PIMAGE_THUNK_DATA32      thunk;
  368.  
  369.         void       **iat;
  370.         char       *libname;
  371.         uint32_t   *exp_functions;
  372.         uint16_t   *exp_ordinals;
  373.         char      **exp_names;
  374.  
  375.         const module_t *api;
  376.  
  377.         libname=MakePtr(char*,imp->Name, img_base);
  378.  
  379.         DBG("import from %s\n",libname);
  380.  
  381.         api = load_library(libname);
  382.         if(unlikely(api == NULL))
  383.         {
  384.             printf("library %s not found\n", libname);
  385.             longjmp(loader_env, 1);
  386.         }
  387.  
  388.         iat = MakePtr(void**,imp->FirstThunk, img_base);
  389.  
  390.         if(imp->OriginalFirstThunk !=0 )
  391.         {
  392.             thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, img_base);
  393.         }
  394.         else
  395.         {
  396.             thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, img_base);
  397.         };
  398.  
  399.         exp = api->img_exp;
  400.  
  401.         exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start);
  402.         exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,api->start);
  403.         exp_names = MakePtr(char**, exp->AddressOfNames,api->start);
  404.  
  405.         while ( thunk->u1.AddressOfData != 0 )
  406.         {
  407.             PIMAGE_IMPORT_BY_NAME imp_name;
  408.  
  409.             if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
  410.             {
  411. //                ordinal = (*func_list) & 0x7fffffff;
  412. //               *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
  413. //                if ((*ImportAddressList) == NULL)
  414. //                {
  415. //                    DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
  416. //                    RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
  417. //                    return STATUS_ENTRYPOINT_NOT_FOUND;
  418. //                }
  419.             }
  420.             else
  421.             {
  422.                 char *export_name;
  423.                 uint16_t   ordinal;
  424.                 void      *function;
  425.                 uint32_t   minn;
  426.                 uint32_t   maxn;
  427.  
  428.                 imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
  429.                               thunk->u1.AddressOfData, img_base);
  430.                 *iat = NULL;
  431.  
  432.                 DBG("import %s", imp_name->Name);
  433.  
  434.                 if(imp_name->Hint < exp->NumberOfNames)
  435.                 {
  436.                     export_name = MakePtr(char*,exp_names[imp_name->Hint],
  437.                                           api->start);
  438.                     if(strcmp(imp_name->Name, export_name) == 0)
  439.                     {
  440.                         ordinal = exp_ordinals[imp_name->Hint];
  441.                         function = MakePtr(void*,exp_functions[ordinal], api->start);
  442.                         if((uint32_t)function >= (uint32_t)exp)
  443.                         {
  444.                             printf("forward %s\n", function);
  445.                             warn=1;
  446.                         }
  447.                         else
  448.                         {
  449.                             DBG(" \t\tat %x\n", function);
  450.                             *iat = function;
  451.                         };
  452.                         thunk++;  // Advance to next thunk
  453.                         iat++;
  454.                         continue;
  455.                     };
  456.                 };
  457.  
  458.                 minn = 0;
  459.                 maxn = exp->NumberOfNames - 1;
  460.                 while (minn <= maxn)
  461.                 {
  462.                     int mid;
  463.                     int res;
  464.  
  465.                     mid = (minn + maxn) / 2;
  466.  
  467.                     export_name = MakePtr(char*,exp_names[mid],api->start);
  468.  
  469.                     res = strcmp(export_name, imp_name->Name);
  470.                     if (res == 0)
  471.                     {
  472.                         ordinal  = exp_ordinals[mid];
  473.                         function = MakePtr(void*,exp_functions[ordinal], api->start);
  474.  
  475.                         if((uint32_t)function >= (uint32_t)exp)
  476.                         {
  477.                             printf("forward %s\n", function);
  478.                             warn=1;
  479.                         }
  480.                         else
  481.                         {
  482.                             DBG(" \t\tat %x\n", function);
  483.                             *iat = function;
  484.                         };
  485.                         break;
  486.                     }
  487.                     else if (minn == maxn)
  488.                     {
  489.                         printf(" unresolved %s\n",imp_name->Name);
  490.                         warn=1;
  491.                         break;
  492.                     }
  493.                     else if (res > 0)
  494.                     {
  495.                         maxn = mid - 1;
  496.                     }
  497.                     else
  498.                     {
  499.                         minn = mid + 1;
  500.                     }
  501.                 };
  502.             };
  503.             thunk++;            // Advance to next thunk
  504.             iat++;
  505.         }
  506.         imp++;  // advance to next IMAGE_IMPORT_DESCRIPTOR
  507.     };
  508.  
  509.     recursion--;
  510.  
  511.     if ( !warn )
  512.         return 1;
  513.     else
  514.         return 0;
  515. }
  516.  
  517. static void send_dbg_msg(void *msg)
  518. {
  519.     __asm__ __volatile__(
  520.     "int $0x40"
  521.     ::"a"(69),
  522.       "b"(10),
  523.       "S"(msg));
  524. };
  525.  
  526.  
  527. int link_app()
  528. {
  529.     struct app_hdr *header = NULL;
  530.     PIMAGE_IMPORT_DESCRIPTOR imp;
  531.  
  532.     imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start;
  533.  
  534.     if(link_image(NULL, imp))
  535.     {
  536.  
  537. #ifdef DEBUG_INFO
  538.         struct
  539.         {
  540.             void     *start;
  541.             uint32_t  end;
  542.             char      name[24];
  543.         } dbg_msg;
  544.  
  545.         module_t *mod = &libc_dll;
  546.  
  547.         do
  548.         {
  549.             printf("%s %x - %x\n",
  550.                    mod->img_name, mod->start, mod->end);
  551.  
  552. //            asm volatile("int3");
  553.  
  554.             dbg_msg.start = mod->start;
  555.             dbg_msg.end   = mod->end;
  556.             strcpy(dbg_msg.name, mod->img_name);
  557.             send_dbg_msg(&dbg_msg);
  558.             mod = (module_t*)mod->list.next;
  559.         }while(mod != &libc_dll);
  560. #endif
  561.  
  562.         return 1;
  563.     };
  564.  
  565.     return 0;
  566. }
  567.  
  568.  
  569. void* get_entry_point(void *raw)
  570. {
  571.     PIMAGE_DOS_HEADER     dos;
  572.     PIMAGE_NT_HEADERS32   nt;
  573.  
  574.     dos = (PIMAGE_DOS_HEADER)raw;
  575.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  576.  
  577.     return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
  578. };
  579.  
  580.  
  581. void *get_proc_address(void *handle, const char *proc_name)
  582. {
  583.  
  584.     module_t *module = handle;
  585.     PIMAGE_DOS_HEADER        expdos;
  586.     PIMAGE_NT_HEADERS32      expnt;
  587.     PIMAGE_EXPORT_DIRECTORY  exp;
  588.  
  589.     uint32_t   *exp_functions;
  590.     uint16_t   *exp_ordinals;
  591.     char      **exp_names;
  592.  
  593.     int minn, maxn;
  594.     char *export_name;
  595.     uint16_t   ordinal;
  596.     void *function=NULL;
  597.  
  598.     exp = module->img_exp;
  599.  
  600.     exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,module->start);
  601.     exp_ordinals = MakePtr(uint16_t*,  exp->AddressOfNameOrdinals,module->start);
  602.     exp_names = MakePtr(char**, exp->AddressOfNames,module->start);
  603.  
  604.     minn = 0;
  605.     maxn = exp->NumberOfNames - 1;
  606.     while (minn <= maxn)
  607.     {
  608.         int mid;
  609.         int res;
  610.  
  611.         mid = (minn + maxn) / 2;
  612.  
  613.         export_name = MakePtr(char*,exp_names[mid],module->start);
  614.  
  615.         res = strcmp(export_name, proc_name);
  616.         if (res == 0)
  617.         {
  618.             ordinal  = exp_ordinals[mid];
  619.             function = MakePtr(void*,exp_functions[ordinal], module->start);
  620.  
  621.             if((uint32_t)function >= (uint32_t)exp)
  622.             {
  623.                 printf("forward %s\n", function);
  624.             }
  625.             else
  626.             {
  627.                 DBG(" \t\tat %x\n", function);
  628.             };
  629.             break;
  630.         }
  631.         else if (minn == maxn)
  632.         {
  633.             DBG(" unresolved %s\n",proc_name);
  634.             break;
  635.         }
  636.         else if (res > 0)
  637.         {
  638.             maxn = mid - 1;
  639.         }
  640.         else
  641.         {
  642.             minn = mid + 1;
  643.         }
  644.     };
  645.  
  646.     return function;
  647. };
  648.  
  649. static void *load_lib_internal(const char *path)
  650. {
  651.     PIMAGE_DOS_HEADER        dos;
  652.     PIMAGE_NT_HEADERS32      nt;
  653.     PIMAGE_EXPORT_DIRECTORY  exp;
  654.  
  655.     ksys_ufile_t   uf;
  656.     void     *raw_img;
  657.     size_t    raw_size;
  658.     void     *img_base = NULL;
  659.  
  660.     uf = _ksys_load_file(path);
  661.     raw_img  = uf.data;
  662.     raw_size = uf.size;
  663.  
  664.     if(raw_img == NULL)
  665.         return NULL;
  666.  
  667.     if( validate_pe(raw_img, raw_size, 0) == 0)
  668.     {
  669.         printf("invalide module %s\n", path);
  670.         _ksys_free(raw_img);
  671.         return NULL;
  672.     };
  673.  
  674.     img_base = create_image(raw_img);
  675.     _ksys_free(raw_img);
  676.  
  677.     if( unlikely(img_base == NULL) )
  678.         printf("cannot create image %s\n",path);
  679.  
  680.     return img_base;
  681. }
  682.  
  683. void* load_library(const char *name)
  684. {
  685.     PIMAGE_DOS_HEADER        dos;
  686.     PIMAGE_NT_HEADERS32      nt;
  687.     PIMAGE_EXPORT_DIRECTORY  exp;
  688.  
  689.     module_t    *module, *mod = &libc_dll;
  690.     dll_path_t  *dllpath;
  691.     char        *path;
  692.     int          len;
  693.     char        *libname, *tmp;
  694.     void        *img_base;
  695.  
  696.  
  697. /*  check for already loaded libraries  */
  698.  
  699.     tmp = strrchr(name, '/');
  700.     libname = path = tmp != NULL ? tmp+1 : (char*)name;
  701.  
  702. //    printf("path %s\n", path);
  703.  
  704.     do
  705.     {
  706.         if( !strncmp(path, mod->img_name, 16))
  707.             return mod;
  708.         mod = (module_t*)mod->list.next;
  709.     }while(mod != &libc_dll);
  710.  
  711.     if(name[0] == '/')
  712.     {
  713.         path = (char*)name;
  714.         img_base = load_lib_internal(path);
  715.     }
  716.     else
  717.     {
  718.         len = strlen(libname);
  719.         list_for_each_entry(dllpath, &path_list, list)
  720.         {
  721.             path = alloca(len+dllpath->path_len+1);
  722.             memcpy(path, dllpath->path, dllpath->path_len);
  723.  
  724.             memcpy(path+dllpath->path_len, libname, len);
  725.             path[len+dllpath->path_len]=0;
  726.  
  727. //            printf("%s\n", path);
  728.  
  729.             img_base = load_lib_internal(path);
  730.  
  731.             if( unlikely(img_base == NULL) )
  732.                 continue;
  733.         };
  734.     }
  735.  
  736.     if( unlikely(img_base == NULL) )
  737.     {
  738.         printf("unable to load %s\n", name);
  739.         return 0;
  740.     };
  741.  
  742.     module = malloc(sizeof(module_t));
  743.  
  744.     if(unlikely(module == NULL))
  745.     {
  746.         printf("%s epic fail: no enough memory\n",__FUNCTION__);
  747.         goto err1;
  748.     }
  749.  
  750.     INIT_LIST_HEAD(&module->list);
  751.  
  752.     module->img_name = strdup(libname);
  753.     module->img_path = strdup(path);
  754.     module->start    = img_base;
  755.     module->entry    = get_entry_point(img_base);
  756.     module->refcount = 1;
  757.  
  758.     dos =  (PIMAGE_DOS_HEADER)img_base;
  759.     nt  =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  760.     exp =  MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  761.                nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  762.  
  763.     module->end   = MakePtr(char*,img_base, nt->OptionalHeader.SizeOfImage);
  764.  
  765.     module->img_hdr  = nt;
  766.     module->img_sec  = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32));
  767.     module->img_exp  = MakePtr(PIMAGE_EXPORT_DIRECTORY, img_base,
  768.                        nt->OptionalHeader.DataDirectory[0].VirtualAddress);
  769.  
  770.     list_add_tail(&module->list, &libc_dll.list);
  771.  
  772.     if(nt->OptionalHeader.DataDirectory[1].Size)
  773.     {
  774.         PIMAGE_IMPORT_DESCRIPTOR imp;
  775.         int (*dll_startup)(module_t *mod, uint32_t reason);
  776.  
  777.         imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
  778.                     nt->OptionalHeader.DataDirectory[1].VirtualAddress);
  779.  
  780.         if(link_image(img_base, imp) == 0)
  781.             goto err2;
  782.  
  783.         dll_startup = get_proc_address(module, "DllStartup");
  784.         if( dll_startup )
  785.         {
  786.             if( 0 == dll_startup(module, 1))
  787.                 goto err2;
  788.         }
  789.     };
  790.  
  791. //    printf("module %s %p - %p\n", name, module->start, module->end);
  792.  
  793.     return module;
  794.  
  795. err2:
  796.     list_del(&module->list);
  797.     free(module->img_name);
  798.     free(module->img_path);
  799.     free(module);
  800. err1:
  801.     _ksys_free(img_base);
  802.     return NULL;
  803. };
  804.  
  805. void enumerate_libraries(int (*callback)(void *handle, const char* name,
  806.                                          uint32_t base, uint32_t size, void *user_data),
  807.                          void *user_data)
  808. {
  809.     module_t *mod = &libc_dll;
  810.  
  811.     do
  812.     {
  813.         if(0 == callback(mod, mod->img_name, (uint32_t)mod->start,
  814.                          mod->end - mod->start, user_data))
  815.             break;
  816.         mod = (module_t*)mod->list.next;
  817.     }while(mod != &libc_dll);
  818. }
  819.