Subversion Repositories Kolibri OS

Rev

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