Bug 1253727: Derive NS_XPCOM_LIBRARY_FILE from the actual location of the loaded library; r?froydnj draft
authorAaron Klotz <aklotz@mozilla.com>
Tue, 08 Mar 2016 14:01:47 -0800
changeset 338367 5cd9963ec73b13d4221145355a4e9d3236703aff
parent 335982 eb25b90a05c194bfd4f498ff3ffee7440f85f1cd
child 515783 2dedd45dedc3f0383558fd7d27d874675d5c4d40
push id12491
push useraklotz@mozilla.com
push dateTue, 08 Mar 2016 22:56:41 +0000
reviewersfroydnj
bugs1253727
milestone47.0a1
Bug 1253727: Derive NS_XPCOM_LIBRARY_FILE from the actual location of the loaded library; r?froydnj MozReview-Commit-ID: HDvkTDhuXyf
xpcom/build/LibPath.cpp
xpcom/build/LibPath.h
xpcom/build/XPCOMInit.cpp
xpcom/build/moz.build
new file mode 100644
--- /dev/null
+++ b/xpcom/build/LibPath.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "LibPath.h"
+
+#include "nsString.h"
+#include "nsXPCOMPrivate.h"
+
+#if defined(XP_WIN)
+#include <windows.h>
+#elif defined(XP_MACOSX)
+#include <dlfcn.h>
+#elif defined(XP_LINUX)
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+#endif
+
+namespace mozilla {
+
+/* static */ nsresult
+LibPath::Get(nsIFile** aFile)
+{
+  if (!aFile) {
+    return NS_ERROR_NULL_POINTER;
+  }
+#if defined(XP_WIN)
+  nsAutoString path;
+  HMODULE module = ::GetModuleHandleW(LXPCOM_DLL);
+  path.SetLength(MAX_PATH);
+  DWORD len = ::GetModuleFileName(module, path.BeginWriting(), MAX_PATH);
+  if (!len || ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+    return NS_ERROR_FAILURE;
+  }
+  path.SetLength(len);
+  return NS_NewLocalFile(path, false, aFile);
+#elif (defined(XP_MACOSX) || defined(XP_LINUX))
+  // We'll pass the address of this function as addr to obtain the path to the
+  // library that contains it.
+  Dl_info info;
+  if (!dladdr((const void*) &LibPath::Get, &info)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_NewNativeLocalFile(nsDependentCString(info.dli_fname), false,
+                               aFile);
+#else
+  // For other platforms, we'll just append to the GRE bin path
+  nsCOMPtr<nsIFile> file;
+  nsresult rv = nsDirectoryService::gService->Get(NS_GRE_BIN_DIR,
+                                                  NS_GET_IID(nsIFile),
+                                                  getter_AddRefs(file));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = file->AppendNative(NS_LITERAL_CSTRING(XPCOM_DLL));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  file.forget(aFile);
+  return NS_OK;
+#endif
+}
+
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/xpcom/build/LibPath.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_LibPath_h
+#define mozilla_LibPath_h
+
+#include "nsXPCOM.h"
+
+namespace mozilla {
+
+class LibPath
+{
+public:
+  static nsresult Get(nsIFile** aFile);
+};
+
+} // namespace mozilla
+
+#endif // mozilla_LibPath_h
+
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
+#include "LibPath.h"
 #include "mozilla/AbstractThread.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Poison.h"
 #include "mozilla/SharedThreadPool.h"
 #include "mozilla/XPCOM.h"
 #include "nsXULAppAPI.h"
 
 #include "nsXPCOMPrivate.h"
@@ -589,28 +590,31 @@ NS_InitXPCOM2(nsIServiceManager** aResul
 
   if (aAppFileLocationProvider) {
     rv = nsDirectoryService::gService->RegisterProvider(aAppFileLocationProvider);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
 
-  nsCOMPtr<nsIFile> xpcomLib;
+  nsCOMPtr<nsIFile> greBinDir;
   nsDirectoryService::gService->Get(NS_GRE_BIN_DIR,
                                     NS_GET_IID(nsIFile),
-                                    getter_AddRefs(xpcomLib));
-  MOZ_ASSERT(xpcomLib);
+                                    getter_AddRefs(greBinDir));
+  MOZ_ASSERT(greBinDir);
 
   // set gGREBinPath
   nsAutoString path;
-  xpcomLib->GetPath(path);
+  greBinDir->GetPath(path);
   gGREBinPath = ToNewUnicode(path);
 
-  xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL));
+  nsCOMPtr<nsIFile> xpcomLib;
+  if (NS_WARN_IF(NS_FAILED(LibPath::Get(getter_AddRefs(xpcomLib))))) {
+    return rv;
+  }
   nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
 
   if (!mozilla::Omnijar::IsInitialized()) {
     mozilla::Omnijar::Init();
   }
 
   if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) {
 #ifdef OS_WIN
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -46,16 +46,17 @@ include('../glue/objs.mozbuild')
 
 UNIFIED_SOURCES += xpcom_gluens_src_cppsrcs
 UNIFIED_SOURCES += xpcom_glue_src_cppsrcs
 
 UNIFIED_SOURCES += [
     'FrozenFunctions.cpp',
     'IOInterposer.cpp',
     'LateWriteChecks.cpp',
+    'LibPath.cpp',
     'MainThreadIOLogger.cpp',
     'nsXPCOMStrings.cpp',
     'Services.cpp',
     'XPCOMInit.cpp',
 ]
 
 if CONFIG['OS_ARCH'] != 'WINNT':
     SOURCES += [