diff --git a/library/changes b/library/changes index 0a9f332..3785c92 100644 --- a/library/changes +++ b/library/changes @@ -1,3 +1,7 @@ +- The shared object initialization has to be performed before any local + constructors are invoked, and after all local destructors have been + invoked. + - Added support for ELF shared objects and libraries. This is implemented through constructor/destructor functions, which means that you can use this functionality even in Amiga Exec style shared libraries, with the proper diff --git a/library/crtbegin.c b/library/crtbegin.c index 3465519..622c10c 100644 --- a/library/crtbegin.c +++ b/library/crtbegin.c @@ -1,5 +1,5 @@ /* - * $Id: crtbegin.c,v 1.11 2006-09-22 09:02:51 obarthel Exp $ + * $Id: crtbegin.c,v 1.12 2010-08-21 09:57:50 obarthel Exp $ * * :ts=4 * @@ -10,9 +10,16 @@ /****************************************************************************/ -#ifndef EXEC_TYPES_H -#include -#endif /* EXEC_TYPES_H */ +#ifndef _STDLIB_HEADERS_H +#include "stdlib_headers.h" +#endif /* _STDLIB_HEADERS_H */ + +/****************************************************************************/ + +#include + +#include +#include /****************************************************************************/ @@ -32,12 +39,117 @@ void _fini(void); /****************************************************************************/ +/* These are used to initialize the shared objects linked to this binary, + and for the dlopen(), dlclose() and dlsym() functions. */ +struct Library * __ElfBase; +struct ElfIFace * __IElf; + +Elf32_Handle __elf_handle; + +/****************************************************************************/ + +static VOID close_elf_library(void) +{ + if(__IElf != NULL) + { + DropInterface((struct Interface *)__IElf); + __IElf = NULL; + } + + if(__ElfBase != NULL) + { + CloseLibrary(__ElfBase); + __ElfBase = NULL; + } +} + +/****************************************************************************/ + +static BOOL open_elf_library(void) +{ + BOOL success = FALSE; + + /* We need elf.library V52.2 or higher. */ + __ElfBase = OpenLibrary("elf.library",0); + if(__ElfBase == NULL || (__ElfBase->lib_Version < 52) || (__ElfBase->lib_Version == 52 && __ElfBase->lib_Revision < 2)) + goto out; + + __IElf = (struct ElfIFace *)GetInterface(__ElfBase,"main",1,NULL); + if(__IElf == NULL) + goto out; + + success = TRUE; + + out: + + return(success); +} + +/****************************************************************************/ + +static void shared_obj_exit(void) +{ + /* If we got what we wanted, trigger the destructors, + etc. in the shared objects linked to this binary. */ + if(__elf_handle != NULL) + InitSHLibs(__elf_handle,FALSE); + + close_elf_library(); +} + +/****************************************************************************/ + +static void shared_obj_init(void) +{ + struct ElfIFace * IElf; + BOOL success = FALSE; + BPTR segment_list; + + if(!open_elf_library()) + goto out; + + /* Try to find the Elf handle associated with this + program's segment list. */ + segment_list = GetProcSegList(NULL,GPSLF_CLI | GPSLF_SEG); + if(segment_list == ZERO) + goto out; + + if(GetSegListInfoTags(segment_list, + GSLI_ElfHandle,&__elf_handle, + TAG_DONE) != 1) + { + goto out; + } + + if(__elf_handle == NULL) + goto out; + + IElf = __IElf; + + /* Trigger the constructors, etc. in the shared objects + linked to this binary. */ + InitSHLibs(__elf_handle,TRUE); + + success = TRUE; + + out: + + if(!success) + close_elf_library(); +} + +/****************************************************************************/ + void _init(void) { int num_ctors,i; int j; + /* The shared objects need to be set up before any local + constructors are invoked. */ + shared_obj_init(); + for(i = 1, num_ctors = 0 ; __CTOR_LIST__[i] != NULL ; i++) num_ctors++; @@ -58,6 +170,10 @@ _fini(void) while(j++ < num_dtors) __DTOR_LIST__[j](); + + /* The shared objects need to be cleaned up after all local + destructors have been invoked. */ + shared_obj_exit(); } /****************************************************************************/ diff --git a/library/libc.gmk b/library/libc.gmk index 5831629..13d630c 100755 --- a/library/libc.gmk +++ b/library/libc.gmk @@ -1,5 +1,5 @@ # -# $Id: libc.gmk,v 1.5 2010-08-20 15:33:36 obarthel Exp $ +# $Id: libc.gmk,v 1.6 2010-08-21 09:57:50 obarthel Exp $ # # :ts=8 # @@ -248,7 +248,6 @@ C_LIB := \ stdlib_setjmp.o \ stdlib_set_errno.o \ stdlib_set_process_window.o \ - stdlib_shared_libs.o \ stdlib_shell_escape.o \ stdlib_showerror.o \ stdlib_srand.o \