lowhash_vector.c (5449B)
1 /* 2 * loader.c - load platform dependent DSO containing freebl implementation. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #define _GNU_SOURCE 1 9 #include "loader.h" 10 #include "prmem.h" 11 #include "prerror.h" 12 #include "prinit.h" 13 #include "prenv.h" 14 #include "blname.c" 15 16 #include "prio.h" 17 #include "prprf.h" 18 #include <stdio.h> 19 #include "prsystem.h" 20 #include "nsslowhash.h" 21 #include <dlfcn.h> 22 #include "pratom.h" 23 24 static PRLibrary *blLib; 25 26 #define LSB(x) ((x)&0xff) 27 #define MSB(x) ((x) >> 8) 28 29 static const NSSLOWVector *vector; 30 static const char *libraryName = NULL; 31 32 /* pretty much only glibc uses this, make sure we don't have any depenencies 33 * on nspr.. */ 34 #undef PORT_Alloc 35 #undef PORT_Free 36 #define PORT_Alloc malloc 37 #define PR_Malloc malloc 38 #define PORT_Free free 39 #define PR_Free free 40 #define PR_GetDirectorySeparator() '/' 41 #define PR_LoadLibraryWithFlags(libspec, flags) \ 42 (PRLibrary *)dlopen(libSpec.value.pathname, RTLD_NOW | RTLD_LOCAL) 43 #define PR_GetLibraryFilePathname(name, addr) \ 44 freebl_lowhash_getLibraryFilePath(addr) 45 46 static char * 47 freebl_lowhash_getLibraryFilePath(void *addr) 48 { 49 Dl_info dli; 50 if (dladdr(addr, &dli) == 0) { 51 return NULL; 52 } 53 return strdup(dli.dli_fname); 54 } 55 56 /* 57 * The PR_LoadLibraryWithFlags call above defines this variable away, so we 58 * don't need it.. 59 */ 60 #ifdef nodef 61 static const char *NameOfThisSharedLib = 62 SHLIB_PREFIX "freebl" SHLIB_VERSION "." SHLIB_SUFFIX; 63 #endif 64 65 #include "genload.c" 66 67 /* This function must be run only once. */ 68 /* determine if hybrid platform, then actually load the DSO. */ 69 static PRStatus 70 freebl_LoadDSO(void) 71 { 72 PRLibrary *handle; 73 const char *name = getLibName(); 74 75 if (!name) { 76 /*PR_SetError(PR_LOAD_LIBRARY_ERROR,0); */ 77 return PR_FAILURE; 78 } 79 handle = loader_LoadLibrary(name); 80 if (handle) { 81 void *address = dlsym(handle, "NSSLOW_GetVector"); 82 if (address) { 83 NSSLOWGetVectorFn *getVector = (NSSLOWGetVectorFn *)address; 84 const NSSLOWVector *dsoVector = getVector(); 85 if (dsoVector) { 86 unsigned short dsoVersion = dsoVector->version; 87 unsigned short myVersion = NSSLOW_VERSION; 88 if (MSB(dsoVersion) == MSB(myVersion) && 89 LSB(dsoVersion) >= LSB(myVersion) && 90 dsoVector->length >= sizeof(NSSLOWVector)) { 91 vector = dsoVector; 92 libraryName = name; 93 blLib = handle; 94 return PR_SUCCESS; 95 } 96 } 97 } 98 (void)dlclose(handle); 99 } 100 return PR_FAILURE; 101 } 102 103 static PRCallOnceType loadFreeBLOnce; 104 105 static void 106 freebl_RunLoaderOnce(void) 107 { 108 /* Don't have NSPR, so can use the real PR_CallOnce, implement a stripped 109 * down version. */ 110 if (loadFreeBLOnce.initialized) { 111 return; 112 } 113 if (__sync_lock_test_and_set(&loadFreeBLOnce.inProgress, 1) == 0) { 114 loadFreeBLOnce.status = freebl_LoadDSO(); 115 loadFreeBLOnce.initialized = 1; 116 } else { 117 /* shouldn't have a lot of takers on the else clause, which is good 118 * since we don't have condition variables yet. 119 * 'initialized' only ever gets set (not cleared) so we don't 120 * need the traditional locks. */ 121 while (!loadFreeBLOnce.initialized) { 122 sleep(1); /* don't have condition variables, just give up the CPU */ 123 } 124 } 125 } 126 127 static const NSSLOWVector * 128 freebl_InitVector(void) 129 { 130 if (!vector) { 131 freebl_RunLoaderOnce(); 132 } 133 return vector; 134 } 135 136 const FREEBLVector * 137 FREEBL_GetVector(void) 138 { 139 if (freebl_InitVector()) { 140 return (vector->p_FREEBL_GetVector)(); 141 } 142 return NULL; 143 } 144 145 NSSLOWInitContext * 146 NSSLOW_Init(void) 147 { 148 if (freebl_InitVector()) { 149 return (vector->p_NSSLOW_Init)(); 150 } 151 return NULL; 152 } 153 154 void 155 NSSLOW_Shutdown(NSSLOWInitContext *context) 156 { 157 if (freebl_InitVector()) { 158 (vector->p_NSSLOW_Shutdown)(context); 159 } 160 } 161 162 void 163 NSSLOW_Reset(NSSLOWInitContext *context) 164 { 165 if (freebl_InitVector()) { 166 (vector->p_NSSLOW_Reset)(context); 167 } 168 } 169 170 NSSLOWHASHContext * 171 NSSLOWHASH_NewContext( 172 NSSLOWInitContext *initContext, 173 HASH_HashType hashType) 174 { 175 if (freebl_InitVector()) { 176 return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType); 177 } 178 return NULL; 179 } 180 181 void 182 NSSLOWHASH_Begin(NSSLOWHASHContext *context) 183 { 184 if (freebl_InitVector()) { 185 (vector->p_NSSLOWHASH_Begin)(context); 186 } 187 } 188 189 void 190 NSSLOWHASH_Update(NSSLOWHASHContext *context, 191 const unsigned char *buf, 192 unsigned int len) 193 { 194 if (freebl_InitVector()) { 195 (vector->p_NSSLOWHASH_Update)(context, buf, len); 196 } 197 } 198 199 void 200 NSSLOWHASH_End(NSSLOWHASHContext *context, 201 unsigned char *buf, 202 unsigned int *ret, unsigned int len) 203 { 204 if (freebl_InitVector()) { 205 (vector->p_NSSLOWHASH_End)(context, buf, ret, len); 206 } 207 } 208 209 void 210 NSSLOWHASH_Destroy(NSSLOWHASHContext *context) 211 { 212 if (freebl_InitVector()) { 213 (vector->p_NSSLOWHASH_Destroy)(context); 214 } 215 } 216 217 unsigned int 218 NSSLOWHASH_Length(NSSLOWHASHContext *context) 219 { 220 if (freebl_InitVector()) { 221 return (vector->p_NSSLOWHASH_Length)(context); 222 } 223 return -1; 224 }