Subversion Repositories Kolibri OS

Rev

Rev 3805 | Go to most recent revision | Blame | Last modification | View Log | Download | 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 <kos32sys.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, int is_exec)
  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(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
  67.         return 0;
  68.  
  69.     if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  70.         return 0;
  71.  
  72.     if( is_exec && nt->OptionalHeader.ImageBase != 0)
  73.         return 0;
  74.  
  75.     if(nt->OptionalHeader.SectionAlignment < 4096)
  76.     {
  77.         if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
  78.             return 0;
  79.     }
  80.     else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
  81.         return 0;
  82.  
  83.     if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
  84.        !IsPowerOf2(nt->OptionalHeader.FileAlignment))
  85.         return 0;
  86.  
  87.     if(nt->FileHeader.NumberOfSections > 96)
  88.         return 0;
  89.  
  90.     return 1;
  91. }
  92.  
  93. void* create_image(void *raw)
  94. {
  95.     PIMAGE_DOS_HEADER     dos;
  96.     PIMAGE_NT_HEADERS32   nt;
  97.     PIMAGE_SECTION_HEADER img_sec;
  98.  
  99.     void  *img_base;
  100.     uint32_t  sec_align;
  101.     int    i;
  102.  
  103.     dos = (PIMAGE_DOS_HEADER)raw;
  104.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  105.  
  106.     img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
  107.  
  108.     if(unlikely(img_base == NULL))
  109.         return 0;
  110.  
  111.     sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
  112.  
  113.     img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
  114.  
  115.     sec_align = nt->OptionalHeader.SectionAlignment;
  116.  
  117.     for(i=0; i< nt->FileHeader.NumberOfSections; i++)
  118.     {
  119.         void *src_ptr;
  120.         void *dest_ptr;
  121.         size_t   sec_size;
  122.  
  123.         if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
  124.         {
  125.             src_ptr  = MakePtr(void*, raw, img_sec->PointerToRawData);
  126.             dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
  127.             sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
  128.         };
  129.  
  130.         img_sec++;
  131.     };
  132.  
  133.     if(nt->OptionalHeader.DataDirectory[5].Size)
  134.     {
  135.         PIMAGE_BASE_RELOCATION reloc;
  136.  
  137.         uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
  138.  
  139.         reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
  140.                         nt->OptionalHeader.DataDirectory[5].VirtualAddress);
  141.  
  142.         while ( reloc->SizeOfBlock != 0 )
  143.         {
  144.             uint32_t  cnt;
  145.             uint16_t *entry;
  146.             uint16_t  reltype;
  147.             uint32_t  offs;
  148.  
  149.             cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
  150.             entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
  151.  
  152.             for ( i=0; i < cnt; i++ )
  153.             {
  154.                 uint16_t *p16;
  155.                 uint32_t *p32;
  156.  
  157.                 reltype = (*entry & 0xF000) >> 12;
  158.                 offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
  159.                 switch(reltype)
  160.                 {
  161.                     case 1:
  162.                         p16 = MakePtr(uint16_t*, img_base, offs);
  163.                         *p16+= (uint16_t)(delta>>16);
  164.                         break;
  165.                     case 2:
  166.                         p16 = MakePtr(uint16_t*, img_base, offs);
  167.                         *p16+= (uint16_t)delta;
  168.                         break;
  169.                     case 3:
  170.                         p32 = MakePtr(uint32_t*, img_base, offs);
  171.                         *p32+= delta;
  172.                 }
  173.                 entry++;
  174.             }
  175.             reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
  176.         };
  177. //        printf("unmap base %p offset %x %d page(s)\n",
  178. //                img_base,
  179. //                nt->OptionalHeader.DataDirectory[5].VirtualAddress,
  180. //                (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
  181.  
  182.         user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
  183.                    nt->OptionalHeader.DataDirectory[5].Size);
  184.     };
  185.     return img_base;
  186. };
  187.  
  188. void* get_entry_point(void *raw)
  189. {
  190.     PIMAGE_DOS_HEADER     dos;
  191.     PIMAGE_NT_HEADERS32   nt;
  192.  
  193.     dos = (PIMAGE_DOS_HEADER)raw;
  194.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  195.  
  196.     return  MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
  197. };
  198.  
  199.  
  200. void* load_libc()
  201. {
  202.     void     *raw_img;
  203.     size_t    raw_size;
  204.     void     *img_base = NULL;
  205.     ufile_t   uf;
  206.  
  207.     uf = load_file("/kolibrios/lib/libc.dll");
  208.  
  209.     raw_img   = uf.data;
  210.     raw_size  = uf.size;
  211.  
  212.     if(raw_img == NULL)
  213.         return NULL;
  214.  
  215. //    printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
  216.  
  217.     if(validate_pe(raw_img, raw_size, 0) != 0)
  218.     {
  219. //        printf("invalide libc.dll\n");
  220.         img_base = create_image(raw_img);
  221.     };
  222.  
  223.     user_free(raw_img);
  224.  
  225.     return img_base;
  226.  
  227. }
  228.  
  229.  
  230.