Subversion Repositories Kolibri OS

Rev

Rev 908 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1.  
  2. #include <types.h>
  3. #include <core.h>
  4. #include <spinlock.h>
  5. #include <link.h>
  6. #include <mm.h>
  7. #include <slab.h>
  8. #include <pe.h>
  9.  
  10.  
  11. static inline bool IsPowerOf2(u32_t val)
  12. {
  13.     if(val == 0)
  14.         return false;
  15.     return (val & (val - 1)) == 0;
  16. }
  17.  
  18.  
  19. static inline void sec_copy(addr_t dst, addr_t src, size_t len)
  20. {
  21.     u32_t tmp;
  22.     __asm__ __volatile__ (
  23.     "shrl $2, %%ecx         \n\t"
  24.     "rep movsl"
  25.     :"=c"(tmp),"=S"(tmp),"=D"(tmp)
  26.     :"c"(len),"S"(src),"D"(dst)
  27.     :"cc");
  28. };
  29.  
  30. static inline void sec_clear(addr_t dst, size_t len)
  31. {
  32.     u32_t tmp;
  33.     __asm__ __volatile__ (
  34.     "xorl %%eax, %%eax      \n\t"
  35.     "rep stosb"
  36.     :"=c"(tmp),"=D"(tmp)
  37.     :"c"(len),"D"(dst)
  38.     :"eax","cc");
  39. };
  40.  
  41. int __stdcall strncmp(const char *s1, const char *s2, size_t n);
  42.  
  43. void __export create_image(addr_t img_base, addr_t raw) asm ("CreateImage");
  44. bool link_image(addr_t img_base);
  45.  
  46. md_t* __fastcall load_image(const char *path);
  47.  
  48. /*
  49. void* __fastcall load_pe(const char *path)
  50. {
  51.     md_t  *md;
  52.  
  53.     md = load_image(path);
  54.  
  55.     if( md )
  56.         return (void*)md->base;
  57.  
  58.     return NULL;
  59. };
  60. */
  61.  
  62. bool validate_pe(void *raw, size_t raw_size)
  63. {
  64.     PIMAGE_DOS_HEADER     dos;
  65.     PIMAGE_NT_HEADERS32   nt;
  66.  
  67.     dos = (PIMAGE_DOS_HEADER)raw;
  68.  
  69.     if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
  70.         return false;
  71.  
  72.     if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
  73.         return false;
  74.  
  75.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  76.  
  77.     if( (addr_t)nt < (addr_t)raw)
  78.         return false;
  79.  
  80.     if(nt->Signature != IMAGE_NT_SIGNATURE)
  81.         return false;
  82.  
  83.     if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
  84.         return false;
  85.  
  86.     if(nt->OptionalHeader.SectionAlignment < PAGE_SIZE)
  87.         {
  88.         if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
  89.             return false;
  90.         }
  91.     else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
  92.         return false;
  93.  
  94.     if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
  95.        !IsPowerOf2(nt->OptionalHeader.FileAlignment))
  96.         return false;
  97.  
  98.     if(nt->FileHeader.NumberOfSections > 96)
  99.         return false;
  100.  
  101.     return true;
  102. }
  103.  
  104. md_t* __fastcall load_image(const char *path)
  105. {
  106.     PIMAGE_DOS_HEADER     dos;
  107.     PIMAGE_NT_HEADERS32   nt;
  108.  
  109.     md_t    *img_md;
  110.  
  111.     size_t   img_size;
  112.     addr_t   img_base;
  113.     count_t  img_pages;
  114.  
  115.     size_t   raw_size = 0;
  116.     void    *raw;
  117.  
  118.     DBG("\nload image %s", path);
  119.  
  120.     raw = load_file(path, &raw_size);
  121.  
  122.     DBG("  raw = %x\n", raw);
  123.  
  124.     if( ! raw)
  125.     {
  126.         DBG("file not found: %s\n", path);
  127.         return NULL;
  128.     };
  129.  
  130.     if( ! validate_pe(raw, raw_size) )
  131.         {
  132.         DBG("invalid pe file %s\n", path);
  133.         mem_free(raw);
  134.             return NULL;
  135.         }
  136.  
  137.     dos = (PIMAGE_DOS_HEADER)raw;
  138.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  139.  
  140.     img_size  =  nt->OptionalHeader.SizeOfImage;
  141.  
  142.     img_md  = md_alloc(img_size, PG_SW);
  143.  
  144.  
  145.     if( !img_md)
  146.     {
  147.         mem_free(raw);
  148.         return NULL;
  149.     };
  150.  
  151.     img_base = img_md->base;
  152.  
  153.     create_image(img_base, (addr_t)raw);
  154.  
  155.     mem_free(raw);
  156.  
  157. //    dos = (PIMAGE_DOS_HEADER)img_base;
  158. //    nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  159.  
  160.     return img_md;
  161. };
  162.  
  163.  
  164. /*
  165. addr_t get_proc_addr(addr_t module, char *name)
  166. {
  167.     PIMAGE_DOS_HEADER  expdos;
  168.     PIMAGE_NT_HEADERS32  expnt;
  169.     PIMAGE_EXPORT_DIRECTORY exp;
  170.     u32_t *functions;
  171.     char **funcname;
  172.     int ind;
  173.  
  174.     expdos = (PIMAGE_DOS_HEADER)module;
  175.     expnt =  MakePtr( PIMAGE_NT_HEADERS32, expdos, expdos->e_lfanew);
  176.  
  177.     exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,module,
  178.                   expnt->OptionalHeader.DataDirectory[0].VirtualAddress);
  179.  
  180.     functions = MakePtr(DWORD*,exp->AddressOfFunctions,module);
  181.     funcname = MakePtr(char**,exp->AddressOfNames,module);
  182.  
  183.     for(ind=0; *funcname;funcname++,ind++)
  184.     {
  185.         if(!strcmp(name,MakePtr(char*,*funcname,module)))
  186.             return functions[ind] + module;
  187.     };
  188.     return -1;
  189. };
  190. */
  191.  
  192.  
  193. void create_image(addr_t img_base, addr_t raw)
  194. {
  195.     PIMAGE_DOS_HEADER     dos;
  196.     PIMAGE_NT_HEADERS32   nt;
  197.     PIMAGE_SECTION_HEADER img_sec;
  198.  
  199.     u32_t  sec_align;
  200.     int    i;
  201.  
  202.  
  203. /* assumed that image is valid */
  204.  
  205.     dos = (PIMAGE_DOS_HEADER)raw;
  206.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  207.  
  208.     sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
  209.  
  210.     img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
  211.  
  212.     sec_align = nt->OptionalHeader.SectionAlignment;
  213.  
  214.     for(i=0; i< nt->FileHeader.NumberOfSections; i++)
  215.     {
  216.         addr_t src_ptr;
  217.         addr_t dest_ptr;
  218.         size_t sec_size;
  219.  
  220.         src_ptr = MakePtr(addr_t, raw, img_sec->PointerToRawData);
  221.         dest_ptr = MakePtr(addr_t,img_base, img_sec->VirtualAddress);
  222.  
  223.         if(img_sec->SizeOfRawData)
  224.             sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
  225.  
  226.         sec_size = (img_sec->Misc.VirtualSize + sec_align -1) & -sec_align;
  227.  
  228.         if(sec_size > img_sec->SizeOfRawData)
  229.             sec_clear(dest_ptr + img_sec->SizeOfRawData,
  230.                       sec_size - img_sec->SizeOfRawData);
  231.         img_sec++;
  232.     }
  233.  
  234.     if(nt->OptionalHeader.DataDirectory[5].Size)
  235.     {
  236.         PIMAGE_BASE_RELOCATION reloc;
  237.  
  238. /* FIXME addr_t */
  239.  
  240.         u32_t delta = (u32_t)img_base - nt->OptionalHeader.ImageBase;
  241.  
  242.         reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
  243.                         nt->OptionalHeader.DataDirectory[5].VirtualAddress);
  244.  
  245.         while ( reloc->SizeOfBlock != 0 )
  246.         {
  247.             u32_t  cnt;
  248.             u16_t *entry;
  249.             u16_t  reltype;
  250.             u32_t  offs;
  251.  
  252.             cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(u16_t);
  253.             entry = MakePtr( u16_t*, reloc, sizeof(*reloc) );
  254.  
  255.             for ( i=0; i < cnt; i++ )
  256.             {
  257.                 u16_t *p16;
  258.                 u32_t *p32;
  259.  
  260.                 reltype = (*entry & 0xF000) >> 12;
  261.                 offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
  262.                 switch(reltype)
  263.                 {
  264.                     case 1:
  265.                         p16 = MakePtr(u16_t*, img_base, offs);
  266.                         *p16+= (u16_t)(delta>>16);
  267.                         break;
  268.                     case 2:
  269.                         p16 = MakePtr(u16_t*, img_base, offs);
  270.                         *p16+= (u16_t)delta;
  271.                         break;
  272.                     case 3:
  273.                         p32 = MakePtr(u32_t*, img_base, offs);
  274.                         *p32+= delta;
  275.                 }
  276.                 entry++;
  277.             }
  278.             reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
  279.         }
  280.     };
  281.  
  282.     DBG("\ncreate pe base %x, size %x, %d sections\n\n",img_base,
  283.          nt->OptionalHeader.SizeOfImage, nt->FileHeader.NumberOfSections);
  284. };
  285.  
  286.  
  287. bool link_image(addr_t img_base)
  288. {
  289.     PIMAGE_DOS_HEADER     dos;
  290.     PIMAGE_NT_HEADERS32   nt;
  291.  
  292.     int warn = 0;
  293.  
  294. /* assumed that image is valid */
  295.  
  296.     dos = (PIMAGE_DOS_HEADER)img_base;
  297.     nt =  MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
  298.  
  299.     if(nt->OptionalHeader.DataDirectory[1].Size)
  300.     {
  301.         PIMAGE_IMPORT_DESCRIPTOR imp;
  302.  
  303.         imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
  304.                       nt->OptionalHeader.DataDirectory[1].VirtualAddress);
  305.  
  306.  
  307.  
  308.         while ( 1 )
  309.         {
  310.             PIMAGE_THUNK_DATA32     thunk;
  311.  
  312.             PIMAGE_DOS_HEADER       expdos;
  313.             PIMAGE_NT_HEADERS32     expnt;
  314.             PIMAGE_EXPORT_DIRECTORY exp;
  315.  
  316.             u32_t   *iat;
  317.             char    *libname;
  318.             addr_t  *functions;
  319.             u16_t   *ordinals;
  320.             char   **funcname;
  321.  
  322.             dll_t   *exp_dll;
  323.  
  324.             if ( (imp->TimeDateStamp==0 ) && (imp->Name==0) )
  325.                 break;
  326.  
  327.             libname=MakePtr(char*,imp->Name, img_base);
  328.  
  329.             DBG("import from %s\n",libname);
  330.  
  331.             exp_dll = find_dll(libname);
  332.             if(exp_dll != NULL)
  333.             {
  334.                 DBG("find %s\n", exp_dll->img_name);
  335.             }
  336.             else
  337.             {
  338.                 DBG("can't find %s\n", libname);
  339.                 return false;
  340.             }
  341.  
  342.             exp = exp_dll->img_exp;
  343.  
  344.             functions = MakePtr(DWORD*,exp->AddressOfFunctions,exp_dll->img_base);
  345.             ordinals = MakePtr(WORD*,  exp->AddressOfNameOrdinals,exp_dll->img_base);
  346.             funcname = MakePtr(char**, exp->AddressOfNames,exp_dll->img_base);
  347.  
  348.             thunk = MakePtr(PIMAGE_THUNK_DATA32,
  349.                             imp->Characteristics, img_base);
  350.             iat= MakePtr(DWORD*,imp->FirstThunk, img_base);
  351.  
  352.             while ( 1 ) // Loop forever (or until we break out)
  353.             {
  354.                 PIMAGE_IMPORT_BY_NAME ord;
  355.                 addr_t addr;
  356.  
  357.                 if ( thunk->u1.AddressOfData == 0 )
  358.                     break;
  359.  
  360.                 if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG )
  361.                 {
  362.         //  printf("  %4u\n", thunk->u1.Ordinal & 0xFFFF);
  363.                     break;
  364.                 }
  365.                 else
  366.                 {
  367.                     ord = MakePtr(PIMAGE_IMPORT_BY_NAME,
  368.                                   thunk->u1.AddressOfData, img_base);
  369.                     *iat=0;
  370.  
  371.                     DBG("import %s", ord->Name);
  372.  
  373.                     if(strncmp(ord->Name,
  374.                        MakePtr(char*,funcname[ord->Hint],exp_dll->img_base),32))
  375.                     {
  376.                         int ind;
  377.                         char **names=funcname;
  378.  
  379.                         for(names = funcname,ind = 0;
  380.                             ind < exp->NumberOfNames; names++,ind++)
  381.                         {
  382.                             if(!strncmp(ord->Name,MakePtr(char*,*names,exp_dll->img_base),32))
  383.                             {
  384.                                 DBG(" \tat %x\n", functions[ind] + exp_dll->img_base);
  385.                                 *iat = functions[ind] + exp_dll->img_base;
  386.                                 break;
  387.                             };
  388.                         };
  389.                         if(ind == exp->NumberOfNames)
  390.                         {
  391.                             DBG(" unresolved import %s\n",ord->Name);
  392.                             warn=1;
  393.                         };
  394.                     }
  395.                     else
  396.                     {
  397.                         DBG(" \tat %x\n", functions[ord->Hint] + exp_dll->img_base);
  398.                         *iat = functions[ord->Hint] + exp_dll->img_base;
  399.                     };
  400.                 };
  401.                 thunk++;            // Advance to next thunk
  402.                 iat++;
  403.             }
  404.             imp++;  // advance to next IMAGE_IMPORT_DESCRIPTOR
  405.         };
  406.     };
  407.  
  408.     if ( !warn )
  409.         return true;
  410.         else
  411.         return false;
  412. }
  413.  
  414.  
  415.