VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/components/xcDll.cpp

Last change on this file was 109068, checked in by vboxsync, 3 weeks ago

libs/xpcom: Disabled loading dependencies listed in compreg.dat, since we disabled generating those some 16 years ago. bugref:10896 ticketref:22193

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/* nsDll
39 *
40 * Abstraction of a Dll. Stores modifiedTime and size for easy detection of
41 * change in dll.
42 *
43 * dp Suresh <dp@netscape.com>
44 */
45
46#include "xcDll.h"
47#include "nsDebug.h"
48#include "nsIComponentManager.h"
49#include "nsIComponentLoaderManager.h"
50#include "nsIModule.h"
51#include "nsILocalFile.h"
52#include "nsDirectoryServiceDefs.h"
53#include "nsDirectoryServiceUtils.h"
54#include "nsCOMPtr.h"
55#include "nsCRT.h"
56#include "nsString.h"
57#include "nsModule.h"
58#ifdef DEBUG
59#if defined(XP_MACOSX)
60#include <signal.h>
61#endif
62#endif /* defined(DEBUG) */
63
64#include "nsTraceRefcntImpl.h"
65
66#include "nsNativeComponentLoader.h"
67#include "nsMemory.h"
68#include <VBox/log.h>
69
70
71nsDll::nsDll(nsIFile *dllSpec, nsNativeComponentLoader *loader)
72 : m_dllSpec(do_QueryInterface(dllSpec)),
73 m_hMod(NIL_RTLDRMOD),
74 m_moduleObject(NULL),
75 m_loader(loader),
76 m_markForUnload(PR_FALSE)
77{
78 NS_ASSERTION(loader, "Null loader when creating a nsDLL");
79}
80
81nsDll::~nsDll(void)
82{
83 /** @todo r=aeichner Does this need fixing at all? */
84 //#if DEBUG_dougt
85 // The dll gets deleted when the dllStore is destroyed. This happens on
86 // app shutdown. At that point, unloading dlls can cause crashes if we have
87 // - dll dependencies
88 // - callbacks
89 // - static dtors
90 // Hence turn it back on after all the above have been removed.
91#ifdef VBOX_WITH_GCC_SANITIZER
92 /* Although this looks like it's what we should be doing here, we don't want to enable this for release builds (yet).
93 * Needs more testing and/or debugging first. See @bugref{10545c6}. */
94 Unload();
95#endif
96 //#endif
97}
98
99void
100nsDll::GetDisplayPath(nsACString& aLeafName)
101{
102 m_dllSpec->GetNativeLeafName(aLeafName);
103
104 if (aLeafName.IsEmpty())
105 aLeafName.AssignLiteral("unknown!");
106}
107
108PRBool
109nsDll::HasChanged()
110{
111 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
112 if (!manager)
113 return PR_TRUE;
114
115 // If mod date has changed, then dll has changed
116 PRInt64 currentDate;
117 nsresult rv = m_dllSpec->GetLastModifiedTime(&currentDate);
118 if (NS_FAILED(rv))
119 return PR_TRUE;
120 Log2(("nsDll::HasChanged: currentDate=%RI64\n", currentDate));
121 PRBool changed = PR_TRUE;
122 manager->HasFileChanged(m_dllSpec, nsnull, currentDate, &changed);
123 return changed;
124}
125
126PRBool nsDll::Load(void)
127{
128 /* Already loaded? Nothing to do. */
129 if (m_hMod != NIL_RTLDRMOD)
130 return PR_TRUE;
131
132 if (m_dllSpec)
133 {
134#ifdef NS_BUILD_REFCNT_LOGGING
135 nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
136#endif
137#ifndef VBOX /* This is related to DEPENDENT_LIBS, which we've disabled. */
138 // Load any library dependencies
139 // The Component Loader Manager may hold onto some extra data
140 // set by either the native component loader or the native
141 // component. We assume that this data is a space delimited
142 // listing of dependent libraries which are required to be
143 // loaded prior to us loading the given component. Once, the
144 // component is loaded into memory, we can release our hold
145 // on the dependent libraries with the assumption that the
146 // component library holds a reference via the OS so loader.
147 nsCOMPtr<nsIComponentLoaderManager> manager = do_QueryInterface(m_loader->mCompMgr);
148 if (!manager)
149 return PR_TRUE;
150
151
152 nsXPIDLCString extraData;
153 manager->GetOptionalData(m_dllSpec, nsnull, getter_Copies(extraData));
154
155 nsVoidArray dependentLibArray;
156
157 // if there was any extra data, treat it as a listing of dependent libs
158 if (extraData != nsnull)
159 {
160 // all dependent libraries are suppose to be in the "gre" directory.
161 // note that the gre directory is the same as the "bin" directory,
162 // when there isn't a real "gre" found.
163
164 nsXPIDLCString path;
165 nsCOMPtr<nsIFile> file;
166 NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
167
168 if (!file)
169 return NS_ERROR_FAILURE;
170
171 // we are talking about a file in the GRE dir. Lets append something
172 // stupid right now, so that later we can just set the leaf name.
173 file->AppendNative(NS_LITERAL_CSTRING("dummy"));
174
175 char *buffer = (char *)nsMemory::Clone(extraData, strlen(extraData) + 1);
176 if (!buffer)
177 return NS_ERROR_OUT_OF_MEMORY;
178
179 char* newStr;
180 char *token = nsCRT::strtok(buffer, " ", &newStr);
181 while (token!=nsnull)
182 {
183 nsCStringKey key(token);
184 if (m_loader->mLoadedDependentLibs.Get(&key)) {
185 token = nsCRT::strtok(newStr, " ", &newStr);
186 continue;
187 }
188
189 m_loader->mLoadedDependentLibs.Put(&key, (void*)1);
190
191 nsXPIDLCString libpath;
192 file->SetNativeLeafName(nsDependentCString(token));
193 file->GetNativePath(path);
194 if (!path)
195 return NS_ERROR_FAILURE;
196
197 // Load this dependent library with the global flag and stash
198 // the result for later so that we can unload it.
199 const char *pszFilename = NULL;
200
201 // if the depend library path starts with a / we are
202 // going to assume that it is a full path and should
203 // be loaded without prepending the gre diretory
204 // location. We could have short circuited the
205 // SetNativeLeafName above, but this is clearer and
206 // the common case is a relative path.
207 if (token[0] == '/')
208 pszFilename = token;
209 else
210 pszFilename = path;
211
212 RTLDRMOD hMod = NIL_RTLDRMOD;
213 RTERRINFOSTATIC ErrInfo;
214 RTErrInfoInitStatic(&ErrInfo);
215
216 int vrc = RTLdrLoadEx(pszFilename, &hMod, RTLDRLOAD_FLAGS_LOCAL, &ErrInfo.Core);
217 // if we couldn't load the dependent library. We did the best we
218 // can. Now just let us fail later if this really was a required
219 // dependency.
220 if (RT_SUCCESS(vrc))
221 dependentLibArray.AppendElement((void*)hMod);
222
223 token = nsCRT::strtok(newStr, " ", &newStr);
224 }
225 nsMemory::Free(buffer);
226 }
227#endif /* !VBOX */
228
229 // load the component
230 nsCOMPtr<nsILocalFile> lf(do_QueryInterface(m_dllSpec));
231 NS_ASSERTION(lf, "nsIFile here must implement a nsILocalFile");
232 lf->Load(&m_hMod);
233
234#ifndef VBOX /* This is related to DEPENDENT_LIBS, which we've disabled. */
235 // Unload any of library dependencies we loaded earlier. The assumption
236 // here is that the component will have a "internal" reference count to
237 // the dependency library we just loaded.
238 // XXX should we unload later - or even at all?
239 if (extraData != nsnull)
240 {
241 PRInt32 arrayCount = dependentLibArray.Count();
242 for (PRInt32 index = 0; index < arrayCount; index++)
243 RTLdrClose((RTLDRMOD)dependentLibArray.ElementAt(index));
244 }
245#endif /* !VBOX */
246
247#ifdef NS_BUILD_REFCNT_LOGGING
248 nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
249 if (m_hMod != NIL_RTLDRMOD)
250 {
251 // Inform refcnt tracer of new library so that calls through the
252 // new library can be traced.
253 nsXPIDLCString displayPath;
254 GetDisplayPath(displayPath);
255 nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_hMod);
256 }
257#endif
258 }
259
260 return ((m_hMod == NIL_RTLDRMOD) ? PR_FALSE : PR_TRUE);
261}
262
263PRBool nsDll::Unload(void)
264{
265 if (m_hMod == NULL)
266 return PR_FALSE;
267
268 // Shutdown the dll
269 Shutdown();
270
271#ifdef NS_BUILD_REFCNT_LOGGING
272 nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
273#endif
274 int vrc = RTLdrClose(m_hMod);
275#ifdef NS_BUILD_REFCNT_LOGGING
276 nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
277#endif
278
279 if (RT_SUCCESS(vrc))
280 {
281 m_hMod = NIL_RTLDRMOD;
282 return PR_TRUE;
283 }
284
285 return PR_FALSE;
286}
287
288void * nsDll::FindSymbol(const char *symbol)
289{
290 if (symbol == NULL)
291 return NULL;
292
293 // If not already loaded, load it now.
294 if (Load() != PR_TRUE)
295 return NULL;
296
297 void *pvSym = NULL;
298 int vrc = RTLdrGetSymbol(m_hMod, symbol, &pvSym);
299 RT_NOREF(vrc);
300
301 return pvSym;
302}
303
304
305// Component dll specific functions
306nsresult nsDll::GetDllSpec(nsIFile **fsobj)
307{
308 NS_ASSERTION(m_dllSpec, "m_dllSpec NULL");
309 NS_ASSERTION(fsobj, "xcDll::GetModule : Null argument" );
310
311 *fsobj = m_dllSpec;
312 NS_ADDREF(*fsobj);
313 return NS_OK;
314}
315
316nsresult nsDll::GetModule(nsISupports *servMgr, nsIModule **cobj)
317{
318 // using the backpointer of the loader.
319 nsIComponentManager* compMgr = m_loader->mCompMgr;
320 NS_ASSERTION(compMgr, "Global Component Manager is null" );
321 if (!compMgr) return NS_ERROR_UNEXPECTED;
322
323 NS_ASSERTION(cobj, "xcDll::GetModule : Null argument" );
324
325 if (m_moduleObject)
326 {
327 NS_ADDREF(m_moduleObject);
328 *cobj = m_moduleObject;
329 return NS_OK;
330 }
331
332 // If not already loaded, load it now.
333 if (Load() != PR_TRUE) return NS_ERROR_FAILURE;
334
335 // We need a nsIFile for location
336 if (!m_dllSpec)
337 {
338 return NS_ERROR_FAILURE;
339 }
340
341 nsGetModuleProc proc =
342 (nsGetModuleProc) FindSymbol(NS_GET_MODULE_SYMBOL);
343
344 if (proc == NULL)
345 return NS_ERROR_FACTORY_NOT_LOADED;
346
347 nsresult rv = (*proc) (compMgr, m_dllSpec, &m_moduleObject);
348 if (NS_SUCCEEDED(rv))
349 {
350 NS_ADDREF(m_moduleObject);
351 *cobj = m_moduleObject;
352 }
353 return rv;
354}
355
356nsresult nsDll::Shutdown(void)
357{
358 // Release the module object if we got one
359 nsrefcnt refcnt;
360 if (m_moduleObject)
361 {
362 NS_RELEASE2(m_moduleObject, refcnt);
363 NS_ASSERTION(refcnt == 0, "Dll moduleObject refcount non zero");
364 }
365
366 return NS_OK;
367
368}
369
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette