forked from KolibriOS/kolibrios
upload sdk
git-svn-id: svn://kolibrios.org@4349 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
223
contrib/sdk/sources/newlib/pe/crtloader.c
Normal file
223
contrib/sdk/sources/newlib/pe/crtloader.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <alloca.h>
|
||||
#include <malloc.h>
|
||||
#include <setjmp.h>
|
||||
#include <envz.h>
|
||||
|
||||
#include <kos32sys.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "pe.h"
|
||||
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
//#define DBG(format,...) printf(format,##__VA_ARGS__)
|
||||
|
||||
#define DBG(format,...)
|
||||
|
||||
static inline void sec_copy(void *dst, void *src, size_t len)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"shrl $2, %%ecx \n\t"
|
||||
"rep movsl"
|
||||
:
|
||||
:"c"(len),"S"(src),"D"(dst)
|
||||
:"cc");
|
||||
__asm__ __volatile__ (
|
||||
""
|
||||
:::"ecx","esi","edi");
|
||||
};
|
||||
|
||||
void* load_libc();
|
||||
|
||||
static inline int IsPowerOf2(uint32_t val)
|
||||
{
|
||||
if(val == 0)
|
||||
return 0;
|
||||
return (val & (val - 1)) == 0;
|
||||
}
|
||||
|
||||
int validate_pe(void *raw, size_t raw_size)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
|
||||
if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) )
|
||||
return 0;
|
||||
|
||||
if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0)
|
||||
return 0;
|
||||
|
||||
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
if( (uint32_t)nt < (uint32_t)raw)
|
||||
return 0;
|
||||
|
||||
if(nt->Signature != IMAGE_NT_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
|
||||
return 0;
|
||||
|
||||
if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
return 0;
|
||||
|
||||
if(nt->OptionalHeader.SectionAlignment < 4096)
|
||||
{
|
||||
if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment)
|
||||
return 0;
|
||||
}
|
||||
else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment)
|
||||
return 0;
|
||||
|
||||
if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) ||
|
||||
!IsPowerOf2(nt->OptionalHeader.FileAlignment))
|
||||
return 0;
|
||||
|
||||
if(nt->FileHeader.NumberOfSections > 96)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* create_image(void *raw)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
PIMAGE_SECTION_HEADER img_sec;
|
||||
|
||||
void *img_base;
|
||||
uint32_t sec_align;
|
||||
int i;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
img_base = user_alloc(nt->OptionalHeader.SizeOfImage);
|
||||
|
||||
if(unlikely(img_base == NULL))
|
||||
return 0;
|
||||
|
||||
sec_copy(img_base, raw, nt->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
img_sec = MakePtr(PIMAGE_SECTION_HEADER, nt, sizeof(IMAGE_NT_HEADERS32));
|
||||
|
||||
sec_align = nt->OptionalHeader.SectionAlignment;
|
||||
|
||||
for(i=0; i< nt->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
void *src_ptr;
|
||||
void *dest_ptr;
|
||||
size_t sec_size;
|
||||
|
||||
if ( img_sec->SizeOfRawData && img_sec->PointerToRawData )
|
||||
{
|
||||
src_ptr = MakePtr(void*, raw, img_sec->PointerToRawData);
|
||||
dest_ptr = MakePtr(void*, img_base, img_sec->VirtualAddress);
|
||||
sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData);
|
||||
};
|
||||
|
||||
img_sec++;
|
||||
};
|
||||
|
||||
if(nt->OptionalHeader.DataDirectory[5].Size)
|
||||
{
|
||||
PIMAGE_BASE_RELOCATION reloc;
|
||||
|
||||
uint32_t delta = (uint32_t)img_base - nt->OptionalHeader.ImageBase;
|
||||
|
||||
reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base,
|
||||
nt->OptionalHeader.DataDirectory[5].VirtualAddress);
|
||||
|
||||
while ( reloc->SizeOfBlock != 0 )
|
||||
{
|
||||
uint32_t cnt;
|
||||
uint16_t *entry;
|
||||
uint16_t reltype;
|
||||
uint32_t offs;
|
||||
|
||||
cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(uint16_t);
|
||||
entry = MakePtr( uint16_t*, reloc, sizeof(*reloc) );
|
||||
|
||||
for ( i=0; i < cnt; i++ )
|
||||
{
|
||||
uint16_t *p16;
|
||||
uint32_t *p32;
|
||||
|
||||
reltype = (*entry & 0xF000) >> 12;
|
||||
offs = (*entry & 0x0FFF) + reloc->VirtualAddress;
|
||||
switch(reltype)
|
||||
{
|
||||
case 1:
|
||||
p16 = MakePtr(uint16_t*, img_base, offs);
|
||||
*p16+= (uint16_t)(delta>>16);
|
||||
break;
|
||||
case 2:
|
||||
p16 = MakePtr(uint16_t*, img_base, offs);
|
||||
*p16+= (uint16_t)delta;
|
||||
break;
|
||||
case 3:
|
||||
p32 = MakePtr(uint32_t*, img_base, offs);
|
||||
*p32+= delta;
|
||||
}
|
||||
entry++;
|
||||
}
|
||||
reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock);
|
||||
};
|
||||
// printf("unmap base %p offset %x %d page(s)\n",
|
||||
// img_base,
|
||||
// nt->OptionalHeader.DataDirectory[5].VirtualAddress,
|
||||
// (nt->OptionalHeader.DataDirectory[5].Size+4095)>>12);
|
||||
|
||||
user_unmap(img_base,nt->OptionalHeader.DataDirectory[5].VirtualAddress,
|
||||
nt->OptionalHeader.DataDirectory[5].Size);
|
||||
};
|
||||
return img_base;
|
||||
};
|
||||
|
||||
void* get_entry_point(void *raw)
|
||||
{
|
||||
PIMAGE_DOS_HEADER dos;
|
||||
PIMAGE_NT_HEADERS32 nt;
|
||||
|
||||
dos = (PIMAGE_DOS_HEADER)raw;
|
||||
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew);
|
||||
|
||||
return MakePtr(void*, raw, nt->OptionalHeader.AddressOfEntryPoint);
|
||||
};
|
||||
|
||||
|
||||
void* load_libc()
|
||||
{
|
||||
void *raw_img;
|
||||
size_t raw_size;
|
||||
void *img_base = NULL;
|
||||
ufile_t uf;
|
||||
|
||||
uf = load_file("/kolibrios/lib/libc.dll");
|
||||
|
||||
raw_img = uf.data;
|
||||
raw_size = uf.size;
|
||||
|
||||
if(raw_img == NULL)
|
||||
return NULL;
|
||||
|
||||
// printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
|
||||
|
||||
if(validate_pe(raw_img, raw_size) != 0)
|
||||
{
|
||||
// printf("invalide libc.dll\n");
|
||||
img_base = create_image(raw_img);
|
||||
};
|
||||
|
||||
user_free(raw_img);
|
||||
|
||||
return img_base;
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user