newlib: dynamic loader

git-svn-id: svn://kolibrios.org@3809 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
Sergey Semyonov (Serge) 2013-07-11 17:20:47 +00:00
parent 89c2639856
commit 1707fbc555
6 changed files with 77 additions and 243 deletions

View File

@ -1,7 +1,7 @@
CC = gcc CC = gcc
CFLAGS = -c -O2 -fomit-frame-pointer CFLAGS = -c -O2 -fomit-frame-pointer -DBUILD_DLL
LDFLAGS = -nostdlib -shared -s -T libcdll.lds --out-implib libcimp.a --image-base 0 LDFLAGS = -nostdlib -shared -s -T libcdll.lds --out-implib libcimp.a --image-base 0
LIBC_TOPDIR = . LIBC_TOPDIR = .
@ -21,11 +21,12 @@ STATIC_SRCS:= \
crt/exit.S \ crt/exit.S \
pe/crtloader.c pe/crtloader.c
DLL_SRCS:= \ LIBDLL_SRCS:= \
crt/crtbegin.c \ crt/dllstart.c \
crt/pseudo-reloc.c \
crt/chkstk.S \ crt/chkstk.S \
crt/exit.S crt/exit.S \
crt/pseudo-reloc.c \
crt/setjmp.S
LIBCDLL_SRCS:= \ LIBCDLL_SRCS:= \
@ -39,7 +40,6 @@ LIBCRT_SRCS:= \
crt/start.S \ crt/start.S \
crt/chkstk.S \ crt/chkstk.S \
crt/crt3.c \ crt/crt3.c \
crt/crtbegin.o \
pe/crtloader.c pe/crtloader.c
CORE_SRCS:= \ CORE_SRCS:= \
@ -306,7 +306,7 @@ STATIC_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(STATIC_SRCS)))
LIBCRT_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCRT_SRCS))) LIBCRT_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCRT_SRCS)))
DLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(DLL_SRCS))) LIBDLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBDLL_SRCS)))
LIBCDLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCDLL_SRCS))) LIBCDLL_OBJS = $(patsubst %.S, %.o, $(patsubst %.c, %.o, $(LIBCDLL_SRCS)))
@ -374,11 +374,8 @@ $(NAME).dll: $(LIB_OBJS) $(SRC_DEP) Makefile
libcrt.a: $(LIBCRT_OBJS) Makefile libcrt.a: $(LIBCRT_OBJS) Makefile
ar rc libcrt.a $(LIBCRT_OBJS) ar rc libcrt.a $(LIBCRT_OBJS)
libdll.a: $(DLL_OBJS) Makefile libdll.a: $(LIBDLL_OBJS) Makefile
ar rc libdll.a $(DLL_OBJS) ar rc libdll.a $(LIBDLL_OBJS)
libc.obj: $(NAME).dll
fasm pe/libc.asm ./libc.obj
static: $(NAME).a static: $(NAME).a

View File

@ -1,9 +1,6 @@
extern void _pei386_runtime_relocator (void); extern void _pei386_runtime_relocator (void);
int DllStartup(void *module, int reason);// __attribute__ ((dllexport));
int DllStartup(void *module, int reason) int DllStartup(void *module, int reason)
{ {
_pei386_runtime_relocator(); _pei386_runtime_relocator();

View File

@ -0,0 +1,11 @@
void _pei386_runtime_relocator (void);
int DllStartup(void *module, int reason);
int DllStartup(void *module, int reason)
{
_pei386_runtime_relocator();
return 1;
};

View File

@ -1,8 +1,6 @@
OUTPUT_FORMAT(pei-i386) OUTPUT_FORMAT(pei-i386)
ENTRY("____dll_start")
SECTIONS SECTIONS
{ {

View File

@ -209,20 +209,18 @@ void* load_libc()
raw_img = uf.data; raw_img = uf.data;
raw_size = uf.size; raw_size = uf.size;
if(raw_img == NULL) if(raw_img == NULL)
return NULL; return NULL;
// printf("libc.dll raw %p, size %d\n", raw_img, raw_size); // printf("libc.dll raw %p, size %d\n", raw_img, raw_size);
if( validate_pe(raw_img, raw_size, 0) == 0) if(validate_pe(raw_img, raw_size, 0) != 0)
{ {
// printf("invalide libc.dll\n"); // printf("invalide libc.dll\n");
user_free(raw_img); img_base = create_image(raw_img);
}; };
img_base = create_image(raw_img); user_free(raw_img);
return img_base; return img_base;

View File

@ -20,10 +20,8 @@
void init_loader(void *libc_image); void init_loader(void *libc_image);
void* __fastcall create_image(void *raw); void* create_image(void *raw);
int __fastcall link_image(void *img_base); int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp);
int __fastcall do_exec(uint32_t my_app, uint32_t *params);
extern char* __appenv; extern char* __appenv;
extern int __appenv_size; extern int __appenv_size;
@ -148,6 +146,8 @@ void init_loader(void *libc_image)
PIMAGE_EXPORT_DIRECTORY exp; PIMAGE_EXPORT_DIRECTORY exp;
struct app_hdr *header; struct app_hdr *header;
dll_path_t *path;
#if 0 #if 0
dll_path_t *path; dll_path_t *path;
int len; int len;
@ -212,16 +212,14 @@ void init_loader(void *libc_image)
DBG("add libraries path %s\n", path->path); DBG("add libraries path %s\n", path->path);
list_add_tail(&path->list, &path_list); list_add_tail(&path->list, &path_list);
#endif
#if 0
path = (dll_path_t*)malloc(sizeof(dll_path_t)); path = (dll_path_t*)malloc(sizeof(dll_path_t));
INIT_LIST_HEAD(&path->list); INIT_LIST_HEAD(&path->list);
path->path = "/sys/lib/"; path->path = "/kolibrios/lib/";
path->path_len = 9; /* FIXME */ path->path_len = 15; /* FIXME */
DBG("add libraries path %s\n", path->path); DBG("add libraries path %s\n", path->path);
list_add_tail(&path->list, &path_list); list_add_tail(&path->list, &path_list);
#endif
#endif
INIT_LIST_HEAD(&libc_dll.list); INIT_LIST_HEAD(&libc_dll.list);
@ -273,7 +271,7 @@ static inline void sec_copy(void *dst, void *src, size_t len)
}; };
void* __fastcall create_image(void *raw) void* create_image(void *raw)
{ {
PIMAGE_DOS_HEADER dos; PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS32 nt; PIMAGE_NT_HEADERS32 nt;
@ -361,16 +359,13 @@ void* __fastcall create_image(void *raw)
return img_base; return img_base;
}; };
static jmp_buf loader_env; //static jmp_buf loader_env;
static loader_recursion; //static loader_recursion;
int __fastcall link_image(void *img_base) int link_image(void *img_base, PIMAGE_IMPORT_DESCRIPTOR imp)
{ {
static jmp_buf loader_env; static jmp_buf loader_env;
static recursion = -1; static recursion = -1;
PIMAGE_DOS_HEADER dos;
PIMAGE_NT_HEADERS32 nt;
int warn = 0; int warn = 0;
recursion++; recursion++;
@ -383,16 +378,6 @@ int __fastcall link_image(void *img_base)
}; };
}; };
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 ( imp->Name ) while ( imp->Name )
{ {
PIMAGE_DOS_HEADER expdos; PIMAGE_DOS_HEADER expdos;
@ -540,7 +525,6 @@ int __fastcall link_image(void *img_base)
} }
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR
}; };
};
recursion--; recursion--;
@ -552,175 +536,15 @@ int __fastcall link_image(void *img_base)
int link_app() int link_app()
{ {
PIMAGE_IMPORT_DESCRIPTOR imp;
struct app_hdr *header = NULL; struct app_hdr *header = NULL;
PIMAGE_IMPORT_DESCRIPTOR imp;
int warn = 0;
if( unlikely(setjmp(loader_env) != 0))
{
loader_recursion = 0;
return 0;
};
imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start; imp = (PIMAGE_IMPORT_DESCRIPTOR)header->__idata_start;
while ( imp->Name ) return link_image(NULL, imp);
{
PIMAGE_DOS_HEADER expdos;
PIMAGE_NT_HEADERS32 expnt;
PIMAGE_EXPORT_DIRECTORY exp;
PIMAGE_THUNK_DATA32 thunk;
void **iat;
char *libname;
uint32_t *exp_functions;
uint16_t *exp_ordinals;
char **exp_names;
const module_t *api;
libname=MakePtr(char*,imp->Name, NULL);
DBG("import from %s\n",libname);
api = find_module(libname);
if(unlikely(api == NULL))
{
printf("library %s not found\n", libname);
longjmp(loader_env, 1);
} }
iat = MakePtr(void**,imp->FirstThunk, NULL);
if(imp->OriginalFirstThunk !=0 )
{
thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->OriginalFirstThunk, NULL);
}
else
{
thunk = MakePtr(PIMAGE_THUNK_DATA32,imp->FirstThunk, NULL);
};
exp = api->img_exp;
exp_functions = MakePtr(uint32_t*,exp->AddressOfFunctions,api->start);
exp_ordinals = MakePtr(uint16_t*, exp->AddressOfNameOrdinals,api->start);
exp_names = MakePtr(char**, exp->AddressOfNames,api->start);
while ( thunk->u1.AddressOfData != 0 )
{
PIMAGE_IMPORT_BY_NAME imp_name;
if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
// ordinal = (*func_list) & 0x7fffffff;
// *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
// if ((*ImportAddressList) == NULL)
// {
// DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
// RtlpRaiseImportNotFound(NULL, Ordinal, &ImportedModule->FullDllName);
// return STATUS_ENTRYPOINT_NOT_FOUND;
// }
}
else
{
char *export_name;
uint16_t ordinal;
void *function;
uint32_t minn;
uint32_t maxn;
imp_name = MakePtr(PIMAGE_IMPORT_BY_NAME,
thunk->u1.AddressOfData, NULL);
*iat = NULL;
DBG("import %s", imp_name->Name);
if(imp_name->Hint < exp->NumberOfNames)
{
export_name = MakePtr(char*,exp_names[imp_name->Hint],
api->start);
if(strcmp(imp_name->Name, export_name) == 0)
{
ordinal = exp_ordinals[imp_name->Hint];
function = MakePtr(void*,exp_functions[ordinal], api->start);
if((uint32_t)function >= (uint32_t)exp)
{
printf("forward %s\n", function);
warn=1;
}
else
{
DBG(" \t\tat %x\n", function);
*iat = function;
};
thunk++; // Advance to next thunk
iat++;
continue;
};
};
minn = 0;
maxn = exp->NumberOfNames - 1;
while (minn <= maxn)
{
int mid;
int res;
mid = (minn + maxn) / 2;
export_name = MakePtr(char*,exp_names[mid],api->start);
res = strcmp(export_name, imp_name->Name);
if (res == 0)
{
ordinal = exp_ordinals[mid];
function = MakePtr(void*,exp_functions[ordinal], api->start);
if((uint32_t)function >= (uint32_t)exp)
{
DBG("forward %s\n", function);
warn=1;
}
else
{
DBG(" \t\tat %x\n", function);
*iat = function;
};
break;
}
else if (minn == maxn)
{
printf(" unresolved %s\n",imp_name->Name);
warn=1;
break;
}
else if (res > 0)
{
maxn = mid - 1;
}
else
{
minn = mid + 1;
}
};
};
thunk++; // Advance to next thunk
iat++;
}
imp++; // advance to next IMAGE_IMPORT_DESCRIPTOR
};
if ( !warn )
return 1;
else
return 0;
}
void* get_entry_point(void *raw) void* get_entry_point(void *raw)
{ {
@ -804,13 +628,13 @@ void *get_proc_address(module_t *module, char *proc_name)
module_t* load_module(const char *name) module_t* load_module(const char *name)
{ {
dll_path_t *dllpath;
char *path; char *path;
int len; int len;
len = strlen(name); len = strlen(name);
dll_path_t *dllpath;
list_for_each_entry(dllpath, &path_list, list) list_for_each_entry(dllpath, &path_list, list)
{ {
PIMAGE_DOS_HEADER dos; PIMAGE_DOS_HEADER dos;
@ -818,6 +642,7 @@ module_t* load_module(const char *name)
PIMAGE_EXPORT_DIRECTORY exp; PIMAGE_EXPORT_DIRECTORY exp;
module_t *module; module_t *module;
ufile_t uf;
void *raw_img; void *raw_img;
size_t raw_size; size_t raw_size;
void *img_base; void *img_base;
@ -828,10 +653,16 @@ module_t* load_module(const char *name)
memcpy(path+dllpath->path_len, name, len); memcpy(path+dllpath->path_len, name, len);
path[len+dllpath->path_len]=0; path[len+dllpath->path_len]=0;
// raw_img = load_file(path, &raw_size); // printf("%s %s\n", path);
uf = load_file(path);
raw_img = uf.data;
raw_size = uf.size;
if(raw_img == NULL) if(raw_img == NULL)
continue; continue;
if( validate_pe(raw_img, raw_size, 0) == 0) if( validate_pe(raw_img, raw_size, 0) == 0)
{ {
printf("invalide module %s\n", path); printf("invalide module %s\n", path);
@ -854,7 +685,7 @@ module_t* load_module(const char *name)
{ {
printf("%s epic fail: no enough memory\n",__FUNCTION__); printf("%s epic fail: no enough memory\n",__FUNCTION__);
user_free(img_base); user_free(img_base);
return 0; return NULL;
} }
INIT_LIST_HEAD(&module->list); INIT_LIST_HEAD(&module->list);
@ -879,22 +710,24 @@ module_t* load_module(const char *name)
list_add_tail(&module->list, &libc_dll.list); list_add_tail(&module->list, &libc_dll.list);
if( link_image(img_base)) if(nt->OptionalHeader.DataDirectory[1].Size)
{ {
PIMAGE_IMPORT_DESCRIPTOR imp;
int (*dll_startup)(module_t *mod, uint32_t reason); int (*dll_startup)(module_t *mod, uint32_t reason);
imp = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, img_base,
nt->OptionalHeader.DataDirectory[1].VirtualAddress);
if(link_image(img_base, imp) == 0)
return NULL;
dll_startup = get_proc_address(module, "DllStartup"); dll_startup = get_proc_address(module, "DllStartup");
if( dll_startup ) if( dll_startup )
{
if( 0 == dll_startup(module, 1)) if( 0 == dll_startup(module, 1))
return 0; return NULL;
} };
return module; return module;
}; };
return NULL;
};
return NULL; return NULL;
}; };