VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp@ 79559

Last change on this file since 79559 was 79559, checked in by vboxsync, 5 years ago

IPRT/process-creation-posix.cpp: Try to dynamically resolve crypt_r on linux. [adjustments] ticketref:18682

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.7 KB
Line 
1/* $Id: ldrNative-posix.cpp 79559 2019-07-05 15:42:51Z vboxsync $ */
2/** @file
3 * IPRT - Binary Image Loader, POSIX native.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_LDR
32#include <dlfcn.h>
33
34#include <iprt/ldr.h>
35#include <iprt/assert.h>
36#include <iprt/path.h>
37#include <iprt/alloca.h>
38#include <iprt/string.h>
39#include <iprt/err.h>
40#include <iprt/log.h>
41#include "internal/ldr.h"
42
43
44/*********************************************************************************************************************************
45* Global Variables *
46*********************************************************************************************************************************/
47#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
48static const char g_szSuff[] = ".DLL";
49#elif defined(RT_OS_L4)
50static const char g_szSuff[] = ".s.so";
51#elif defined(RT_OS_DARWIN)
52static const char g_szSuff[] = ".dylib";
53#else
54static const char g_szSuff[] = ".so";
55#endif
56
57
58DECLHIDDEN(int) rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlags, PRTERRINFO pErrInfo)
59{
60 /*
61 * Do we need to add an extension?
62 */
63 if (!RTPathHasSuffix(pszFilename) && !(fFlags & RTLDRLOAD_FLAGS_NO_SUFFIX))
64 {
65 size_t cch = strlen(pszFilename);
66 char *psz = (char *)alloca(cch + sizeof(g_szSuff));
67 if (!psz)
68 return RTErrInfoSet(pErrInfo, VERR_NO_MEMORY, "alloca failed");
69 memcpy(psz, pszFilename, cch);
70 memcpy(psz + cch, g_szSuff, sizeof(g_szSuff));
71 pszFilename = psz;
72 }
73
74 /*
75 * Attempt load.
76 */
77 int fFlagsNative = RTLD_NOW;
78 if (fFlags & RTLDRLOAD_FLAGS_GLOBAL)
79 fFlagsNative |= RTLD_GLOBAL;
80 else
81 fFlagsNative |= RTLD_LOCAL;
82 void *pvMod = dlopen(pszFilename, fFlagsNative);
83 if (pvMod)
84 {
85 *phHandle = (uintptr_t)pvMod;
86 return VINF_SUCCESS;
87 }
88
89 const char *pszDlError = dlerror();
90 RTErrInfoSet(pErrInfo, VERR_FILE_NOT_FOUND, pszDlError);
91 LogRel(("rtldrNativeLoad: dlopen('%s', RTLD_NOW | RTLD_LOCAL) failed: %s\n", pszFilename, pszDlError));
92 return VERR_FILE_NOT_FOUND;
93}
94
95
96DECLCALLBACK(int) rtldrNativeGetSymbol(PRTLDRMODINTERNAL pMod, const char *pszSymbol, void **ppvValue)
97{
98 PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod;
99#ifdef RT_OS_OS2
100 /* Prefix the symbol with an underscore (assuming __cdecl/gcc-default). */
101 size_t cch = strlen(pszSymbol);
102 char *psz = (char *)alloca(cch + 2);
103 psz[0] = '_';
104 memcpy(psz + 1, pszSymbol, cch + 1);
105 pszSymbol = psz;
106#endif
107 *ppvValue = dlsym((void *)pModNative->hNative, pszSymbol);
108 if (*ppvValue)
109 return VINF_SUCCESS;
110 return VERR_SYMBOL_NOT_FOUND;
111}
112
113
114DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod)
115{
116 PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod;
117#ifdef __SANITIZE_ADDRESS__
118 /* If we are compiled with enabled address sanitizer (gcc/llvm), don't
119 * unload the module to prevent <unknown module> in the stack trace */
120 pModNative->fFlags |= RTLDRLOAD_FLAGS_NO_UNLOAD;
121#endif
122 if ( (pModNative->fFlags & RTLDRLOAD_FLAGS_NO_UNLOAD)
123 || !dlclose((void *)pModNative->hNative))
124 {
125 pModNative->hNative = (uintptr_t)0;
126 return VINF_SUCCESS;
127 }
128 Log(("rtldrNativeFree: dlclose(%p) failed: %s\n", pModNative->hNative, dlerror()));
129 return VERR_GENERAL_FAILURE;
130}
131
132
133DECLHIDDEN(int) rtldrNativeLoadSystem(const char *pszFilename, const char *pszExt, uint32_t fFlags, PRTLDRMOD phLdrMod)
134{
135 /*
136 * For the present we ASSUME that we can trust dlopen to load what we want
137 * when not specifying a path. There seems to be very little we can do to
138 * restrict the places dlopen will search for library without doing
139 * auditing (linux) or something like that.
140 */
141 Assert(strchr(pszFilename, '/') == NULL);
142
143 /* Easy if suffix was included. */
144 if (!pszExt)
145 return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, NULL);
146
147 /* Combine filename and suffix and then do the loading. */
148 size_t const cchFilename = strlen(pszFilename);
149 size_t const cchSuffix = strlen(pszExt);
150 char *pszTmp = (char *)alloca(cchFilename + cchSuffix + 16 + 1);
151 memcpy(pszTmp, pszFilename, cchFilename);
152 memcpy(&pszTmp[cchFilename], pszExt, cchSuffix);
153 pszTmp[cchFilename + cchSuffix] = '\0';
154
155 int rc = RTLdrLoadEx(pszTmp, phLdrMod, fFlags, NULL);
156
157#if !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2) && !defined(RT_OS_WINDOWS)
158 /*
159 * If no version was given after the .so and do .so.MAJOR search according
160 * to the range in the fFlags.
161 */
162 if (RT_FAILURE(rc) && !(fFlags & RTLDRLOAD_FLAGS_NO_SUFFIX))
163 {
164 const char *pszActualSuff = RTPathSuffix(pszTmp);
165 if (pszActualSuff && strcmp(pszActualSuff, ".so") == 0)
166 {
167 uint32_t const uBegin = (fFlags & RTLDRLOAD_FLAGS_SO_VER_BEGIN_MASK) >> RTLDRLOAD_FLAGS_SO_VER_BEGIN_SHIFT;
168 uint32_t const uEnd = (fFlags & RTLDRLOAD_FLAGS_SO_VER_END_MASK) >> RTLDRLOAD_FLAGS_SO_VER_END_SHIFT;
169 int32_t const iIncr = uBegin <= uEnd ? 1 : -1;
170 for (uint32_t uMajorVer = uBegin; uMajorVer != uEnd; uMajorVer += iIncr)
171 {
172 RTStrPrintf(&pszTmp[cchFilename + cchSuffix], 16 + 1, ".%u", uMajorVer);
173 rc = RTLdrLoadEx(pszTmp, phLdrMod, fFlags, NULL);
174 if (RT_SUCCESS(rc))
175 break;
176 }
177 }
178 }
179#endif
180
181 return rc;
182}
183
Note: See TracBrowser for help on using the repository browser.

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