Subversion Repositories Kolibri OS

Rev

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

  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <alloca.h>
  5. #include <malloc.h>
  6. #include <setjmp.h>
  7. #include <envz.h>
  8.  
  9. #include <sys/ksys.h>
  10.  
  11. #include "list.h"
  12. #include "pe.h"
  13.  
  14. #define unlikely(x)     __builtin_expect(!!(x), 0)
  15.  
  16. //#define DBG(format,...) printf(format,##__VA_ARGS__)
  17.  
  18. #define DBG(format,...)
  19.  
  20. static inline void sec_copy(void *dst, void *src, size_t len)
  21. {
  22.     __asm__ __volatile__ (
  23.     "shrl $2, %%ecx         \n\t"
  24.     "rep movsl"
  25.     :
  26.     :"c"(len),"S"(src),"D"(dst)
  27.     :"cc");
  28.     __asm__ __volatile__ (
  29.     ""
  30.     :::"ecx","esi","edi");
  31. };
  32.  
  33. void* load_libc();
  34.  
  35. static inline int IsPowerOf2(uint32_t val)
  36. {
  37.     if(val == 0)
  38.         return 0;
  39.     return (val & (val - 1)) == 0;
  40. }
  41.  
  42. int validate_pe(void *raw, size_t raw_size)
  43. {
  44.     PIMAGE_DOS_HEADER     dos;
  45.     PIMAGE_NT_HEADERS32   nt;
  46.  
  47.     dos = (PIMAGE_DOS_HEADER)raw;
  48.  
  49.     if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
  50.         return 0;
  51.  
  52.     if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
  53.         return 0;
  54.  
  55.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  56.  
  57.     if( (uint32_t)nt < (uint32_t)raw)
  58.         return 0;
  59.  
  60.     if(nt->Signature != IMAGE_NT_SIGNATURE)
  61.         return 0;
  62.  
  63.     if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
  64.         return 0;
  65.  
  66.     if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  67.         return 0;
  68.  
  69.     if(nt->OptionalHeader.SectionAlignment < 4096)
  70.     {
  71.         if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
  72.             return 0;
  73.     }
  74.     else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
  75.         return 0;
  76.  
  77.     if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
  78.        !IsPowerOf2(nt->OptionalHeader.FileAlignment))
  79.         return 0;
  80.  
  81.     if(nt->FileHeader.NumberOfSections > 96)
  82.         return 0;
  83.  
  84.     return 1;
  85. }
  86.  
  87. void* create_image(void *raw)
  88. {
  89.     PIMAGE_DOS_HEADER     dos;
  90.     PIMAGE_NT_HEADERS32   nt;
  91.     PIMAGE_SECTION_HEADER img_sec;
  92.  
  93.     void  *img_base;
  94.     uint32_t  sec_align;
  95.     int    i;
  96.  
  97.     dos = (PIMAGE_DOS_HEADER)raw;
  98.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  99.  
  100.     img_base = _ksys_alloc(nt->OptionalHeader.SizeOfImage);
  101.  
  102.     if(unlikely(img_base == NULL))
  103.         return 0;
  104.  
  105.     sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
  106.  
  107.     img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
  108.  
  109.     sec_align = nt->OptionalHeader.SectionAlignment;
  110.  
  111.     for(i=0; i< nt->FileHeader.NumberOfSections; i++)
  112.     {
  113.         void *src_ptr;
  114.         void *dest_ptr;
  115.         size_t   sec_size;
  116.  
  117.         if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
  118.         {
  119.             src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
  120.             dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
  121.             sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
  122.         };
  123.  
  124.         img_sec++;
  125.     };
  126.  
  127.     if(nt->OptionalHeader.DataDirectory[5].Size)
  128.     {
  129.         PIMAGE_BASE_RELOCATION reloc;
  130.  
  131.         uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
  132.  
  133.         reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
  134.                         nt->OptionalHeader.DataDirectory[5].VirtualAddress);
  135.  
  136.         while ( reloc->SizeOfBlock != 0 )
  137.         {
  138.             uint32_t  cnt;
  139.             uint16_t *entry;
  140.             uint16_t  reltype;
  141.             uint32_t  offs;
  142.  
  143.             cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
  144.             entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
  145.  
  146.             for ( i=0; i < cnt; i++ )
  147.             {
  148.                 uint16_t *p16;
  149.                 uint32_t *p32;
  150.  
  151.                 reltype = (*entry & 0xF000) >> 12;
  152.                 offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
  153.                 switch(reltype)
  154.                 {
  155.                     case 1:
  156.                         p16 = MakePtr(uint16_t*, img_base, offs);
  157.                         *p16+= (uint16_t)(delta>>16);
  158.                         break;
  159.                     case 2:
  160.                         p16 = MakePtr(uint16_t*, img_base, offs);
  161.                         *p16+= (uint16_t)delta;
  162.                         break;
  163.                     case 3:
  164.                         p32 = MakePtr(uint32_t*, img_base, offs);
  165.                         *p32+= delta;
  166.                 }
  167.                 entry++;
  168.             }
  169.             reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
  170.         };
  171. //        printf("unmap base %p offset %x %d page(s)\n",
  172. //                img_base,
  173. //                nt->OptionalHeader.DataDirectory[5].VirtualAddress,
  174. //                (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
  175.  
  176.         user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
  177.                    nt->OptionalHeader.DataDirectory[5].Size);
  178.     };
  179.     return img_base;
  180. };
  181.  
  182. void* get_entry_point(void *raw)
  183. {
  184.     PIMAGE_DOS_HEADER     dos;
  185.     PIMAGE_NT_HEADERS32   nt;
  186.  
  187.     dos = (PIMAGE_DOS_HEADER)raw;
  188.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  189.  
  190.     return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
  191. };
  192.  
  193.  
  194. void* load_libc()
  195. {
  196.     void     *raw_img;
  197.     size_t    raw_size;
  198.     void     *img_base = NULL;
  199.     ksys_ufile_t   uf;
  200.  
  201.     uf = _ksys_load_file("/kolibrios/lib/libc.dll");
  202.  
  203.     raw_img   = uf.data;
  204.     raw_size  = uf.size;
  205.  
  206.     if(raw_img == NULL)
  207.         return NULL;
  208.  
  209. //    printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
  210.  
  211.     if(validate_pe(raw_img, raw_size) != 0)
  212.     {
  213. //        printf("invalide libc.dll\n");
  214.         img_base = create_image(raw_img);
  215.     };
  216.  
  217.     _ksys_free(raw_img);
  218.  
  219.     return img_base;
  220.  
  221. }
  222.  
  223.  
  224.