Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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