Subversion Repositories Kolibri OS

Rev

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