1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_arch_dso.h" 18#include "apr_strings.h" 19#include "apr_portable.h" 20 21#if APR_HAS_DSO 22 23#if !defined(DSO_USE_DLFCN) && !defined(DSO_USE_SHL) && !defined(DSO_USE_DYLD) 24#error No DSO implementation specified. 25#endif 26 27#ifdef HAVE_STDDEF_H 28#include <stddef.h> 29#endif 30#if APR_HAVE_STDLIB_H 31#include <stdlib.h> /* malloc(), free() */ 32#endif 33#if APR_HAVE_STRING_H 34#include <string.h> /* for strerror() on HP-UX */ 35#endif 36 37#if defined(DSO_USE_DYLD) 38#define DYLD_LIBRARY_HANDLE (void *)-1 39#endif 40 41APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, 42 apr_os_dso_handle_t osdso, 43 apr_pool_t *pool) 44{ 45 *aprdso = apr_pcalloc(pool, sizeof **aprdso); 46 (*aprdso)->handle = osdso; 47 (*aprdso)->pool = pool; 48 return APR_SUCCESS; 49} 50 51APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, 52 apr_dso_handle_t *aprdso) 53{ 54 *osdso = aprdso->handle; 55 return APR_SUCCESS; 56} 57 58static apr_status_t dso_cleanup(void *thedso) 59{ 60 apr_dso_handle_t *dso = thedso; 61 62 if (dso->handle == NULL) 63 return APR_SUCCESS; 64 65#if defined(DSO_USE_SHL) 66 shl_unload((shl_t)dso->handle); 67#elif defined(DSO_USE_DYLD) 68 if (dso->handle != DYLD_LIBRARY_HANDLE) { 69 NSUnLinkModule(dso->handle, FALSE); 70 } 71#elif defined(DSO_USE_DLFCN) 72 if (dlclose(dso->handle) != 0) 73 return APR_EINIT; 74#endif 75 dso->handle = NULL; 76 77 return APR_SUCCESS; 78} 79 80APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, 81 const char *path, apr_pool_t *pool) 82{ 83#if defined(DSO_USE_SHL) 84 shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L); 85 86#elif defined(DSO_USE_DYLD) 87 NSObjectFileImage image; 88 NSModule os_handle = NULL; 89 NSObjectFileImageReturnCode dsoerr; 90 const char* err_msg = NULL; 91 dsoerr = NSCreateObjectFileImageFromFile(path, &image); 92 93 if (dsoerr == NSObjectFileImageSuccess) { 94#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE) 95 os_handle = NSLinkModule(image, path, 96 NSLINKMODULE_OPTION_RETURN_ON_ERROR | 97 NSLINKMODULE_OPTION_NONE); 98 /* If something went wrong, get the errors... */ 99 if (!os_handle) { 100 NSLinkEditErrors errors; 101 int errorNumber; 102 const char *fileName; 103 NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg); 104 } 105#else 106 os_handle = NSLinkModule(image, path, FALSE); 107#endif 108 NSDestroyObjectFileImage(image); 109 } 110 else if ((dsoerr == NSObjectFileImageFormat || 111 dsoerr == NSObjectFileImageInappropriateFile) && 112 NSAddLibrary(path) == TRUE) { 113 os_handle = (NSModule)DYLD_LIBRARY_HANDLE; 114 } 115 else { 116 err_msg = "cannot create object file image or add library"; 117 } 118 119#elif defined(DSO_USE_DLFCN) 120#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\ 121 (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\ 122 defined(__DragonFly__) 123 void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL); 124 125#else 126 int flags = RTLD_NOW | RTLD_GLOBAL; 127 void *os_handle; 128#ifdef _AIX 129 if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')') 130 { 131 /* This special archive.a(dso.so) syntax is required for 132 * the way libtool likes to build shared libraries on AIX. 133 * dlopen() support for such a library requires that the 134 * RTLD_MEMBER flag be enabled. 135 */ 136 flags |= RTLD_MEMBER; 137 } 138#endif 139 os_handle = dlopen(path, flags); 140#endif 141#endif /* DSO_USE_x */ 142 143 *res_handle = apr_pcalloc(pool, sizeof(**res_handle)); 144 145 if(os_handle == NULL) { 146#if defined(DSO_USE_SHL) 147 (*res_handle)->errormsg = strerror(errno); 148 return APR_EDSOOPEN; 149#elif defined(DSO_USE_DYLD) 150 (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed"; 151 return APR_EDSOOPEN; 152#elif defined(DSO_USE_DLFCN) 153 (*res_handle)->errormsg = dlerror(); 154 return APR_EDSOOPEN; 155#endif 156 } 157 158 (*res_handle)->handle = (void*)os_handle; 159 (*res_handle)->pool = pool; 160 (*res_handle)->errormsg = NULL; 161 162 apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); 163 164 return APR_SUCCESS; 165} 166 167APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) 168{ 169 return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); 170} 171 172APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, 173 apr_dso_handle_t *handle, 174 const char *symname) 175{ 176#if defined(DSO_USE_SHL) 177 void *symaddr = NULL; 178 int status; 179 180 errno = 0; 181 status = shl_findsym((void *)&handle->handle, symname, TYPE_PROCEDURE, &symaddr); 182 if (status == -1 && errno == 0) /* try TYPE_DATA instead */ 183 status = shl_findsym((void *)&handle->handle, symname, TYPE_DATA, &symaddr); 184 if (status == -1) 185 return APR_ESYMNOTFOUND; 186 *ressym = symaddr; 187 return APR_SUCCESS; 188 189#elif defined(DSO_USE_DYLD) 190 void *retval = NULL; 191 NSSymbol symbol; 192 char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2)); 193 sprintf(symname2, "_%s", symname); 194#ifdef NSLINKMODULE_OPTION_PRIVATE 195 if (handle->handle == DYLD_LIBRARY_HANDLE) { 196 symbol = NSLookupAndBindSymbol(symname2); 197 } 198 else { 199 symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2); 200 } 201#else 202 symbol = NSLookupAndBindSymbol(symname2); 203#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