1264601Sbz/* Licensed to the Apache Software Foundation (ASF) under one or more 2264601Sbz * contributor license agreements. See the NOTICE file distributed with 3264601Sbz * this work for additional information regarding copyright ownership. 4264601Sbz * The ASF licenses this file to You under the Apache License, Version 2.0 5264601Sbz * (the "License"); you may not use this file except in compliance with 6264601Sbz * the License. You may obtain a copy of the License at 7264601Sbz * 8264601Sbz * http://www.apache.org/licenses/LICENSE-2.0 9264601Sbz * 10264601Sbz * Unless required by applicable law or agreed to in writing, software 11264601Sbz * distributed under the License is distributed on an "AS IS" BASIS, 12264601Sbz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13264601Sbz * See the License for the specific language governing permissions and 14264601Sbz * limitations under the License. 15264601Sbz */ 16264601Sbz 17264601Sbz#include "apr_arch_dso.h" 18264601Sbz#include "apr_strings.h" 19264601Sbz#include "apr_portable.h" 20264601Sbz 21264601Sbz#if APR_HAS_DSO 22264601Sbz 23264601Sbz#if !defined(DSO_USE_DLFCN) && !defined(DSO_USE_SHL) && !defined(DSO_USE_DYLD) 24264601Sbz#error No DSO implementation specified. 25264601Sbz#endif 26264601Sbz 27264601Sbz#ifdef HAVE_STDDEF_H 28264601Sbz#include <stddef.h> 29264601Sbz#endif 30264601Sbz#if APR_HAVE_STDLIB_H 31264601Sbz#include <stdlib.h> /* malloc(), free() */ 32264601Sbz#endif 33264601Sbz#if APR_HAVE_STRING_H 34264601Sbz#include <string.h> /* for strerror() on HP-UX */ 35264601Sbz#endif 36264601Sbz 37264601Sbz#if defined(DSO_USE_DYLD) 38264601Sbz#define DYLD_LIBRARY_HANDLE (void *)-1 39264601Sbz#endif 40264601Sbz 41264601SbzAPR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, 42264601Sbz apr_os_dso_handle_t osdso, 43264601Sbz apr_pool_t *pool) 44264601Sbz{ 45264601Sbz *aprdso = apr_pcalloc(pool, sizeof **aprdso); 46264601Sbz (*aprdso)->handle = osdso; 47264601Sbz (*aprdso)->pool = pool; 48264601Sbz return APR_SUCCESS; 49264601Sbz} 50264601Sbz 51264601SbzAPR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, 52264601Sbz apr_dso_handle_t *aprdso) 53264601Sbz{ 54264601Sbz *osdso = aprdso->handle; 55264601Sbz return APR_SUCCESS; 56264601Sbz} 57264601Sbz 58264601Sbzstatic apr_status_t dso_cleanup(void *thedso) 59264601Sbz{ 60264601Sbz apr_dso_handle_t *dso = thedso; 61264601Sbz 62264601Sbz if (dso->handle == NULL) 63264601Sbz return APR_SUCCESS; 64264601Sbz 65264601Sbz#if defined(DSO_USE_SHL) 66264601Sbz shl_unload((shl_t)dso->handle); 67264601Sbz#elif defined(DSO_USE_DYLD) 68264601Sbz if (dso->handle != DYLD_LIBRARY_HANDLE) { 69264601Sbz NSUnLinkModule(dso->handle, FALSE); 70264601Sbz } 71264601Sbz#elif defined(DSO_USE_DLFCN) 72264601Sbz if (dlclose(dso->handle) != 0) 73264601Sbz return APR_EINIT; 74264601Sbz#endif 75264601Sbz dso->handle = NULL; 76264601Sbz 77264601Sbz return APR_SUCCESS; 78264601Sbz} 79264601Sbz 80264601SbzAPR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 81264601Sbz const char *path, apr_pool_t *pool) 82264601Sbz{ 83264601Sbz#if defined(DSO_USE_SHL) 84264601Sbz shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L); 85264601Sbz 86264601Sbz#elif defined(DSO_USE_DYLD) 87264601Sbz NSObjectFileImage image; 88265766Sbz NSModule os_handle = NULL; 89264601Sbz NSObjectFileImageReturnCode dsoerr; 90264601Sbz const char* err_msg = NULL; 91265766Sbz dsoerr = NSCreateObjectFileImageFromFile(path, &image); 92265766Sbz 93267920Sbz if (dsoerr == NSObjectFileImageSuccess) { 94265766Sbz#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE) 95265766Sbz os_handle = NSLinkModule(image, path, 96265766Sbz NSLINKMODULE_OPTION_RETURN_ON_ERROR | 97265766Sbz NSLINKMODULE_OPTION_NONE); 98265766Sbz /* If something went wrong, get the errors... */ 99265766Sbz if (!os_handle) { 100265766Sbz NSLinkEditErrors errors; 101265766Sbz int errorNumber; 102265766Sbz const char *fileName; 103265766Sbz NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg); 104265766Sbz } 105265766Sbz#else 106265766Sbz os_handle = NSLinkModule(image, path, FALSE); 107265766Sbz#endif 108265766Sbz NSDestroyObjectFileImage(image); 109264601Sbz } 110264601Sbz else if ((dsoerr == NSObjectFileImageFormat || 111267920Sbz dsoerr == NSObjectFileImageInappropriateFile) && 112267920Sbz NSAddLibrary(path) == TRUE) { 113267920Sbz os_handle = (NSModule)DYLD_LIBRARY_HANDLE; 114264601Sbz } 115265766Sbz else { 116264601Sbz err_msg = "cannot create object file image or add library"; 117264601Sbz } 118264601Sbz 119264601Sbz#elif defined(DSO_USE_DLFCN) 120264601Sbz#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\ 121264601Sbz (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\ 122264601Sbz defined(__DragonFly__) 123264601Sbz void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL); 124264601Sbz 125264601Sbz#else 126264601Sbz int flags = RTLD_NOW | RTLD_GLOBAL; 127264601Sbz void *os_handle; 128264601Sbz#ifdef _AIX 129264601Sbz if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')') 130264601Sbz { 131267920Sbz /* This special archive.a(dso.so) syntax is required for 132267920Sbz * the way libtool likes to build shared libraries on AIX. 133267920Sbz * dlopen() support for such a library requires that the 134264601Sbz * RTLD_MEMBER flag be enabled. 135265766Sbz */ 136264601Sbz flags |= RTLD_MEMBER; 137264601Sbz } 138264601Sbz#endif 139264601Sbz os_handle = dlopen(path, flags); 140264601Sbz#endif 141264601Sbz#endif /* DSO_USE_x */ 142264601Sbz 143264601Sbz *res_handle = apr_pcalloc(pool, sizeof(**res_handle)); 144264601Sbz 145264601Sbz if(os_handle == NULL) { 146264601Sbz#if defined(DSO_USE_SHL) 147264601Sbz (*res_handle)->errormsg = strerror(errno); 148264601Sbz return APR_EDSOOPEN; 149264601Sbz#elif defined(DSO_USE_DYLD) 150265766Sbz (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed"; 151267920Sbz return APR_EDSOOPEN; 152267920Sbz#elif defined(DSO_USE_DLFCN) 153264601Sbz (*res_handle)->errormsg = dlerror(); 154265766Sbz return APR_EDSOOPEN; 155265766Sbz#endif 156265766Sbz } 157265766Sbz 158265766Sbz (*res_handle)->handle = (void*)os_handle; 159264601Sbz (*res_handle)->pool = pool; 160264601Sbz (*res_handle)->errormsg = NULL; 161264601Sbz 162264601Sbz apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); 163265766Sbz 164265766Sbz return APR_SUCCESS; 165265766Sbz} 166265766Sbz 167264601SbzAPR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) 168265766Sbz{ 169265766Sbz return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); 170265766Sbz} 171265766Sbz 172265766SbzAPR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 173264601Sbz apr_dso_handle_t *handle, 174264601Sbz const char *symname) 175264601Sbz{ 176264601Sbz#if defined(DSO_USE_SHL) 177264601Sbz void *symaddr = NULL; 178264601Sbz int status; 179264601Sbz 180264601Sbz errno = 0; 181264601Sbz status = shl_findsym((void *)&handle->handle, symname, TYPE_PROCEDURE, &symaddr); 182264601Sbz if (status == -1 && errno == 0) /* try TYPE_DATA instead */ 183264601Sbz status = shl_findsym((void *)&handle->handle, symname, TYPE_DATA, &symaddr); 184264601Sbz if (status == -1) 185264601Sbz return APR_ESYMNOTFOUND; 186264601Sbz *ressym = symaddr; 187264601Sbz return APR_SUCCESS; 188264601Sbz 189264601Sbz#elif defined(DSO_USE_DYLD) 190264601Sbz void *retval = NULL; 191264601Sbz NSSymbol symbol; 192264601Sbz char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2)); 193264601Sbz sprintf(symname2, "_%s", symname); 194264601Sbz#ifdef NSLINKMODULE_OPTION_PRIVATE 195264601Sbz if (handle->handle == DYLD_LIBRARY_HANDLE) { 196264601Sbz symbol = NSLookupAndBindSymbol(symname2); 197264601Sbz } 198264601Sbz else { 199264601Sbz symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2); 200264601Sbz } 201264601Sbz#else 202264601Sbz symbol = NSLookupAndBindSymbol(symname2); 203264601Sbz#endif 204 free(symname2); 205 if (symbol == NULL) { 206 handle->errormsg = "undefined symbol"; 207 return APR_ESYMNOTFOUND; 208 } 209 retval = NSAddressOfSymbol(symbol); 210 if (retval == NULL) { 211 handle->errormsg = "cannot resolve symbol"; 212 return APR_ESYMNOTFOUND; 213 } 214 *ressym = retval; 215 return APR_SUCCESS; 216#elif defined(DSO_USE_DLFCN) 217 218#if defined(DLSYM_NEEDS_UNDERSCORE) 219 void *retval; 220 char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2)); 221 sprintf(symbol, "_%s", symname); 222 retval = dlsym(handle->handle, symbol); 223 free(symbol); 224#elif defined(SEQUENT) || defined(SNI) 225 void *retval = dlsym(handle->handle, (char *)symname); 226#else 227 void *retval = dlsym(handle->handle, symname); 228#endif /* DLSYM_NEEDS_UNDERSCORE */ 229 230 if (retval == NULL) { 231 handle->errormsg = dlerror(); 232 return APR_ESYMNOTFOUND; 233 } 234 235 *ressym = retval; 236 237 return APR_SUCCESS; 238#endif /* DSO_USE_x */ 239} 240 241APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, 242 apr_size_t buflen) 243{ 244 if (dso->errormsg) { 245 apr_cpystrn(buffer, dso->errormsg, buflen); 246 return dso->errormsg; 247 } 248 return "No Error"; 249} 250 251#endif 252