Subversion Repositories Kolibri OS

Rev

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