From f600c5e37afa4484b22588eec8009ecd32a42cf3 Mon Sep 17 00:00:00 2001 From: Olaf Barthel Date: Sat, 21 Aug 2010 11:37:03 +0000 Subject: [PATCH] - Added dlclose(), dlerror(), dlopen() and dlsym() functions, which are available only under OS4. There is a variant of dlopen() in libunix.a which will perform a path name conversion. Note that these functions will not work in the thread-safe variant of the library because it would be unwise to tinker with the currently running program's binary. git-svn-id: file:///Users/olsen/Code/migration-svn-zu-git/logical-line-staging/clib2/trunk@15207 87f5fb63-7c3d-0410-a384-fd976d0f7a62 --- library/changes | 8 +- library/crtbegin.c | 118 ++------------------- library/include/dlfcn.h | 11 +- library/libc.gmk | 3 +- library/stdlib_dlclose.c | 11 +- library/stdlib_dlerror.c | 6 +- library/stdlib_dlopen.c | 19 ++-- library/stdlib_dlsym.c | 13 +-- library/stdlib_shared_libs.c | 150 --------------------------- library/stdlib_shared_objs.c | 192 +++++++++++++++++++++++++++++++++++ 10 files changed, 232 insertions(+), 299 deletions(-) delete mode 100644 library/stdlib_shared_libs.c create mode 100644 library/stdlib_shared_objs.c diff --git a/library/changes b/library/changes index 9574dde..cf5927b 100644 --- a/library/changes +++ b/library/changes @@ -1,10 +1,8 @@ - Added dlclose(), dlerror(), dlopen() and dlsym() functions, which are available only under OS4. There is a variant of dlopen() in libunix.a - which will perform a path name conversion. - -- The shared object initialization has to be performed before any local - constructors are invoked, and after all local destructors have been - invoked. + which will perform a path name conversion. Note that these functions + will not work in the thread-safe variant of the library because it + would be unwise to tinker with the currently running program's binary. - Added support for ELF shared objects and libraries. This is implemented through constructor/destructor functions, which means that you can use this diff --git a/library/crtbegin.c b/library/crtbegin.c index 622c10c..7ebbdd9 100644 --- a/library/crtbegin.c +++ b/library/crtbegin.c @@ -1,5 +1,5 @@ /* - * $Id: crtbegin.c,v 1.12 2010-08-21 09:57:50 obarthel Exp $ + * $Id: crtbegin.c,v 1.13 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -10,16 +10,9 @@ /****************************************************************************/ -#ifndef _STDLIB_HEADERS_H -#include "stdlib_headers.h" -#endif /* _STDLIB_HEADERS_H */ - -/****************************************************************************/ - -#include - -#include -#include +#ifndef EXEC_TYPES_H +#include +#endif /* EXEC_TYPES_H */ /****************************************************************************/ @@ -39,110 +32,10 @@ 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) { + extern void shared_obj_init(void); int num_ctors,i; int j; @@ -162,6 +55,7 @@ _init(void) void _fini(void) { + extern void shared_obj_exit(void); int num_dtors,i; static int j; diff --git a/library/include/dlfcn.h b/library/include/dlfcn.h index e1c1a7e..0f53a57 100644 --- a/library/include/dlfcn.h +++ b/library/include/dlfcn.h @@ -1,5 +1,5 @@ /* - * $Id: dlfcn.h,v 1.1 2010-08-21 10:59:34 obarthel Exp $ + * $Id: dlfcn.h,v 1.2 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -59,10 +59,11 @@ extern "C" { /****************************************************************************/ /* We only support a subset of the flags available on Unix systems. */ -#define RTLD_LAZY 0 -#define RTLD_NOW 0 -#define RTLD_LOCAL 4 -#define RTLD_GLOBAL 8 +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_LOCAL 4 +#define RTLD_GLOBAL 8 +#define RTLD_DEFAULT ((void *)0) /****************************************************************************/ diff --git a/library/libc.gmk b/library/libc.gmk index f0cd2e8..d892cef 100755 --- a/library/libc.gmk +++ b/library/libc.gmk @@ -1,5 +1,5 @@ # -# $Id: libc.gmk,v 1.7 2010-08-21 10:59:34 obarthel Exp $ +# $Id: libc.gmk,v 1.8 2010-08-21 11:37:03 obarthel Exp $ # # :ts=8 # @@ -252,6 +252,7 @@ C_LIB := \ stdlib_setjmp.o \ stdlib_set_errno.o \ stdlib_set_process_window.o \ + stdlib_shared_objs.o \ stdlib_shell_escape.o \ stdlib_showerror.o \ stdlib_srand.o \ diff --git a/library/stdlib_dlclose.c b/library/stdlib_dlclose.c index 95dabef..9dfa940 100644 --- a/library/stdlib_dlclose.c +++ b/library/stdlib_dlclose.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_dlclose.c,v 1.1 2010-08-21 10:59:34 obarthel Exp $ + * $Id: stdlib_dlclose.c,v 1.2 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -52,10 +52,7 @@ /****************************************************************************/ extern struct ElfIFace * __IElf; -extern Elf32_Handle __elf_handle; - -/****************************************************************************/ - +extern Elf32_Handle __dl_elf_handle; extern Elf32_Error __elf_error_code; /****************************************************************************/ @@ -64,12 +61,12 @@ int dlclose(void * handle) { int result = -1; - if(__elf_handle != NULL) + if(__dl_elf_handle != NULL) { struct ElfIFace * IElf = __IElf; Elf32_Error error; - error = DLClose(__elf_handle,handle); + error = DLClose(__dl_elf_handle,handle); if(error != ELF32_NO_ERROR) { __elf_error_code = error; diff --git a/library/stdlib_dlerror.c b/library/stdlib_dlerror.c index e45beeb..1f38d3f 100644 --- a/library/stdlib_dlerror.c +++ b/library/stdlib_dlerror.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_dlerror.c,v 1.1 2010-08-21 10:59:34 obarthel Exp $ + * $Id: stdlib_dlerror.c,v 1.2 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -62,6 +62,7 @@ const char * dlerror(void) { case ELF32_NO_ERROR: + result = NULL; break; case ELF32_OUT_OF_MEMORY: @@ -111,7 +112,7 @@ const char * dlerror(void) case ELF32_REQUIRED_OBJECT_MISSING: - result = required object missing"; + result = "required object missing"; break; default: @@ -120,6 +121,7 @@ const char * dlerror(void) break; } + /* Calling dlerror() will clear the error code. */ __elf_error_code = ELF32_NO_ERROR; return(result); diff --git a/library/stdlib_dlopen.c b/library/stdlib_dlopen.c index fe7a041..484d906 100644 --- a/library/stdlib_dlopen.c +++ b/library/stdlib_dlopen.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_dlopen.c,v 1.1 2010-08-21 10:59:34 obarthel Exp $ + * $Id: stdlib_dlopen.c,v 1.2 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -52,7 +52,7 @@ /****************************************************************************/ extern struct ElfIFace * __IElf; -extern Elf32_Handle __elf_handle; +extern Elf32_Handle __dl_elf_handle; /****************************************************************************/ @@ -88,21 +88,22 @@ void * dlopen(const char * path_name,int mode) } #endif /* UNIX_PATH_SEMANTICS */ - if(__elf_handle != NULL) + if(__dl_elf_handle != NULL) { struct ElfIFace * IElf = __IElf; - uint32 flags; + uint32 flags = 0; if(mode & RTLD_LOCAL) flags = ELF32_RTLD_LOCAL; - else if (mode & RTLD_GLOBAL) - flags = ELF32_RTLD_GLOBAL; - else - flags = 0; - result = DLOpen(__elf_handle,path_name,flags); + if(mode & RTLD_GLOBAL) + flags = ELF32_RTLD_GLOBAL; + + result = DLOpen(__dl_elf_handle,path_name,flags); } + out: + return(result); } diff --git a/library/stdlib_dlsym.c b/library/stdlib_dlsym.c index a9f6ccf..2ec982a 100644 --- a/library/stdlib_dlsym.c +++ b/library/stdlib_dlsym.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_dlsym.c,v 1.1 2010-08-21 10:59:34 obarthel Exp $ + * $Id: stdlib_dlsym.c,v 1.2 2010-08-21 11:37:03 obarthel Exp $ * * :ts=4 * @@ -52,25 +52,22 @@ /****************************************************************************/ extern struct ElfIFace * __IElf; -extern Elf32_Handle __elf_handle; - -/****************************************************************************/ - +extern Elf32_Handle __dl_elf_handle; extern Elf32_Error __elf_error_code; /****************************************************************************/ -void dlsym(void * handle,const char * symbol_name) +void * dlsym(void * handle,const char * symbol_name) { void * result = NULL; - if(__elf_handle != NULL) + if(__dl_elf_handle != NULL) { struct ElfIFace * IElf = __IElf; APTR symbol_data = NULL; Elf32_Error error; - error = DLSym(__elf_handle,handle,symbol_name,&symbol_data); + error = DLSym(__dl_elf_handle,handle,symbol_name,&symbol_data); if(error != ELF32_NO_ERROR) { __elf_error_code = error; diff --git a/library/stdlib_shared_libs.c b/library/stdlib_shared_libs.c deleted file mode 100644 index 090b1cd..0000000 --- a/library/stdlib_shared_libs.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * $Id: stdlib_shared_libs.c,v 1.1 2010-08-20 15:33:36 obarthel Exp $ - * - * :ts=4 - * - * Portable ISO 'C' (1994) runtime library for the Amiga computer - * Copyright (c) 2002-2010 by Olaf Barthel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Neither the name of Olaf Barthel nor the names of contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if defined(__amigaos4__) - -/****************************************************************************/ - -/* The following is not part of the ISO 'C' (1994) standard. */ - -/****************************************************************************/ - -#ifndef _STDLIB_HEADERS_H -#include "stdlib_headers.h" -#endif /* _STDLIB_HEADERS_H */ - -/****************************************************************************/ - -#ifndef _STDLIB_CONSTRUCTOR_H -#include "stdlib_constructor.h" -#endif /* _STDLIB_CONSTRUCTOR_H */ - -/****************************************************************************/ - -#include - -#include -#include - -/****************************************************************************/ - -static VOID shared_libs_init_exit(BOOL init_or_exit) -{ - struct Library * ElfBase; - struct Library * DOSBase = NULL; - struct ElfIFace * IElf = NULL; - struct DOSIFace * IDOS = NULL; - BPTR segment_list; - - ENTER(); - - /* 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; - - DOSBase = OpenLibrary("dos.library",0); - if(DOSBase == NULL) - goto out; - - IDOS = (struct DOSIFace *)GetInterface(DOSBase,"main",1,NULL); - if(IDOS == NULL) - 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) - { - Elf32_Handle elf_handle = NULL; - - if(GetSegListInfoTags(segment_list, - GSLI_ElfHandle,&elf_handle, - TAG_DONE) == 1) - { - /* Initialize the shared object system. Note that - we have no way of finding out whether this actually - worked... */ - if(elf_handle != NULL) - InitSHLibs(elf_handle,init_or_exit); - } - } - - out: - - if(IDOS != NULL) - DropInterface((struct Interface *)IDOS); - - if(DOSBase != NULL) - CloseLibrary(DOSBase); - - if(IElf != NULL) - DropInterface((struct Interface *)IElf); - - if(ElfBase != NULL) - CloseLibrary(ElfBase); - - LEAVE(); -} - -/****************************************************************************/ - -CLIB_DESTRUCTOR(shared_libs_exit) -{ - ENTER(); - - shared_libs_init_exit(FALSE); - - LEAVE(); -} - -/****************************************************************************/ - -CLIB_CONSTRUCTOR(shared_libs_init) -{ - ENTER(); - - shared_libs_init_exit(TRUE); - - LEAVE(); - - CONSTRUCTOR_SUCCEED(); -} - -/****************************************************************************/ - -#endif /* __amigaos4__ */ diff --git a/library/stdlib_shared_objs.c b/library/stdlib_shared_objs.c new file mode 100644 index 0000000..bc29c68 --- /dev/null +++ b/library/stdlib_shared_objs.c @@ -0,0 +1,192 @@ +/* + * $Id: stdlib_shared_objs.c,v 1.1 2010-08-21 11:37:03 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2010 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(__amigaos4__) + +/****************************************************************************/ + +#ifndef _STDLIB_HEADERS_H +#include "stdlib_headers.h" +#endif /* _STDLIB_HEADERS_H */ + +/****************************************************************************/ + +#include +#include + +/****************************************************************************/ + +/* 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; + +/* This is used with the dlopen(), dlclose() and dlsym() functions. */ +Elf32_Handle __dl_elf_handle; + +/****************************************************************************/ + +/* This is used to initialize the shared objects only. */ +static Elf32_Handle elf_handle; + +/****************************************************************************/ + +void shared_obj_init(void); +void shared_obj_exit(void); + +/****************************************************************************/ + +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); +} + +/****************************************************************************/ + +void shared_obj_exit(void) +{ + struct ElfIFace * IElf = __IElf; + + #ifndef __THREAD_SAFE + { + /* Release this program's Elf handle, if we grabbed it below. */ + if(__dl_elf_handle != NULL) + { + CloseElfTags(__dl_elf_handle, + CET_ReClose,TRUE, + TAG_DONE); + + __dl_elf_handle = NULL; + } + } + #endif /* __THREAD_SAFE */ + + /* 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); + elf_handle = NULL; + } + + close_elf_library(); +} + +/****************************************************************************/ + +void shared_obj_init(void) +{ + if(open_elf_library()) + { + struct ElfIFace * IElf = __IElf; + BPTR segment_list; + + /* 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) + { + if(GetSegListInfoTags(segment_list, + GSLI_ElfHandle,&elf_handle, + TAG_DONE) == 1) + { + if(elf_handle != NULL) + { + /* Trigger the constructors, etc. in the shared objects + linked to this binary. */ + InitSHLibs(elf_handle,TRUE); + } + } + } + + /* Next: try to grab the Elf handle associated with the currently + running process. This is not thread-safe! */ + #ifndef __THREAD_SAFE + { + segment_list = GetProcSegList(NULL,GPSLF_RUN); + if(segment_list != ZERO) + { + Elf32_Handle handle = NULL; + + if(GetSegListInfoTags(segment_list, + GSLI_ElfHandle,&handle, + TAG_DONE) == 1) + { + if(handle != NULL) + { + __dl_elf_handle = OpenElfTags( + OET_ElfHandle,handle, + TAG_DONE); + } + } + } + } + #endif /* __THREAD_SAFE */ + } +} + +/****************************************************************************/ + +#endif /*__amigaos4__ */