/kernel/branches/kolibri_pe/make.sh |
---|
File deleted |
Property changes: |
Deleted: svn:executable |
-* |
\ No newline at end of property |
/kernel/branches/kolibri_pe/build.bat |
---|
File deleted |
/kernel/branches/kolibri_pe/core/dll.c |
---|
5,244 → 5,75 |
#include <link.h> |
#include <mm.h> |
#include <slab.h> |
#include <pe.h> |
typedef unsigned short WORD; |
typedef unsigned int DWORD; |
typedef unsigned int LONG; |
typedef unsigned char BYTE; |
int __stdcall strncmp(const char *s1, const char *s2, size_t n); |
#define IMAGE_DOS_SIGNATURE 0x5A4D |
#define IMAGE_NT_SIGNATURE 0x00004550 |
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b |
static dll_t core_dll; |
#pragma pack(push,2) |
typedef struct _IMAGE_DOS_HEADER |
static char* strupr(char *str ) |
{ |
WORD e_magic; |
WORD e_cblp; |
WORD e_cp; |
WORD e_crlc; |
WORD e_cparhdr; |
WORD e_minalloc; |
WORD e_maxalloc; |
WORD e_ss; |
WORD e_sp; |
WORD e_csum; |
WORD e_ip; |
WORD e_cs; |
WORD e_lfarlc; |
WORD e_ovno; |
WORD e_res[4]; |
WORD e_oemid; |
WORD e_oeminfo; |
WORD e_res2[10]; |
LONG e_lfanew; |
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; |
#pragma pack(pop) |
char *p; |
unsigned char c; |
#pragma pack(push,4) |
typedef struct _IMAGE_FILE_HEADER |
p = str; |
while( (c = *p) ) |
{ |
WORD Machine; |
WORD NumberOfSections; |
DWORD TimeDateStamp; |
DWORD PointerToSymbolTable; |
DWORD NumberOfSymbols; |
WORD SizeOfOptionalHeader; |
WORD Characteristics; |
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; |
if( c >= 'a' && c <= 'z' ) |
*p = c - 'a' + 'A'; |
++p; |
} |
typedef struct _IMAGE_DATA_DIRECTORY { |
DWORD VirtualAddress; |
DWORD Size; |
} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; |
return( str ); |
} |
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 |
void init_core_dll() |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_EXPORT_DIRECTORY exp; |
typedef struct _IMAGE_OPTIONAL_HEADER { |
WORD Magic; |
BYTE MajorLinkerVersion; |
BYTE MinorLinkerVersion; |
DWORD SizeOfCode; |
DWORD SizeOfInitializedData; |
DWORD SizeOfUninitializedData; |
DWORD AddressOfEntryPoint; |
DWORD BaseOfCode; |
DWORD BaseOfData; |
DWORD ImageBase; |
DWORD SectionAlignment; |
DWORD FileAlignment; |
WORD MajorOperatingSystemVersion; |
WORD MinorOperatingSystemVersion; |
WORD MajorImageVersion; |
WORD MinorImageVersion; |
WORD MajorSubsystemVersion; |
WORD MinorSubsystemVersion; |
DWORD Win32VersionValue; |
DWORD SizeOfImage; |
DWORD SizeOfHeaders; |
DWORD CheckSum; |
WORD Subsystem; |
WORD DllCharacteristics; |
DWORD SizeOfStackReserve; |
DWORD SizeOfStackCommit; |
DWORD SizeOfHeapReserve; |
DWORD SizeOfHeapCommit; |
DWORD LoaderFlags; |
DWORD NumberOfRvaAndSizes; |
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; |
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; |
dos = (PIMAGE_DOS_HEADER)LOAD_BASE; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
#pragma pack(pop) |
list_initialize(&core_dll.link); |
core_dll.img_base = LOAD_BASE; |
core_dll.img_size = nt->OptionalHeader.SizeOfImage; |
core_dll.img_md = NULL; |
#pragma pack(push,4) |
typedef struct _IMAGE_NT_HEADERS |
{ |
DWORD Signature; |
IMAGE_FILE_HEADER FileHeader; |
IMAGE_OPTIONAL_HEADER OptionalHeader; |
} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32; |
core_dll.img_hdr = nt; |
core_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); |
core_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE, |
nt->OptionalHeader.DataDirectory[0].VirtualAddress); |
core_dll.img_name = strupr(MakePtr(char*, LOAD_BASE, exp->Name)); |
#define IMAGE_SIZEOF_SHORT_NAME 8 |
typedef struct _IMAGE_SECTION_HEADER |
{ |
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; |
union |
{ |
DWORD PhysicalAddress; |
DWORD VirtualSize; |
} Misc; |
DWORD VirtualAddress; |
DWORD SizeOfRawData; |
DWORD PointerToRawData; |
DWORD PointerToRelocations; |
DWORD PointerToLinenumbers; |
WORD NumberOfRelocations; |
WORD NumberOfLinenumbers; |
DWORD Characteristics; |
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_BASE_RELOCATION { |
DWORD VirtualAddress; |
DWORD SizeOfBlock; |
} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; |
#pragma pack(pop) |
typedef struct _IMAGE_IMPORT_DESCRIPTOR |
{ |
union |
{ |
DWORD Characteristics; |
DWORD OriginalFirstThunk; |
DBG("%s base %x size %x sections %d exports %x\n", |
core_dll.img_name, core_dll.img_base, |
core_dll.img_size, nt->FileHeader.NumberOfSections, |
core_dll.img_exp ); |
}; |
DWORD TimeDateStamp; |
DWORD ForwarderChain; |
DWORD Name; |
DWORD FirstThunk; |
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; |
typedef struct _IMAGE_THUNK_DATA32 |
{ |
union |
{ |
DWORD ForwarderString; |
DWORD Function; |
DWORD Ordinal; |
DWORD AddressOfData; |
} u1; |
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32; |
typedef struct _IMAGE_IMPORT_BY_NAME |
dll_t * find_dll(const char *name) |
{ |
WORD Hint; |
BYTE Name[1]; |
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; |
dll_t* dll = &core_dll; |
#define IMAGE_ORDINAL_FLAG 0x80000000 |
typedef struct _IMAGE_EXPORT_DIRECTORY { |
DWORD Characteristics; |
DWORD TimeDateStamp; |
WORD MajorVersion; |
WORD MinorVersion; |
DWORD Name; |
DWORD Base; |
DWORD NumberOfFunctions; |
DWORD NumberOfNames; |
DWORD AddressOfFunctions; |
DWORD AddressOfNames; |
DWORD AddressOfNameOrdinals; |
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; |
//extern IMAGE_EXPORT_DIRECTORY kernel_exports; |
#define MakePtr( cast, ptr, addValue ) (cast)( (addr_t)(ptr) + (addValue) ) |
typedef struct |
do |
{ |
addr_t base; |
addr_t frame; |
md_t *md; |
if( !strncmp(name,dll->img_name,16)) |
return dll; |
IMAGE_OPTIONAL_HEADER *opthdr; |
dll = (dll_t*)dll->link.next; |
}dll_t; |
}while(&dll->link != &core_dll.link); |
static inline bool IsPowerOf2(u32_t val) |
{ |
if(val == 0) |
return false; |
return (val & (val - 1)) == 0; |
} |
static inline void sec_copy(void *dst, const void *src, size_t len) |
{ |
u32_t tmp; |
__asm__ __volatile__ ( |
"shrl $2, %%ecx \n\t" |
"rep movsl" |
:"=c"(tmp),"=S"(tmp),"=D"(tmp) |
:"c"(len),"S"(src),"D"(dst) |
:"cc"); |
return NULL; |
}; |
static inline void sec_clear(void *dst, size_t len) |
{ |
u32_t tmp; |
__asm__ __volatile__ ( |
"xorl %%eax, %%eax \n\t" |
"rep stosb" |
:"=c"(tmp),"=D"(tmp) |
:"c"(len),"D"(dst) |
:"eax","cc"); |
}; |
int __stdcall strncmp(const char *s1, const char *s2, size_t n); |
void __export create_image(void *img_base, void *image) asm ("CreateImage"); |
md_t* __fastcall load_image(const char *path); |
void* __fastcall load_pe(const char *path) |
{ |
md_t *md; |
md = load_image(path); |
if( md ) |
return (void*)md->base; |
return NULL; |
}; |
typedef struct |
{ |
char srv_name[16]; // ASCIIZ string |
271,6 → 102,8 |
if( ! md ) |
return 0; |
if( link_image( md->base ) ) |
{ |
dos = (PIMAGE_DOS_HEADER)md->base; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
284,405 → 117,10 |
return srv; |
} |
md_t* __fastcall load_image(const char *path) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
md_t *img_md; |
size_t img_size; |
void *img_base; |
count_t img_pages; |
size_t raw_size = 0; |
void *raw; |
// void *image; |
DBG("load file %s\n", path); |
raw = load_file(path, &raw_size); |
DBG("raw = %x\n\n", raw); |
dos = (PIMAGE_DOS_HEADER)raw; |
if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) |
return NULL; |
if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
return NULL; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
if( (addr_t)nt < (addr_t)raw) |
return NULL; |
if(nt->Signature != IMAGE_NT_SIGNATURE) |
return NULL; |
if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
return NULL; |
if(nt->OptionalHeader.SectionAlignment < PAGE_SIZE) |
{ |
if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
return NULL; |
} |
else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
return NULL; |
if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
!IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
return NULL; |
if(nt->FileHeader.NumberOfSections > 96) |
return NULL; |
img_size = nt->OptionalHeader.SizeOfImage; |
// img_pages = img_size / PAGE_SIZE; |
img_md = md_alloc(img_size, PG_SW); |
if( !img_md) |
{ |
mem_free(raw); |
return NULL; |
}; |
img_base = (void*)img_md->base; |
create_image(img_base, raw); |
mem_free(raw); |
// dos = (PIMAGE_DOS_HEADER)img_base; |
// nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
return img_md; |
}; |
/* |
addr_t get_proc_addr(addr_t module, char *name) |
{ |
PIMAGE_DOS_HEADER expdos; |
PIMAGE_NT_HEADERS32 expnt; |
PIMAGE_EXPORT_DIRECTORY exp; |
u32_t *functions; |
char **funcname; |
int ind; |
expdos = (PIMAGE_DOS_HEADER)module; |
expnt = MakePtr( PIMAGE_NT_HEADERS32, expdos, expdos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,module, |
expnt->OptionalHeader.DataDirectory[0].VirtualAddress); |
functions = MakePtr(DWORD*,exp->AddressOfFunctions,module); |
funcname = MakePtr(char**,exp->AddressOfNames,module); |
for(ind=0; *funcname;funcname++,ind++) |
{ |
if(!strcmp(name,MakePtr(char*,*funcname,module))) |
return functions[ind] + module; |
}; |
return -1; |
}; |
*/ |
void create_image(void *img_base, void *image) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_SECTION_HEADER img_sec; |
u32_t sec_align; |
int i; |
/* assumed that image is valid */ |
dos = (PIMAGE_DOS_HEADER)image; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
sec_copy(img_base,image,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++) |
{ |
char *src_ptr; |
char *dest_ptr; |
size_t sec_size; |
src_ptr = MakePtr(char*, image, img_sec->PointerToRawData); |
dest_ptr = MakePtr(char*,img_base, img_sec->VirtualAddress); |
if(img_sec->SizeOfRawData) |
sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
sec_size = (img_sec->Misc.VirtualSize + sec_align -1) & -sec_align; |
if(sec_size > img_sec->SizeOfRawData) |
sec_clear(dest_ptr + img_sec->SizeOfRawData, |
sec_size - img_sec->SizeOfRawData); |
img_sec++; |
} |
if(nt->OptionalHeader.DataDirectory[5].Size) |
{ |
PIMAGE_BASE_RELOCATION reloc; |
/* FIXME addr_t */ |
u32_t delta = (u32_t)img_base - nt->OptionalHeader.ImageBase; |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
while ( reloc->SizeOfBlock != 0 ) |
{ |
u32_t cnt; |
u16_t *entry; |
u16_t reltype; |
u32_t offs; |
cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(u16_t); |
entry = MakePtr( u16_t*, reloc, sizeof(*reloc) ); |
for ( i=0; i < cnt; i++ ) |
{ |
u16_t *p16; |
u32_t *p32; |
reltype = (*entry & 0xF000) >> 12; |
offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
switch(reltype) |
{ |
case 1: |
p16 = MakePtr(u16_t*, img_base, offs); |
*p16+= (u16_t)(delta>>16); |
break; |
case 2: |
p16 = MakePtr(u16_t*, img_base, offs); |
*p16+= (u16_t)delta; |
break; |
case 3: |
p32 = MakePtr(u32_t*, img_base, offs); |
*p32+= delta; |
} |
entry++; |
} |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
} |
}; |
if(nt->OptionalHeader.DataDirectory[1].Size) |
{ |
PIMAGE_IMPORT_DESCRIPTOR imp; |
int warn = 0; |
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
while ( 1 ) |
{ |
PIMAGE_THUNK_DATA32 thunk; |
PIMAGE_DOS_HEADER expdos; |
PIMAGE_NT_HEADERS32 expnt; |
PIMAGE_EXPORT_DIRECTORY exp; |
u32_t *iat; |
char *libname; |
addr_t *functions; |
u16_t *ordinals; |
char **funcname; |
if ( (imp->TimeDateStamp==0 ) && (imp->Name==0) ) |
break; |
libname=MakePtr(char*,imp->Name, img_base); |
DBG("import from %s\n",libname); |
expdos = (PIMAGE_DOS_HEADER)IMAGE_BASE; |
expnt = MakePtr( PIMAGE_NT_HEADERS32, expdos, expdos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE, |
expnt->OptionalHeader.DataDirectory[0].VirtualAddress); |
functions = MakePtr(DWORD*,exp->AddressOfFunctions,LOAD_BASE); |
ordinals = MakePtr(WORD*, exp->AddressOfNameOrdinals,LOAD_BASE); |
funcname = MakePtr(char**, exp->AddressOfNames,LOAD_BASE); |
thunk = MakePtr(PIMAGE_THUNK_DATA32, |
imp->Characteristics, img_base); |
iat= MakePtr(DWORD*,imp->FirstThunk, img_base); |
while ( 1 ) // Loop forever (or until we break out) |
{ |
PIMAGE_IMPORT_BY_NAME ord; |
addr_t addr; |
if ( thunk->u1.AddressOfData == 0 ) |
break; |
if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG ) |
{ |
// printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF); |
break; |
} |
else |
{ |
ord = MakePtr(PIMAGE_IMPORT_BY_NAME, |
thunk->u1.AddressOfData, img_base); |
*iat=0; |
DBG("import %s", ord->Name); |
if(strncmp(ord->Name, |
MakePtr(char*,funcname[ord->Hint],LOAD_BASE),32)) |
{ |
int ind; |
char **names=funcname; |
for(names = funcname,ind = 0; |
ind < exp->NumberOfNames; names++,ind++) |
{ |
if(!strncmp(ord->Name,MakePtr(char*,*names,LOAD_BASE),32)) |
{ |
DBG(" \tat %x\n", functions[ind] + LOAD_BASE); |
*iat = functions[ind] + LOAD_BASE; |
break; |
}; |
}; |
if(ind == exp->NumberOfNames) |
{ |
DBG(" unresolved import %s\n",ord->Name); |
warn=1; |
}; |
} |
else |
{ |
DBG(" \tat %x\n", functions[ord->Hint] + LOAD_BASE); |
*iat = functions[ord->Hint] + LOAD_BASE; |
}; |
}; |
thunk++; // Advance to next thunk |
iat++; |
} |
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
}; |
}; |
DBG("\ncreate pe base %x, size %x, %d sections\n\n",img_base, |
nt->OptionalHeader.SizeOfImage, nt->FileHeader.NumberOfSections); |
}; |
/* |
u32 map_PE(u32 base, void *image) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_SECTION_HEADER sec; |
int i; |
int pages; |
dos = (PIMAGE_DOS_HEADER)image; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
img_size = nt->OptionalHeader.SizeOfImage; |
img_pages = img_size / PAGE_SIZE; |
img_md = md_alloc(img_size, PG_SW); |
if( !img_md) |
md_free( md ); |
return NULL; |
scopy(base,(u32)image,nt->OptionalHeader.SizeOfHeaders); |
sec = MakePtr(PIMAGE_SECTION_HEADER,nt,sizeof(IMAGE_NT_HEADERS32)); |
if(nt->OptionalHeader.DataDirectory[1].Size) |
{ |
PIMAGE_IMPORT_DESCRIPTOR imp; |
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR,base, |
nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
while ( 1 ) |
{ |
PIMAGE_THUNK_DATA32 thunk; |
u32 *iat; |
char *libname; |
if ( (imp->TimeDateStamp==0 ) && (imp->Name==0) ) |
break; |
thunk = MakePtr(PIMAGE_THUNK_DATA32, |
imp->Characteristics, base); |
iat= MakePtr(DWORD*,imp->FirstThunk, base); |
while ( 1 ) // Loop forever (or until we break out) |
{ |
PIMAGE_IMPORT_BY_NAME ord; |
u32 addr; |
if ( thunk->u1.AddressOfData == 0 ) |
break; |
if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG ) |
{ |
// printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF); |
break; |
} |
else |
{ |
PKERNEL_EXPORT exp; |
exp = kernel_export; |
ord = MakePtr(PIMAGE_IMPORT_BY_NAME, |
thunk->u1.AddressOfData,base); |
*iat=-1; |
do |
{ |
if(!strncmp(ord->Name,exp->name,16)) |
{ |
*iat = exp->address; |
break; |
} |
exp++; |
} while(exp->name != 0); |
}; |
thunk++; // Advance to next thunk |
iat++; |
} |
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
} |
}; |
*/ |
/kernel/branches/kolibri_pe/core/export.asm |
---|
3,24 → 3,24 |
.section .drectve |
.ascii " -export:CreateImage" |
.ascii " -export:LoadFile" |
.ascii " -export:CreateImage" # cdecl |
.ascii " -export:LoadFile" # stdcall |
.ascii " -export:Kmalloc" # |
.ascii " -export:Kfree" # |
.ascii " -export:Kmalloc" # eax FIXME |
.ascii " -export:Kfree" # eax FIXME |
.ascii " -export:UserAlloc" # stdcall |
.ascii " -export:UserFree" # stdcall |
.ascii " -export:GetPgAddr" # eax FIXME |
.ascii " -export:MapIoMem" # stdcall |
.ascii " -export:GetPgAddr" # eax |
.ascii " -export:CreateObject" # |
.ascii " -export:DestroyObject" # |
.ascii " -export:CreateRingBuffer" # stdcall |
.ascii " -export:CommitPages" # eax, ebx, ecx |
.ascii " -export:CommitPages" # eax, ebx, ecx FIXME |
.ascii " -export:UnmapPages" # eax, ecx FIXME |
.ascii " -export:CreateObject" # eax, ebx FIXME |
.ascii " -export:DestroyObject" # eax |
.ascii " -export:RegService" # stdcall |
.ascii " -export:UnmapPages" # eax, ecx |
.ascii " -export:SysMsgBoardStr" # |
.ascii " -export:SetScreen" # |
/kernel/branches/kolibri_pe/core/heap.c |
---|
110,7 → 110,7 |
if(idx0 == 31) |
{ |
md_t *tmp = (md_t*)lheap.unmapped[31].next; |
while((link_t*)tmp != &lheap.unmapped[31]) |
while(&tmp->link != &lheap.unmapped[31]) |
{ |
if(tmp->size >= size) |
{ |
193,7 → 193,7 |
ASSERT( !list_empty(&sheap.unmapped[31])); |
md_t *tmp = (md_t*)sheap.unmapped[31].next; |
while((link_t*)tmp != &sheap.unmapped[31]) |
while( &tmp->link != &sheap.unmapped[31]) |
{ |
if(tmp->size >= size) |
{ |
283,7 → 283,7 |
{ |
md_t *tmp = (md_t*)sheap.unmapped[31].next; |
while((link_t*)tmp != &sheap.unmapped[31]) |
while( &tmp->link != &sheap.unmapped[31]) |
{ |
if(md->base < tmp->base) |
break; |
333,7 → 333,7 |
ASSERT( !list_empty(&sheap.mapped[31])); |
md_t *tmp = (md_t*)sheap.mapped[31].next; |
while((link_t*)tmp != &sheap.mapped[31]) |
while( &tmp->link != &sheap.mapped[31]) |
{ |
if(tmp->size >= size) |
{ |
437,7 → 437,7 |
{ |
md_t *tmp = (md_t*)sheap.mapped[31].next; |
while((link_t*)tmp != &sheap.mapped[31]) |
while( &tmp->link != &sheap.mapped[31]) |
{ |
if(md->base < tmp->base) |
break; |
521,7 → 521,7 |
{ |
md_t *tmp = (md_t*)sheap.unmapped[31].next; |
while((link_t*)tmp != &sheap.unmapped[31]) |
while( &tmp->link != &sheap.unmapped[31]) |
{ |
if(md->base < tmp->base) |
break; |
598,7 → 598,7 |
{ |
md_t *tmp = (md_t*)sheap.mapped[31].next; |
while((link_t*)tmp != &sheap.mapped[31]) |
while( &tmp->link != &sheap.mapped[31]) |
{ |
if(md->base < tmp->base) |
break; |
663,6 → 663,44 |
}; |
void __fastcall md_free(md_t *md) |
{ |
if( md ) |
{ |
md_t *lmd; |
DBG("free md: %x base: %x size: %x\n",md, md->base, md->size); |
ASSERT(md->state == MD_USED); |
list_remove((link_t*)md); |
lmd = (md_t*)md->parent; |
ASSERT(lmd != 0); |
if(lmd->parent != 0) |
{ |
addr_t mem = md->base; |
addr_t *pte = &((addr_t*)page_tabs)[md->base>>12]; |
count_t tmp = md->size >> 12; |
while(tmp--) |
{ |
*pte++ = 0; |
asm volatile ( "invlpg (%0)" ::"r" (mem) ); |
mem+= 4096; |
}; |
free_mapped_md( md ); |
} |
else |
free_unmapped_md( md ); |
} |
return; |
}; |
void * __fastcall mem_alloc(size_t size, u32_t flags) |
{ |
eflags_t efl; |
687,7 → 725,7 |
{ |
md_t *tmp = (md_t*)sheap.used.next; |
while((link_t*)tmp != &sheap.used) |
while( &tmp->link != &sheap.used) |
{ |
if(md->base < tmp->base) |
break; |
720,7 → 758,7 |
tmp = (md_t*)sheap.used.next; |
while((link_t*)tmp != &sheap.used) |
while( &tmp->link != &sheap.used) |
{ |
if( tmp->base == (addr_t)mem ) |
{ |
732,38 → 770,10 |
if( md ) |
{ |
md_t *lmd; |
md_free( md ); |
DBG("\tmd: %x base: %x size: %x\n",md, md->base, md->size); |
ASSERT(md->state == MD_USED); |
list_remove((link_t*)md); |
lmd = (md_t*)md->parent; |
ASSERT(lmd != 0); |
if(lmd->parent != 0) |
{ |
count_t tmp = md->size >> 12; |
addr_t *pte = &((addr_t*)page_tabs)[md->base>>12]; |
while(tmp--) |
{ |
*pte++ = 0; |
asm volatile ( |
"invlpg (%0)" |
::"r" (mem) ); |
mem+= 4096; |
}; |
free_mapped_md( md ); |
} |
else |
free_unmapped_md( md ); |
} |
else |
DBG("\tERROR: invalid base address: %x\n", mem); |
safe_sti(efl); |
/kernel/branches/kolibri_pe/core/pe.c |
---|
0,0 → 1,414 |
#include <types.h> |
#include <core.h> |
#include <spinlock.h> |
#include <link.h> |
#include <mm.h> |
#include <slab.h> |
#include <pe.h> |
static inline bool IsPowerOf2(u32_t val) |
{ |
if(val == 0) |
return false; |
return (val & (val - 1)) == 0; |
} |
static inline void sec_copy(addr_t dst, addr_t src, size_t len) |
{ |
u32_t tmp; |
__asm__ __volatile__ ( |
"shrl $2, %%ecx \n\t" |
"rep movsl" |
:"=c"(tmp),"=S"(tmp),"=D"(tmp) |
:"c"(len),"S"(src),"D"(dst) |
:"cc"); |
}; |
static inline void sec_clear(addr_t dst, size_t len) |
{ |
u32_t tmp; |
__asm__ __volatile__ ( |
"xorl %%eax, %%eax \n\t" |
"rep stosb" |
:"=c"(tmp),"=D"(tmp) |
:"c"(len),"D"(dst) |
:"eax","cc"); |
}; |
int __stdcall strncmp(const char *s1, const char *s2, size_t n); |
void __export create_image(addr_t img_base, addr_t raw) asm ("CreateImage"); |
bool link_image(addr_t img_base); |
md_t* __fastcall load_image(const char *path); |
/* |
void* __fastcall load_pe(const char *path) |
{ |
md_t *md; |
md = load_image(path); |
if( md ) |
return (void*)md->base; |
return NULL; |
}; |
*/ |
bool 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 false; |
if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) |
return false; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
if( (addr_t)nt < (addr_t)raw) |
return false; |
if(nt->Signature != IMAGE_NT_SIGNATURE) |
return false; |
if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) |
return false; |
if(nt->OptionalHeader.SectionAlignment < PAGE_SIZE) |
{ |
if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) |
return false; |
} |
else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) |
return false; |
if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || |
!IsPowerOf2(nt->OptionalHeader.FileAlignment)) |
return false; |
if(nt->FileHeader.NumberOfSections > 96) |
return false; |
return true; |
} |
md_t* __fastcall load_image(const char *path) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
md_t *img_md; |
size_t img_size; |
addr_t img_base; |
count_t img_pages; |
size_t raw_size = 0; |
void *raw; |
DBG("\nload image %s", path); |
raw = load_file(path, &raw_size); |
DBG(" raw = %x\n", raw); |
if( ! raw) |
{ |
DBG("file not found: %s\n", path); |
return NULL; |
}; |
if( ! validate_pe(raw, raw_size) ) |
{ |
DBG("invalid pe file %s\n", path); |
mem_free(raw); |
return NULL; |
} |
dos = (PIMAGE_DOS_HEADER)raw; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
img_size = nt->OptionalHeader.SizeOfImage; |
img_md = md_alloc(img_size, PG_SW); |
if( !img_md) |
{ |
mem_free(raw); |
return NULL; |
}; |
img_base = img_md->base; |
create_image(img_base, (addr_t)raw); |
mem_free(raw); |
// dos = (PIMAGE_DOS_HEADER)img_base; |
// nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
return img_md; |
}; |
/* |
addr_t get_proc_addr(addr_t module, char *name) |
{ |
PIMAGE_DOS_HEADER expdos; |
PIMAGE_NT_HEADERS32 expnt; |
PIMAGE_EXPORT_DIRECTORY exp; |
u32_t *functions; |
char **funcname; |
int ind; |
expdos = (PIMAGE_DOS_HEADER)module; |
expnt = MakePtr( PIMAGE_NT_HEADERS32, expdos, expdos->e_lfanew); |
exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,module, |
expnt->OptionalHeader.DataDirectory[0].VirtualAddress); |
functions = MakePtr(DWORD*,exp->AddressOfFunctions,module); |
funcname = MakePtr(char**,exp->AddressOfNames,module); |
for(ind=0; *funcname;funcname++,ind++) |
{ |
if(!strcmp(name,MakePtr(char*,*funcname,module))) |
return functions[ind] + module; |
}; |
return -1; |
}; |
*/ |
void create_image(addr_t img_base, addr_t raw) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
PIMAGE_SECTION_HEADER img_sec; |
u32_t sec_align; |
int i; |
/* assumed that image is valid */ |
dos = (PIMAGE_DOS_HEADER)raw; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
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++) |
{ |
addr_t src_ptr; |
addr_t dest_ptr; |
size_t sec_size; |
src_ptr = MakePtr(addr_t, raw, img_sec->PointerToRawData); |
dest_ptr = MakePtr(addr_t,img_base, img_sec->VirtualAddress); |
if(img_sec->SizeOfRawData) |
sec_copy(dest_ptr, src_ptr, img_sec->SizeOfRawData); |
sec_size = (img_sec->Misc.VirtualSize + sec_align -1) & -sec_align; |
if(sec_size > img_sec->SizeOfRawData) |
sec_clear(dest_ptr + img_sec->SizeOfRawData, |
sec_size - img_sec->SizeOfRawData); |
img_sec++; |
} |
if(nt->OptionalHeader.DataDirectory[5].Size) |
{ |
PIMAGE_BASE_RELOCATION reloc; |
/* FIXME addr_t */ |
u32_t delta = (u32_t)img_base - nt->OptionalHeader.ImageBase; |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, img_base, |
nt->OptionalHeader.DataDirectory[5].VirtualAddress); |
while ( reloc->SizeOfBlock != 0 ) |
{ |
u32_t cnt; |
u16_t *entry; |
u16_t reltype; |
u32_t offs; |
cnt = (reloc->SizeOfBlock - sizeof(*reloc))/sizeof(u16_t); |
entry = MakePtr( u16_t*, reloc, sizeof(*reloc) ); |
for ( i=0; i < cnt; i++ ) |
{ |
u16_t *p16; |
u32_t *p32; |
reltype = (*entry & 0xF000) >> 12; |
offs = (*entry & 0x0FFF) + reloc->VirtualAddress; |
switch(reltype) |
{ |
case 1: |
p16 = MakePtr(u16_t*, img_base, offs); |
*p16+= (u16_t)(delta>>16); |
break; |
case 2: |
p16 = MakePtr(u16_t*, img_base, offs); |
*p16+= (u16_t)delta; |
break; |
case 3: |
p32 = MakePtr(u32_t*, img_base, offs); |
*p32+= delta; |
} |
entry++; |
} |
reloc = MakePtr(PIMAGE_BASE_RELOCATION, reloc,reloc->SizeOfBlock); |
} |
}; |
DBG("\ncreate pe base %x, size %x, %d sections\n\n",img_base, |
nt->OptionalHeader.SizeOfImage, nt->FileHeader.NumberOfSections); |
}; |
bool link_image(addr_t img_base) |
{ |
PIMAGE_DOS_HEADER dos; |
PIMAGE_NT_HEADERS32 nt; |
int warn = 0; |
/* assumed that image is valid */ |
dos = (PIMAGE_DOS_HEADER)img_base; |
nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); |
if(nt->OptionalHeader.DataDirectory[1].Size) |
{ |
PIMAGE_IMPORT_DESCRIPTOR imp; |
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base, |
nt->OptionalHeader.DataDirectory[1].VirtualAddress); |
while ( 1 ) |
{ |
PIMAGE_THUNK_DATA32 thunk; |
PIMAGE_DOS_HEADER expdos; |
PIMAGE_NT_HEADERS32 expnt; |
PIMAGE_EXPORT_DIRECTORY exp; |
u32_t *iat; |
char *libname; |
addr_t *functions; |
u16_t *ordinals; |
char **funcname; |
dll_t *exp_dll; |
if ( (imp->TimeDateStamp==0 ) && (imp->Name==0) ) |
break; |
libname=MakePtr(char*,imp->Name, img_base); |
DBG("import from %s\n",libname); |
exp_dll = find_dll(libname); |
if(exp_dll != NULL) |
{ |
DBG("find %s\n", exp_dll->img_name); |
} |
else |
{ |
DBG("can't find %s\n", libname); |
return false; |
} |
exp = exp_dll->img_exp; |
functions = MakePtr(DWORD*,exp->AddressOfFunctions,exp_dll->img_base); |
ordinals = MakePtr(WORD*, exp->AddressOfNameOrdinals,exp_dll->img_base); |
funcname = MakePtr(char**, exp->AddressOfNames,exp_dll->img_base); |
thunk = MakePtr(PIMAGE_THUNK_DATA32, |
imp->Characteristics, img_base); |
iat= MakePtr(DWORD*,imp->FirstThunk, img_base); |
while ( 1 ) // Loop forever (or until we break out) |
{ |
PIMAGE_IMPORT_BY_NAME ord; |
addr_t addr; |
if ( thunk->u1.AddressOfData == 0 ) |
break; |
if ( thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG ) |
{ |
// printf(" %4u\n", thunk->u1.Ordinal & 0xFFFF); |
break; |
} |
else |
{ |
ord = MakePtr(PIMAGE_IMPORT_BY_NAME, |
thunk->u1.AddressOfData, img_base); |
*iat=0; |
DBG("import %s", ord->Name); |
if(strncmp(ord->Name, |
MakePtr(char*,funcname[ord->Hint],exp_dll->img_base),32)) |
{ |
int ind; |
char **names=funcname; |
for(names = funcname,ind = 0; |
ind < exp->NumberOfNames; names++,ind++) |
{ |
if(!strncmp(ord->Name,MakePtr(char*,*names,exp_dll->img_base),32)) |
{ |
DBG(" \tat %x\n", functions[ind] + exp_dll->img_base); |
*iat = functions[ind] + exp_dll->img_base; |
break; |
}; |
}; |
if(ind == exp->NumberOfNames) |
{ |
DBG(" unresolved import %s\n",ord->Name); |
warn=1; |
}; |
} |
else |
{ |
DBG(" \tat %x\n", functions[ord->Hint] + exp_dll->img_base); |
*iat = functions[ord->Hint] + exp_dll->img_base; |
}; |
}; |
thunk++; // Advance to next thunk |
iat++; |
} |
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR |
}; |
}; |
if ( !warn ) |
return true; |
else |
return false; |
} |
/kernel/branches/kolibri_pe/include/mm.h |
---|
87,6 → 87,7 |
md_t* __fastcall md_alloc(size_t size, u32_t flags) ; |
void __fastcall md_free(md_t *md); |
void* __fastcall __export mem_alloc(size_t size, u32_t flags) asm ("MemAlloc"); |
void __fastcall __export mem_free(void *mem) asm ("MemFree"); |
/kernel/branches/kolibri_pe/include/pe.h |
---|
0,0 → 1,202 |
typedef unsigned short WORD; |
typedef unsigned int DWORD; |
typedef unsigned int LONG; |
typedef unsigned char BYTE; |
#define IMAGE_DOS_SIGNATURE 0x5A4D |
#define IMAGE_NT_SIGNATURE 0x00004550 |
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b |
#pragma pack(push,2) |
typedef struct _IMAGE_DOS_HEADER |
{ |
WORD e_magic; |
WORD e_cblp; |
WORD e_cp; |
WORD e_crlc; |
WORD e_cparhdr; |
WORD e_minalloc; |
WORD e_maxalloc; |
WORD e_ss; |
WORD e_sp; |
WORD e_csum; |
WORD e_ip; |
WORD e_cs; |
WORD e_lfarlc; |
WORD e_ovno; |
WORD e_res[4]; |
WORD e_oemid; |
WORD e_oeminfo; |
WORD e_res2[10]; |
LONG e_lfanew; |
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_FILE_HEADER |
{ |
WORD Machine; |
WORD NumberOfSections; |
DWORD TimeDateStamp; |
DWORD PointerToSymbolTable; |
DWORD NumberOfSymbols; |
WORD SizeOfOptionalHeader; |
WORD Characteristics; |
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; |
typedef struct _IMAGE_DATA_DIRECTORY { |
DWORD VirtualAddress; |
DWORD Size; |
} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY; |
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 |
typedef struct _IMAGE_OPTIONAL_HEADER { |
WORD Magic; |
BYTE MajorLinkerVersion; |
BYTE MinorLinkerVersion; |
DWORD SizeOfCode; |
DWORD SizeOfInitializedData; |
DWORD SizeOfUninitializedData; |
DWORD AddressOfEntryPoint; |
DWORD BaseOfCode; |
DWORD BaseOfData; |
DWORD ImageBase; |
DWORD SectionAlignment; |
DWORD FileAlignment; |
WORD MajorOperatingSystemVersion; |
WORD MinorOperatingSystemVersion; |
WORD MajorImageVersion; |
WORD MinorImageVersion; |
WORD MajorSubsystemVersion; |
WORD MinorSubsystemVersion; |
DWORD Win32VersionValue; |
DWORD SizeOfImage; |
DWORD SizeOfHeaders; |
DWORD CheckSum; |
WORD Subsystem; |
WORD DllCharacteristics; |
DWORD SizeOfStackReserve; |
DWORD SizeOfStackCommit; |
DWORD SizeOfHeapReserve; |
DWORD SizeOfHeapCommit; |
DWORD LoaderFlags; |
DWORD NumberOfRvaAndSizes; |
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; |
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_NT_HEADERS |
{ |
DWORD Signature; |
IMAGE_FILE_HEADER FileHeader; |
IMAGE_OPTIONAL_HEADER OptionalHeader; |
} IMAGE_NT_HEADERS32,*PIMAGE_NT_HEADERS32; |
#define IMAGE_SIZEOF_SHORT_NAME 8 |
typedef struct _IMAGE_SECTION_HEADER |
{ |
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; |
union |
{ |
DWORD PhysicalAddress; |
DWORD VirtualSize; |
} Misc; |
DWORD VirtualAddress; |
DWORD SizeOfRawData; |
DWORD PointerToRawData; |
DWORD PointerToRelocations; |
DWORD PointerToLinenumbers; |
WORD NumberOfRelocations; |
WORD NumberOfLinenumbers; |
DWORD Characteristics; |
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER; |
#pragma pack(pop) |
#pragma pack(push,4) |
typedef struct _IMAGE_BASE_RELOCATION { |
DWORD VirtualAddress; |
DWORD SizeOfBlock; |
} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; |
#pragma pack(pop) |
typedef struct _IMAGE_IMPORT_DESCRIPTOR |
{ |
union |
{ |
DWORD Characteristics; |
DWORD OriginalFirstThunk; |
}; |
DWORD TimeDateStamp; |
DWORD ForwarderChain; |
DWORD Name; |
DWORD FirstThunk; |
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; |
typedef struct _IMAGE_THUNK_DATA32 |
{ |
union |
{ |
DWORD ForwarderString; |
DWORD Function; |
DWORD Ordinal; |
DWORD AddressOfData; |
} u1; |
} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32; |
typedef struct _IMAGE_IMPORT_BY_NAME |
{ |
WORD Hint; |
BYTE Name[1]; |
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; |
#define IMAGE_ORDINAL_FLAG 0x80000000 |
typedef struct _IMAGE_EXPORT_DIRECTORY { |
DWORD Characteristics; |
DWORD TimeDateStamp; |
WORD MajorVersion; |
WORD MinorVersion; |
DWORD Name; |
DWORD Base; |
DWORD NumberOfFunctions; |
DWORD NumberOfNames; |
DWORD AddressOfFunctions; |
DWORD AddressOfNames; |
DWORD AddressOfNameOrdinals; |
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; |
typedef struct |
{ |
link_t link; |
addr_t img_base; |
size_t img_size; |
char *img_name; |
md_t *img_md; |
PIMAGE_NT_HEADERS32 img_hdr; |
PIMAGE_SECTION_HEADER img_sec; |
PIMAGE_EXPORT_DIRECTORY img_exp; |
u32_t img_map[8]; /* mapped treads */ |
}dll_t; |
#define MakePtr( cast, ptr, addValue ) (cast)( (addr_t)(ptr) + (addr_t)(addValue) ) |
dll_t * find_dll(const char *name); |
md_t* __fastcall load_image(const char *path); |
void __export create_image(addr_t img_base, addr_t image) asm ("CreateImage"); |
/kernel/branches/kolibri_pe/kernel.asm |
---|
179,11 → 179,12 |
extrn _init |
extrn _init_mm |
extrn @init_heap@8 |
extrn _init_core_dll |
extrn @core_alloc@4 |
extrn @core_free@4 |
extrn @init_heap@8 |
extrn @find_large_md@4 |
extrn _MemAlloc |
402,6 → 403,8 |
mov edx, 0x40000000 |
call @init_heap@8 |
call _init_core_dll |
mov esi, _16bit_start |
mov ecx, _16bit_end |
shr ecx, 2 |
/kernel/branches/kolibri_pe/makefile |
---|
30,6 → 30,7 |
mm.c \ |
slab.c \ |
heap.c \ |
pe.c \ |
dll.c \ |
spinlock.c \ |
boot/boot.asm \ |