Bug 191270: added the ability to load a dynamic shared library (.dylib) on NSPRPUB_PRE_4_2_CLIENT_BRANCH
authorwtc%netscape.com
Wed, 26 Feb 2003 23:57:47 +0000
branchNSPRPUB_PRE_4_2_CLIENT_BRANCH
changeset 2734 c5d30d5895d4bad1041b407bd67f9a9c1c4f5dae
parent 2733 117b078074d66882fd6392b80dea13ae615ee47f
child 2735 e20125316cf0f68247bbb6ec16342f0afe0cc237
push idunknown
push userunknown
push dateunknown
bugs191270
Bug 191270: added the ability to load a dynamic shared library (.dylib) on Mac OS X. passed the XXX_RETURN_ON_ERROR flags to several Mac OS X linker functions. Correctly handle the return value of NSUnLinkModule. Pass NSADDIMAGE_OPTION_WITH_SEARCHING to NSAddImage. Tag: NSPRPUB_PRE_4_2_CLIENT_BRANCH
pr/src/linking/prlink.c
--- a/pr/src/linking/prlink.c
+++ b/pr/src/linking/prlink.c
@@ -193,16 +193,17 @@ struct PRLibrary {
 #if TARGET_CARBON
     CFBundleRef                 bundle;
 #endif
 
     Ptr                         main;
 
 #if defined(XP_MACOSX)
     CFMutableDictionaryRef      wrappers;
+    const struct mach_header*   image;
 #endif /* XP_MACOSX */
 #endif
 
 #ifdef XP_UNIX
 #if defined(USE_HPSHL)
     shl_t                       dlh;
 #elif defined(USE_MACH_DYLD)
     NSModule                    dlh;
@@ -636,17 +637,28 @@ PR_LoadLibrary(const char *name)
 #if defined(USE_MACH_DYLD)
 static NSModule
 pr_LoadMachDyldModule(const char *name)
 {
     NSObjectFileImage ofi;
     NSModule h = NULL;
     if (NSCreateObjectFileImageFromFile(name, &ofi)
             == NSObjectFileImageSuccess) {
-        h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE);
+        h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE
+                         | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+        /*
+         * TODO: If NSLinkModule fails, use NSLinkEditError to retrieve
+         * error information.
+         */
+        if (NSDestroyObjectFileImage(ofi) == FALSE) {
+            if (h) {
+                (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE);
+                h = NULL;
+            }
+        }
     }
     return h;
 }
 #endif
 
 #if defined(XP_MAC) || defined(XP_MACOSX)
 
 #ifdef XP_MACOSX
@@ -874,17 +886,25 @@ pr_LoadCFBundle(const char *name, PRLibr
 }
 #endif
 
 #ifdef XP_MACOSX
 static PRStatus
 pr_LoadViaDyld(const char *name, PRLibrary *lm)
 {
     lm->dlh = pr_LoadMachDyldModule(name);
-    return (lm->dlh != NULL) ? PR_SUCCESS : PR_FAILURE;
+    if (lm->dlh == NULL) {
+        lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR
+                               | NSADDIMAGE_OPTION_WITH_SEARCHING);
+        /*
+         * TODO: If NSAddImage fails, use NSLinkEditError to retrieve
+         * error information.
+         */
+    }
+    return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE;
 }
 #endif
 
 #endif /* defined(XP_MAC) || defined(XP_MACOSX) */
 
 /*
 ** Dynamically load a library. Only load libraries once, so scan the load
 ** map first.
@@ -1328,17 +1348,17 @@ PR_UnloadLibrary(PRLibrary *lib)
 
 #ifdef XP_UNIX
 #ifdef HAVE_DLL
 #ifdef USE_DLFCN
     result = dlclose(lib->dlh);
 #elif defined(USE_HPSHL)
     result = shl_unload(lib->dlh);
 #elif defined(USE_MACH_DYLD)
-    result = NSUnLinkModule(lib->dlh, FALSE);
+    result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1;
 #else
 #error Configuration error
 #endif
 #endif /* HAVE_DLL */
 #endif /* XP_UNIX */
 #ifdef XP_PC
     if (lib->dlh) {
         FreeLibrary((HINSTANCE)(lib->dlh));
@@ -1352,16 +1372,17 @@ PR_UnloadLibrary(PRLibrary *lib)
         CloseConnection(&(lib->connection));
 #if TARGET_CARBON
     if (lib->bundle)
         CFRelease(lib->bundle);
 #endif
 #if defined(XP_MACOSX)
     if (lib->wrappers)
         CFRelease(lib->wrappers);
+    /* No way to unload an image (lib->image) */
 #endif
 #endif
 
     /* unlink from library search list */
     if (pr_loadmap == lib)
         pr_loadmap = pr_loadmap->next;
     else if (pr_loadmap != NULL) {
         PRLibrary* prev = pr_loadmap;
@@ -1389,17 +1410,17 @@ PR_UnloadLibrary(PRLibrary *lib)
      * succeeds or not.
      */
 
   freeLib:
     PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name));
     free(lib->name);
     lib->name = NULL;
     PR_DELETE(lib);
-    if (result == -1) {
+    if (result != 0) {
         PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO());
         DLLErrorInternal(_MD_ERRNO());
         status = PR_FAILURE;
     }
 
 done:
     PR_ExitMonitor(pr_linker_lock);
     return status;
@@ -1469,16 +1490,28 @@ pr_FindSymbolInLib(PRLibrary *lm, const 
         /* callers expect mach-o function pointers, so must wrap tvectors with glue. */
         if (f && symClass == kTVectorCFragSymbol) {
             f = TV2FP(lm->wrappers, name + SYM_OFFSET, f);
         }
 #endif
         
         if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main;
     }
+#if defined(XP_MACOSX)
+    if (lm->image) {
+        NSSymbol symbol;
+        symbol = NSLookupSymbolInImage(lm->image, name,
+                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+                 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+        if (symbol != NULL)
+            f = NSAddressOfSymbol(symbol);
+        else
+            f = NULL;
+    }
+#endif
 #undef SYM_OFFSET
 #endif /* XP_MAC */
 
 #ifdef XP_BEOS
     if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_TEXT, &f ) ) {
         f = NULL;
     }
 #endif