]> git.pld-linux.org Git - packages/VirtualBox.git/blame - kernel-5.8.patch
workaround misdetection of shared object without dynamic section; rel 3
[packages/VirtualBox.git] / kernel-5.8.patch
CommitLineData
17e3308c
JP
1fix Linux 5.8
2
3This is a squashed patch with following upstream revisions:
4
5 r85208
6 r85430
7 r85431
8 r85432
9 r85447 # context required adjustment
10 r85453
11 r85460
12 r85461 # context required adjustment
13 r85500
14 r85501
15 r85503
16 r85504
17 r85505
18 r85506
19 r85507 # context required adjustment
20 r85509
21 r85510
22 r85511
23 r85514
24 r85516
25 r85517
26 r85518
27 r85525
28 r85526
29 r85527
30 r85533
31 r85534
32 r85540
33 r85541
34 r85545
35 r85546
36 r85552
37 r85555
38 r85556
39 r85590
40
41Thanks a lot to loqs for his hard work on FS#67488!
42
43Index: src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c
44===================================================================
45diff --git a/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c
46--- a/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c (revision 85207)
47+++ b/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c (revision 85208)
48@@ -31,6 +31,12 @@
49 #define LOG_GROUP RTLOGGROUP_TIME
50 #include "the-linux-kernel.h"
51 #include "internal/iprt.h"
52+/* Make sure we have the setting functions we need for RTTimeNow: */
53+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
54+# define RTTIME_INCL_TIMEVAL
55+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
56+# define RTTIME_INCL_TIMESPEC
57+#endif
58 #include <iprt/time.h>
59 #include <iprt/asm.h>
60
61@@ -182,22 +188,19 @@
62 RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
63 {
64 IPRT_LINUX_SAVE_EFL_AC();
65-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
66-/* On Linux 4.20, time.h includes time64.h and we have to use 64-bit times. */
67-# ifdef _LINUX_TIME64_H
68+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
69 struct timespec64 Ts;
70- ktime_get_real_ts64(&Ts);
71-# else
72+ ktime_get_real_ts64(&Ts); /* ktime_get_real_ts64 was added as a macro in 3.17, function since 4.18. */
73+ IPRT_LINUX_RESTORE_EFL_AC();
74+ return RTTimeSpecSetTimespec64(pTime, &Ts);
75+
76+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 16)
77 struct timespec Ts;
78- ktime_get_real_ts(&Ts);
79-# endif
80+ ktime_get_real_ts(&Ts); /* ktime_get_real_ts was removed in Linux 4.20. */
81 IPRT_LINUX_RESTORE_EFL_AC();
82-# ifdef _LINUX_TIME64_H
83- return RTTimeSpecSetTimespec64(pTime, &Ts);
84-# else
85 return RTTimeSpecSetTimespec(pTime, &Ts);
86-# endif
87-#else /* < 2.6.16 */
88+
89+#else /* < 2.6.16 */
90 struct timeval Tv;
91 do_gettimeofday(&Tv);
92 IPRT_LINUX_RESTORE_EFL_AC();
93Index: src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
94===================================================================
95diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
96--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85429)
97+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85430)
98@@ -72,7 +72,22 @@
99 # define gfp_t unsigned
100 #endif
101
102+/*
103+ * Wrappers around mmap_lock/mmap_sem difference.
104+ */
105+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
106+# define LNX_MM_DOWN_READ(a_pMm) down_read(&(a_pMm)->mmap_lock)
107+# define LNX_MM_UP_READ(a_pMm) up_read(&(a_pMm)->mmap_lock)
108+# define LNX_MM_DOWN_WRITE(a_pMm) down_write(&(a_pMm)->mmap_lock)
109+# define LNX_MM_UP_WRITE(a_pMm) up_write(&(a_pMm)->mmap_lock)
110+#else
111+# define LNX_MM_DOWN_READ(a_pMm) down_read(&(a_pMm)->mmap_sem)
112+# define LNX_MM_UP_READ(a_pMm) up_read(&(a_pMm)->mmap_sem)
113+# define LNX_MM_DOWN_WRITE(a_pMm) down_write(&(a_pMm)->mmap_sem)
114+# define LNX_MM_UP_WRITE(a_pMm) up_write(&(a_pMm)->mmap_sem)
115+#endif
116
117+
118 /*********************************************************************************************************************************
119 * Structures and Typedefs *
120 *********************************************************************************************************************************/
121@@ -182,7 +197,7 @@
122 * Worker for rtR0MemObjNativeReserveUser and rtR0MemObjNativerMapUser that creates
123 * an empty user space mapping.
124 *
125- * We acquire the mmap_sem of the task!
126+ * We acquire the mmap_sem/mmap_lock of the task!
127 *
128 * @returns Pointer to the mapping.
129 * (void *)-1 on failure.
130@@ -222,9 +237,9 @@
131 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
132 ulAddr = vm_mmap(NULL, R3PtrFixed, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, 0);
133 #else
134- down_write(&pTask->mm->mmap_sem);
135+ LNX_MM_DOWN_WRITE(pTask->mm);
136 ulAddr = do_mmap(NULL, R3PtrFixed, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, 0);
137- up_write(&pTask->mm->mmap_sem);
138+ LNX_MM_UP_WRITE(pTask->mm);
139 #endif
140 }
141 else
142@@ -232,9 +247,9 @@
143 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
144 ulAddr = vm_mmap(NULL, 0, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS, 0);
145 #else
146- down_write(&pTask->mm->mmap_sem);
147+ LNX_MM_DOWN_WRITE(pTask->mm);
148 ulAddr = do_mmap(NULL, 0, cb, fLnxProt, MAP_SHARED | MAP_ANONYMOUS, 0);
149- up_write(&pTask->mm->mmap_sem);
150+ LNX_MM_UP_WRITE(pTask->mm);
151 #endif
152 if ( !(ulAddr & ~PAGE_MASK)
153 && (ulAddr & (uAlignment - 1)))
154@@ -257,7 +272,7 @@
155 * Worker that destroys a user space mapping.
156 * Undoes what rtR0MemObjLinuxDoMmap did.
157 *
158- * We acquire the mmap_sem of the task!
159+ * We acquire the mmap_sem/mmap_lock of the task!
160 *
161 * @param pv The ring-3 mapping.
162 * @param cb The size of the mapping.
163@@ -269,13 +284,13 @@
164 Assert(pTask == current); RT_NOREF_PV(pTask);
165 vm_munmap((unsigned long)pv, cb);
166 #elif defined(USE_RHEL4_MUNMAP)
167- down_write(&pTask->mm->mmap_sem);
168+ LNX_MM_DOWN_WRITE(pTask->mm);
169 do_munmap(pTask->mm, (unsigned long)pv, cb, 0); /* should it be 1 or 0? */
170- up_write(&pTask->mm->mmap_sem);
171+ LNX_MM_UP_WRITE(pTask->mm);
172 #else
173- down_write(&pTask->mm->mmap_sem);
174+ LNX_MM_DOWN_WRITE(pTask->mm);
175 do_munmap(pTask->mm, (unsigned long)pv, cb);
176- up_write(&pTask->mm->mmap_sem);
177+ LNX_MM_UP_WRITE(pTask->mm);
178 #endif
179 }
180
181@@ -593,7 +608,7 @@
182 size_t iPage;
183 Assert(pTask);
184 if (pTask && pTask->mm)
185- down_read(&pTask->mm->mmap_sem);
186+ LNX_MM_DOWN_READ(pTask->mm);
187
188 iPage = pMemLnx->cPages;
189 while (iPage-- > 0)
190@@ -608,7 +623,7 @@
191 }
192
193 if (pTask && pTask->mm)
194- up_read(&pTask->mm->mmap_sem);
195+ LNX_MM_UP_READ(pTask->mm);
196 }
197 /* else: kernel memory - nothing to do here. */
198 break;
199@@ -1076,7 +1091,7 @@
200 papVMAs = (struct vm_area_struct **)RTMemAlloc(sizeof(*papVMAs) * cPages);
201 if (papVMAs)
202 {
203- down_read(&pTask->mm->mmap_sem);
204+ LNX_MM_DOWN_READ(pTask->mm);
205
206 /*
207 * Get user pages.
208@@ -1162,7 +1177,7 @@
209 papVMAs[rc]->vm_flags |= VM_DONTCOPY | VM_LOCKED;
210 }
211
212- up_read(&pTask->mm->mmap_sem);
213+ LNX_MM_UP_READ(pTask->mm);
214
215 RTMemFree(papVMAs);
216
217@@ -1189,7 +1204,7 @@
218 #endif
219 }
220
221- up_read(&pTask->mm->mmap_sem);
222+ LNX_MM_UP_READ(pTask->mm);
223
224 RTMemFree(papVMAs);
225 rc = VERR_LOCK_FAILED;
226@@ -1604,7 +1619,7 @@
227 const size_t cPages = (offSub + cbSub) >> PAGE_SHIFT;
228 size_t iPage;
229
230- down_write(&pTask->mm->mmap_sem);
231+ LNX_MM_DOWN_WRITE(pTask->mm);
232
233 rc = VINF_SUCCESS;
234 if (pMemLnxToMap->cPages)
235@@ -1721,7 +1736,7 @@
236 }
237 #endif /* CONFIG_NUMA_BALANCING */
238
239- up_write(&pTask->mm->mmap_sem);
240+ LNX_MM_UP_WRITE(pTask->mm);
241
242 if (RT_SUCCESS(rc))
243 {
244Index: src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
245===================================================================
246diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
247--- a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c (revision 85430)
248+++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c (revision 85431)
249@@ -756,20 +756,25 @@
250
251 RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
252 {
253-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
254- RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4);
255- RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
256+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
257+ RTCCUINTREG const uOld = __read_cr4();
258+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
259+ RTCCUINTREG const uOld = this_cpu_read(cpu_tlbstate.cr4);
260+#else
261+ RTCCUINTREG const uOld = ASMGetCR4();
262+#endif
263+ RTCCUINTREG const uNew = (uOld & fAndMask) | fOrMask;
264 if (uNew != uOld)
265 {
266+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
267+ ASMSetCR4(uNew);
268+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
269 this_cpu_write(cpu_tlbstate.cr4, uNew);
270 __write_cr4(uNew);
271- }
272 #else
273- RTCCUINTREG uOld = ASMGetCR4();
274- RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
275- if (uNew != uOld)
276 ASMSetCR4(uNew);
277 #endif
278+ }
279 return uOld;
280 }
281
282Index: src/VBox/Additions/linux/sharedfolders/vfsmod.c
283===================================================================
284diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c
285--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c (revision 85431)
286+++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c (revision 85432)
287@@ -52,7 +52,7 @@
288 #endif
289 #include <linux/seq_file.h>
290 #include <linux/vfs.h>
291-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 62)
292+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 62) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
293 # include <linux/vermagic.h>
294 #endif
295 #include <VBox/err.h>
296Index: Config.kmk
297===================================================================
298diff --git a/Config.kmk b/Config.kmk
299--- a/Config.kmk (revision 85446)
300+++ b/Config.kmk (revision 85447)
301@@ -4462,10 +4462,17 @@ endif # pe
302
303 ifeq ($(VBOX_LDR_FMT),elf)
304 TEMPLATE_VBoxR0_TOOL = $(VBOX_GCC_TOOL)
305-TEMPLATE_VBoxR0_CFLAGS = -fno-pie -nostdinc -g $(VBOX_GCC_pipe) $(VBOX_GCC_WERR) $(VBOX_GCC_PEDANTIC_C) $(VBOX_GCC_Wno-variadic-macros) $(VBOX_GCC_R0_OPT) $(VBOX_GCC_R0_FP) -fno-strict-aliasing -fno-exceptions $(VBOX_GCC_fno-stack-protector) -fno-common $(VBOX_GCC_fvisibility-hidden) -std=gnu99 $(VBOX_GCC_IPRT_FMT_CHECK)
306-TEMPLATE_VBoxR0_CXXFLAGS = -fno-pie -nostdinc -g $(VBOX_GCC_pipe) $(VBOX_GCC_WERR) $(VBOX_GCC_PEDANTIC_CXX) $(VBOX_GCC_Wno-variadic-macros) $(VBOX_GCC_R0_OPT) $(VBOX_GCC_R0_FP) -fno-strict-aliasing -fno-exceptions $(VBOX_GCC_fno-stack-protector) -fno-common $(VBOX_GCC_fvisibility-inlines-hidden) $(VBOX_GCC_fvisibility-hidden) -fno-rtti $(VBOX_GCC_IPRT_FMT_CHECK)
307-TEMPLATE_VBoxR0_CFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fasynchronous-unwind-tables -ffreestanding
308-TEMPLATE_VBoxR0_CXXFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fasynchronous-unwind-tables
309+TEMPLATE_VBoxR0_CFLAGS = -fno-pie -nostdinc -g $(VBOX_GCC_pipe) $(VBOX_GCC_WERR) $(VBOX_GCC_PEDANTIC_C) \
310+ $(VBOX_GCC_Wno-variadic-macros) $(VBOX_GCC_R0_OPT) $(VBOX_GCC_R0_FP) -fno-strict-aliasing -fno-exceptions \
311+ $(VBOX_GCC_fno-stack-protector) -fno-common $(VBOX_GCC_fvisibility-hidden) -std=gnu99 $(VBOX_GCC_IPRT_FMT_CHECK)
312+TEMPLATE_VBoxR0_CXXFLAGS = -fno-pie -nostdinc -g $(VBOX_GCC_pipe) $(VBOX_GCC_WERR) $(VBOX_GCC_PEDANTIC_CXX) \
313+ $(VBOX_GCC_Wno-variadic-macros) $(VBOX_GCC_R0_OPT) $(VBOX_GCC_R0_FP) -fno-strict-aliasing -fno-exceptions \
314+ $(VBOX_GCC_fno-stack-protector) -fno-common $(VBOX_GCC_fvisibility-inlines-hidden) $(VBOX_GCC_fvisibility-hidden) \
315+ -fno-rtti $(VBOX_GCC_std) $(VBOX_GCC_IPRT_FMT_CHECK)
316+TEMPLATE_VBoxR0_CFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow \
317+ -fasynchronous-unwind-tables -ffreestanding
318+TEMPLATE_VBoxR0_CXXFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow \
319+ -fasynchronous-unwind-tables
320 TEMPLATE_VBoxR0_CXXFLAGS.freebsd = -ffreestanding
321 if $(VBOX_GCC_VERSION_CC) < 30400
322 TEMPLATE_VBoxR0_DEFS += RT_WITHOUT_PRAGMA_ONCE
323@@ -4491,7 +4498,8 @@ ifn1of ($(KBUILD_TARGET),solaris freebsd)
324 $(VBOX_GCC_LIBGCC) # intrinsics
325 endif
326 if1of ($(KBUILD_TARGET),linux)
327- TEMPLATE_VBoxR0_POST_CMDS = $(if $(eq $(tool_do),LINK_SYSMOD),if readelf -S $(out)|grep -q "[cd]tors"; then echo "Found ctors/dtors in $(out)!"; exit 1; fi)
328+ TEMPLATE_VBoxR0_POST_CMDS = \
329+ $(if $(eq $(tool_do),LINK_SYSMOD),if readelf -S $(out)|grep -q "[cd]tors"; then echo "Found ctors/dtors in $(out)!"; exit 1; fi)
330 endif
331 endif
332
333Index: tools/bin/gen-slickedit-workspace.sh
334===================================================================
335diff --git a/tools/bin/gen-slickedit-workspace.sh b/tools/bin/gen-slickedit-workspace.sh
336--- a/tools/bin/gen-slickedit-workspace.sh (revision 85452)
337+++ b/tools/bin/gen-slickedit-workspace.sh (revision 85453)
338@@ -490,11 +490,13 @@
339 #
340 # Probe the slickedit user config, picking the most recent version.
341 #
342+ MY_VSLICK_DB_OLD=
343 if test -z "${MY_SLICK_CONFIG}"; then
344 if test -d "${HOME}/Library/Application Support/SlickEdit"; then
345 MY_SLICKDIR_="${HOME}/Library/Application Support/SlickEdit"
346 MY_USERCPP_H="unxcpp.h"
347 MY_VSLICK_DB="vslick.sta" # was .stu earlier, 24 is using .sta.
348+ MY_VSLICK_DB_OLD="vslick.stu"
349 elif test -d "${HOMEDRIVE}${HOMEPATH}/Documents/My SlickEdit Config"; then
350 MY_SLICKDIR_="${HOMEDRIVE}${HOMEPATH}/Documents/My SlickEdit Config"
351 MY_USERCPP_H="usercpp.h"
352@@ -502,7 +504,8 @@
353 else
354 MY_SLICKDIR_="${HOME}/.slickedit"
355 MY_USERCPP_H="unxcpp.h"
356- MY_VSLICK_DB="vslick.stu"
357+ MY_VSLICK_DB="vslick.sta"
358+ MY_VSLICK_DB_OLD="vslick.stu"
359 fi
360 else
361 MY_SLICKDIR_="${MY_SLICK_CONFIG}"
362@@ -511,7 +514,8 @@
363 MY_VSLICK_DB="vslick.sta"
364 else
365 MY_USERCPP_H="unxcpp.h"
366- MY_VSLICK_DB="vslick.stu"
367+ MY_VSLICK_DB="vslick.sta"
368+ MY_VSLICK_DB_OLD="vslick.stu"
369 fi
370 # MacOS: Implement me!
371 fi
372@@ -520,7 +524,9 @@
373 MY_VER="0.0.0"
374 for subdir in "${MY_SLICKDIR_}/"*;
375 do
376- if test -f "${subdir}/${MY_USERCPP_H}" -o -f "${subdir}/${MY_VSLICK_DB}"; then
377+ if test -f "${subdir}/${MY_USERCPP_H}" \
378+ -o -f "${subdir}/${MY_VSLICK_DB}" \
379+ -o '(' -n "${MY_VSLICK_DB_OLD}" -a -f "${subdir}/${MY_VSLICK_DB_OLD}" ')'; then
380 MY_CUR_VER_NUM=0
381 MY_CUR_VER=`echo "${subdir}" | ${MY_SED} -e 's,^.*/,,g'`
382
383@@ -555,6 +561,7 @@
384 echo "Found SlickEdit v${MY_VER} preprocessor file: ${MY_USERCPP_H_FULL}"
385 else
386 echo "Failed to locate SlickEdit preprocessor file. You need to manually merge ${MY_USERCPP_H}."
387+ echo "dbg: MY_SLICKDIR=${MY_SLICKDIR} MY_USERCPP_H_FULL=${MY_USERCPP_H_FULL}"
388 MY_USERCPP_H_FULL=""
389 fi
390
391@@ -716,6 +723,10 @@
392 #define RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm) int a_ImplExtNm##_Init(P##a_TypeNm pThis, PCRTASN1ALLOCATORVTABLE pAllocator); int a_ImplExtNm##_Clone(P##a_TypeNm pThis, PC##a_TypeNm) pSrc, PCRTASN1ALLOCATORVTABLE pAllocator); void a_ImplExtNm##_Delete(P##a_TypeNm pThis); int a_ImplExtNm##_Enum(P##a_TypeNm pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser); int a_ImplExtNm##_Compare(PC##a_TypeNm) pLeft, PC##a_TypeNm pRight); int a_ImplExtNm##_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags, P##a_TypeNm pThis, const char *pszErrorTag); int a_ImplExtNm##_CheckSanity(PC##a_TypeNm pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
393 #define RTASN1TYPE_STANDARD_PROTOTYPES(a_TypeNm, a_DeclMacro, a_ImplExtNm, a_Asn1CoreNm) inline PRTASN1CORE a_ImplExtNm##_GetAsn1Core(PC##a_TypeNm pThis) { return (PRTASN1CORE)&pThis->a_Asn1CoreNm; } inline bool a_ImplExtNm##_IsPresent(PC##a_TypeNm pThis) { return pThis && RTASN1CORE_IS_PRESENT(&pThis->a_Asn1CoreNm); } RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm)
394
395+#define RTLDRELF_NAME(name) rtldrELF64##name
396+#define RTLDRELF_SUFF(name) name##64
397+#define RTLDRELF_MID(pre,suff) pre##64##suff
398+
399 #define BS3_DECL(type) type
400 #define BS3_DECL_CALLBACK(type) type
401 #define TMPL_NM(name) name##_mmm
402Index: include/iprt/asmdefs.mac
403===================================================================
404diff --git a/include/iprt/asmdefs.mac b/include/iprt/asmdefs.mac
405--- a/include/iprt/asmdefs.mac (revision 85459)
406+++ b/include/iprt/asmdefs.mac (revision 85460)
407@@ -841,18 +841,18 @@
408 ; is defined and RT_WITHOUT_NOCRT_WRAPPERS isn't.
409 ;
410 %macro RT_NOCRT_BEGINPROC 1
411-%ifdef RT_WITH_NOCRT_ALIASES
412-BEGINPROC RT_NOCRT(%1)
413-%ifdef ASM_FORMAT_ELF
414+ %ifdef RT_WITH_NOCRT_ALIASES
415+BEGINPROC_EXPORTED RT_NOCRT(%1)
416+ %ifdef ASM_FORMAT_ELF
417 global NAME(%1)
418 weak NAME(%1)
419 NAME(%1):
420-%else
421+ %else
422 GLOBALNAME %1
423-%endif
424-%else ; !RT_WITH_NOCRT_ALIASES
425-BEGINPROC RT_NOCRT(%1)
426-%endif ; !RT_WITH_NOCRT_ALIASES
427+ %endif
428+ %else ; !RT_WITH_NOCRT_ALIASES
429+BEGINPROC_EXPORTED RT_NOCRT(%1)
430+ %endif ; !RT_WITH_NOCRT_ALIASES
431 %endmacro ; RT_NOCRT_BEGINPROC
432
433 %ifdef RT_WITH_NOCRT_ALIASES
434Index: src/VBox/Runtime/testcase/tstLdr-4.cpp
435===================================================================
436diff --git a/src/VBox/Runtime/testcase/tstLdr-4.cpp b/src/VBox/Runtime/testcase/tstLdr-4.cpp
437--- a/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85460)
438+++ b/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85461)
439@@ -214,7 +214,7 @@ static int testLdrOne(const char *pszFilename)
440 break;
441 }
442 DECLCALLBACKPTR(int, pfnDisasmTest1)(void) = (DECLCALLBACKPTR(int, RT_NOTHING)(void))(uintptr_t)Value; /* eeeh. */
443- RTPrintf("tstLdr-4: pfnDisasmTest1=%p / add-symbol-file %s %#x\n", pfnDisasmTest1, pszFilename, aLoads[i].pvBits);
444+ RTPrintf("tstLdr-4: pfnDisasmTest1=%p / add-symbol-file %s %#p\n", pfnDisasmTest1, pszFilename, aLoads[i].pvBits);
445 uint32_t iSeg = 0;
446 RTLdrEnumSegments(aLoads[i].hLdrMod, testEnumSegment, &iSeg);
447
448Index: src/VBox/Runtime/testcase/tstLdr-4.cpp
449===================================================================
450diff --git a/src/VBox/Runtime/testcase/tstLdr-4.cpp b/src/VBox/Runtime/testcase/tstLdr-4.cpp
451--- a/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85499)
452+++ b/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85500)
453@@ -35,9 +35,9 @@
454 #include <iprt/assert.h>
455 #include <iprt/param.h>
456 #include <iprt/path.h>
457-#include <iprt/initterm.h>
458 #include <iprt/err.h>
459 #include <iprt/string.h>
460+#include <iprt/test.h>
461
462 #include <VBox/sup.h>
463
464@@ -45,8 +45,9 @@
465 /*********************************************************************************************************************************
466 * Global Variables *
467 *********************************************************************************************************************************/
468-static SUPGLOBALINFOPAGE g_MyGip = { SUPGLOBALINFOPAGE_MAGIC, SUPGLOBALINFOPAGE_VERSION, SUPGIPMODE_INVARIANT_TSC, 42 };
469-static PSUPGLOBALINFOPAGE g_pMyGip = &g_MyGip;
470+static RTTEST g_hTest;
471+static SUPGLOBALINFOPAGE g_MyGip = { SUPGLOBALINFOPAGE_MAGIC, SUPGLOBALINFOPAGE_VERSION, SUPGIPMODE_INVARIANT_TSC, 42 };
472+static PSUPGLOBALINFOPAGE g_pMyGip = &g_MyGip;
473
474 extern "C" DECLEXPORT(int) DisasmTest1(void);
475
476@@ -58,6 +59,50 @@
477 " link=%RTptr LB %RTptr align=%RTptr fProt=%#x offFile=%RTfoff\n"
478 , *piSeg, pSeg->RVA, pSeg->cbMapped, pSeg->pszName,
479 pSeg->LinkAddress, pSeg->cb, pSeg->Alignment, pSeg->fProt, pSeg->offFile);
480+
481+ /*
482+ * Do some address conversion tests:
483+ */
484+ if (pSeg->cbMapped != NIL_RTLDRADDR)
485+ {
486+ /* RTLdrRvaToSegOffset: */
487+ uint32_t iSegConv = ~(uint32_t)42;
488+ RTLDRADDR offSegConv = ~(RTLDRADDR)22;
489+ int rc = RTLdrRvaToSegOffset(hLdrMod, pSeg->RVA, &iSegConv, &offSegConv);
490+ if (RT_FAILURE(rc))
491+ RTTestIFailed("RTLdrRvaToSegOffset failed on Seg #%u / RVA %#RTptr: %Rrc", *piSeg, pSeg->RVA, rc);
492+ else if (iSegConv != *piSeg || offSegConv != 0)
493+ RTTestIFailed("RTLdrRvaToSegOffset on Seg #%u / RVA %#RTptr returned: iSegConv=%#x offSegConv=%RTptr, expected %#x and 0",
494+ *piSeg, pSeg->RVA, iSegConv, offSegConv, *piSeg);
495+
496+ /* RTLdrSegOffsetToRva: */
497+ RTLDRADDR uRvaConv = ~(RTLDRADDR)22;
498+ rc = RTLdrSegOffsetToRva(hLdrMod, *piSeg, 0, &uRvaConv);
499+ if (RT_FAILURE(rc))
500+ RTTestIFailed("RTLdrSegOffsetToRva failed on Seg #%u / off 0: %Rrc", *piSeg, rc);
501+ else if (uRvaConv != pSeg->RVA)
502+ RTTestIFailed("RTLdrSegOffsetToRva on Seg #%u / off 0 returned: %RTptr, expected %RTptr", *piSeg, uRvaConv, pSeg->RVA);
503+
504+ /* RTLdrLinkAddressToRva: */
505+ uRvaConv = ~(RTLDRADDR)22;
506+ rc = RTLdrLinkAddressToRva(hLdrMod, pSeg->LinkAddress, &uRvaConv);
507+ if (RT_FAILURE(rc))
508+ RTTestIFailed("RTLdrLinkAddressToRva failed on Seg #%u / %RTptr: %Rrc", *piSeg, pSeg->LinkAddress, rc);
509+ else if (uRvaConv != pSeg->RVA)
510+ RTTestIFailed("RTLdrLinkAddressToRva on Seg #%u / %RTptr returned: %RTptr, expected %RTptr",
511+ *piSeg, pSeg->LinkAddress, uRvaConv, pSeg->RVA);
512+
513+ /* RTLdrLinkAddressToSegOffset: */
514+ iSegConv = ~(uint32_t)42;
515+ offSegConv = ~(RTLDRADDR)22;
516+ rc = RTLdrLinkAddressToSegOffset(hLdrMod, pSeg->LinkAddress, &iSegConv, &offSegConv);
517+ if (RT_FAILURE(rc))
518+ RTTestIFailed("RTLdrLinkAddressToSegOffset failed on Seg #%u / %#RTptr: %Rrc", *piSeg, pSeg->LinkAddress, rc);
519+ else if (iSegConv != *piSeg || offSegConv != 0)
520+ RTTestIFailed("RTLdrLinkAddressToSegOffset on Seg #%u / %#RTptr returned: iSegConv=%#x offSegConv=%RTptr, expected %#x and 0",
521+ *piSeg, pSeg->LinkAddress, iSegConv, offSegConv, *piSeg);
522+ }
523+
524 *piSeg += 1;
525 RT_NOREF(hLdrMod);
526 return VINF_SUCCESS;
527@@ -125,12 +170,12 @@
528 * regions the for compare usage. The third is loaded into one
529 * and then relocated between the two and other locations a few times.
530 *
531- * @returns number of errors.
532 * @param pszFilename The file to load the mess with.
533 */
534-static int testLdrOne(const char *pszFilename)
535+static void testLdrOne(const char *pszFilename)
536 {
537- int cErrors = 0;
538+ RTTestSub(g_hTest, RTPathFilename(pszFilename));
539+
540 size_t cbImage = 0;
541 struct Load
542 {
543@@ -155,9 +200,8 @@
544 rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &aLoads[i].hLdrMod);
545 if (RT_FAILURE(rc))
546 {
547- RTPrintf("tstLdr-4: Failed to open '%s'/%d, rc=%Rrc. aborting test.\n", pszFilename, i, rc);
548+ RTTestIFailed("tstLdr-4: Failed to open '%s'/%d, rc=%Rrc. aborting test.", pszFilename, i, rc);
549 Assert(aLoads[i].hLdrMod == NIL_RTLDRMOD);
550- cErrors++;
551 break;
552 }
553
554@@ -165,8 +209,7 @@
555 size_t cb = RTLdrSize(aLoads[i].hLdrMod);
556 if (cbImage && cb != cbImage)
557 {
558- RTPrintf("tstLdr-4: Size mismatch '%s'/%d. aborting test.\n", pszFilename, i);
559- cErrors++;
560+ RTTestIFailed("tstLdr-4: Size mismatch '%s'/%d. aborting test.", pszFilename, i);
561 break;
562 }
563 aLoads[i].cbBits = cbImage = cb;
564@@ -175,8 +218,7 @@
565 aLoads[i].pvBits = RTMemExecAlloc(cb);
566 if (!aLoads[i].pvBits)
567 {
568- RTPrintf("tstLdr-4: Out of memory '%s'/%d cbImage=%d. aborting test.\n", pszFilename, i, cbImage);
569- cErrors++;
570+ RTTestIFailed("Out of memory '%s'/%d cbImage=%d. aborting test.", pszFilename, i, cbImage);
571 break;
572 }
573
574@@ -184,8 +226,7 @@
575 rc = RTLdrGetBits(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, testGetImport, NULL);
576 if (RT_FAILURE(rc))
577 {
578- RTPrintf("tstLdr-4: Failed to get bits for '%s'/%d, rc=%Rrc. aborting test\n", pszFilename, i, rc);
579- cErrors++;
580+ RTTestIFailed("Failed to get bits for '%s'/%d, rc=%Rrc. aborting test", pszFilename, i, rc);
581 break;
582 }
583 }
584@@ -193,7 +234,7 @@
585 /*
586 * Execute the code.
587 */
588- if (!cErrors)
589+ if (!RTTestSubErrorCount(g_hTest))
590 {
591 for (i = 0; i < RT_ELEMENTS(aLoads); i += 1)
592 {
593@@ -209,8 +250,7 @@
594 UINT32_MAX, "_DisasmTest1", &Value);
595 if (RT_FAILURE(rc))
596 {
597- RTPrintf("tstLdr-4: Failed to get symbol \"DisasmTest1\" from load #%d: %Rrc\n", i, rc);
598- cErrors++;
599+ RTTestIFailed("Failed to get symbol \"DisasmTest1\" from load #%d: %Rrc", i, rc);
600 break;
601 }
602 typedef DECLCALLBACKPTR(int, PFNDISASMTEST1,(void));
603@@ -222,10 +262,7 @@
604 /* call the test function. */
605 rc = pfnDisasmTest1();
606 if (rc)
607- {
608- RTPrintf("tstLdr-4: load #%d Test1 -> %#x\n", i, rc);
609- cErrors++;
610- }
611+ RTTestIFailed("load #%d Test1 -> %#x", i, rc);
612
613 /* While we're here, check a couple of RTLdrQueryProp calls too */
614 void *pvBits = aLoads[i].pvBits;
615@@ -256,56 +293,42 @@
616 {
617 rc = RTLdrClose(aLoads[i].hLdrMod);
618 if (RT_FAILURE(rc))
619- {
620- RTPrintf("tstLdr-4: Failed to close '%s' i=%d, rc=%Rrc.\n", pszFilename, i, rc);
621- cErrors++;
622- }
623+ RTTestIFailed("Failed to close '%s' i=%d, rc=%Rrc.", pszFilename, i, rc);
624 }
625 }
626
627- return cErrors;
628 }
629
630
631
632-int main(int argc, char **argv)
633+int main()
634 {
635- int cErrors = 0;
636- RTR3InitExe(argc, &argv, 0);
637+ RTEXITCODE rcExit = RTTestInitAndCreate("tstLdr-4", &g_hTest);
638+ if (rcExit != RTEXITCODE_SUCCESS)
639+ return rcExit;
640
641 /*
642 * Sanity check.
643 */
644 int rc = DisasmTest1();
645- if (rc)
646+ if (rc == 0)
647 {
648- RTPrintf("tstLdr-4: FATAL ERROR - DisasmTest1 is buggy: rc=%#x\n", rc);
649- return 1;
650- }
651+ /*
652+ * Execute the test.
653+ */
654+ char szPath[RTPATH_MAX];
655+ rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/tstLdrObjR0.r0"));
656+ if (RT_SUCCESS(rc))
657+ {
658+ strcat(szPath, "/tstLdrObjR0.r0");
659
660- /*
661- * Execute the test.
662- */
663- char szPath[RTPATH_MAX];
664- rc = RTPathExecDir(szPath, sizeof(szPath) - sizeof("/tstLdrObjR0.r0"));
665- if (RT_SUCCESS(rc))
666- {
667- strcat(szPath, "/tstLdrObjR0.r0");
668- RTPrintf("tstLdr-4: TESTING '%s'...\n", szPath);
669- cErrors += testLdrOne(szPath);
670+ testLdrOne(szPath);
671+ }
672+ else
673+ RTTestIFailed("RTPathExecDir -> %Rrc", rc);
674 }
675 else
676- {
677- RTPrintf("tstLdr-4: RTPathExecDir -> %Rrc\n", rc);
678- cErrors++;
679- }
680+ RTTestIFailed("FATAL ERROR - DisasmTest1 is buggy: rc=%#x", rc);
681
682- /*
683- * Test result summary.
684- */
685- if (!cErrors)
686- RTPrintf("tstLdr-4: SUCCESS\n");
687- else
688- RTPrintf("tstLdr-4: FAILURE - %d errors\n", cErrors);
689- return !!cErrors;
690+ return RTTestSummaryAndDestroy(g_hTest);
691 }
692Index: include/iprt/formats/elf-common.h
693===================================================================
694diff --git a/include/iprt/formats/elf-common.h b/include/iprt/formats/elf-common.h
695--- a/include/iprt/formats/elf-common.h (revision 85500)
696+++ b/include/iprt/formats/elf-common.h (revision 85501)
697@@ -198,6 +198,12 @@
698 #define PT_LOPROC 0x70000000 /* First processor-specific type. */
699 #define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
700
701+#define PT_GNU_EH_FRAME 0x6474e550 /**< GNU/Linux -> .eh_frame_hdr */
702+#define PT_GNU_STACK 0x6474e551 /**< GNU/Linux -> stack prot (RWX or RW) */
703+#define PT_GNU_RELRO 0x6474e552 /**< GNU/Linux -> make RO after relocations */
704+#define PT_GNU_PROPERTY 0x6474e553 /**< GNU/Linux -> .note.gnu.property */
705+
706+
707 /* Values for p_flags. */
708 #define PF_X 0x1 /* Executable. */
709 #define PF_W 0x2 /* Writable. */
710Index: src/VBox/Runtime/common/ldr/ldrELF.cpp
711===================================================================
712diff --git a/src/VBox/Runtime/common/ldr/ldrELF.cpp b/src/VBox/Runtime/common/ldr/ldrELF.cpp
713--- a/src/VBox/Runtime/common/ldr/ldrELF.cpp (revision 85500)
714+++ b/src/VBox/Runtime/common/ldr/ldrELF.cpp (revision 85501)
715@@ -51,9 +51,11 @@
716 * Defined Constants And Macros *
717 *********************************************************************************************************************************/
718 /** Finds an ELF symbol table string. */
719-#define ELF_STR(pHdrs, iStr) ((pHdrs)->pStr + (iStr))
720+#define ELF_STR(pHdrs, iStr) ((pHdrs)->Rel.pStr + (iStr))
721+/** Finds an ELF symbol table string. */
722+#define ELF_DYN_STR(pHdrs, iStr) ((pHdrs)->Dyn.pStr + (iStr))
723 /** Finds an ELF section header string. */
724-#define ELF_SH_STR(pHdrs, iStr) ((pHdrs)->pShStr + (iStr))
725+#define ELF_SH_STR(pHdrs, iStr) ((pHdrs)->pShStr + (iStr))
726
727
728
729@@ -62,6 +64,7 @@
730 *********************************************************************************************************************************/
731 #ifdef LOG_ENABLED
732 static const char *rtldrElfGetShdrType(uint32_t iType);
733+static const char *rtldrElfGetPhdrType(uint32_t iType);
734 #endif
735
736
737@@ -81,6 +84,7 @@
738
739
740 #ifdef LOG_ENABLED
741+
742 /**
743 * Gets the section type.
744 *
745@@ -91,25 +95,53 @@
746 {
747 switch (iType)
748 {
749- case SHT_NULL: return "SHT_NULL";
750- case SHT_PROGBITS: return "SHT_PROGBITS";
751- case SHT_SYMTAB: return "SHT_SYMTAB";
752- case SHT_STRTAB: return "SHT_STRTAB";
753- case SHT_RELA: return "SHT_RELA";
754- case SHT_HASH: return "SHT_HASH";
755- case SHT_DYNAMIC: return "SHT_DYNAMIC";
756- case SHT_NOTE: return "SHT_NOTE";
757- case SHT_NOBITS: return "SHT_NOBITS";
758- case SHT_REL: return "SHT_REL";
759- case SHT_SHLIB: return "SHT_SHLIB";
760- case SHT_DYNSYM: return "SHT_DYNSYM";
761+ RT_CASE_RET_STR(SHT_NULL);
762+ RT_CASE_RET_STR(SHT_PROGBITS);
763+ RT_CASE_RET_STR(SHT_SYMTAB);
764+ RT_CASE_RET_STR(SHT_STRTAB);
765+ RT_CASE_RET_STR(SHT_RELA);
766+ RT_CASE_RET_STR(SHT_HASH);
767+ RT_CASE_RET_STR(SHT_DYNAMIC);
768+ RT_CASE_RET_STR(SHT_NOTE);
769+ RT_CASE_RET_STR(SHT_NOBITS);
770+ RT_CASE_RET_STR(SHT_REL);
771+ RT_CASE_RET_STR(SHT_SHLIB);
772+ RT_CASE_RET_STR(SHT_DYNSYM);
773 default:
774 return "";
775 }
776 }
777-#endif
778
779+/**
780+ * Gets the program header type.
781+ *
782+ * @returns Pointer to read only string.
783+ * @param iType The section type index.
784+ */
785+static const char *rtldrElfGetPhdrType(uint32_t iType)
786+{
787+ switch (iType)
788+ {
789+ RT_CASE_RET_STR(PT_NULL);
790+ RT_CASE_RET_STR(PT_LOAD);
791+ RT_CASE_RET_STR(PT_DYNAMIC);
792+ RT_CASE_RET_STR(PT_INTERP);
793+ RT_CASE_RET_STR(PT_NOTE);
794+ RT_CASE_RET_STR(PT_SHLIB);
795+ RT_CASE_RET_STR(PT_PHDR);
796+ RT_CASE_RET_STR(PT_TLS);
797+ RT_CASE_RET_STR(PT_GNU_EH_FRAME);
798+ RT_CASE_RET_STR(PT_GNU_STACK);
799+ RT_CASE_RET_STR(PT_GNU_RELRO);
800+ RT_CASE_RET_STR(PT_GNU_PROPERTY);
801+ default:
802+ return "";
803+ }
804+}
805
806+#endif /* LOG_ENABLED*/
807+
808+
809 /**
810 * Open an ELF image.
811 *
812@@ -124,8 +156,6 @@
813 {
814 const char *pszLogName = pReader->pfnLogName(pReader); NOREF(pszLogName);
815
816- RT_NOREF_PV(pErrInfo); /** @todo implement */
817-
818 /*
819 * Read the ident to decide if this is 32-bit or 64-bit
820 * and worth dealing with.
821@@ -134,6 +164,7 @@
822 int rc = pReader->pfnRead(pReader, &e_ident, sizeof(e_ident), 0);
823 if (RT_FAILURE(rc))
824 return rc;
825+
826 if ( e_ident[EI_MAG0] != ELFMAG0
827 || e_ident[EI_MAG1] != ELFMAG1
828 || e_ident[EI_MAG2] != ELFMAG2
829@@ -141,19 +172,17 @@
830 || ( e_ident[EI_CLASS] != ELFCLASS32
831 && e_ident[EI_CLASS] != ELFCLASS64)
832 )
833- {
834- Log(("RTLdrELF: %s: Unsupported/invalid ident %.*Rhxs\n", pszLogName, sizeof(e_ident), e_ident));
835- return VERR_BAD_EXE_FORMAT;
836- }
837+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
838+ "%s: Unsupported/invalid ident %.*Rhxs", pszLogName, sizeof(e_ident), e_ident);
839+
840 if (e_ident[EI_DATA] != ELFDATA2LSB)
841- {
842- Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, e_ident[EI_DATA]));
843- return VERR_LDRELF_ODD_ENDIAN;
844- }
845+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_ODD_ENDIAN,
846+ "%s: ELF endian %x is unsupported", pszLogName, e_ident[EI_DATA]);
847+
848 if (e_ident[EI_CLASS] == ELFCLASS32)
849- rc = rtldrELF32Open(pReader, fFlags, enmArch, phLdrMod);
850+ rc = rtldrELF32Open(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
851 else
852- rc = rtldrELF64Open(pReader, fFlags, enmArch, phLdrMod);
853+ rc = rtldrELF64Open(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
854 return rc;
855 }
856
857Index: src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
858===================================================================
859diff --git a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
860--- a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85500)
861+++ b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85501)
862@@ -29,31 +29,37 @@
863 * Defined Constants And Macros *
864 *******************************************************************************/
865 #if ELF_MODE == 32
866-#define RTLDRELF_NAME(name) rtldrELF32##name
867-#define RTLDRELF_SUFF(name) name##32
868-#define RTLDRELF_MID(pre,suff) pre##32##suff
869-#define FMT_ELF_ADDR "%08RX32"
870-#define FMT_ELF_HALF "%04RX16"
871-#define FMT_ELF_OFF "%08RX32"
872-#define FMT_ELF_SIZE "%08RX32"
873-#define FMT_ELF_SWORD "%RI32"
874-#define FMT_ELF_WORD "%08RX32"
875-#define FMT_ELF_XWORD "%08RX32"
876-#define FMT_ELF_SXWORD "%RI32"
877+# define RTLDRELF_NAME(name) rtldrELF32##name
878+# define RTLDRELF_SUFF(name) name##32
879+# define RTLDRELF_MID(pre,suff) pre##32##suff
880+# define FMT_ELF_ADDR "%08RX32"
881+# define FMT_ELF_ADDR7 "%07RX32"
882+# define FMT_ELF_HALF "%04RX16"
883+# define FMT_ELF_OFF "%08RX32"
884+# define FMT_ELF_SIZE "%08RX32"
885+# define FMT_ELF_SWORD "%RI32"
886+# define FMT_ELF_WORD "%08RX32"
887+# define FMT_ELF_XWORD "%08RX32"
888+# define FMT_ELF_SXWORD "%RI32"
889+# define Elf_Xword Elf32_Word
890+# define Elf_Sxword Elf32_Sword
891
892 #elif ELF_MODE == 64
893-#define RTLDRELF_NAME(name) rtldrELF64##name
894-#define RTLDRELF_SUFF(name) name##64
895-#define RTLDRELF_MID(pre,suff) pre##64##suff
896-#define FMT_ELF_ADDR "%016RX64"
897-#define FMT_ELF_HALF "%04RX16"
898-#define FMT_ELF_SHALF "%RI16"
899-#define FMT_ELF_OFF "%016RX64"
900-#define FMT_ELF_SIZE "%016RX64"
901-#define FMT_ELF_SWORD "%RI32"
902-#define FMT_ELF_WORD "%08RX32"
903-#define FMT_ELF_XWORD "%016RX64"
904-#define FMT_ELF_SXWORD "%RI64"
905+# define RTLDRELF_NAME(name) rtldrELF64##name
906+# define RTLDRELF_SUFF(name) name##64
907+# define RTLDRELF_MID(pre,suff) pre##64##suff
908+# define FMT_ELF_ADDR "%016RX64"
909+# define FMT_ELF_ADDR7 "%08RX64"
910+# define FMT_ELF_HALF "%04RX16"
911+# define FMT_ELF_SHALF "%RI16"
912+# define FMT_ELF_OFF "%016RX64"
913+# define FMT_ELF_SIZE "%016RX64"
914+# define FMT_ELF_SWORD "%RI32"
915+# define FMT_ELF_WORD "%08RX32"
916+# define FMT_ELF_XWORD "%016RX64"
917+# define FMT_ELF_SXWORD "%RI64"
918+# define Elf_Xword Elf64_Xword
919+# define Elf_Sxword Elf64_Sxword
920 #endif
921
922 #define Elf_Ehdr RTLDRELF_MID(Elf,_Ehdr)
923@@ -74,6 +80,9 @@
924 #define RTLDRMODELF RTLDRELF_MID(RTLDRMODELF,RT_NOTHING)
925 #define PRTLDRMODELF RTLDRELF_MID(PRTLDRMODELF,RT_NOTHING)
926
927+#define RTLDRMODELFSHX RTLDRELF_MID(RTLDRMODELFSHX,RT_NOTHING)
928+#define PRTLDRMODELFSHX RTLDRELF_MID(PRTLDRMODELFSHX,RT_NOTHING)
929+
930 #define ELF_R_SYM(info) RTLDRELF_MID(ELF,_R_SYM)(info)
931 #define ELF_R_TYPE(info) RTLDRELF_MID(ELF,_R_TYPE)(info)
932 #define ELF_R_INFO(sym, type) RTLDRELF_MID(ELF,_R_INFO)(sym, type)
933@@ -86,6 +95,20 @@
934 * Structures and Typedefs *
935 *******************************************************************************/
936 /**
937+ * Extra section info.
938+ */
939+typedef struct RTLDRMODELFSHX
940+{
941+ /** The corresponding program header. */
942+ uint16_t idxPhdr;
943+ /** The corresponding dynamic section entry (address). */
944+ uint16_t idxDt;
945+ /** The DT tag. */
946+ uint32_t uDtTag;
947+} RTLDRMODELFSHX;
948+typedef RTLDRMODELFSHX *PRTLDRMODELFSHX;
949+
950+/**
951 * The ELF loader structure.
952 */
953 typedef struct RTLDRMODELF
954@@ -105,6 +128,11 @@
955 /** Unmodified section headers (allocated after paShdrs, so no need to free).
956 * Not valid if the image is DONE. */
957 Elf_Shdr const *paOrgShdrs;
958+ /** Runs parallel to paShdrs and is part of the same allocation. */
959+ PRTLDRMODELFSHX paShdrExtras;
960+ /** Base section number, either 1 or zero depending on whether we've
961+ * re-used the NULL entry for .elf.headers in ET_EXEC/ET_DYN. */
962+ unsigned iFirstSect;
963 /** The size of the loaded image. */
964 size_t cbImage;
965
966@@ -111,32 +139,71 @@
967 /** The image base address if it's an EXEC or DYN image. */
968 Elf_Addr LinkAddress;
969
970- /** The symbol section index. */
971- unsigned iSymSh;
972- /** Number of symbols in the table. */
973- unsigned cSyms;
974- /** Pointer to symbol table within RTLDRMODELF::pvBits. */
975- const Elf_Sym *paSyms;
976+ struct
977+ {
978+ /** The symbol section index. */
979+ unsigned iSymSh;
980+ /** Number of symbols in the table. */
981+ unsigned cSyms;
982+ /** Pointer to symbol table within RTLDRMODELF::pvBits. */
983+ const Elf_Sym *paSyms;
984
985- /** The string section index. */
986- unsigned iStrSh;
987- /** Size of the string table. */
988- unsigned cbStr;
989- /** Pointer to string table within RTLDRMODELF::pvBits. */
990- const char *pStr;
991+ /** The string section index. */
992+ unsigned iStrSh;
993+ /** Size of the string table. */
994+ unsigned cbStr;
995+ /** Pointer to string table within RTLDRMODELF::pvBits. */
996+ const char *pStr;
997+ } Rel /**< Regular symbols and strings. */
998+ , Dyn /**< Dynamic symbols and strings. */;
999
1000+ /** Pointer to section header string table within RTLDRMODELF::pvBits. */
1001+ const char *pShStr;
1002 /** Size of the section header string table. */
1003 unsigned cbShStr;
1004- /** Pointer to section header string table within RTLDRMODELF::pvBits. */
1005- const char *pShStr;
1006
1007 /** The '.eh_frame' section index. Zero if not searched for, ~0U if not found. */
1008 unsigned iShEhFrame;
1009 /** The '.eh_frame_hdr' section index. Zero if not searched for, ~0U if not found. */
1010 unsigned iShEhFrameHdr;
1011-} RTLDRMODELF, *PRTLDRMODELF;
1012
1013+ /** The '.dynamic' / SHT_DYNAMIC section index. ~0U if not present. */
1014+ unsigned iShDynamic;
1015+ /** Number of entries in paDynamic. */
1016+ unsigned cDynamic;
1017+ /** The dynamic section (NULL for ET_REL). */
1018+ Elf_Dyn *paDynamic;
1019+ /** Program headers (NULL for ET_REL). */
1020+ Elf_Phdr *paPhdrs;
1021
1022+ /** Info extracted from PT_DYNAMIC and the program headers. */
1023+ struct
1024+ {
1025+ /** DT_RELA/DT_REL. */
1026+ Elf_Addr uPtrRelocs;
1027+ /** DT_RELASZ/DT_RELSZ. */
1028+ Elf_Xword cbRelocs;
1029+ /** Non-zero if we've seen DT_RELAENT/DT_RELENT. */
1030+ unsigned cbRelocEntry;
1031+ /** DT_RELA or DT_REL. */
1032+ unsigned uRelocType;
1033+ /** The index of the section header matching DT_RELA/DT_REL. */
1034+ unsigned idxShRelocs;
1035+
1036+ /** DT_JMPREL. */
1037+ Elf_Addr uPtrJmpRelocs;
1038+ /** DT_PLTRELSZ. */
1039+ Elf_Xword cbJmpRelocs;
1040+ /** DT_RELA or DT_REL (if we've seen DT_PLTREL). */
1041+ unsigned uJmpRelocType;
1042+ /** The index of the section header matching DT_JMPREL. */
1043+ unsigned idxShJmpRelocs;
1044+ } DynInfo;
1045+} RTLDRMODELF;
1046+/** Pointer to an ELF module instance. */
1047+typedef RTLDRMODELF *PRTLDRMODELF;
1048+
1049+
1050 /**
1051 * Maps the image bits into memory and resolve pointers into it.
1052 *
1053@@ -154,11 +221,15 @@
1054 if (RT_SUCCESS(rc))
1055 {
1056 const uint8_t *pu8 = (const uint8_t *)pModElf->pvBits;
1057- if (pModElf->iSymSh != ~0U)
1058- pModElf->paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->iSymSh].sh_offset);
1059- if (pModElf->iStrSh != ~0U)
1060- pModElf->pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->iStrSh].sh_offset);
1061- pModElf->pShStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset);
1062+ if (pModElf->Rel.iSymSh != ~0U)
1063+ pModElf->Rel.paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->Rel.iSymSh].sh_offset);
1064+ if (pModElf->Rel.iStrSh != ~0U)
1065+ pModElf->Rel.pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Rel.iStrSh].sh_offset);
1066+ if (pModElf->Dyn.iSymSh != ~0U)
1067+ pModElf->Dyn.paSyms = (const Elf_Sym *)(pu8 + pModElf->paShdrs[pModElf->Dyn.iSymSh].sh_offset);
1068+ if (pModElf->Dyn.iStrSh != ~0U)
1069+ pModElf->Dyn.pStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Dyn.iStrSh].sh_offset);
1070+ pModElf->pShStr = (const char *)(pu8 + pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_offset);
1071
1072 /*
1073 * Verify that the ends of the string tables have a zero terminator
1074@@ -167,10 +238,14 @@
1075 * sh_offset and sh_size were verfied in RTLDRELF_NAME(ValidateSectionHeader)() already so they
1076 * are safe to use.
1077 */
1078- AssertMsgStmt( pModElf->iStrSh == ~0U
1079- || pModElf->pStr[pModElf->paShdrs[pModElf->iStrSh].sh_size - 1] == '\0',
1080+ AssertMsgStmt( pModElf->Rel.iStrSh == ~0U
1081+ || pModElf->Rel.pStr[pModElf->paShdrs[pModElf->Rel.iStrSh].sh_size - 1] == '\0',
1082 ("The string table is not zero terminated!\n"),
1083 rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
1084+ AssertMsgStmt( pModElf->Dyn.iStrSh == ~0U
1085+ || pModElf->Dyn.pStr[pModElf->paShdrs[pModElf->Dyn.iStrSh].sh_size - 1] == '\0',
1086+ ("The string table is not zero terminated!\n"),
1087+ rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
1088 AssertMsgStmt(pModElf->pShStr[pModElf->paShdrs[pModElf->Ehdr.e_shstrndx].sh_size - 1] == '\0',
1089 ("The section header string table is not zero terminated!\n"),
1090 rc = VERR_LDRELF_UNTERMINATED_STRING_TAB);
1091@@ -180,10 +255,12 @@
1092 /* Unmap. */
1093 int rc2 = pModElf->Core.pReader->pfnUnmap(pModElf->Core.pReader, pModElf->pvBits);
1094 AssertRC(rc2);
1095- pModElf->pvBits = NULL;
1096- pModElf->paSyms = NULL;
1097- pModElf->pStr = NULL;
1098- pModElf->pShStr = NULL;
1099+ pModElf->pvBits = NULL;
1100+ pModElf->Rel.paSyms = NULL;
1101+ pModElf->Rel.pStr = NULL;
1102+ pModElf->Dyn.paSyms = NULL;
1103+ pModElf->Dyn.pStr = NULL;
1104+ pModElf->pShStr = NULL;
1105 }
1106 }
1107 return rc;
1108@@ -200,7 +277,102 @@
1109 *
1110 */
1111
1112+/**
1113+ * Get the symbol and symbol value.
1114+ *
1115+ * @returns iprt status code.
1116+ * @param pModElf The ELF loader module instance data.
1117+ * @param BaseAddr The base address which the module is being fixedup to.
1118+ * @param pfnGetImport The callback function to use to resolve imports (aka unresolved externals).
1119+ * @param pvUser User argument to pass to the callback.
1120+ * @param iSym The symbol to get.
1121+ * @param ppSym Where to store the symbol pointer on success. (read only)
1122+ * @param pSymValue Where to store the symbol value on success.
1123+ */
1124+static int RTLDRELF_NAME(SymbolExecDyn)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
1125+ Elf_Size iSym, const Elf_Sym **ppSym, Elf_Addr *pSymValue)
1126+{
1127+ /*
1128+ * Validate and find the symbol.
1129+ */
1130+ AssertMsgReturn(iSym < pModElf->Dyn.cSyms, ("iSym=%d is an invalid symbol index!\n", iSym), VERR_LDRELF_INVALID_SYMBOL_INDEX);
1131+ const Elf_Sym *pSym = &pModElf->Dyn.paSyms[iSym];
1132+ *ppSym = pSym;
1133
1134+ AssertMsgReturn(pSym->st_name < pModElf->Dyn.cbStr,
1135+ ("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->Dyn.cbStr),
1136+ VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
1137+ const char * const pszName = pModElf->Dyn.pStr + pSym->st_name;
1138+
1139+ /*
1140+ * Determine the symbol value.
1141+ *
1142+ * Symbols needs different treatment depending on which section their are in.
1143+ * Undefined and absolute symbols goes into special non-existing sections.
1144+ */
1145+ switch (pSym->st_shndx)
1146+ {
1147+ /*
1148+ * Undefined symbol, needs resolving.
1149+ *
1150+ * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
1151+ * has but that's an OS extension and only applies to programs and dlls), we'll have to ask
1152+ * the resolver callback to do a global search.
1153+ */
1154+ case SHN_UNDEF:
1155+ {
1156+ /* Try to resolve the symbol. */
1157+ RTUINTPTR Value;
1158+ int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &Value, pvUser);
1159+ AssertMsgRCReturn(rc, ("Failed to resolve '%s' (iSym=" FMT_ELF_SIZE " rc=%Rrc\n", pszName, iSym, rc), rc);
1160+
1161+ *pSymValue = (Elf_Addr)Value;
1162+ AssertMsgReturn((RTUINTPTR)*pSymValue == Value,
1163+ ("Symbol value overflowed! '%s' (iSym=" FMT_ELF_SIZE "\n", pszName, iSym), VERR_SYMBOL_VALUE_TOO_BIG);
1164+
1165+ Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
1166+ break;
1167+ }
1168+
1169+ /*
1170+ * Absolute symbols needs no fixing since they are, well, absolute.
1171+ */
1172+ case SHN_ABS:
1173+ *pSymValue = pSym->st_value;
1174+ Log2(("rtldrELF: #%-3d - ABS " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
1175+ break;
1176+
1177+ /*
1178+ * All other symbols are addressed relative the image base in DYN and EXEC binaries.
1179+ */
1180+ default:
1181+ AssertMsgReturn(pSym->st_shndx < pModElf->Ehdr.e_shnum,
1182+ ("iSym=%d st_shndx=%d e_shnum=%d pszName=%s\n", iSym, pSym->st_shndx, pModElf->Ehdr.e_shnum, pszName),
1183+ VERR_BAD_EXE_FORMAT);
1184+ *pSymValue = pSym->st_value + BaseAddr;
1185+ Log2(("rtldrELF: #%-3d - %5d " FMT_ELF_ADDR " '%s'\n", iSym, pSym->st_shndx, *pSymValue, pszName));
1186+ break;
1187+ }
1188+
1189+ return VINF_SUCCESS;
1190+}
1191+
1192+
1193+#if ELF_MODE == 32
1194+/** Helper for RelocateSectionExecDyn. */
1195+DECLINLINE(const Elf_Shdr *) RTLDRELF_NAME(RvaToSectionHeader)(PRTLDRMODELF pModElf, Elf_Addr uRva)
1196+{
1197+ const Elf_Shdr * const pShdrFirst = pModElf->paShdrs;
1198+ const Elf_Shdr *pShdr = pShdrFirst + pModElf->Ehdr.e_shnum;
1199+ while (--pShdr != pShdrFirst)
1200+ if (uRva - pShdr->sh_addr /*rva*/ < pShdr->sh_size)
1201+ return pShdr;
1202+ AssertFailed();
1203+ return pShdr;
1204+}
1205+#endif
1206+
1207+
1208 /**
1209 * Applies the fixups for a section in an executable image.
1210 *
1211@@ -230,84 +402,106 @@
1212 * Iterate the relocations.
1213 * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
1214 */
1215+#if ELF_MODE == 32
1216+ const Elf_Shdr *pShdr = pModElf->paShdrs;
1217 const Elf_Addr offDelta = BaseAddr - pModElf->LinkAddress;
1218+#endif
1219 const Elf_Reloc *paRels = (const Elf_Reloc *)pvRelocs;
1220- const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
1221+ const unsigned iRelMax = (unsigned)(cbRelocs / sizeof(paRels[0]));
1222 AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])),
1223 VERR_IMAGE_TOO_BIG);
1224 for (unsigned iRel = 0; iRel < iRelMax; iRel++)
1225 {
1226 /*
1227- * Skip R_XXX_NONE entries early to avoid confusion in the symbol
1228- * getter code.
1229+ * Apply fixups not taking a symbol (will 'continue' rather than 'break').
1230 */
1231+ AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec),
1232+ VERR_LDRELF_INVALID_RELOCATION_OFFSET);
1233 #if ELF_MODE == 32
1234- if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
1235- continue;
1236+ if (paRels[iRel].r_offset - pShdr->sh_addr /*rva*/ >= pShdr->sh_size)
1237+ pShdr = RTLDRELF_NAME(RvaToSectionHeader)(pModElf, paRels[iRel].r_offset);
1238+ static const Elf_Addr s_uZero = 0;
1239+ const Elf_Addr *pAddrR = RT_LIKELY(pShdr->sh_type != SHT_NOBITS) /* Where to read the addend. */
1240+ ? (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset - pShdr->sh_addr /*rva*/
1241+ + pShdr->sh_offset)
1242+ : &s_uZero;
1243+#endif
1244+ Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
1245+ switch (ELF_R_TYPE(paRels[iRel].r_info))
1246+ {
1247+ /*
1248+ * Image relative (addend + base).
1249+ */
1250+#if ELF_MODE == 32
1251+ case R_386_RELATIVE:
1252+ {
1253+ const Elf_Addr Value = *pAddrR + BaseAddr;
1254+ *(uint32_t *)pAddrW = Value;
1255+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_RELATIVE Value=" FMT_ELF_ADDR "\n",
1256+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
1257+ AssertCompile(sizeof(Value) == sizeof(uint32_t));
1258+ continue;
1259+ }
1260 #elif ELF_MODE == 64
1261- if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
1262- continue;
1263+ case R_X86_64_RELATIVE:
1264+ {
1265+ const Elf_Addr Value = paRels[iRel].r_addend + BaseAddr;
1266+ *(uint64_t *)pAddrW = (uint64_t)Value;
1267+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_RELATIVE Value=" FMT_ELF_ADDR "\n",
1268+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
1269+ AssertCompile(sizeof(Value) == sizeof(uint64_t));
1270+ continue;
1271+ }
1272 #endif
1273
1274+ /*
1275+ * R_XXX_NONE.
1276+ */
1277+#if ELF_MODE == 32
1278+ case R_386_NONE:
1279+#elif ELF_MODE == 64
1280+ case R_X86_64_NONE:
1281+#endif
1282+ continue;
1283+ }
1284+
1285 /*
1286 * Validate and find the symbol, resolve undefined ones.
1287 */
1288- Elf_Size iSym = ELF_R_SYM(paRels[iRel].r_info);
1289- if (iSym >= pModElf->cSyms)
1290- {
1291- AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
1292- return VERR_LDRELF_INVALID_SYMBOL_INDEX;
1293- }
1294- const Elf_Sym *pSym = &pModElf->paSyms[iSym];
1295- if (pSym->st_name >= pModElf->cbStr)
1296- {
1297- AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
1298- return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
1299- }
1300+ const Elf_Sym *pSym = NULL; /* shut up gcc */
1301+ Elf_Addr SymValue = 0; /* shut up gcc-4 */
1302+ int rc = RTLDRELF_NAME(SymbolExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser, ELF_R_SYM(paRels[iRel].r_info), &pSym, &SymValue);
1303+ if (RT_FAILURE(rc))
1304+ return rc;
1305
1306- Elf_Addr SymValue = 0;
1307- if (pSym->st_shndx == SHN_UNDEF)
1308- {
1309- /* Try to resolve the symbol. */
1310- const char *pszName = ELF_STR(pModElf, pSym->st_name);
1311- RTUINTPTR ExtValue;
1312- int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &ExtValue, pvUser);
1313- AssertMsgRCReturn(rc, ("Failed to resolve '%s' rc=%Rrc\n", pszName, rc), rc);
1314- SymValue = (Elf_Addr)ExtValue;
1315- AssertMsgReturn((RTUINTPTR)SymValue == ExtValue, ("Symbol value overflowed! '%s'\n", pszName),
1316- VERR_SYMBOL_VALUE_TOO_BIG);
1317- Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, SymValue, pszName));
1318- }
1319- else
1320- {
1321- AssertMsgReturn(pSym->st_shndx < pModElf->Ehdr.e_shnum || pSym->st_shndx == SHN_ABS, ("%#x\n", pSym->st_shndx),
1322- VERR_LDRELF_INVALID_RELOCATION_OFFSET);
1323-#if ELF_MODE == 64
1324- SymValue = pSym->st_value;
1325-#endif
1326- }
1327-
1328-#if ELF_MODE == 64
1329- /* Calc the value (indexes checked above; assumes SHN_UNDEF == 0). */
1330- Elf_Addr Value;
1331- if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
1332- Value = SymValue + offDelta;
1333- else /* SHN_ABS: */
1334- Value = SymValue + paRels[iRel].r_addend;
1335-#endif
1336-
1337 /*
1338 * Apply the fixup.
1339 */
1340- AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
1341-#if ELF_MODE == 32
1342- const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset); /* Where to read the addend. */
1343-#endif
1344- Elf_Addr *pAddrW = (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset); /* Where to write the fixup. */
1345 switch (ELF_R_TYPE(paRels[iRel].r_info))
1346 {
1347 #if ELF_MODE == 32
1348 /*
1349+ * GOT/PLT.
1350+ */
1351+ case R_386_GLOB_DAT:
1352+ {
1353+ *(uint32_t *)pAddrW = (uint32_t)SymValue;
1354+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_GLOB_DAT Value=" FMT_ELF_ADDR "\n",
1355+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
1356+ AssertCompile(sizeof(SymValue) == sizeof(uint32_t));
1357+ break;
1358+ }
1359+
1360+ case R_386_JMP_SLOT:
1361+ {
1362+ *(uint32_t *)pAddrW = (uint32_t)SymValue;
1363+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_JMP_SLOT Value=" FMT_ELF_ADDR "\n",
1364+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
1365+ AssertCompile(sizeof(SymValue) == sizeof(uint32_t));
1366+ break;
1367+ }
1368+
1369+ /*
1370 * Absolute addressing.
1371 */
1372 case R_386_32:
1373@@ -322,7 +516,8 @@
1374 else
1375 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
1376 *(uint32_t *)pAddrW = Value;
1377- Log4((FMT_ELF_ADDR": R_386_32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
1378+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_32 Value=" FMT_ELF_ADDR "\n",
1379+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
1380 break;
1381 }
1382
1383@@ -344,20 +539,42 @@
1384 }
1385 else
1386 AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
1387- Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
1388+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_386_PC32 Value=" FMT_ELF_ADDR "\n",
1389+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value));
1390 break;
1391 }
1392
1393 #elif ELF_MODE == 64
1394+ /*
1395+ * GOT/PLT.
1396+ */
1397+ case R_X86_64_GLOB_DAT:
1398+ {
1399+ *(uint64_t *)pAddrW = (uint64_t)SymValue;
1400+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_GLOB_DAT Value=" FMT_ELF_ADDR "\n",
1401+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
1402+ AssertCompile(sizeof(SymValue) == sizeof(uint64_t));
1403+ break;
1404+ }
1405
1406+ case R_X86_64_JMP_SLOT:
1407+ {
1408+ *(uint64_t *)pAddrW = (uint64_t)SymValue;
1409+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_JMP_SLOT Value=" FMT_ELF_ADDR "\n",
1410+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, SymValue));
1411+ AssertCompile(sizeof(SymValue) == sizeof(uint64_t));
1412+ break;
1413+ }
1414+
1415 /*
1416- * Absolute addressing
1417+ * Absolute addressing.
1418 */
1419 case R_X86_64_64:
1420 {
1421+ const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
1422 *(uint64_t *)pAddrW = Value;
1423- Log4((FMT_ELF_ADDR": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1424- SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
1425+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_64 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1426+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
1427 break;
1428 }
1429
1430@@ -366,9 +583,10 @@
1431 */
1432 case R_X86_64_32:
1433 {
1434+ const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
1435 *(uint32_t *)pAddrW = (uint32_t)Value;
1436- Log4((FMT_ELF_ADDR": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1437- SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
1438+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1439+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
1440 AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == SymValue, ("Value=" FMT_ELF_ADDR "\n", SymValue),
1441 VERR_SYMBOL_VALUE_TOO_BIG);
1442 break;
1443@@ -379,9 +597,10 @@
1444 */
1445 case R_X86_64_32S:
1446 {
1447+ const Elf_Addr Value = SymValue + paRels[iRel].r_addend;
1448 *(int32_t *)pAddrW = (int32_t)Value;
1449- Log4((FMT_ELF_ADDR": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1450- SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
1451+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_32S Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1452+ SecAddr + paRels[iRel].r_offset + BaseAddr, paRels[iRel].r_offset, Value, SymValue));
1453 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
1454 break;
1455 }
1456@@ -390,18 +609,17 @@
1457 * PC relative addressing.
1458 */
1459 case R_X86_64_PC32:
1460- case R_X86_64_PLT32: /* binutils commit 451875b4f976a527395e9303224c7881b65e12ed feature/regression. */
1461 {
1462- const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
1463- Value -= SourceAddr;
1464+ const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
1465+ const Elf_Addr Value = SymValue + paRels[iRel].r_addend - SourceAddr;
1466 *(int32_t *)pAddrW = (int32_t)Value;
1467- Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1468- SourceAddr, Value, SymValue));
1469+ Log4((FMT_ELF_ADDR "/" FMT_ELF_ADDR7 ": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
1470+ SourceAddr, paRels[iRel].r_offset, Value, SymValue));
1471 AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
1472 break;
1473 }
1474+
1475 #endif
1476-
1477 default:
1478 AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
1479 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
1480@@ -442,19 +660,13 @@
1481 /*
1482 * Validate and find the symbol.
1483 */
1484- if (iSym >= pModElf->cSyms)
1485- {
1486- AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
1487- return VERR_LDRELF_INVALID_SYMBOL_INDEX;
1488- }
1489- const Elf_Sym *pSym = &pModElf->paSyms[iSym];
1490+ AssertMsgReturn(iSym < pModElf->Rel.cSyms, ("iSym=%d is an invalid symbol index!\n", iSym), VERR_LDRELF_INVALID_SYMBOL_INDEX);
1491+ const Elf_Sym *pSym = &pModElf->Rel.paSyms[iSym];
1492 *ppSym = pSym;
1493
1494- if (pSym->st_name >= pModElf->cbStr)
1495- {
1496- AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
1497- return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
1498- }
1499+ AssertMsgReturn(pSym->st_name < pModElf->Rel.cbStr,
1500+ ("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->Rel.cbStr),
1501+ VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
1502 const char *pszName = ELF_STR(pModElf, pSym->st_name);
1503
1504 /*
1505@@ -469,7 +681,7 @@
1506 * Undefined symbol, needs resolving.
1507 *
1508 * Since ELF has no generic concept of importing from specific module (the OS/2 ELF format
1509- * has but that's a OS extension and only applies to programs and dlls), we'll have to ask
1510+ * has but that's an OS extension and only applies to programs and dlls), we'll have to ask
1511 * the resolver callback to do a global search.
1512 */
1513 case SHN_UNDEF:
1514@@ -477,18 +689,13 @@
1515 /* Try to resolve the symbol. */
1516 RTUINTPTR Value;
1517 int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0U, &Value, pvUser);
1518- if (RT_FAILURE(rc))
1519- {
1520- AssertMsgFailed(("Failed to resolve '%s' rc=%Rrc\n", pszName, rc));
1521- return rc;
1522- }
1523+ AssertMsgRCReturn(rc, ("Failed to resolve '%s' (iSym=" FMT_ELF_SIZE " rc=%Rrc\n", pszName, iSym, rc), rc);
1524 *pSymValue = (Elf_Addr)Value;
1525- if ((RTUINTPTR)*pSymValue != Value)
1526- {
1527- AssertMsgFailed(("Symbol value overflowed! '%s'\n", pszName));
1528- return VERR_SYMBOL_VALUE_TOO_BIG;
1529- }
1530
1531+ AssertMsgReturn((RTUINTPTR)*pSymValue == Value,
1532+ ("Symbol value overflowed! '%s' (iSym=" FMT_ELF_SIZE ")\n", pszName, iSym),
1533+ VERR_SYMBOL_VALUE_TOO_BIG);
1534+
1535 Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, *pSymValue, pszName));
1536 break;
1537 }
1538@@ -536,9 +743,9 @@
1539 * @param pvRelocs Pointer to where we read the relocations from.
1540 * @param cbRelocs Size of the relocations.
1541 */
1542-static int RTLDRELF_NAME(RelocateSection)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
1543- const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
1544- const void *pvRelocs, Elf_Size cbRelocs)
1545+static int RTLDRELF_NAME(RelocateSectionRel)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr, PFNRTLDRIMPORT pfnGetImport, void *pvUser,
1546+ const Elf_Addr SecAddr, Elf_Size cbSec, const uint8_t *pu8SecBaseR,
1547+ uint8_t *pu8SecBaseW, const void *pvRelocs, Elf_Size cbRelocs)
1548 {
1549 #if ELF_MODE != 32
1550 NOREF(pu8SecBaseR);
1551@@ -702,6 +909,18 @@
1552 pModElf->paShdrs = NULL;
1553 }
1554
1555+ if (pModElf->paPhdrs)
1556+ {
1557+ RTMemFree(pModElf->paPhdrs);
1558+ pModElf->paPhdrs = NULL;
1559+ }
1560+
1561+ if (pModElf->paDynamic)
1562+ {
1563+ RTMemFree(pModElf->paDynamic);
1564+ pModElf->paDynamic = NULL;
1565+ }
1566+
1567 if (pModElf->pvBits)
1568 {
1569 pModElf->Core.pReader->pfnUnmap(pModElf->Core.pReader, pModElf->pvBits);
1570@@ -721,9 +940,9 @@
1571 }
1572
1573
1574-/** @copydoc RTLDROPS::EnumSymbols */
1575-static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
1576- PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
1577+/** @copydoc RTLDROPS::pfnEnumSymbols */
1578+static DECLCALLBACK(int) RTLDRELF_NAME(EnumSymbols)(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits,
1579+ RTUINTPTR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
1580 {
1581 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1582 NOREF(pvBits);
1583@@ -744,8 +963,20 @@
1584 /*
1585 * Enumerate the symbol table.
1586 */
1587- const Elf_Sym *paSyms = pModElf->paSyms;
1588- unsigned cSyms = pModElf->cSyms;
1589+ const Elf_Sym *paSyms = pModElf->Rel.paSyms;
1590+ unsigned cSyms = pModElf->Rel.cSyms;
1591+ const char *pszzStr = pModElf->Rel.pStr;
1592+ unsigned cbStr = pModElf->Rel.cbStr;
1593+ if ( ( !(fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
1594+ && pModElf->Dyn.cSyms > 0)
1595+ || cSyms == 0)
1596+ {
1597+ paSyms = pModElf->Dyn.paSyms;
1598+ cSyms = pModElf->Dyn.cSyms;
1599+ pszzStr = pModElf->Dyn.pStr;
1600+ cbStr = pModElf->Dyn.cbStr;
1601+ }
1602+
1603 for (unsigned iSym = 1; iSym < cSyms; iSym++)
1604 {
1605 /*
1606@@ -774,22 +1005,21 @@
1607 return VERR_BAD_EXE_FORMAT;
1608 }
1609
1610- AssertMsgReturn(paSyms[iSym].st_name < pModElf->cbStr,
1611+ AssertMsgReturn(paSyms[iSym].st_name < cbStr,
1612 ("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name),
1613 VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
1614+ const char * const pszName = pszzStr + paSyms[iSym].st_name;
1615
1616- const char *pszName = ELF_STR(pModElf, paSyms[iSym].st_name);
1617 /* String termination was already checked when the string table was mapped. */
1618- if ( (pszName && *pszName)
1619+ if ( *pszName != '\0'
1620 && ( (fFlags & RTLDR_ENUM_SYMBOL_FLAGS_ALL)
1621- || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL)
1622- )
1623+ || ELF_ST_BIND(paSyms[iSym].st_info) == STB_GLOBAL) )
1624 {
1625 /*
1626 * Call back.
1627 */
1628 AssertMsgReturn(Value == (RTUINTPTR)Value, (FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG);
1629- rc = pfnCallback(pMod, pszName, ~0U, (RTUINTPTR)Value, pvUser);
1630+ rc = pfnCallback(pMod, pszName, iSym, (RTUINTPTR)Value, pvUser);
1631 if (rc)
1632 return rc;
1633 }
1634@@ -820,13 +1050,11 @@
1635 switch (pModElf->Ehdr.e_type)
1636 {
1637 case ET_REL:
1638+ case ET_DYN:
1639 break;
1640 case ET_EXEC:
1641 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader)));
1642 return VERR_LDRELF_EXEC;
1643- case ET_DYN:
1644- Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pModElf->Core.pReader->pfnLogName(pModElf->Core.pReader)));
1645- return VERR_LDRELF_DYN;
1646 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
1647 }
1648
1649@@ -885,13 +1113,11 @@
1650 switch (pModElf->Ehdr.e_type)
1651 {
1652 case ET_REL:
1653+ case ET_DYN:
1654 break;
1655 case ET_EXEC:
1656 Log(("RTLdrELF: %s: Executable images are not supported yet!\n", pszLogName));
1657 return VERR_LDRELF_EXEC;
1658- case ET_DYN:
1659- Log(("RTLdrELF: %s: Dynamic images are not supported yet!\n", pszLogName));
1660- return VERR_LDRELF_DYN;
1661 default: AssertFailedReturn(VERR_BAD_EXE_FORMAT);
1662 }
1663
1664@@ -910,8 +1136,9 @@
1665
1666 /*
1667 * Iterate the sections looking for interesting SHT_REL[A] sections.
1668- * SHT_REL[A] sections have the section index of the section they contain fixups
1669- * for in the sh_info member.
1670+ *
1671+ * In ET_REL files the SHT_REL[A] sections have the section index of
1672+ * the section they contain fixups for in the sh_info member.
1673 */
1674 const Elf_Shdr *paShdrs = pModElf->paShdrs;
1675 Log2(("rtLdrElf: %s: Fixing up image\n", pszLogName));
1676@@ -928,36 +1155,37 @@
1677 if (pShdrRel->sh_type != SHT_RELA)
1678 #endif
1679 continue;
1680- if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
1681- continue;
1682- const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
1683- if (!(pShdr->sh_flags & SHF_ALLOC))
1684- continue;
1685+ if (pModElf->Ehdr.e_type == ET_REL)
1686+ {
1687+ if (pShdrRel->sh_info >= pModElf->Ehdr.e_shnum)
1688+ continue;
1689+ const Elf_Shdr *pShdr = &paShdrs[pShdrRel->sh_info]; /* the section to fixup. */
1690+ if (!(pShdr->sh_flags & SHF_ALLOC))
1691+ continue;
1692
1693- /*
1694- * Relocate the section.
1695- */
1696- Log2(("rtldrELF: %s: Relocation records for #%d [%s] (sh_info=%d sh_link=%d) found in #%d [%s] (sh_info=%d sh_link=%d)\n",
1697- pszLogName, (int)pShdrRel->sh_info, ELF_SH_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
1698- iShdr, ELF_SH_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
1699+ /*
1700+ * Relocate the section.
1701+ */
1702+ Log2(("rtldrELF: %s: Relocation records for #%d [%s] (sh_info=%d sh_link=%d) found in #%d [%s] (sh_info=%d sh_link=%d)\n",
1703+ pszLogName, (int)pShdrRel->sh_info, ELF_SH_STR(pModElf, pShdr->sh_name), (int)pShdr->sh_info, (int)pShdr->sh_link,
1704+ iShdr, ELF_SH_STR(pModElf, pShdrRel->sh_name), (int)pShdrRel->sh_info, (int)pShdrRel->sh_link));
1705
1706- /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */
1707- if (pModElf->Ehdr.e_type == ET_REL)
1708- rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
1709- pShdr->sh_addr,
1710- pShdr->sh_size,
1711- (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
1712- (uint8_t *)pvBits + pShdr->sh_addr,
1713- (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
1714- pShdrRel->sh_size);
1715+ rc = RTLDRELF_NAME(RelocateSectionRel)(pModElf, BaseAddr, pfnGetImport, pvUser,
1716+ pShdr->sh_addr,
1717+ pShdr->sh_size,
1718+ (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
1719+ (uint8_t *)pvBits + pShdr->sh_addr,
1720+ (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
1721+ pShdrRel->sh_size);
1722+ }
1723 else
1724 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser,
1725- pShdr->sh_addr,
1726- pShdr->sh_size,
1727- (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
1728- (uint8_t *)pvBits + pShdr->sh_addr,
1729+ 0, pModElf->cbImage,
1730+ (const uint8_t *)pModElf->pvBits /** @todo file offset ?? */,
1731+ (uint8_t *)pvBits,
1732 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
1733 pShdrRel->sh_size);
1734+
1735 if (RT_FAILURE(rc))
1736 return rc;
1737 }
1738@@ -1016,11 +1244,20 @@
1739 /*
1740 * Calc all kinds of pointers before we start iterating the symbol table.
1741 */
1742- const Elf_Sym *paSyms = pModElf->paSyms;
1743- unsigned cSyms = pModElf->cSyms;
1744+ const Elf_Sym *paSyms = pModElf->Rel.paSyms;
1745+ unsigned cSyms = pModElf->Rel.cSyms;
1746+ const char *pszzStr = pModElf->Rel.pStr;
1747+ unsigned cbStr = pModElf->Rel.cbStr;
1748+ if (pModElf->Dyn.cSyms > 0)
1749+ {
1750+ paSyms = pModElf->Dyn.paSyms;
1751+ cSyms = pModElf->Dyn.cSyms;
1752+ pszzStr = pModElf->Dyn.pStr;
1753+ cbStr = pModElf->Dyn.cbStr;
1754+ }
1755+
1756 if (iOrdinal == UINT32_MAX)
1757 {
1758- const char *pStr = pModElf->pStr;
1759 for (unsigned iSym = 1; iSym < cSyms; iSym++)
1760 {
1761 /* Undefined symbols are not exports, they are imports. */
1762@@ -1029,19 +1266,14 @@
1763 || ELF_ST_BIND(paSyms[iSym].st_info) == STB_WEAK))
1764 {
1765 /* Validate the name string and try match with it. */
1766- if (paSyms[iSym].st_name < pModElf->cbStr)
1767+ AssertMsgReturn(paSyms[iSym].st_name < cbStr,
1768+ ("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name),
1769+ VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET);
1770+ if (!strcmp(pszSymbol, pszzStr + paSyms[iSym].st_name))
1771 {
1772- if (!strcmp(pszSymbol, pStr + paSyms[iSym].st_name))
1773- {
1774- /* matched! */
1775- return RTLDRELF_NAME(ReturnSymbol)(pModElf, &paSyms[iSym], uBaseAddr, pValue);
1776- }
1777+ /* matched! */
1778+ return RTLDRELF_NAME(ReturnSymbol)(pModElf, &paSyms[iSym], uBaseAddr, pValue);
1779 }
1780- else
1781- {
1782- AssertMsgFailed(("String outside string table! iSym=%d paSyms[iSym].st_name=%#x\n", iSym, paSyms[iSym].st_name));
1783- return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
1784- }
1785 }
1786 }
1787 }
1788@@ -1163,16 +1395,24 @@
1789 Elf_Addr uPrevMappedRva = 0;
1790 const Elf_Shdr *paShdrs = pModElf->paShdrs;
1791 const Elf_Shdr *paOrgShdrs = pModElf->paOrgShdrs;
1792- for (unsigned iShdr = 1; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
1793+ for (unsigned iShdr = pModElf->iFirstSect; iShdr < pModElf->Ehdr.e_shnum; iShdr++)
1794 {
1795 RTLDRSEG Seg;
1796- Seg.pszName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
1797- Seg.cchName = (uint32_t)strlen(Seg.pszName);
1798- if (Seg.cchName == 0)
1799+ if (iShdr != 0)
1800 {
1801- Seg.pszName = szName;
1802- Seg.cchName = (uint32_t)RTStrPrintf(szName, sizeof(szName), "UnamedSect%02u", iShdr);
1803+ Seg.pszName = ELF_SH_STR(pModElf, paShdrs[iShdr].sh_name);
1804+ Seg.cchName = (uint32_t)strlen(Seg.pszName);
1805+ if (Seg.cchName == 0)
1806+ {
1807+ Seg.pszName = szName;
1808+ Seg.cchName = (uint32_t)RTStrPrintf(szName, sizeof(szName), "UnamedSect%02u", iShdr);
1809+ }
1810 }
1811+ else
1812+ {
1813+ Seg.pszName = ".elf.headers";
1814+ Seg.cchName = 12;
1815+ }
1816 Seg.SelFlat = 0;
1817 Seg.Sel16bit = 0;
1818 Seg.fFlags = 0;
1819@@ -1230,10 +1470,11 @@
1820 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1821
1822 const Elf_Shdr *pShdrEnd = NULL;
1823- unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
1824- const Elf_Shdr *pShdr = &pModElf->paOrgShdrs[cLeft];
1825+ unsigned cLeft = pModElf->Ehdr.e_shnum - pModElf->iFirstSect;
1826+ const Elf_Shdr *pShdr = &pModElf->paOrgShdrs[pModElf->Ehdr.e_shnum];
1827 while (cLeft-- > 0)
1828 {
1829+ pShdr--;
1830 if (pShdr->sh_flags & SHF_ALLOC)
1831 {
1832 RTLDRADDR offSeg = LinkAddress - pShdr->sh_addr;
1833@@ -1246,13 +1487,12 @@
1834 if (offSeg == pShdr->sh_size)
1835 pShdrEnd = pShdr;
1836 }
1837- pShdr--;
1838 }
1839
1840 if (pShdrEnd)
1841 {
1842 *poffSeg = pShdrEnd->sh_size;
1843- *piSeg = pShdrEnd - pModElf->paOrgShdrs - 1;
1844+ *piSeg = pShdrEnd - pModElf->paOrgShdrs - pModElf->iFirstSect;
1845 return VINF_SUCCESS;
1846 }
1847
1848@@ -1268,7 +1508,7 @@
1849 RTLDRADDR offSeg;
1850 int rc = RTLDRELF_NAME(LinkAddressToSegOffset)(pMod, LinkAddress, &iSeg, &offSeg);
1851 if (RT_SUCCESS(rc))
1852- *pRva = pModElf->paShdrs[iSeg + 1].sh_addr + offSeg;
1853+ *pRva = pModElf->paShdrs[iSeg + pModElf->iFirstSect].sh_addr + offSeg;
1854 return rc;
1855 }
1856
1857@@ -1278,10 +1518,10 @@
1858 PRTLDRADDR pRva)
1859 {
1860 PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1861- if (iSeg >= pModElf->Ehdr.e_shnum - 1U)
1862+ if (iSeg >= pModElf->Ehdr.e_shnum - pModElf->iFirstSect)
1863 return VERR_LDR_INVALID_SEG_OFFSET;
1864
1865- iSeg++; /* skip section 0 */
1866+ iSeg += pModElf->iFirstSect; /* skip section 0 if not used */
1867 if (offSeg > pModElf->paShdrs[iSeg].sh_size)
1868 {
1869 const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&pModElf->paShdrs[iSeg + 1],
1870@@ -1303,13 +1543,13 @@
1871 static DECLCALLBACK(int) RTLDRELF_NAME(RvaToSegOffset)(PRTLDRMODINTERNAL pMod, RTLDRADDR Rva,
1872 uint32_t *piSeg, PRTLDRADDR poffSeg)
1873 {
1874- PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1875-
1876+ PRTLDRMODELF pModElf = (PRTLDRMODELF)pMod;
1877 Elf_Addr PrevAddr = 0;
1878- unsigned cLeft = pModElf->Ehdr.e_shnum - 1;
1879- const Elf_Shdr *pShdr = &pModElf->paShdrs[cLeft];
1880+ unsigned cLeft = pModElf->Ehdr.e_shnum - pModElf->iFirstSect;
1881+ const Elf_Shdr *pShdr = &pModElf->paShdrs[pModElf->Ehdr.e_shnum];
1882 while (cLeft-- > 0)
1883 {
1884+ pShdr--;
1885 if (pShdr->sh_flags & SHF_ALLOC)
1886 {
1887 Elf_Addr cbSeg = PrevAddr ? PrevAddr - pShdr->sh_addr : pShdr->sh_size;
1888@@ -1322,7 +1562,6 @@
1889 }
1890 PrevAddr = pShdr->sh_addr;
1891 }
1892- pShdr--;
1893 }
1894
1895 return VERR_LDR_INVALID_RVA;
1896@@ -1413,14 +1652,14 @@
1897 * Apply the relocations.
1898 */
1899 if (pThis->Ehdr.e_type == ET_REL)
1900- rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress,
1901- RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1902- pThis->paShdrs[iDbgInfo].sh_addr,
1903- pThis->paShdrs[iDbgInfo].sh_size,
1904- (const uint8_t *)pvBuf,
1905- (uint8_t *)pvBuf,
1906- pbRelocs,
1907- pThis->paShdrs[iRelocs].sh_size);
1908+ rc = RTLDRELF_NAME(RelocateSectionRel)(pThis, pThis->LinkAddress,
1909+ RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1910+ pThis->paShdrs[iDbgInfo].sh_addr,
1911+ pThis->paShdrs[iDbgInfo].sh_size,
1912+ (const uint8_t *)pvBuf,
1913+ (uint8_t *)pvBuf,
1914+ pbRelocs,
1915+ pThis->paShdrs[iRelocs].sh_size);
1916 else
1917 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress,
1918 RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
1919@@ -1561,11 +1800,13 @@
1920 *
1921 * @returns iprt status code.
1922 * @param pEhdr Pointer to the ELF header.
1923+ * @param cbRawImage The size of the raw image.
1924 * @param pszLogName The log name.
1925- * @param cbRawImage The size of the raw image.
1926+ * @param penmArch Where to return the architecture.
1927+ * @param pErrInfo Where to return extended error info. Optional.
1928 */
1929-static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, const char *pszLogName, uint64_t cbRawImage,
1930- PRTLDRARCH penmArch)
1931+static int RTLDRELF_NAME(ValidateElfHeader)(const Elf_Ehdr *pEhdr, uint64_t cbRawImage, const char *pszLogName,
1932+ PRTLDRARCH penmArch, PRTERRINFO pErrInfo)
1933 {
1934 Log3(("RTLdrELF: e_ident: %.*Rhxs\n"
1935 "RTLdrELF: e_type: " FMT_ELF_HALF "\n"
1936@@ -1587,48 +1828,31 @@
1937 if ( pEhdr->e_ident[EI_MAG0] != ELFMAG0
1938 || pEhdr->e_ident[EI_MAG1] != ELFMAG1
1939 || pEhdr->e_ident[EI_MAG2] != ELFMAG2
1940- || pEhdr->e_ident[EI_MAG3] != ELFMAG3
1941- )
1942- {
1943- Log(("RTLdrELF: %s: Invalid ELF magic (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident)); NOREF(pszLogName);
1944- return VERR_BAD_EXE_FORMAT;
1945- }
1946+ || pEhdr->e_ident[EI_MAG3] != ELFMAG3)
1947+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
1948+ "%s: Invalid ELF magic (%.*Rhxs)", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident);
1949 if (pEhdr->e_ident[EI_CLASS] != RTLDRELF_SUFF(ELFCLASS))
1950- {
1951- Log(("RTLdrELF: %s: Invalid ELF class (%.*Rhxs)\n", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident));
1952- return VERR_BAD_EXE_FORMAT;
1953- }
1954+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
1955+ "%s: Invalid ELF class (%.*Rhxs)", pszLogName, sizeof(pEhdr->e_ident), pEhdr->e_ident);
1956 if (pEhdr->e_ident[EI_DATA] != ELFDATA2LSB)
1957- {
1958- Log(("RTLdrELF: %s: ELF endian %x is unsupported\n", pszLogName, pEhdr->e_ident[EI_DATA]));
1959- return VERR_LDRELF_ODD_ENDIAN;
1960- }
1961+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_ODD_ENDIAN,
1962+ "%s: ELF endian %x is unsupported", pszLogName, pEhdr->e_ident[EI_DATA]);
1963 if (pEhdr->e_version != EV_CURRENT)
1964- {
1965- Log(("RTLdrELF: %s: ELF version %x is unsupported\n", pszLogName, pEhdr->e_version));
1966- return VERR_LDRELF_VERSION;
1967- }
1968+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_VERSION,
1969+ "%s: ELF version %x is unsupported", pszLogName, pEhdr->e_version);
1970
1971 if (sizeof(Elf_Ehdr) != pEhdr->e_ehsize)
1972- {
1973- Log(("RTLdrELF: %s: Elf header e_ehsize is %d expected %d!\n",
1974- pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr)));
1975- return VERR_BAD_EXE_FORMAT;
1976- }
1977+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
1978+ "%s: Elf header e_ehsize is %d expected %d!", pszLogName, pEhdr->e_ehsize, sizeof(Elf_Ehdr));
1979 if ( sizeof(Elf_Phdr) != pEhdr->e_phentsize
1980- && ( pEhdr->e_phnum != 0
1981- || pEhdr->e_type == ET_DYN))
1982- {
1983- Log(("RTLdrELF: %s: Elf header e_phentsize is %d expected %d!\n",
1984- pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr)));
1985- return VERR_BAD_EXE_FORMAT;
1986- }
1987+ && ( pEhdr->e_phnum != 0
1988+ || pEhdr->e_type == ET_DYN
1989+ || pEhdr->e_type == ET_EXEC))
1990+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Elf header e_phentsize is %d expected %d!",
1991+ pszLogName, pEhdr->e_phentsize, sizeof(Elf_Phdr));
1992 if (sizeof(Elf_Shdr) != pEhdr->e_shentsize)
1993- {
1994- Log(("RTLdrELF: %s: Elf header e_shentsize is %d expected %d!\n",
1995- pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr)));
1996- return VERR_BAD_EXE_FORMAT;
1997- }
1998+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Elf header e_shentsize is %d expected %d!",
1999+ pszLogName, pEhdr->e_shentsize, sizeof(Elf_Shdr));
2000
2001 switch (pEhdr->e_type)
2002 {
2003@@ -1637,8 +1861,8 @@
2004 case ET_DYN:
2005 break;
2006 default:
2007- Log(("RTLdrELF: %s: image type %#x is not supported!\n", pszLogName, pEhdr->e_type));
2008- return VERR_BAD_EXE_FORMAT;
2009+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: image type %#x is not supported!",
2010+ pszLogName, pEhdr->e_type);
2011 }
2012
2013 switch (pEhdr->e_machine)
2014@@ -1654,52 +1878,43 @@
2015 break;
2016 #endif
2017 default:
2018- Log(("RTLdrELF: %s: machine type %u is not supported!\n", pszLogName, pEhdr->e_machine));
2019- return VERR_LDRELF_MACHINE;
2020+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MACHINE,
2021+ "%s: machine type %u is not supported!", pszLogName, pEhdr->e_machine);
2022 }
2023
2024 if ( pEhdr->e_phoff < pEhdr->e_ehsize
2025 && !(pEhdr->e_phoff && pEhdr->e_phnum)
2026 && pEhdr->e_phnum)
2027- {
2028- Log(("RTLdrELF: %s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF "\n",
2029- pszLogName, pEhdr->e_phoff));
2030- return VERR_BAD_EXE_FORMAT;
2031- }
2032+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2033+ "%s: The program headers overlap with the ELF header! e_phoff=" FMT_ELF_OFF,
2034+ pszLogName, pEhdr->e_phoff);
2035 if ( pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize > cbRawImage
2036 || pEhdr->e_phoff + pEhdr->e_phnum * pEhdr->e_phentsize < pEhdr->e_phoff)
2037- {
2038- Log(("RTLdrELF: %s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF "\n",
2039- pszLogName, pEhdr->e_phoff, pEhdr->e_phnum));
2040- return VERR_BAD_EXE_FORMAT;
2041- }
2042+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2043+ "%s: The program headers extends beyond the file! e_phoff=" FMT_ELF_OFF " e_phnum=" FMT_ELF_HALF,
2044+ pszLogName, pEhdr->e_phoff, pEhdr->e_phnum);
2045
2046
2047 if ( pEhdr->e_shoff < pEhdr->e_ehsize
2048 && !(pEhdr->e_shoff && pEhdr->e_shnum))
2049- {
2050- Log(("RTLdrELF: %s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF "\n",
2051- pszLogName, pEhdr->e_shoff));
2052- return VERR_BAD_EXE_FORMAT;
2053- }
2054+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2055+ "%s: The section headers overlap with the ELF header! e_shoff=" FMT_ELF_OFF,
2056+ pszLogName, pEhdr->e_shoff);
2057 if ( pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize > cbRawImage
2058 || pEhdr->e_shoff + pEhdr->e_shnum * pEhdr->e_shentsize < pEhdr->e_shoff)
2059- {
2060- Log(("RTLdrELF: %s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF "\n",
2061- pszLogName, pEhdr->e_shoff, pEhdr->e_shnum));
2062- return VERR_BAD_EXE_FORMAT;
2063- }
2064+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2065+ "%s: The section headers extends beyond the file! e_shoff=" FMT_ELF_OFF " e_shnum=" FMT_ELF_HALF,
2066+ pszLogName, pEhdr->e_shoff, pEhdr->e_shnum);
2067
2068 if (pEhdr->e_shstrndx == 0 || pEhdr->e_shstrndx > pEhdr->e_shnum)
2069- {
2070- Log(("RTLdrELF: %s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF "\n",
2071- pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum));
2072- return VERR_BAD_EXE_FORMAT;
2073- }
2074+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2075+ "%s: The section headers string table is out of bounds! e_shstrndx=" FMT_ELF_HALF " e_shnum=" FMT_ELF_HALF,
2076+ pszLogName, pEhdr->e_shstrndx, pEhdr->e_shnum);
2077
2078 return VINF_SUCCESS;
2079 }
2080
2081+
2082 /**
2083 * Gets the section header name.
2084 *
2085@@ -1739,10 +1954,12 @@
2086 * @param pModElf Pointer to the module structure.
2087 * @param iShdr The index of section header which should be validated.
2088 * The section headers are found in the pModElf->paShdrs array.
2089+ * @param cbRawImage The size of the raw image.
2090 * @param pszLogName The log name.
2091- * @param cbRawImage The size of the raw image.
2092+ * @param pErrInfo Where to return extended error info. Optional.
2093 */
2094-static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, const char *pszLogName, uint64_t cbRawImage)
2095+static int RTLDRELF_NAME(ValidateSectionHeader)(PRTLDRMODELF pModElf, unsigned iShdr, uint64_t cbRawImage,
2096+ const char *pszLogName, PRTERRINFO pErrInfo)
2097 {
2098 const Elf_Shdr *pShdr = &pModElf->paShdrs[iShdr];
2099 char szSectionName[80]; NOREF(szSectionName);
2100@@ -1774,26 +1991,20 @@
2101 || pShdr->sh_link != SHN_UNDEF
2102 || pShdr->sh_addralign != 0
2103 || pShdr->sh_entsize != 0 )
2104- {
2105- Log(("RTLdrELF: %s: Bad #0 section: %.*Rhxs\n", pszLogName, sizeof(*pShdr), pShdr ));
2106- return VERR_BAD_EXE_FORMAT;
2107- }
2108+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2109+ "%s: Bad #0 section: %.*Rhxs", pszLogName, sizeof(*pShdr), pShdr);
2110 return VINF_SUCCESS;
2111 }
2112
2113 if (pShdr->sh_name >= pModElf->cbShStr)
2114- {
2115- Log(("RTLdrELF: %s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!\n",
2116- pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr)); NOREF(pszLogName);
2117- return VERR_BAD_EXE_FORMAT;
2118- }
2119+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2120+ "%s: Shdr #%d: sh_name (%d) is beyond the end of the section header string table (%d)!",
2121+ pszLogName, iShdr, pShdr->sh_name, pModElf->cbShStr);
2122
2123 if (pShdr->sh_link >= pModElf->Ehdr.e_shnum)
2124- {
2125- Log(("RTLdrELF: %s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!\n",
2126- pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum)); NOREF(pszLogName);
2127- return VERR_BAD_EXE_FORMAT;
2128- }
2129+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2130+ "%s: Shdr #%d: sh_link (%d) is beyond the end of the section table (%d)!",
2131+ pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum);
2132
2133 switch (pShdr->sh_type)
2134 {
2135@@ -1800,11 +2011,9 @@
2136 /** @todo find specs and check up which sh_info fields indicates section table entries */
2137 case 12301230:
2138 if (pShdr->sh_info >= pModElf->Ehdr.e_shnum)
2139- {
2140- Log(("RTLdrELF: %s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!\n",
2141- pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum));
2142- return VERR_BAD_EXE_FORMAT;
2143- }
2144+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2145+ "%s: Shdr #%d: sh_info (%d) is beyond the end of the section table (%d)!",
2146+ pszLogName, iShdr, pShdr->sh_link, pModElf->Ehdr.e_shnum);
2147 break;
2148
2149 case SHT_NULL:
2150@@ -1838,19 +2047,741 @@
2151 uint64_t offEnd = pShdr->sh_offset + pShdr->sh_size;
2152 if ( offEnd > cbRawImage
2153 || offEnd < (uint64_t)pShdr->sh_offset)
2154+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2155+ "%s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RX64) is beyond the end of the file (%RX64)!",
2156+ pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage);
2157+ if (pShdr->sh_offset < sizeof(Elf_Ehdr))
2158+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2159+ "%s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!",
2160+ pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size);
2161+ }
2162+
2163+ return VINF_SUCCESS;
2164+}
2165+
2166+
2167+/**
2168+ * Process the section headers.
2169+ *
2170+ * @returns iprt status code.
2171+ * @param pModElf Pointer to the module structure.
2172+ * @param paShdrs The section headers.
2173+ * @param cbRawImage The size of the raw image.
2174+ * @param pszLogName The log name.
2175+ * @param pErrInfo Where to return extended error info. Optional.
2176+ */
2177+static int RTLDRELF_NAME(ValidateAndProcessSectionHeaders)(PRTLDRMODELF pModElf, Elf_Shdr *paShdrs, uint64_t cbRawImage,
2178+ const char *pszLogName, PRTERRINFO pErrInfo)
2179+{
2180+ Elf_Addr uNextAddr = 0;
2181+ for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2182+ {
2183+ int rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, cbRawImage, pszLogName, pErrInfo);
2184+ if (RT_FAILURE(rc))
2185+ return rc;
2186+
2187+ /*
2188+ * We're looking for symbol tables.
2189+ */
2190+ if (paShdrs[i].sh_type == SHT_SYMTAB)
2191 {
2192- Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD " = %RX64) is beyond the end of the file (%RX64)!\n",
2193- pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size, offEnd, cbRawImage));
2194- return VERR_BAD_EXE_FORMAT;
2195+ if (pModElf->Rel.iSymSh != ~0U)
2196+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MULTIPLE_SYMTABS,
2197+ "%s: Multiple symbol tabs! iSymSh=%d i=%d", pszLogName, pModElf->Rel.iSymSh, i);
2198+ pModElf->Rel.iSymSh = i;
2199+ pModElf->Rel.cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
2200+ AssertBreakStmt(pModElf->Rel.cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
2201+ pModElf->Rel.iStrSh = paShdrs[i].sh_link;
2202+ pModElf->Rel.cbStr = (unsigned)paShdrs[pModElf->Rel.iStrSh].sh_size;
2203+ AssertBreakStmt(pModElf->Rel.cbStr == paShdrs[pModElf->Rel.iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
2204 }
2205- if (pShdr->sh_offset < sizeof(Elf_Ehdr))
2206+ else if (paShdrs[i].sh_type == SHT_DYNSYM)
2207 {
2208- Log(("RTLdrELF: %s: Shdr #%d: sh_offset (" FMT_ELF_OFF ") + sh_size (" FMT_ELF_XWORD ") is starting in the ELF header!\n",
2209- pszLogName, iShdr, pShdr->sh_offset, pShdr->sh_size));
2210- return VERR_BAD_EXE_FORMAT;
2211+ if (pModElf->Dyn.iSymSh != ~0U)
2212+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDRELF_MULTIPLE_SYMTABS,
2213+ "%s: Multiple dynamic symbol tabs! iSymSh=%d i=%d", pszLogName, pModElf->Dyn.iSymSh, i);
2214+ if (pModElf->Ehdr.e_type != ET_DYN && pModElf->Ehdr.e_type != ET_EXEC)
2215+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2216+ "%s: Unexpected SHT_DYNSYM (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
2217+ pModElf->Dyn.iSymSh = i;
2218+ pModElf->Dyn.cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
2219+ AssertBreakStmt(pModElf->Dyn.cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
2220+ pModElf->Dyn.iStrSh = paShdrs[i].sh_link;
2221+ pModElf->Dyn.cbStr = (unsigned)paShdrs[pModElf->Dyn.iStrSh].sh_size;
2222+ AssertBreakStmt(pModElf->Dyn.cbStr == paShdrs[pModElf->Dyn.iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
2223 }
2224+ /*
2225+ * We're also look for the dynamic section.
2226+ */
2227+ else if (paShdrs[i].sh_type == SHT_DYNAMIC)
2228+ {
2229+ if (pModElf->iShDynamic != ~0U)
2230+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2231+ "%s: Multiple dynamic sections! iShDynamic=%d i=%d",
2232+ pszLogName, pModElf->iShDynamic, i);
2233+ if (pModElf->Ehdr.e_type != ET_DYN && pModElf->Ehdr.e_type != ET_EXEC)
2234+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2235+ "Unexpected SHT_DYNAMIC (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
2236+ if (paShdrs[i].sh_entsize != sizeof(Elf_Dyn))
2237+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2238+ "%s: SHT_DYNAMIC (i=%d) sh_entsize=" FMT_ELF_XWORD ", expected %#zx",
2239+ pszLogName, i, paShdrs[i].sh_entsize, sizeof(Elf_Dyn));
2240+ pModElf->iShDynamic = i;
2241+ Elf_Xword const cDynamic = paShdrs[i].sh_size / sizeof(Elf_Dyn);
2242+ if (cDynamic > _64K || cDynamic < 2)
2243+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2244+ "%s: SHT_DYNAMIC (i=%d) sh_size=" FMT_ELF_XWORD " is out of range, expected %u",
2245+ pszLogName, i, paShdrs[i].sh_size);
2246+ pModElf->cDynamic = (unsigned)cDynamic;
2247+ }
2248+
2249+ /*
2250+ * Special checks for the section string table.
2251+ */
2252+ if (i == pModElf->Ehdr.e_shstrndx)
2253+ {
2254+ if (paShdrs[i].sh_type != SHT_STRTAB)
2255+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2256+ "%s: Section header string table is not a SHT_STRTAB: %#x",
2257+ pszLogName, paShdrs[i].sh_type);
2258+ if (paShdrs[i].sh_size == 0)
2259+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Section header string table is empty", pszLogName);
2260+ }
2261+
2262+ /*
2263+ * Kluge for the .data..percpu segment in 64-bit linux kernels.
2264+ */
2265+ if (paShdrs[i].sh_flags & SHF_ALLOC)
2266+ {
2267+ if ( paShdrs[i].sh_addr == 0
2268+ && paShdrs[i].sh_addr < uNextAddr)
2269+ {
2270+ Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
2271+ Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
2272+ i, paShdrs[i].sh_addr, uAddr));
2273+ paShdrs[i].sh_addr = uAddr;
2274+ }
2275+ uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
2276+ }
2277+ } /* for each section header */
2278+
2279+ return VINF_SUCCESS;
2280+}
2281+
2282+
2283+/**
2284+ * Process the section headers.
2285+ *
2286+ * @returns iprt status code.
2287+ * @param pModElf Pointer to the module structure.
2288+ * @param paShdrs The section headers.
2289+ * @param cbRawImage The size of the raw image.
2290+ * @param pszLogName The log name.
2291+ * @param pErrInfo Where to return extended error info. Optional.
2292+ */
2293+static int RTLDRELF_NAME(ValidateAndProcessDynamicInfo)(PRTLDRMODELF pModElf, uint64_t cbRawImage, uint32_t fFlags,
2294+ const char *pszLogName, PRTERRINFO pErrInfo)
2295+{
2296+ /*
2297+ * Check preconditions.
2298+ */
2299+ AssertReturn(pModElf->Ehdr.e_type == ET_DYN || pModElf->Ehdr.e_type == ET_EXEC, VERR_INTERNAL_ERROR_2);
2300+ if (pModElf->Ehdr.e_phnum <= 1 || pModElf->Ehdr.e_phnum >= _32K)
2301+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2302+ "%s: e_phnum=%u is out of bounds (2..32K)", pszLogName, pModElf->Ehdr.e_phnum);
2303+ if (pModElf->iShDynamic == ~0U)
2304+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: no .dynamic section", pszLogName);
2305+ AssertReturn(pModElf->cDynamic > 1 && pModElf->cDynamic <= _64K, VERR_INTERNAL_ERROR_3);
2306+
2307+ /* ASSUME that the sections are ordered by address. That simplifies
2308+ validation code further down. */
2309+ AssertReturn(pModElf->Ehdr.e_shnum >= 2, VERR_INTERNAL_ERROR_4);
2310+ Elf_Shdr const *paShdrs = pModElf->paShdrs;
2311+ Elf_Addr uPrevEnd = paShdrs[1].sh_addr + paShdrs[1].sh_size;
2312+ for (unsigned i = 2; i < pModElf->Ehdr.e_shnum; i++)
2313+ if (paShdrs[i].sh_flags & SHF_ALLOC)
2314+ {
2315+ if (uPrevEnd > paShdrs[i].sh_addr)
2316+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2317+ "%s: section %u is out of order: uPrevEnd=" FMT_ELF_ADDR " sh_addr=" FMT_ELF_ADDR,
2318+ pszLogName, i, uPrevEnd, paShdrs[i].sh_addr);
2319+ uPrevEnd = paShdrs[i].sh_addr + paShdrs[i].sh_size;
2320+ }
2321+
2322+ /* Must have string and symbol tables. */
2323+ if (pModElf->Dyn.iStrSh == ~0U)
2324+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: No dynamic string table section", pszLogName);
2325+ if (pModElf->Dyn.iSymSh == ~0U)
2326+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: No dynamic symbol table section", pszLogName);
2327+
2328+ /*
2329+ * Load the program headers.
2330+ */
2331+ size_t const cbPhdrs = sizeof(pModElf->paPhdrs[0]) * pModElf->Ehdr.e_phnum;
2332+ Elf_Phdr *paPhdrs = (Elf_Phdr *)RTMemAllocZ(cbPhdrs);
2333+ pModElf->paPhdrs = paPhdrs;
2334+ AssertReturn(paPhdrs, VERR_NO_MEMORY);
2335+
2336+ int rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, paPhdrs, cbPhdrs, pModElf->Ehdr.e_phoff);
2337+ if (RT_FAILURE(rc))
2338+ return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: pfnRead(,,%#zx, " FMT_ELF_OFF ") -> %Rrc",
2339+ pszLogName, cbPhdrs, pModElf->Ehdr.e_phoff, rc);
2340+
2341+ /*
2342+ * Validate them.
2343+ */
2344+ unsigned cbPage = _4K; /** @todo generalize architecture specific stuff using its own code template header. */
2345+ switch (pModElf->Core.enmArch)
2346+ {
2347+ case RTLDRARCH_AMD64:
2348+ case RTLDRARCH_X86_32:
2349+ break;
2350+ default:
2351+ AssertFailedBreak(/** @todo page size for got.plt hacks */);
2352 }
2353+ unsigned iLoad = 0;
2354+ unsigned iLoadShdr = 1; /* ASSUMES ordered (checked above). */
2355+ unsigned cDynamic = 0;
2356+ Elf_Addr cbImage = 0;
2357+ Elf_Addr uLinkAddress = ~(Elf_Addr)0;
2358+ for (unsigned i = 0; i < pModElf->Ehdr.e_phnum; i++)
2359+ {
2360+ const Elf_Phdr * const pPhdr = &paPhdrs[i];
2361+ Log3(("RTLdrELF: Program Header #%d:\n"
2362+ "RTLdrELF: p_type: " FMT_ELF_WORD " (%s)\n"
2363+ "RTLdrELF: p_flags: " FMT_ELF_WORD "\n"
2364+ "RTLdrELF: p_offset: " FMT_ELF_OFF "\n"
2365+ "RTLdrELF: p_vaddr: " FMT_ELF_ADDR "\n"
2366+ "RTLdrELF: p_paddr: " FMT_ELF_ADDR "\n"
2367+ "RTLdrELF: p_filesz: " FMT_ELF_XWORD "\n"
2368+ "RTLdrELF: p_memsz: " FMT_ELF_XWORD "\n"
2369+ "RTLdrELF: p_align: " FMT_ELF_XWORD "\n",
2370+ i,
2371+ pPhdr->p_type, rtldrElfGetPhdrType(pPhdr->p_type), pPhdr->p_flags, pPhdr->p_offset,
2372+ pPhdr->p_vaddr, pPhdr->p_paddr, pPhdr->p_filesz, pPhdr->p_memsz, pPhdr->p_align));
2373
2374+ if (pPhdr->p_type == DT_NULL)
2375+ continue;
2376+
2377+ if ( pPhdr->p_filesz != 0
2378+ && ( pPhdr->p_offset >= cbRawImage
2379+ || pPhdr->p_filesz > cbRawImage
2380+ || pPhdr->p_offset + pPhdr->p_filesz > cbRawImage))
2381+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2382+ "%s: Prog Hdr #%u: bogus p_offset=" FMT_ELF_OFF " & p_filesz=" FMT_ELF_XWORD " (file size %#RX64)",
2383+ pszLogName, i, pPhdr->p_offset, pPhdr->p_filesz, cbRawImage);
2384+
2385+ if (pPhdr->p_flags & ~(Elf64_Word)(PF_X | PF_R | PF_W))
2386+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Prog Hdr #%u: bogus p_flags=" FMT_ELF_WORD,
2387+ pszLogName, i, pPhdr->p_flags);
2388+
2389+ if (!RT_IS_POWER_OF_TWO(pPhdr->p_align))
2390+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Prog Hdr #%u: bogus p_align=" FMT_ELF_XWORD,
2391+ pszLogName, i, pPhdr->p_align);
2392+
2393+ if ( pPhdr->p_align > 1
2394+ && pPhdr->p_memsz > 0
2395+ && pPhdr->p_filesz > 0
2396+ && (pPhdr->p_offset & (pPhdr->p_align - 1)) != (pPhdr->p_vaddr & (pPhdr->p_align - 1)))
2397+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2398+ "%s: Prog Hdr #%u: misaligned p_offset=" FMT_ELF_OFF " p_vaddr=" FMT_ELF_ADDR " p_align=" FMT_ELF_XWORD,
2399+ pszLogName, i, pPhdr->p_offset, pPhdr->p_vaddr, pPhdr->p_align);
2400+
2401+ /* Do some type specfic checks: */
2402+ switch (pPhdr->p_type)
2403+ {
2404+ case PT_LOAD:
2405+ {
2406+ if (pPhdr->p_memsz < pPhdr->p_filesz)
2407+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2408+ "%s: Prog Hdr #%u/LOAD#%u: bogus p_memsz=" FMT_ELF_XWORD " or p_filesz=" FMT_ELF_XWORD,
2409+ pszLogName, i, iLoad, pPhdr->p_memsz, pPhdr->p_filesz);
2410+ cbImage = pPhdr->p_vaddr + pPhdr->p_memsz;
2411+ if (iLoad == 0)
2412+ uLinkAddress = pPhdr->p_vaddr;
2413+
2414+ /* Find the corresponding sections, checking their addresses and
2415+ file offsets since the rest of the code is still section based
2416+ rather than using program headers as it should... */
2417+ Elf_Off off = pPhdr->p_offset;
2418+ Elf_Addr uAddr = pPhdr->p_vaddr;
2419+ Elf_Xword cbMem = pPhdr->p_memsz;
2420+ Elf_Xword cbFile = pPhdr->p_filesz;
2421+ while (cbMem > 0)
2422+ {
2423+ if (iLoadShdr < pModElf->Ehdr.e_shnum)
2424+ { /* likely */ }
2425+ else if (iLoadShdr == pModElf->Ehdr.e_shnum)
2426+ {
2427+ /** @todo anything else to check here? */
2428+ iLoadShdr++;
2429+ break;
2430+ }
2431+ else
2432+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2433+ "%s: Prog Hdr #%u/LOAD#%u: Out of sections at " FMT_ELF_ADDR " LB " FMT_ELF_XWORD,
2434+ pszLogName, i, iLoad, uAddr, cbMem);
2435+ if (!(paShdrs[iLoadShdr].sh_flags & SHF_ALLOC))
2436+ {
2437+ if ( paShdrs[iLoadShdr].sh_type != SHT_NOBITS
2438+ && paShdrs[iLoadShdr].sh_size > 0
2439+ && off < paShdrs[iLoadShdr].sh_offset + paShdrs[iLoadShdr].sh_size
2440+ && paShdrs[iLoadShdr].sh_offset < off + cbMem)
2441+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2442+ "%s: Prog Hdr #%u/LOAD#%u: Overlaps with !SHF_ALLOC section at " FMT_ELF_OFF " LB " FMT_ELF_XWORD,
2443+ pszLogName, i, iLoad, paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_size);
2444+ pModElf->paShdrExtras[iLoadShdr].idxPhdr = UINT16_MAX;
2445+ iLoadShdr++;
2446+ continue;
2447+ }
2448+
2449+ if (uAddr != paShdrs[iLoadShdr].sh_addr)
2450+ {
2451+ /* Before the first section we expect headers to be loaded, so
2452+ that the file is simply mapped from file offset zero. */
2453+ if ( iLoadShdr == 1
2454+ && iLoad == 0
2455+ && paShdrs[1].sh_addr == paShdrs[1].sh_offset
2456+ && cbFile >= paShdrs[1].sh_offset
2457+ && cbMem >= paShdrs[1].sh_offset)
2458+ {
2459+ /* Modify paShdrs[0] to describe the gap. ".elf.headers" */
2460+ pModElf->iFirstSect = 0;
2461+ pModElf->paShdrs[0].sh_name = 0;
2462+ pModElf->paShdrs[0].sh_type = SHT_PROGBITS;
2463+ pModElf->paShdrs[0].sh_flags = SHF_ALLOC
2464+ | (pPhdr->p_flags & PF_W ? SHF_WRITE : 0)
2465+ | (pPhdr->p_flags & PF_X ? SHF_EXECINSTR : 0);
2466+ pModElf->paShdrs[0].sh_addr = uAddr;
2467+ pModElf->paShdrs[0].sh_offset = off;
2468+ pModElf->paShdrs[0].sh_size = paShdrs[1].sh_offset;
2469+ pModElf->paShdrs[0].sh_link = 0;
2470+ pModElf->paShdrs[0].sh_info = 0;
2471+ pModElf->paShdrs[0].sh_addralign = pPhdr->p_align;
2472+ pModElf->paShdrs[0].sh_entsize = 0;
2473+ *(Elf_Shdr *)pModElf->paOrgShdrs = pModElf->paShdrs[0]; /* (necessary for segment enumeration) */
2474+
2475+ uAddr += paShdrs[1].sh_offset;
2476+ cbMem -= paShdrs[1].sh_offset;
2477+ cbFile -= paShdrs[1].sh_offset;
2478+ off = paShdrs[1].sh_offset;
2479+ }
2480+ /* Alignment padding? Allow up to a page size. */
2481+ else if ( paShdrs[iLoadShdr].sh_addr > uAddr
2482+ && paShdrs[iLoadShdr].sh_addr - uAddr
2483+ < RT_MAX(paShdrs[iLoadShdr].sh_addralign, cbPage /*got.plt hack*/))
2484+ {
2485+ Elf_Xword cbAlignPadding = paShdrs[iLoadShdr].sh_addr - uAddr;
2486+ if (cbAlignPadding >= cbMem)
2487+ break;
2488+ cbMem -= cbAlignPadding;
2489+ uAddr += cbAlignPadding;
2490+ if (cbFile > cbAlignPadding)
2491+ {
2492+ off += cbAlignPadding;
2493+ cbFile -= cbAlignPadding;
2494+ }
2495+ else
2496+ {
2497+ off += cbFile;
2498+ cbFile = 0;
2499+ }
2500+ }
2501+ }
2502+
2503+ if ( uAddr == paShdrs[iLoadShdr].sh_addr
2504+ && cbMem >= paShdrs[iLoadShdr].sh_size
2505+ && ( paShdrs[iLoadShdr].sh_type != SHT_NOBITS
2506+ ? off == paShdrs[iLoadShdr].sh_offset
2507+ && cbFile >= paShdrs[iLoadShdr].sh_size /* this might be too strict... */
2508+ : cbFile == 0) )
2509+ {
2510+ if (paShdrs[iLoadShdr].sh_type != SHT_NOBITS)
2511+ {
2512+ off += paShdrs[iLoadShdr].sh_size;
2513+ cbFile -= paShdrs[iLoadShdr].sh_size;
2514+ }
2515+ uAddr += paShdrs[iLoadShdr].sh_size;
2516+ cbMem -= paShdrs[iLoadShdr].sh_size;
2517+ }
2518+ else
2519+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2520+ "%s: Prog Hdr #%u/LOAD#%u: Mismatch at " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " LB " FMT_ELF_XWORD ") with section #%u " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " sh_type=" FMT_ELF_WORD ")",
2521+ pszLogName, i, iLoad, uAddr, cbMem, off, cbFile,
2522+ iLoadShdr, paShdrs[iLoadShdr].sh_addr, paShdrs[iLoadShdr].sh_size,
2523+ paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_type);
2524+
2525+ pModElf->paShdrExtras[iLoadShdr].idxPhdr = iLoad;
2526+ iLoadShdr++;
2527+ } /* section loop */
2528+
2529+ iLoad++;
2530+ break;
2531+ }
2532+
2533+ case PT_DYNAMIC:
2534+ {
2535+ const Elf_Shdr *pShdr = &pModElf->paShdrs[pModElf->iShDynamic];
2536+ if (pPhdr->p_offset != pShdr->sh_offset)
2537+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2538+ "%s: Prog Hdr #%u/DYNAMIC: p_offset=" FMT_ELF_OFF " expected " FMT_ELF_OFF,
2539+ pszLogName, i, pPhdr->p_offset, pShdr->sh_offset);
2540+ if (RT_MAX(pPhdr->p_memsz, pPhdr->p_filesz) != pShdr->sh_size)
2541+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2542+ "%s: Prog Hdr #%u/DYNAMIC: expected " FMT_ELF_XWORD " for RT_MAX(p_memsz=" FMT_ELF_XWORD ", p_filesz=" FMT_ELF_XWORD ")",
2543+ pszLogName, i, pShdr->sh_size, pPhdr->p_memsz, pPhdr->p_filesz);
2544+ cDynamic++;
2545+ break;
2546+ }
2547+ }
2548+ }
2549+
2550+ if (iLoad == 0)
2551+ return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: No PT_LOAD program headers", pszLogName);
2552+ if (cDynamic != 1)
2553+ return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: No program header for the DYNAMIC section", pszLogName);
2554+
2555+ cbImage -= uLinkAddress;
2556+ pModElf->cbImage = (uint64_t)cbImage;
2557+ pModElf->LinkAddress = uLinkAddress;
2558+ AssertReturn(pModElf->cbImage == cbImage, VERR_INTERNAL_ERROR_5);
2559+ Log3(("RTLdrELF: LinkAddress=" FMT_ELF_ADDR " cbImage=" FMT_ELF_ADDR " (from PT_LOAD)\n", uLinkAddress, cbImage));
2560+
2561+ for (; iLoadShdr < pModElf->Ehdr.e_shnum; iLoadShdr++)
2562+ if ( !(paShdrs[iLoadShdr].sh_flags & SHF_ALLOC)
2563+ || paShdrs[iLoadShdr].sh_size == 0)
2564+ pModElf->paShdrExtras[iLoadShdr].idxPhdr = UINT16_MAX;
2565+ else
2566+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2567+ "%s: No PT_LOAD for section #%u " FMT_ELF_ADDR " LB " FMT_ELF_XWORD " (file " FMT_ELF_OFF " sh_type=" FMT_ELF_WORD ")",
2568+ pszLogName, iLoadShdr, paShdrs[iLoadShdr].sh_addr, paShdrs[iLoadShdr].sh_size,
2569+ paShdrs[iLoadShdr].sh_offset, paShdrs[iLoadShdr].sh_type);
2570+
2571+ /*
2572+ * Load and validate the dynamic table. We have got / will get most of the
2573+ * info we need from the section table, so we must make sure this matches up.
2574+ */
2575+ Log3(("RTLdrELF: Dynamic section - %u entries\n", pModElf->cDynamic));
2576+ size_t const cbDynamic = pModElf->cDynamic * sizeof(pModElf->paDynamic[0]);
2577+ Elf_Dyn * const paDynamic = (Elf_Dyn *)RTMemAlloc(cbDynamic);
2578+ AssertReturn(paDynamic, VERR_NO_MEMORY);
2579+ pModElf->paDynamic = paDynamic;
2580+
2581+ rc = pModElf->Core.pReader->pfnRead(pModElf->Core.pReader, paDynamic, cbDynamic, paShdrs[pModElf->iShDynamic].sh_offset);
2582+ if (RT_FAILURE(rc))
2583+ return RTERRINFO_LOG_SET_F(pErrInfo, rc, "%s: pfnRead(,,%#zx, " FMT_ELF_OFF ") -> %Rrc",
2584+ pszLogName, cbDynamic, paShdrs[pModElf->iShDynamic].sh_offset, rc);
2585+
2586+ for (uint32_t i = 0; i < pModElf->cDynamic; i++)
2587+ {
2588+#define LOG_VALIDATE_PTR_RET(szName) do { \
2589+ Log3(("RTLdrELF: DT[%u]: %16s " FMT_ELF_ADDR "\n", i, szName, paDynamic[i].d_un.d_ptr)); \
2590+ if ((uint64_t)paDynamic[i].d_un.d_ptr - uLinkAddress < cbImage) { /* likely */ } \
2591+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": Invalid address " FMT_ELF_ADDR " (valid range: " FMT_ELF_ADDR " LB " FMT_ELF_ADDR ")", \
2592+ pszLogName, i, paDynamic[i].d_un.d_ptr, uLinkAddress, cbImage); \
2593+ } while (0)
2594+#define LOG_VALIDATE_PTR_VAL_RET(szName, uExpected) do { \
2595+ Log3(("RTLdrELF: DT[%u]: %16s " FMT_ELF_ADDR "\n", i, szName, (uint64_t)paDynamic[i].d_un.d_ptr)); \
2596+ if (paDynamic[i].d_un.d_ptr == (Elf_Addr)(uExpected)) { /* likely */ } \
2597+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": " FMT_ELF_ADDR ", expected " FMT_ELF_ADDR, \
2598+ pszLogName, i, paDynamic[i].d_un.d_ptr, (Elf_Addr)(uExpected)); \
2599+ } while (0)
2600+#define LOG_VALIDATE_STR_RET(szName) do { \
2601+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, szName, (uint64_t)paDynamic[i].d_un.d_val)); \
2602+ if ((uint64_t)paDynamic[i].d_un.d_val < pModElf->Dyn.cbStr) { /* likely */ } \
2603+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": Invalid string table offset %#RX64 (max %#x)", \
2604+ pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val, pModElf->Dyn.cbStr); \
2605+ } while (0)
2606+#define LOG_VALIDATE_VAL_RET(szName, uExpected) do { \
2607+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, szName, (uint64_t)paDynamic[i].d_un.d_val)); \
2608+ if ((uint64_t)paDynamic[i].d_un.d_val == (uint64_t)(uExpected)) { /* likely */ } \
2609+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" szName ": %#RX64, expected %#RX64", \
2610+ pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val, (uint64_t)(uExpected)); \
2611+ } while (0)
2612+#define SET_RELOC_TYPE_RET(a_szName, a_uType) do { \
2613+ if (pModElf->DynInfo.uRelocType == 0 || pModElf->DynInfo.uRelocType == (a_uType)) \
2614+ pModElf->DynInfo.uRelocType = (a_uType); \
2615+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Mixing DT_RELA and DT_REL", pszLogName, i); \
2616+ } while (0)
2617+#define SET_INFO_FIELD_RET(a_szName, a_Field, a_Value, a_UnsetValue, a_szFmt) do { \
2618+ if ((a_Field) == (a_UnsetValue) && (a_Value) != (a_UnsetValue)) \
2619+ (a_Field) = (a_Value); /* likely */ \
2620+ else if ((a_Field) != (a_UnsetValue)) \
2621+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Multiple entries (first value " a_szFmt ", second " a_szFmt ")", pszLogName, i, (a_Field), (a_Value)); \
2622+ else if ((a_Value) != (a_UnsetValue)) \
2623+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Unexpected value " a_szFmt, pszLogName, i, (a_Value)); \
2624+ } while (0)
2625+#define FIND_MATCHING_SECTION_RET(a_szName, a_ExtraMatchExpr, a_idxShFieldToSet) do { \
2626+ unsigned iSh; \
2627+ for (iSh = 1; iSh < pModElf->Ehdr.e_shnum; iSh++) \
2628+ if ( paShdrs[iSh].sh_addr == paDynamic[i].d_un.d_ptr \
2629+ && (a_ExtraMatchExpr)) \
2630+ { \
2631+ (a_idxShFieldToSet) = iSh; \
2632+ if (pModElf->paShdrExtras[iSh].idxDt != UINT16_MAX) \
2633+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, \
2634+ "%s: DT[%u]/" a_szName ": section #%u (" FMT_ELF_ADDR ") already referenced by DT[%u]", \
2635+ pszLogName, i, iSh, paShdrs[iSh].sh_addr, pModElf->paShdrExtras[iSh].idxDt); \
2636+ pModElf->paShdrExtras[iSh].idxDt = i; \
2637+ pModElf->paShdrExtras[iSh].uDtTag = (uint32_t)paDynamic[i].d_tag; \
2638+ break; \
2639+ } \
2640+ if (iSh < pModElf->Ehdr.e_shnum) { /* likely */ } \
2641+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": No matching section for " FMT_ELF_ADDR, pszLogName, i, paDynamic[i].d_un.d_ptr); \
2642+ } while (0)
2643+#define ONLY_FOR_DEBUG_OR_VALIDATION_RET(a_szName) do { \
2644+ if (fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)) { /* likely */ } \
2645+ else return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/" a_szName ": Not supported (" FMT_ELF_ADDR ")", pszLogName, i, paDynamic[i].d_un.d_ptr); \
2646+ } while (0)
2647+#define LOG_NON_VALUE_ENTRY(a_szName) Log3(("RTLdrELF: DT[%u]: %16s (%#RX64)\n", i, a_szName, (uint64_t)paDynamic[i].d_un.d_val))
2648+
2649+ switch (paDynamic[i].d_tag)
2650+ {
2651+ case DT_NULL:
2652+ LOG_NON_VALUE_ENTRY("DT_NULL");
2653+ for (unsigned iNull = i + 1; iNull < pModElf->cDynamic; iNull++)
2654+ if (paDynamic[i].d_tag == DT_NULL) /* Not technically a bug, but let's try being extremely strict for now */
2655+ LOG_NON_VALUE_ENTRY("DT_NULL");
2656+ else if (!(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)))
2657+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2658+ "%s: DT[%u]/DT_NULL: Dynamic section isn't zero padded (extra #%u of #%u)",
2659+ pszLogName, i, iNull - i, pModElf->cDynamic - i);
2660+ i = pModElf->cDynamic;
2661+ break;
2662+ case DT_NEEDED:
2663+ LOG_VALIDATE_STR_RET("DT_NEEDED");
2664+ break;
2665+ case DT_PLTRELSZ:
2666+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_PLTRELSZ", (uint64_t)paDynamic[i].d_un.d_val));
2667+ SET_INFO_FIELD_RET("DT_PLTRELSZ", pModElf->DynInfo.cbJmpRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
2668+ break;
2669+ case DT_PLTGOT:
2670+ LOG_VALIDATE_PTR_RET("DT_PLTGOT");
2671+ break;
2672+ case DT_HASH:
2673+ LOG_VALIDATE_PTR_RET("DT_HASH");
2674+ break;
2675+ case DT_STRTAB:
2676+ LOG_VALIDATE_PTR_VAL_RET("DT_STRTAB", paShdrs[pModElf->Dyn.iStrSh].sh_addr);
2677+ pModElf->paShdrExtras[pModElf->Dyn.iStrSh].idxDt = i;
2678+ pModElf->paShdrExtras[pModElf->Dyn.iSymSh].uDtTag = DT_STRTAB;
2679+ break;
2680+ case DT_SYMTAB:
2681+ LOG_VALIDATE_PTR_VAL_RET("DT_SYMTAB", paShdrs[pModElf->Dyn.iSymSh].sh_addr);
2682+ pModElf->paShdrExtras[pModElf->Dyn.iSymSh].idxDt = i;
2683+ pModElf->paShdrExtras[pModElf->Dyn.iSymSh].uDtTag = DT_SYMTAB;
2684+ break;
2685+ case DT_RELA:
2686+ LOG_VALIDATE_PTR_RET("DT_RELA");
2687+ SET_RELOC_TYPE_RET("DT_RELA", DT_RELA);
2688+ SET_INFO_FIELD_RET("DT_RELA", pModElf->DynInfo.uPtrRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
2689+ FIND_MATCHING_SECTION_RET("DT_RELA", paShdrs[iSh].sh_type == SHT_RELA, pModElf->DynInfo.idxShRelocs);
2690+ break;
2691+ case DT_RELASZ:
2692+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_RELASZ", (uint64_t)paDynamic[i].d_un.d_val));
2693+ SET_RELOC_TYPE_RET("DT_RELASZ", DT_RELA);
2694+ SET_INFO_FIELD_RET("DT_RELASZ", pModElf->DynInfo.cbRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
2695+ break;
2696+ case DT_RELAENT:
2697+ LOG_VALIDATE_VAL_RET("DT_RELAENT", sizeof(Elf_Rela));
2698+ SET_RELOC_TYPE_RET("DT_RELAENT", DT_RELA);
2699+ SET_INFO_FIELD_RET("DT_RELAENT", pModElf->DynInfo.cbRelocEntry, (unsigned)sizeof(Elf_Rela), 0, "%u");
2700+ break;
2701+ case DT_STRSZ:
2702+ LOG_VALIDATE_VAL_RET("DT_STRSZ", pModElf->Dyn.cbStr);
2703+ break;
2704+ case DT_SYMENT:
2705+ LOG_VALIDATE_VAL_RET("DT_SYMENT", sizeof(Elf_Sym));
2706+ break;
2707+ case DT_INIT:
2708+ LOG_VALIDATE_PTR_RET("DT_INIT");
2709+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT");
2710+ break;
2711+ case DT_FINI:
2712+ LOG_VALIDATE_PTR_RET("DT_FINI");
2713+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI");
2714+ break;
2715+ case DT_SONAME:
2716+ LOG_VALIDATE_STR_RET("DT_SONAME");
2717+ break;
2718+ case DT_RPATH:
2719+ LOG_VALIDATE_STR_RET("DT_RPATH");
2720+ break;
2721+ case DT_SYMBOLIC:
2722+ LOG_NON_VALUE_ENTRY("DT_SYMBOLIC");
2723+ break;
2724+ case DT_REL:
2725+ LOG_VALIDATE_PTR_RET("DT_REL");
2726+ SET_RELOC_TYPE_RET("DT_REL", DT_REL);
2727+ SET_INFO_FIELD_RET("DT_REL", pModElf->DynInfo.uPtrRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
2728+ FIND_MATCHING_SECTION_RET("DT_REL", paShdrs[iSh].sh_type == SHT_REL, pModElf->DynInfo.idxShRelocs);
2729+ break;
2730+ case DT_RELSZ:
2731+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_RELSZ", (uint64_t)paDynamic[i].d_un.d_val));
2732+ SET_RELOC_TYPE_RET("DT_RELSZ", DT_REL);
2733+ SET_INFO_FIELD_RET("DT_RELSZ", pModElf->DynInfo.cbRelocs, (Elf_Xword)paDynamic[i].d_un.d_val, 0, FMT_ELF_XWORD);
2734+ break;
2735+ case DT_RELENT:
2736+ LOG_VALIDATE_VAL_RET("DT_RELENT", sizeof(Elf_Rel));
2737+ SET_RELOC_TYPE_RET("DT_RELENT", DT_REL);
2738+ SET_INFO_FIELD_RET("DT_RELENT", pModElf->DynInfo.cbRelocEntry, (unsigned)sizeof(Elf_Rel), 0, "%u");
2739+ break;
2740+ case DT_PLTREL:
2741+ if (paDynamic[i].d_un.d_val != DT_RELA && paDynamic[i].d_un.d_val != DT_REL)
2742+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT[%u]/DT_PLTREL: Invalid value %#RX64",
2743+ pszLogName, i, (uint64_t)paDynamic[i].d_un.d_val);
2744+ Log3(("RTLdrELF: DT[%u]: %16s DT_REL%s\n", i, "DT_PLTREL", paDynamic[i].d_un.d_val == DT_RELA ? "A" : ""));
2745+ SET_INFO_FIELD_RET("DT_PLTREL", pModElf->DynInfo.uJmpRelocType, (unsigned)paDynamic[i].d_un.d_val, 0, "%u");
2746+ break;
2747+ case DT_DEBUG:
2748+ LOG_VALIDATE_PTR_RET("DT_DEBUG");
2749+ break;
2750+ case DT_TEXTREL:
2751+ LOG_NON_VALUE_ENTRY("DT_TEXTREL");
2752+ break;
2753+ case DT_JMPREL:
2754+ LOG_VALIDATE_PTR_RET("DT_JMPREL");
2755+ SET_INFO_FIELD_RET("DT_JMPREL", pModElf->DynInfo.uPtrJmpRelocs, paDynamic[i].d_un.d_ptr, ~(Elf_Addr)0, FMT_ELF_ADDR);
2756+ FIND_MATCHING_SECTION_RET("DT_JMPREL", 1, pModElf->DynInfo.idxShJmpRelocs);
2757+ break;
2758+ case DT_BIND_NOW:
2759+ LOG_NON_VALUE_ENTRY("DT_BIND_NOW");
2760+ break;
2761+ case DT_INIT_ARRAY:
2762+ LOG_VALIDATE_PTR_RET("DT_INIT_ARRAY");
2763+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT_ARRAY");
2764+ break;
2765+ case DT_FINI_ARRAY:
2766+ LOG_VALIDATE_PTR_RET("DT_FINI_ARRAY");
2767+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI_ARRAY");
2768+ break;
2769+ case DT_INIT_ARRAYSZ:
2770+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_INIT_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
2771+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_INIT_ARRAYSZ");
2772+ break;
2773+ case DT_FINI_ARRAYSZ:
2774+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_FINI_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
2775+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_FINI_ARRAYSZ");
2776+ break;
2777+ case DT_RUNPATH:
2778+ LOG_VALIDATE_STR_RET("DT_RUNPATH");
2779+ break;
2780+ case DT_FLAGS:
2781+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64\n", i, "DT_FLAGS", (uint64_t)paDynamic[i].d_un.d_val));
2782+ break;
2783+ case DT_PREINIT_ARRAY:
2784+ LOG_VALIDATE_PTR_RET("DT_PREINIT_ARRAY");
2785+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_PREINIT_ARRAY");
2786+ break;
2787+ case DT_PREINIT_ARRAYSZ:
2788+ Log3(("RTLdrELF: DT[%u]: %16s %#RX64 bytes\n", i, "DT_PREINIT_ARRAYSZ", (uint64_t)paDynamic[i].d_un.d_val));
2789+ ONLY_FOR_DEBUG_OR_VALIDATION_RET("DT_PREINIT_ARRAYSZ");
2790+ break;
2791+ default:
2792+ if ( paDynamic[i].d_un.d_val < DT_ENCODING
2793+ || (paDynamic[i].d_un.d_val & 1))
2794+ Log3(("RTLdrELF: DT[%u]: %#010RX64 %#RX64%s\n", i, (uint64_t)paDynamic[i].d_tag,
2795+ (uint64_t)paDynamic[i].d_un.d_val, paDynamic[i].d_un.d_val >= DT_ENCODING ? " (val)" : ""));
2796+ else
2797+ {
2798+ Log3(("RTLdrELF: DT[%u]: %#010RX64 " FMT_ELF_ADDR " (addr)\n",
2799+ i, (uint64_t)paDynamic[i].d_tag, paDynamic[i].d_un.d_ptr));
2800+ if ((uint64_t)paDynamic[i].d_un.d_ptr - uLinkAddress >= cbImage)
2801+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2802+ "%s: DT[%u]/%#RX64: Invalid address " FMT_ELF_ADDR " (valid range: " FMT_ELF_ADDR " LB " FMT_ELF_ADDR ")",
2803+ pszLogName, i, (uint64_t)paDynamic[i].d_tag,
2804+ paDynamic[i].d_un.d_ptr, uLinkAddress, cbImage);
2805+ }
2806+ break;
2807+ }
2808+#undef LOG_VALIDATE_VAL_RET
2809+#undef LOG_VALIDATE_STR_RET
2810+#undef LOG_VALIDATE_PTR_VAL_RET
2811+#undef LOG_VALIDATE_PTR_RET
2812+#undef SET_RELOC_TYPE_RET
2813+#undef SET_INFO_FIELD_RET
2814+#undef FIND_MATCHING_SECTION_RET
2815+#undef ONLY_FOR_DEBUG_OR_VALIDATION_RET
2816+ }
2817+
2818+ /*
2819+ * Validate the relocation information we've gathered.
2820+ */
2821+ Elf_Word uShTypeArch = SHT_RELA; /** @todo generalize architecture specific stuff using its own code template header. */
2822+ switch (pModElf->Core.enmArch)
2823+ {
2824+ case RTLDRARCH_AMD64:
2825+ break;
2826+ case RTLDRARCH_X86_32:
2827+ uShTypeArch = SHT_REL;
2828+ break;
2829+ default:
2830+ AssertFailedBreak(/** @todo page size for got.plt hacks */);
2831+
2832+ }
2833+
2834+ if (pModElf->DynInfo.uRelocType != 0)
2835+ {
2836+ const char * const pszModifier = pModElf->DynInfo.uRelocType == DT_RELA ? "A" : "";
2837+ if (pModElf->DynInfo.uPtrRelocs == ~(Elf_Addr)0)
2838+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%s", pszLogName, pszModifier);
2839+ if (pModElf->DynInfo.cbRelocs == 0)
2840+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%sSZ", pszLogName, pszModifier);
2841+ if (pModElf->DynInfo.cbRelocEntry == 0)
2842+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_REL%sENT", pszLogName, pszModifier);
2843+ Elf_Shdr const *pShdrRelocs = &paShdrs[pModElf->DynInfo.idxShRelocs];
2844+ Elf_Word const uShType = pModElf->DynInfo.uJmpRelocType == DT_RELA ? SHT_RELA : SHT_REL;
2845+ if (pShdrRelocs->sh_type != uShType)
2846+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%s* does not match section type: %u vs %u",
2847+ pszLogName, pszModifier, pShdrRelocs->sh_type, uShType);
2848+ if (pShdrRelocs->sh_size != pModElf->DynInfo.cbRelocs)
2849+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%sSZ does not match section size: %u vs %u",
2850+ pszLogName, pszModifier, pShdrRelocs->sh_size, pModElf->DynInfo.cbRelocs);
2851+ if (uShType != uShTypeArch)
2852+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_REL%s* does not match architecture: %u, arch wants %u",
2853+ pszLogName, pszModifier, uShType, uShTypeArch);
2854+ }
2855+
2856+ if ( pModElf->DynInfo.uPtrJmpRelocs != ~(Elf_Addr)0
2857+ || pModElf->DynInfo.cbJmpRelocs != 0
2858+ || pModElf->DynInfo.uJmpRelocType != 0)
2859+ {
2860+ if (pModElf->DynInfo.uPtrJmpRelocs == ~(Elf_Addr)0)
2861+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_JMPREL", pszLogName);
2862+ if (pModElf->DynInfo.cbJmpRelocs == 0)
2863+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_PLTRELSZ", pszLogName);
2864+ if (pModElf->DynInfo.uJmpRelocType == 0)
2865+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: Missing DT_PLTREL", pszLogName);
2866+ Elf_Shdr const *pShdrRelocs = &paShdrs[pModElf->DynInfo.idxShJmpRelocs];
2867+ Elf_Word const uShType = pModElf->DynInfo.uJmpRelocType == DT_RELA ? SHT_RELA : SHT_REL;
2868+ if (pShdrRelocs->sh_type != uShType)
2869+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTREL does not match section type: %u vs %u",
2870+ pszLogName, pShdrRelocs->sh_type, uShType);
2871+ if (pShdrRelocs->sh_size != pModElf->DynInfo.cbJmpRelocs)
2872+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTRELSZ does not match section size: %u vs %u",
2873+ pszLogName, pShdrRelocs->sh_size, pModElf->DynInfo.cbJmpRelocs);
2874+ if (uShType != uShTypeArch)
2875+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "%s: DT_PLTREL does not match architecture: %u, arch wants %u",
2876+ pszLogName, uShType, uShTypeArch);
2877+ }
2878+
2879+ /*
2880+ * Check that there aren't any other relocations hiding in the section table.
2881+ */
2882+ for (uint32_t i = 1; i < pModElf->Ehdr.e_shnum; i++)
2883+ if ( (paShdrs[i].sh_type == SHT_REL || paShdrs[i].sh_type == SHT_RELA)
2884+ && pModElf->paShdrExtras[i].uDtTag != DT_REL
2885+ && pModElf->paShdrExtras[i].uDtTag != DT_RELA
2886+ && pModElf->paShdrExtras[i].uDtTag != DT_JMPREL)
2887+ {
2888+ char szSecHdrNm[80];
2889+ return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
2890+ "%s: section header #%u (%s type=" FMT_ELF_WORD " size=" FMT_ELF_XWORD ") contains relocations not referenced by the dynamic section",
2891+ pszLogName,
2892+ RTLDRELF_NAME(GetSHdrName)(pModElf, paShdrs[i].sh_name, szSecHdrNm, sizeof(szSecHdrNm)),
2893+ paShdrs[i].sh_type, paShdrs[i].sh_size);
2894+ }
2895+
2896 return VINF_SUCCESS;
2897 }
2898
2899@@ -1864,8 +2795,9 @@
2900 * @param fFlags Reserved, MBZ.
2901 * @param enmArch Architecture specifier.
2902 * @param phLdrMod Where to store the handle.
2903+ * @param pErrInfo Where to return extended error info. Optional.
2904 */
2905-static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
2906+static int RTLDRELF_NAME(Open)(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
2907 {
2908 const char *pszLogName = pReader->pfnLogName(pReader);
2909 uint64_t cbRawImage = pReader->pfnSize(pReader);
2910@@ -1889,21 +2821,41 @@
2911 #else
2912 pModElf->Core.enmArch = RTLDRARCH_AMD64;
2913 #endif
2914- //pModElf->pvBits = NULL;
2915- //pModElf->Ehdr = {0};
2916- //pModElf->paShdrs = NULL;
2917- //pModElf->paSyms = NULL;
2918- pModElf->iSymSh = ~0U;
2919- //pModElf->cSyms = 0;
2920- pModElf->iStrSh = ~0U;
2921- //pModElf->cbStr = 0;
2922- //pModElf->cbImage = 0;
2923- //pModElf->LinkAddress = 0;
2924- //pModElf->pStr = NULL;
2925- //pModElf->cbShStr = 0;
2926- //pModElf->pShStr = NULL;
2927- //pModElf->iShEhFrame = 0;
2928- //pModElf->iShEhFrameHdr = 0;
2929+ //pModElf->pvBits = NULL;
2930+ //pModElf->Ehdr = {0};
2931+ //pModElf->paShdrs = NULL;
2932+ //pModElf->Rel.paSyms = NULL;
2933+ pModElf->Rel.iSymSh = ~0U;
2934+ //pModElf->Rel.cSyms = 0;
2935+ pModElf->Rel.iStrSh = ~0U;
2936+ //pModElf->Rel.cbStr = 0;
2937+ //pModElf->Rel.pStr = NULL;
2938+ //pModElf->Dyn.paSyms = NULL;
2939+ pModElf->Dyn.iSymSh = ~0U;
2940+ //pModElf->Dyn.cSyms = 0;
2941+ pModElf->Dyn.iStrSh = ~0U;
2942+ //pModElf->Dyn.cbStr = 0;
2943+ //pModElf->Dyn.pStr = NULL;
2944+ //pModElf->iFirstSect = 0;
2945+ //pModElf->cbImage = 0;
2946+ pModElf->LinkAddress = ~(Elf_Addr)0;
2947+ //pModElf->cbShStr = 0;
2948+ //pModElf->pShStr = NULL;
2949+ //pModElf->iShEhFrame = 0;
2950+ //pModElf->iShEhFrameHdr= 0;
2951+ pModElf->iShDynamic = ~0U;
2952+ //pModElf->cDynamic = 0;
2953+ //pModElf->paDynamic = NULL;
2954+ //pModElf->paPhdrs = NULL;
2955+ pModElf->DynInfo.uPtrRelocs = ~(Elf_Addr)0;
2956+ //pModElf->DynInfo.cbRelocs = 0;
2957+ //pModElf->DynInfo.cbRelocEntry = 0;
2958+ //pModElf->DynInfo.uRelocType = 0;
2959+ //pModElf->DynInfo.idxShRelocs = 0;
2960+ pModElf->DynInfo.uPtrJmpRelocs = ~(Elf_Addr)0;
2961+ //pModElf->DynInfo.cbJmpRelocs = 0;
2962+ //pModElf->DynInfo.uJmpRelocType = 0;
2963+ //pModElf->DynInfo.idxShJmpRelocs = 0;
2964
2965 /*
2966 * Read and validate the ELF header and match up the CPU architecture.
2967@@ -1912,7 +2864,7 @@
2968 if (RT_SUCCESS(rc))
2969 {
2970 RTLDRARCH enmArchImage = RTLDRARCH_INVALID; /* shut up gcc */
2971- rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, pszLogName, cbRawImage, &enmArchImage);
2972+ rc = RTLDRELF_NAME(ValidateElfHeader)(&pModElf->Ehdr, cbRawImage, pszLogName, &enmArchImage, pErrInfo);
2973 if (RT_SUCCESS(rc))
2974 {
2975 if ( enmArch != RTLDRARCH_WHATEVER
2976@@ -1927,7 +2879,7 @@
2977 * introspection methods.
2978 */
2979 size_t const cbShdrs = pModElf->Ehdr.e_shnum * sizeof(Elf_Shdr);
2980- Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2);
2981+ Elf_Shdr *paShdrs = (Elf_Shdr *)RTMemAlloc(cbShdrs * 2 + sizeof(RTLDRMODELFSHX) * pModElf->Ehdr.e_shnum);
2982 if (paShdrs)
2983 {
2984 pModElf->paShdrs = paShdrs;
2985@@ -1937,110 +2889,58 @@
2986 memcpy(&paShdrs[pModElf->Ehdr.e_shnum], paShdrs, cbShdrs);
2987 pModElf->paOrgShdrs = &paShdrs[pModElf->Ehdr.e_shnum];
2988
2989+ pModElf->paShdrExtras = (PRTLDRMODELFSHX)&pModElf->paOrgShdrs[pModElf->Ehdr.e_shnum];
2990+ memset(pModElf->paShdrExtras, 0xff, sizeof(RTLDRMODELFSHX) * pModElf->Ehdr.e_shnum);
2991+
2992 pModElf->cbShStr = paShdrs[pModElf->Ehdr.e_shstrndx].sh_size;
2993
2994 /*
2995 * Validate the section headers and find relevant sections.
2996 */
2997- Elf_Addr uNextAddr = 0;
2998- for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
2999- {
3000- rc = RTLDRELF_NAME(ValidateSectionHeader)(pModElf, i, pszLogName, cbRawImage);
3001- if (RT_FAILURE(rc))
3002- break;
3003+ rc = RTLDRELF_NAME(ValidateAndProcessSectionHeaders)(pModElf, paShdrs, cbRawImage, pszLogName, pErrInfo);
3004
3005- /* We're looking for symbol tables. */
3006- if (paShdrs[i].sh_type == SHT_SYMTAB)
3007- {
3008- if (pModElf->iSymSh != ~0U)
3009- {
3010- Log(("RTLdrElf: %s: Multiple symbol tabs! iSymSh=%d i=%d\n", pszLogName, pModElf->iSymSh, i));
3011- rc = VERR_LDRELF_MULTIPLE_SYMTABS;
3012- break;
3013- }
3014- pModElf->iSymSh = i;
3015- pModElf->cSyms = (unsigned)(paShdrs[i].sh_size / sizeof(Elf_Sym));
3016- AssertBreakStmt(pModElf->cSyms == paShdrs[i].sh_size / sizeof(Elf_Sym), rc = VERR_IMAGE_TOO_BIG);
3017- pModElf->iStrSh = paShdrs[i].sh_link;
3018- pModElf->cbStr = (unsigned)paShdrs[pModElf->iStrSh].sh_size;
3019- AssertBreakStmt(pModElf->cbStr == paShdrs[pModElf->iStrSh].sh_size, rc = VERR_IMAGE_TOO_BIG);
3020- }
3021+ /*
3022+ * Read validate and process program headers if ET_DYN or ET_EXEC.
3023+ */
3024+ if (RT_SUCCESS(rc) && (pModElf->Ehdr.e_type == ET_DYN || pModElf->Ehdr.e_type == ET_EXEC))
3025+ rc = RTLDRELF_NAME(ValidateAndProcessDynamicInfo)(pModElf, cbRawImage, fFlags, pszLogName, pErrInfo);
3026
3027- /* Special checks for the section string table. */
3028- if (i == pModElf->Ehdr.e_shstrndx)
3029- {
3030- if (paShdrs[i].sh_type != SHT_STRTAB)
3031- {
3032- Log(("RTLdrElf: Section header string table is not a SHT_STRTAB: %#x\n", paShdrs[i].sh_type));
3033- rc = VERR_BAD_EXE_FORMAT;
3034- break;
3035- }
3036- if (paShdrs[i].sh_size == 0)
3037- {
3038- Log(("RTLdrElf: Section header string table is empty\n"));
3039- rc = VERR_BAD_EXE_FORMAT;
3040- break;
3041- }
3042- }
3043-
3044- /* Kluge for the .data..percpu segment in 64-bit linux kernels. */
3045- if (paShdrs[i].sh_flags & SHF_ALLOC)
3046- {
3047- if ( paShdrs[i].sh_addr == 0
3048- && paShdrs[i].sh_addr < uNextAddr)
3049- {
3050- Elf_Addr uAddr = RT_ALIGN_T(uNextAddr, paShdrs[i].sh_addralign, Elf_Addr);
3051- Log(("RTLdrElf: Out of order section #%d; adjusting sh_addr from " FMT_ELF_ADDR " to " FMT_ELF_ADDR "\n",
3052- i, paShdrs[i].sh_addr, uAddr));
3053- paShdrs[i].sh_addr = uAddr;
3054- }
3055- uNextAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
3056- }
3057- } /* for each section header */
3058-
3059 /*
3060- * Calculate the image base address if the image isn't relocatable.
3061+ * Massage the section headers.
3062 */
3063- if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL)
3064+ if (RT_SUCCESS(rc))
3065 {
3066- pModElf->LinkAddress = ~(Elf_Addr)0;
3067- for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
3068- if ( (paShdrs[i].sh_flags & SHF_ALLOC)
3069- && paShdrs[i].sh_addr < pModElf->LinkAddress)
3070- pModElf->LinkAddress = paShdrs[i].sh_addr;
3071- if (pModElf->LinkAddress == ~(Elf_Addr)0)
3072+ if (pModElf->Ehdr.e_type == ET_REL)
3073 {
3074- AssertFailed();
3075- rc = VERR_LDR_GENERAL_FAILURE;
3076- }
3077- if (pModElf->Ehdr.e_type == ET_DYN && pModElf->LinkAddress < 0x1000)
3078+ /* Do allocations and figure the image size: */
3079 pModElf->LinkAddress = 0;
3080- }
3081-
3082- /*
3083- * Perform allocations / RVA calculations, determine the image size.
3084- */
3085- if (RT_SUCCESS(rc))
3086- for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
3087- if (paShdrs[i].sh_flags & SHF_ALLOC)
3088- {
3089- if (pModElf->Ehdr.e_type == ET_REL)
3090+ for (unsigned i = 1; i < pModElf->Ehdr.e_shnum; i++)
3091+ if (paShdrs[i].sh_flags & SHF_ALLOC)
3092+ {
3093 paShdrs[i].sh_addr = paShdrs[i].sh_addralign
3094 ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
3095 : (Elf_Addr)pModElf->cbImage;
3096- else
3097- paShdrs[i].sh_addr -= pModElf->LinkAddress;
3098- Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
3099- if (pModElf->cbImage < EndAddr)
3100- {
3101- pModElf->cbImage = (size_t)EndAddr;
3102- AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
3103+ Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
3104+ if (pModElf->cbImage < EndAddr)
3105+ {
3106+ pModElf->cbImage = (size_t)EndAddr;
3107+ AssertMsgBreakStmt(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), rc = VERR_IMAGE_TOO_BIG);
3108+ }
3109+ Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
3110 }
3111- Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
3112- }
3113+ }
3114+ else
3115+ {
3116+ /* Convert sh_addr to RVA: */
3117+ Assert(pModElf->LinkAddress != ~(Elf_Addr)0);
3118+ for (unsigned i = 0 /*!*/; i < pModElf->Ehdr.e_shnum; i++)
3119+ if (paShdrs[i].sh_flags & SHF_ALLOC)
3120+ paShdrs[i].sh_addr -= pModElf->LinkAddress;
3121+ }
3122+ }
3123
3124 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
3125- pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc,
3126+ pModElf->Rel.iSymSh, pModElf->Rel.cSyms, pModElf->Rel.iStrSh, pModElf->Rel.cbStr, rc,
3127 pModElf->cbImage, pModElf->LinkAddress));
3128 if (RT_SUCCESS(rc))
3129 {
3130@@ -2075,6 +2975,7 @@
3131 #undef RTLDRELF_MID
3132
3133 #undef FMT_ELF_ADDR
3134+#undef FMT_ELF_ADDR7
3135 #undef FMT_ELF_HALF
3136 #undef FMT_ELF_SHALF
3137 #undef FMT_ELF_OFF
3138@@ -2100,6 +3001,8 @@
3139 #undef Elf_Size
3140 #undef Elf_Sword
3141 #undef Elf_Word
3142+#undef Elf_Xword
3143+#undef Elf_Sxword
3144
3145 #undef RTLDRMODELF
3146 #undef PRTLDRMODELF
3147Index: src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
3148===================================================================
3149diff --git a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
3150--- a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85502)
3151+++ b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85503)
3152@@ -1180,7 +1180,7 @@
3153 }
3154 else
3155 rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser,
3156- 0, pModElf->cbImage,
3157+ 0, (Elf_Size)pModElf->cbImage,
3158 (const uint8_t *)pModElf->pvBits /** @todo file offset ?? */,
3159 (uint8_t *)pvBits,
3160 (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
3161@@ -2121,7 +2121,7 @@
3162 pszLogName, pModElf->iShDynamic, i);
3163 if (pModElf->Ehdr.e_type != ET_DYN && pModElf->Ehdr.e_type != ET_EXEC)
3164 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
3165- "Unexpected SHT_DYNAMIC (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
3166+ "%s: Unexpected SHT_DYNAMIC (i=%d) for e_type=%d", pszLogName, i, pModElf->Ehdr.e_type);
3167 if (paShdrs[i].sh_entsize != sizeof(Elf_Dyn))
3168 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
3169 "%s: SHT_DYNAMIC (i=%d) sh_entsize=" FMT_ELF_XWORD ", expected %#zx",
3170@@ -2130,7 +2130,7 @@
3171 Elf_Xword const cDynamic = paShdrs[i].sh_size / sizeof(Elf_Dyn);
3172 if (cDynamic > _64K || cDynamic < 2)
3173 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
3174- "%s: SHT_DYNAMIC (i=%d) sh_size=" FMT_ELF_XWORD " is out of range, expected %u",
3175+ "%s: SHT_DYNAMIC (i=%d) sh_size=" FMT_ELF_XWORD " is out of range (2..64K)",
3176 pszLogName, i, paShdrs[i].sh_size);
3177 pModElf->cDynamic = (unsigned)cDynamic;
3178 }
3179@@ -2777,7 +2777,7 @@
3180 char szSecHdrNm[80];
3181 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT,
3182 "%s: section header #%u (%s type=" FMT_ELF_WORD " size=" FMT_ELF_XWORD ") contains relocations not referenced by the dynamic section",
3183- pszLogName,
3184+ pszLogName, i,
3185 RTLDRELF_NAME(GetSHdrName)(pModElf, paShdrs[i].sh_name, szSecHdrNm, sizeof(szSecHdrNm)),
3186 paShdrs[i].sh_type, paShdrs[i].sh_size);
3187 }
3188Index: include/iprt/memobj.h
3189===================================================================
3190diff --git a/include/iprt/memobj.h b/include/iprt/memobj.h
3191--- a/include/iprt/memobj.h (revision 85503)
3192+++ b/include/iprt/memobj.h (revision 85504)
3193@@ -127,7 +127,10 @@
3194 * @returns IPRT status code.
3195 * @param pMemObj Where to store the ring-0 memory object handle.
3196 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3197- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3198+ * @param fExecutable Flag indicating whether it should be permitted to
3199+ * executed code in the memory object. The user must
3200+ * use RTR0MemObjProtect after initialization the
3201+ * allocation to actually make it executable.
3202 */
3203 #define RTR0MemObjAllocPage(pMemObj, cb, fExecutable) \
3204 RTR0MemObjAllocPageTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
3205@@ -140,7 +143,10 @@
3206 * @returns IPRT status code.
3207 * @param pMemObj Where to store the ring-0 memory object handle.
3208 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3209- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3210+ * @param fExecutable Flag indicating whether it should be permitted to
3211+ * executed code in the memory object. The user must
3212+ * use RTR0MemObjProtect after initialization the
3213+ * allocation to actually make it executable.
3214 * @param pszTag Allocation tag used for statistics and such.
3215 */
3216 RTR0DECL(int) RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
3217@@ -154,7 +160,10 @@
3218 * @returns IPRT status code.
3219 * @param pMemObj Where to store the ring-0 memory object handle.
3220 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3221- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3222+ * @param fExecutable Flag indicating whether it should be permitted to
3223+ * executed code in the memory object. The user must
3224+ * use RTR0MemObjProtect after initialization the
3225+ * allocation to actually make it executable.
3226 */
3227 #define RTR0MemObjAllocLow(pMemObj, cb, fExecutable) \
3228 RTR0MemObjAllocLowTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
3229@@ -168,7 +177,10 @@
3230 * @returns IPRT status code.
3231 * @param pMemObj Where to store the ring-0 memory object handle.
3232 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3233- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3234+ * @param fExecutable Flag indicating whether it should be permitted to
3235+ * executed code in the memory object. The user must
3236+ * use RTR0MemObjProtect after initialization the
3237+ * allocation to actually make it executable.
3238 * @param pszTag Allocation tag used for statistics and such.
3239 */
3240 RTR0DECL(int) RTR0MemObjAllocLowTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
3241@@ -182,7 +194,10 @@
3242 * @returns IPRT status code.
3243 * @param pMemObj Where to store the ring-0 memory object handle.
3244 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3245- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3246+ * @param fExecutable Flag indicating whether it should be permitted to
3247+ * executed code in the memory object. The user must
3248+ * use RTR0MemObjProtect after initialization the
3249+ * allocation to actually make it executable.
3250 */
3251 #define RTR0MemObjAllocCont(pMemObj, cb, fExecutable) \
3252 RTR0MemObjAllocContTag((pMemObj), (cb), (fExecutable), RTMEM_TAG)
3253@@ -196,7 +211,10 @@
3254 * @returns IPRT status code.
3255 * @param pMemObj Where to store the ring-0 memory object handle.
3256 * @param cb Number of bytes to allocate. This is rounded up to nearest page.
3257- * @param fExecutable Flag indicating whether it should be permitted to executed code in the memory object.
3258+ * @param fExecutable Flag indicating whether it should be permitted to
3259+ * executed code in the memory object. The user must
3260+ * use RTR0MemObjProtect after initialization the
3261+ * allocation to actually make it executable.
3262 * @param pszTag Allocation tag used for statistics and such.
3263 */
3264 RTR0DECL(int) RTR0MemObjAllocContTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
3265Index: src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
3266===================================================================
3267diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
3268--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85503)
3269+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85504)
3270@@ -92,7 +92,7 @@
3271 * Structures and Typedefs *
3272 *********************************************************************************************************************************/
3273 /**
3274- * The Darwin version of the memory object structure.
3275+ * The Linux version of the memory object structure.
3276 */
3277 typedef struct RTR0MEMOBJLNX
3278 {
3279@@ -105,11 +105,20 @@
3280 bool fExecutable;
3281 /** Set if we've vmap'ed the memory into ring-0. */
3282 bool fMappedToRing0;
3283+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
3284+ /** Return from alloc_vm_area() that we now need to use for executable
3285+ * memory. */
3286+ struct vm_struct *pArea;
3287+ /** PTE array that goes along with pArea (must be freed). */
3288+ pte_t **papPtesForArea;
3289+#endif
3290 /** The pages in the apPages array. */
3291 size_t cPages;
3292 /** Array of struct page pointers. (variable size) */
3293 struct page *apPages[1];
3294-} RTR0MEMOBJLNX, *PRTR0MEMOBJLNX;
3295+} RTR0MEMOBJLNX;
3296+/** Pointer to the linux memory object. */
3297+typedef RTR0MEMOBJLNX *PRTR0MEMOBJLNX;
3298
3299
3300 static void rtR0MemObjLinuxFreePages(PRTR0MEMOBJLNX pMemLnx);
3301@@ -535,15 +544,49 @@
3302 pgprot_val(fPg) |= _PAGE_NX;
3303 # endif
3304
3305+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
3306+ if (fExecutable)
3307+ {
3308+ pte_t **papPtes = (pte_t **)kmalloc_array(pMemLnx->cPages, sizeof(papPtes[0]), GFP_KERNEL);
3309+ if (papPtes)
3310+ {
3311+ pMemLnx->pArea = alloc_vm_area(pMemLnx->Core.cb, papPtes); /* Note! pArea->nr_pages is not set. */
3312+ if (pMemLnx->pArea)
3313+ {
3314+ size_t i;
3315+ Assert(pMemLnx->pArea->size >= pMemLnx->Core.cb); /* Note! includes guard page. */
3316+ Assert(pMemLnx->pArea->addr);
3317+# ifdef _PAGE_NX
3318+ pgprot_val(fPg) |= _PAGE_NX; /* Uses RTR0MemObjProtect to clear NX when memory ready, W^X fashion. */
3319+# endif
3320+ pMemLnx->papPtesForArea = papPtes;
3321+ for (i = 0; i < pMemLnx->cPages; i++)
3322+ *papPtes[i] = mk_pte(pMemLnx->apPages[i], fPg);
3323+ pMemLnx->Core.pv = pMemLnx->pArea->addr;
3324+ pMemLnx->fMappedToRing0 = true;
3325+ }
3326+ else
3327+ {
3328+ kfree(papPtes);
3329+ rc = VERR_MAP_FAILED;
3330+ }
3331+ }
3332+ else
3333+ rc = VERR_MAP_FAILED;
3334+ }
3335+ else
3336+# endif
3337+ {
3338 # ifdef VM_MAP
3339- pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_MAP, fPg);
3340+ pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_MAP, fPg);
3341 # else
3342- pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_ALLOC, fPg);
3343+ pMemLnx->Core.pv = vmap(&pMemLnx->apPages[0], pMemLnx->cPages, VM_ALLOC, fPg);
3344 # endif
3345- if (pMemLnx->Core.pv)
3346- pMemLnx->fMappedToRing0 = true;
3347- else
3348- rc = VERR_MAP_FAILED;
3349+ if (pMemLnx->Core.pv)
3350+ pMemLnx->fMappedToRing0 = true;
3351+ else
3352+ rc = VERR_MAP_FAILED;
3353+ }
3354 #else /* < 2.4.22 */
3355 rc = VERR_NOT_SUPPORTED;
3356 #endif
3357@@ -569,6 +612,22 @@
3358 static void rtR0MemObjLinuxVUnmap(PRTR0MEMOBJLNX pMemLnx)
3359 {
3360 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
3361+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
3362+ if (pMemLnx->pArea)
3363+ {
3364+# if 0
3365+ pte_t **papPtes = pMemLnx->papPtesForArea;
3366+ size_t i;
3367+ for (i = 0; i < pMemLnx->cPages; i++)
3368+ *papPtes[i] = 0;
3369+# endif
3370+ free_vm_area(pMemLnx->pArea);
3371+ kfree(pMemLnx->papPtesForArea);
3372+ pMemLnx->pArea = NULL;
3373+ pMemLnx->papPtesForArea = NULL;
3374+ }
3375+ else
3376+# endif
3377 if (pMemLnx->fMappedToRing0)
3378 {
3379 Assert(pMemLnx->Core.pv);
3380@@ -1437,6 +1496,7 @@
3381 * Use vmap - 2.4.22 and later.
3382 */
3383 pgprot_t fPg = rtR0MemObjLinuxConvertProt(fProt, true /* kernel */);
3384+ /** @todo We don't really care too much for EXEC here... 5.8 always adds NX. */
3385 Assert(((offSub + cbSub) >> PAGE_SHIFT) <= pMemLnxToMap->cPages);
3386 # ifdef VM_MAP
3387 pMemLnx->Core.pv = vmap(&pMemLnxToMap->apPages[offSub >> PAGE_SHIFT], cbSub >> PAGE_SHIFT, VM_MAP, fPg);
3388@@ -1768,6 +1828,29 @@
3389
3390 DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
3391 {
3392+# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
3393+ /*
3394+ * Currently only supported when we've got addresses PTEs from the kernel.
3395+ */
3396+ PRTR0MEMOBJLNX pMemLnx = (PRTR0MEMOBJLNX)pMem;
3397+ if (pMemLnx->pArea && pMemLnx->papPtesForArea)
3398+ {
3399+ pgprot_t const fPg = rtR0MemObjLinuxConvertProt(fProt, true /*fKernel*/);
3400+ size_t const cPages = (offSub + cbSub) >> PAGE_SHIFT;
3401+ pte_t **papPtes = pMemLnx->papPtesForArea;
3402+ size_t i;
3403+
3404+ for (i = offSub >> PAGE_SHIFT; i < cPages; i++)
3405+ {
3406+ set_pte(papPtes[i], mk_pte(pMemLnx->apPages[i], fPg));
3407+ }
3408+ preempt_disable();
3409+ __flush_tlb_all();
3410+ preempt_enable();
3411+ return VINF_SUCCESS;
3412+ }
3413+# endif
3414+
3415 NOREF(pMem);
3416 NOREF(offSub);
3417 NOREF(cbSub);
3418Index: src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
3419===================================================================
3420diff --git a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c
3421--- a/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c (revision 85504)
3422+++ b/src/VBox/Runtime/r0drv/linux/alloc-r0drv-linux.c (revision 85505)
3423@@ -38,7 +38,7 @@
3424
3425
3426 #if (defined(RT_ARCH_AMD64) || defined(DOXYGEN_RUNNING)) && !defined(RTMEMALLOC_EXEC_HEAP)
3427-# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
3428+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
3429 /**
3430 * Starting with 2.6.23 we can use __get_vm_area and map_vm_area to allocate
3431 * memory in the moduel range. This is preferrable to the exec heap below.
3432Index: src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
3433===================================================================
3434diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
3435--- a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c (revision 85504)
3436+++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c (revision 85505)
3437@@ -144,9 +144,9 @@
3438 * Memory for the executable memory heap (in IPRT).
3439 */
3440 # ifdef DEBUG
3441+# define EXEC_MEMORY_SIZE 10485760 /* 10 MB */
3442+# else
3443 # define EXEC_MEMORY_SIZE 8388608 /* 8 MB */
3444-# else
3445-# define EXEC_MEMORY_SIZE 2097152 /* 2 MB */
3446 # endif
3447 extern uint8_t g_abExecMemory[EXEC_MEMORY_SIZE];
3448 # ifndef VBOX_WITH_TEXT_MODMEM_HACK
3449Index: include/VBox/sup.h
3450===================================================================
3451diff --git a/include/VBox/sup.h b/include/VBox/sup.h
3452--- a/include/VBox/sup.h (revision 85505)
3453+++ b/include/VBox/sup.h (revision 85506)
3454@@ -1555,8 +1555,10 @@
3455 *
3456 * @returns VBox status code.
3457 * @deprecated Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
3458+ * @param pErrInfo Where to return extended error information.
3459+ * Optional.
3460 */
3461-SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename);
3462+SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename, PRTERRINFO pErrInfo);
3463
3464 /**
3465 * Unloads R0 HC VMM code.
3466Index: src/VBox/Devices/Network/testcase/tstIntNet-1.cpp
3467===================================================================
3468diff --git a/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp b/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp
3469--- a/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp (revision 85505)
3470+++ b/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp (revision 85506)
3471@@ -846,7 +846,7 @@
3472 return 1;
3473 }
3474
3475- rc = SUPR3LoadVMM(szAbsPath);
3476+ rc = SUPR3LoadVMM(szAbsPath, NULL);
3477 if (RT_FAILURE(rc))
3478 {
3479 RTPrintf("tstIntNet-1: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szAbsPath, rc);
3480Index: src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp
3481===================================================================
3482diff --git a/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp b/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp
3483--- a/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp (revision 85505)
3484+++ b/src/VBox/NetworkServices/Dhcpd/VBoxNetDhcpd.cpp (revision 85506)
3485@@ -259,7 +259,7 @@
3486 if (RT_SUCCESS(rc))
3487 rc = RTPathAppend(szPathVMMR0, sizeof(szPathVMMR0), "VMMR0.r0");
3488 if (RT_SUCCESS(rc))
3489- rc = SUPR3LoadVMM(szPathVMMR0);
3490+ rc = SUPR3LoadVMM(szPathVMMR0, NULL /*pErrInfo*/);
3491 return rc;
3492 }
3493
3494Index: src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
3495===================================================================
3496diff --git a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp
3497--- a/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp (revision 85505)
3498+++ b/src/VBox/NetworkServices/NetLib/VBoxNetBaseService.cpp (revision 85506)
3499@@ -383,7 +383,7 @@
3500 return rc;
3501 }
3502
3503- rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"));
3504+ rc = SUPR3LoadVMM(strcat(szPath, "/VMMR0.r0"), NULL);
3505 if (RT_FAILURE(rc))
3506 {
3507 LogRel(("VBoxNetBaseService: SUPR3LoadVMM(\"%s\") -> %Rrc\n", szPath, rc));
3508Index: src/VBox/VMM/testcase/tstGlobalConfig.cpp
3509===================================================================
3510diff --git a/src/VBox/VMM/testcase/tstGlobalConfig.cpp b/src/VBox/VMM/testcase/tstGlobalConfig.cpp
3511--- a/src/VBox/VMM/testcase/tstGlobalConfig.cpp (revision 85505)
3512+++ b/src/VBox/VMM/testcase/tstGlobalConfig.cpp (revision 85506)
3513@@ -102,7 +102,7 @@
3514 return 1;
3515 }
3516
3517- rc = SUPR3LoadVMM("./VMMR0.r0");
3518+ rc = SUPR3LoadVMM("./VMMR0.r0", NULL /*pErrInfo*/);
3519 if (RT_SUCCESS(rc))
3520 {
3521 Req.pSession = pSession;
3522Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
3523===================================================================
3524diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
3525--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85505)
3526+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85506)
3527@@ -682,10 +682,10 @@
3528 }
3529
3530
3531-SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
3532+SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename, PRTERRINFO pErrInfo)
3533 {
3534 void *pvImageBase;
3535- return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
3536+ return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, pErrInfo);
3537 }
3538
3539
3540Index: src/VBox/HostDrivers/Support/testcase/tstInt.cpp
3541===================================================================
3542diff --git a/src/VBox/HostDrivers/Support/testcase/tstInt.cpp b/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
3543--- a/src/VBox/HostDrivers/Support/testcase/tstInt.cpp (revision 85505)
3544+++ b/src/VBox/HostDrivers/Support/testcase/tstInt.cpp (revision 85506)
3545@@ -76,7 +76,8 @@
3546 /*
3547 * Load VMM code.
3548 */
3549- rc = SUPR3LoadVMM(szAbsFile);
3550+ RTERRINFOSTATIC ErrInfo;
3551+ rc = SUPR3LoadVMM(szAbsFile, RTErrInfoInitStatic(&ErrInfo));
3552 if (RT_SUCCESS(rc))
3553 {
3554 /*
3555@@ -208,7 +209,7 @@
3556 }
3557 else
3558 {
3559- RTPrintf("tstInt: SUPR3LoadVMM failed with rc=%Rrc\n", rc);
3560+ RTPrintf("tstInt: SUPR3LoadVMM failed with rc=%Rrc%#RTeim\n", rc, &ErrInfo.Core);
3561 rcRet++;
3562 }
3563
3564Index: Config.kmk
3565===================================================================
3566diff --git a/Config.kmk b/Config.kmk
3567--- a/Config.kmk (revision 85506)
3568+++ b/Config.kmk (revision 85507)
3569@@ -4469,15 +4469,13 @@ TEMPLATE_VBoxR0_CXXFLAGS = -fno-pie -nostdinc -g $(VBOX_GCC_pipe) $(V
3570 $(VBOX_GCC_Wno-variadic-macros) $(VBOX_GCC_R0_OPT) $(VBOX_GCC_R0_FP) -fno-strict-aliasing -fno-exceptions \
3571 $(VBOX_GCC_fno-stack-protector) -fno-common $(VBOX_GCC_fvisibility-inlines-hidden) $(VBOX_GCC_fvisibility-hidden) \
3572 -fno-rtti $(VBOX_GCC_std) $(VBOX_GCC_IPRT_FMT_CHECK)
3573-TEMPLATE_VBoxR0_CFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow \
3574- -fasynchronous-unwind-tables -ffreestanding
3575-TEMPLATE_VBoxR0_CXXFLAGS.amd64 = -m64 -mno-red-zone -mcmodel=kernel -mno-sse -mno-mmx -mno-sse2 -mno-3dnow \
3576- -fasynchronous-unwind-tables
3577++TEMPLATE_VBoxR0_CFLAGS.amd64 = -m64 -mno-red-zone -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fasynchronous-unwind-tables -ffreestanding
3578++TEMPLATE_VBoxR0_CXXFLAGS.amd64 = -m64 -mno-red-zone -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -fasynchronous-unwind-tables
3579 TEMPLATE_VBoxR0_CXXFLAGS.freebsd = -ffreestanding
3580 if $(VBOX_GCC_VERSION_CC) < 30400
3581 TEMPLATE_VBoxR0_DEFS += RT_WITHOUT_PRAGMA_ONCE
3582 endif
3583-ifeq ($(KBUILD_TARGET),solaris)
3584+ ifeq ($(KBUILD_TARGET),solaris)
3585 TEMPLATE_VBoxR0_LDFLAGS = -r
3586 TEMPLATE_VBoxR0_LDFLAGS.solaris = -u _init -u _info
3587 TEMPLATE_VBoxR0_LIBS.solaris = \
3588@@ -4488,20 +4486,32 @@ ifeq ($(KBUILD_TARGET),solaris)
3589 endif
3590 # Solaris driver signing.
3591 TEMPLATE_VBoxR0_POST_CMDS = $(VBOX_SIGN_DRIVER_CMDS)
3592-else
3593+ else
3594 TEMPLATE_VBoxR0_LDFLAGS = -nostdlib -Bsymbolic -g
3595 ## @todo WTF doesn't the globals work? Debug info is supposed to be split everywhere. GRR
3596 TEMPLATE_VBoxR0_LD_DEBUG = split
3597-endif
3598-ifn1of ($(KBUILD_TARGET),solaris freebsd)
3599+ endif
3600+ if 0 #1of ($(KBUILD_TARGET), linux)
3601+VBOX_WITH_VBOXR0_AS_DLL = 1
3602+TEMPLATE_VBoxR0_DLLSUFF = .r0
3603+TEMPLATE_VBoxR0_CFLAGS += -fPIC
3604+TEMPLATE_VBoxR0_CXXFLAGS += -fPIC
3605+TEMPLATE_VBoxR0_LDFLAGS +=
3606+TEMPLATE_VBoxR0_DTRACE_HDR_FLAGS += --pic
3607+TEMPLATE_VBoxR0_DTRACE_OBJ_FLAGS += --pic
3608+ else
3609+TEMPLATE_VBoxR0_CFLAGS.amd64 += -mcmodel=kernel
3610+TEMPLATE_VBoxR0_CXXFLAGS.amd64 += -mcmodel=kernel
3611+ endif
3612+ ifn1of ($(KBUILD_TARGET),solaris freebsd)
3613 TEMPLATE_VBoxR0_LIBS = \
3614 $(VBOX_GCC_LIBGCC) # intrinsics
3615-endif
3616-if1of ($(KBUILD_TARGET),linux)
3617- TEMPLATE_VBoxR0_POST_CMDS = \
3618+ endif
3619+ if1of ($(KBUILD_TARGET),linux)
3620+ TEMPLATE_VBoxR0_POST_CMDS += $(NLTAB)\
3621 $(if $(eq $(tool_do),LINK_SYSMOD),if readelf -S $(out)|grep -q "[cd]tors"; then echo "Found ctors/dtors in $(out)!"; exit 1; fi)
3622-endif
3623-endif
3624+ endif
3625+endif # elf
3626
3627 ifeq ($(VBOX_LDR_FMT),macho)
3628 TEMPLATE_VBoxR0_TOOL = $(VBOX_GCC_TOOL)
3629Index: src/VBox/Devices/Makefile.kmk
3630===================================================================
3631diff --git a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk
3632--- a/src/VBox/Devices/Makefile.kmk (revision 85506)
3633+++ b/src/VBox/Devices/Makefile.kmk (revision 85507)
3634@@ -52,7 +52,7 @@
3635 if1of ($(KBUILD_TARGET_ARCH), $(VBOX_SUPPORTED_HOST_ARCHS))
3636 LIBRARIES += ServicesR0
3637 DLLS += VBoxDDU VBoxDD VBoxDD2
3638- SYSMODS += VBoxDDR0
3639+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxDDR0
3640 ifdef VBOX_WITH_RAW_MODE
3641 SYSMODS += VBoxDDRC
3642 endif
3643@@ -1385,7 +1385,7 @@
3644 USB/DevXHCI.cpp
3645 $(call VBOX_SET_VER_INFO_DLL,VBoxEhciR3,PUEL Extension Pack - EHCI Device)
3646
3647- SYSMODS += VBoxEhciR0
3648+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxEhciR0
3649 VBoxEhciR0_TEMPLATE = VBoxR0ExtPackPuel
3650 VBoxEhciR0_SOURCES = \
3651 USB/DevEHCI.cpp \
3652@@ -1421,7 +1421,7 @@
3653 VBoxPciRawDrv_SOURCES = Bus/DrvPciRaw.cpp
3654 $(call VBOX_SET_VER_INFO_DLL,VBoxPciRawDrv,PUEL Extension Pack - PCI Passthrough Driver)
3655
3656- SYSMODS += VBoxPciRawR0
3657+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxPciRawR0
3658 VBoxPciRawR0_TEMPLATE = VBoxR0ExtPackPuel
3659 VBoxPciRawR0_SOURCES = Bus/DevPciRaw.cpp
3660 $(call VBOX_SET_VER_INFO_R0,VBoxPciRawR0,PUEL Extension Pack - PCI Passthrough Driver$(COMMA) ring-0)
3661@@ -1439,7 +1439,7 @@
3662 Storage/DevNVMe.cpp
3663 $(call VBOX_SET_VER_INFO_DLL,VBoxNvmeR3,PUEL Extension Pack - NVMe Device)
3664
3665- SYSMODS += VBoxNvmeR0
3666+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxNvmeR0
3667 VBoxNvmeR0_TEMPLATE = VBoxR0ExtPackPuel
3668 VBoxNvmeR0_SOURCES = \
3669 Storage/DevNVMe.cpp
3670Index: src/VBox/ExtPacks/VBoxDTrace/Makefile.kmk
3671===================================================================
3672diff --git a/src/VBox/ExtPacks/VBoxDTrace/Makefile.kmk b/src/VBox/ExtPacks/VBoxDTrace/Makefile.kmk
3673--- a/src/VBox/ExtPacks/VBoxDTrace/Makefile.kmk (revision 85506)
3674+++ b/src/VBox/ExtPacks/VBoxDTrace/Makefile.kmk (revision 85507)
3675@@ -252,7 +252,7 @@
3676 # The ring-0 part of VBoxDTrace.
3677 #
3678 ifneq ($(KBUILD_TARGET),solaris) # disabled on solaris - neiter needed nor currently able to build it here.
3679- SYSMODS += VBoxDTraceR0
3680+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxDTraceR0
3681 endif
3682 VBoxDTraceR0_TEMPLATE = VBoxR0ExtPackDTrace
3683 VBoxDTraceR0_DEFS = IN_VBOXDTRACE_R0 IN_RT_R0
3684Index: src/VBox/ExtPacks/BusMouseSample/Makefile.kmk
3685===================================================================
3686diff --git a/src/VBox/ExtPacks/BusMouseSample/Makefile.kmk b/src/VBox/ExtPacks/BusMouseSample/Makefile.kmk
3687--- a/src/VBox/ExtPacks/BusMouseSample/Makefile.kmk (revision 85506)
3688+++ b/src/VBox/ExtPacks/BusMouseSample/Makefile.kmk (revision 85507)
3689@@ -83,7 +83,7 @@
3690 VBoxBusMouseR3_TEMPLATE = VBoxR3ExtPackBusMouse
3691 VBoxBusMouseR3_SOURCES = DevBusMouse.cpp
3692
3693-SYSMODS += VBoxBusMouseR0
3694+$(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VBoxBusMouseR0
3695 VBoxBusMouseR0_TEMPLATE = VBoxR0ExtPackBusMouse
3696 VBoxBusMouseR0_SOURCES = DevBusMouse.cpp
3697
3698Index: src/VBox/Runtime/testcase/Makefile.kmk
3699===================================================================
3700diff --git a/src/VBox/Runtime/testcase/Makefile.kmk b/src/VBox/Runtime/testcase/Makefile.kmk
3701--- a/src/VBox/Runtime/testcase/Makefile.kmk (revision 85506)
3702+++ b/src/VBox/Runtime/testcase/Makefile.kmk (revision 85507)
3703@@ -211,13 +211,13 @@
3704 tstRTR0ThreadDriver
3705 endif
3706 if1of ($(KBUILD_TARGET_ARCH), $(VBOX_SUPPORTED_HOST_ARCHS))
3707- SYSMODS += \
3708+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += \
3709 tstLdrObjR0
3710 ifdef VBOX_WITH_RAW_MODE
3711 SYSMODS += tstLdrObj
3712 endif
3713 endif
3714- SYSMODS += \
3715+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += \
3716 tstRTR0MemUserKernel \
3717 tstRTR0SemMutex \
3718 tstRTR0Timer \
3719@@ -225,7 +225,7 @@
3720 tstRTR0Thread
3721 if1of ($(KBUILD_TARGET), solaris darwin)
3722 PROGRAMS += tstRTR0DbgKrnlInfoDriver
3723- SYSMODS += tstRTR0DbgKrnlInfo
3724+ $(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += tstRTR0DbgKrnlInfo
3725 endif # VBOX_SUPPORTED_HOST_ARCHS only
3726
3727 endif
3728Index: src/VBox/VMM/Makefile.kmk
3729===================================================================
3730diff --git a/src/VBox/VMM/Makefile.kmk b/src/VBox/VMM/Makefile.kmk
3731--- a/src/VBox/VMM/Makefile.kmk (revision 85506)
3732+++ b/src/VBox/VMM/Makefile.kmk (revision 85507)
3733@@ -434,7 +434,7 @@
3734 #
3735 # VMMR0.r0
3736 #
3737-SYSMODS += VMMR0
3738+$(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += VMMR0
3739 VMMR0_TEMPLATE = VBoxR0
3740 VMMR0_SYSSUFF = .r0
3741
3742Index: src/VBox/ValidationKit/utils/misc/Makefile.kmk
3743===================================================================
3744diff --git a/src/VBox/ValidationKit/utils/misc/Makefile.kmk b/src/VBox/ValidationKit/utils/misc/Makefile.kmk
3745--- a/src/VBox/ValidationKit/utils/misc/Makefile.kmk (revision 85506)
3746+++ b/src/VBox/ValidationKit/utils/misc/Makefile.kmk (revision 85507)
3747@@ -31,7 +31,7 @@
3748 LoadGenerator_TEMPLATE = VBoxValidationKitR3SupDrv
3749 LoadGenerator_SOURCES = loadgenerator.cpp
3750
3751-SYSMODS += loadgeneratorR0
3752+$(if-expr defined(VBOX_WITH_VBOXR0_AS_DLL),DLLS,SYSMODS) += loadgeneratorR0
3753 loadgeneratorR0_TEMPLATE = VBoxValidationKitR0
3754 loadgeneratorR0_SOURCES = loadgeneratorR0.cpp
3755
3756Index: src/VBox/HostDrivers/Support/SUPLib.cpp
3757===================================================================
3758diff --git a/src/VBox/HostDrivers/Support/SUPLib.cpp b/src/VBox/HostDrivers/Support/SUPLib.cpp
3759--- a/src/VBox/HostDrivers/Support/SUPLib.cpp (revision 85506)
3760+++ b/src/VBox/HostDrivers/Support/SUPLib.cpp (revision 85507)
3761@@ -275,9 +275,9 @@
3762 CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;
3763 strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
3764 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
3765- const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x002d0000
3766+ const uint32_t uMinVersion = /*(SUPDRV_IOC_VERSION & 0xffff0000) == 0x002d0000
3767 ? 0x002d0001
3768- : SUPDRV_IOC_VERSION & 0xffff0000;
3769+ :*/ SUPDRV_IOC_VERSION & 0xffff0000;
3770 CookieReq.u.In.u32MinVersion = uMinVersion;
3771 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
3772 if ( RT_SUCCESS(rc)
3773Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
3774===================================================================
3775diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
3776--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85506)
3777+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85507)
3778@@ -334,7 +334,364 @@
3779 }
3780
3781
3782+/** Argument package for supLoadModuleCompileSegmentsCB. */
3783+typedef struct SUPLDRCOMPSEGTABARGS
3784+{
3785+ uint32_t uStartRva;
3786+ uint32_t uEndRva;
3787+ uint32_t fProt;
3788+ uint32_t iSegs;
3789+ uint32_t cSegsAlloc;
3790+ PSUPLDRSEG paSegs;
3791+ PRTERRINFO pErrInfo;
3792+} SUPLDRCOMPSEGTABARGS, *PSUPLDRCOMPSEGTABARGS;
3793+
3794 /**
3795+ * @callback_method_impl{FNRTLDRENUMSEGS,
3796+ * Compile list of segments with the same memory protection.}
3797+ */
3798+static DECLCALLBACK(int) supLoadModuleCompileSegmentsCB(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser)
3799+{
3800+ PSUPLDRCOMPSEGTABARGS pArgs = (PSUPLDRCOMPSEGTABARGS)pvUser;
3801+ AssertCompile(RTMEM_PROT_READ == SUPLDR_PROT_READ);
3802+ AssertCompile(RTMEM_PROT_WRITE == SUPLDR_PROT_WRITE);
3803+ AssertCompile(RTMEM_PROT_EXEC == SUPLDR_PROT_EXEC);
3804+ RT_NOREF(hLdrMod);
3805+
3806+ /* Ignore segments not part of the loaded image. */
3807+ if (pSeg->RVA == NIL_RTLDRADDR || pSeg->cbMapped == 0)
3808+ return VINF_SUCCESS;
3809+
3810+ /* We currently ASSUME that all relevant segments are in ascending RVA order. */
3811+ AssertReturn(pSeg->RVA >= pArgs->uEndRva,
3812+ RTERRINFO_LOG_REL_SET_F(pArgs->pErrInfo, VERR_BAD_EXE_FORMAT, "Out of order segment: %p LB %#zx #%.*s",
3813+ pSeg->RVA, pSeg->cb, pSeg->cchName, pSeg->pszName));
3814+
3815+ /* We ASSUME the cbMapped field is implemented. */
3816+ AssertReturn(pSeg->cbMapped != NIL_RTLDRADDR, VERR_INTERNAL_ERROR_2);
3817+ AssertReturn(pSeg->cbMapped < _1G, VERR_INTERNAL_ERROR_4);
3818+ uint32_t cbMapped = (uint32_t)pSeg->cbMapped;
3819+ AssertReturn(pSeg->RVA < _1G, VERR_INTERNAL_ERROR_3);
3820+ uint32_t uRvaSeg = (uint32_t)pSeg->RVA;
3821+ Log2(("supLoadModuleCompileSegmentsCB: %RTptr/%RTptr LB %RTptr prot %#x %s\n",
3822+ pSeg->LinkAddress, pSeg->RVA, pSeg->cbMapped, pSeg->fProt, pSeg->pszName));
3823+
3824+ /*
3825+ * If the protection is the same as the previous segment,
3826+ * just update uEndRva and continue.
3827+ */
3828+ uint32_t fProt = pSeg->fProt;
3829+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
3830+ if (fProt & RTMEM_PROT_EXEC)
3831+ fProt |= fProt & RTMEM_PROT_READ;
3832+#endif
3833+ if (pSeg->fProt == pArgs->fProt)
3834+ {
3835+ pArgs->uEndRva = uRvaSeg + cbMapped;
3836+ Log2(("supLoadModuleCompileSegmentsCB: -> merged\n"));
3837+ return VINF_SUCCESS;
3838+ }
3839+
3840+ /*
3841+ * The protection differs, so commit current segment and start a new one.
3842+ * However, if the new segment and old segment share a page, this becomes
3843+ * a little more complicated...
3844+ */
3845+ if (pArgs->uStartRva < pArgs->uEndRva)
3846+ {
3847+ if (((pArgs->uEndRva - 1) >> PAGE_SHIFT) != (uRvaSeg >> PAGE_SHIFT))
3848+ {
3849+ /* No common page, so make the new segment start on a page boundrary. */
3850+ cbMapped += uRvaSeg & PAGE_OFFSET_MASK;
3851+ uRvaSeg &= ~(uint32_t)PAGE_OFFSET_MASK;
3852+ Assert(pArgs->uEndRva <= uRvaSeg);
3853+ Log2(("supLoadModuleCompileSegmentsCB: -> new, no common\n"));
3854+ }
3855+ else if ((fProt & pArgs->fProt) == fProt)
3856+ {
3857+ /* The current segment includes the memory protections of the
3858+ previous, so include the common page in it: */
3859+ uint32_t const cbCommon = PAGE_SIZE - (uRvaSeg & PAGE_OFFSET_MASK);
3860+ if (cbCommon >= cbMapped)
3861+ {
3862+ pArgs->uEndRva = uRvaSeg + cbMapped;
3863+ Log2(("supLoadModuleCompileSegmentsCB: -> merge, %#x common, upgrading prot to %#x\n", cbCommon, pArgs->fProt));
3864+ return VINF_SUCCESS; /* New segment was smaller than a page. */
3865+ }
3866+ cbMapped -= cbCommon;
3867+ uRvaSeg += cbCommon;
3868+ Assert(pArgs->uEndRva <= uRvaSeg);
3869+ Log2(("supLoadModuleCompileSegmentsCB: -> new, %#x common into previous\n", cbCommon));
3870+ }
3871+ else if ((fProt & pArgs->fProt) == pArgs->fProt)
3872+ {
3873+ /* The new segment includes the memory protections of the
3874+ previous, so include the common page in it: */
3875+ cbMapped += uRvaSeg & PAGE_OFFSET_MASK;
3876+ uRvaSeg &= ~(uint32_t)PAGE_OFFSET_MASK;
3877+ if (uRvaSeg == pArgs->uStartRva)
3878+ {
3879+ pArgs->fProt = fProt;
3880+ pArgs->uEndRva = uRvaSeg + cbMapped;
3881+ Log2(("supLoadModuleCompileSegmentsCB: -> upgrade current protection\n"));
3882+ return VINF_SUCCESS; /* Current segment was smaller than a page. */
3883+ }
3884+ Log2(("supLoadModuleCompileSegmentsCB: -> new, %#x common into new\n", (uint32_t)(pSeg->RVA & PAGE_OFFSET_MASK)));
3885+ }
3886+ else
3887+ {
3888+ /* Create a new segment for the common page with the combined protection. */
3889+ Log2(("supLoadModuleCompileSegmentsCB: -> its complicated...\n"));
3890+ pArgs->uEndRva &= ~(uint32_t)PAGE_OFFSET_MASK;
3891+ if (pArgs->uEndRva > pArgs->uStartRva)
3892+ {
3893+ Log2(("supLoadModuleCompileSegmentsCB: SUP Seg #%u: %#x LB %#x prot %#x\n",
3894+ pArgs->iSegs, pArgs->uStartRva, pArgs->uEndRva - pArgs->uStartRva, pArgs->fProt));
3895+ if (pArgs->paSegs)
3896+ {
3897+ AssertReturn(pArgs->iSegs < pArgs->cSegsAlloc, VERR_INTERNAL_ERROR_5);
3898+ pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
3899+ pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
3900+ pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
3901+ }
3902+ pArgs->iSegs++;
3903+ pArgs->uStartRva = pArgs->uEndRva;
3904+ }
3905+ pArgs->fProt |= fProt;
3906+
3907+ uint32_t const cbCommon = PAGE_SIZE - (uRvaSeg & PAGE_OFFSET_MASK);
3908+ if (cbCommon <= cbMapped)
3909+ {
3910+ fProt |= pArgs->fProt;
3911+ pArgs->uEndRva = uRvaSeg + cbMapped;
3912+ return VINF_SUCCESS; /* New segment was smaller than a page. */
3913+ }
3914+ cbMapped -= cbCommon;
3915+ uRvaSeg += cbCommon;
3916+ Assert(uRvaSeg - pArgs->uStartRva == PAGE_SIZE);
3917+ }
3918+
3919+ /* The current segment should end where the new one starts, no gaps. */
3920+ pArgs->uEndRva = uRvaSeg;
3921+
3922+ /* Emit the current segment */
3923+ Log2(("supLoadModuleCompileSegmentsCB: SUP Seg #%u: %#x LB %#x prot %#x\n",
3924+ pArgs->iSegs, pArgs->uStartRva, pArgs->uEndRva - pArgs->uStartRva, pArgs->fProt));
3925+ if (pArgs->paSegs)
3926+ {
3927+ AssertReturn(pArgs->iSegs < pArgs->cSegsAlloc, VERR_INTERNAL_ERROR_5);
3928+ pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
3929+ pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
3930+ pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
3931+ }
3932+ pArgs->iSegs++;
3933+ }
3934+ /* else: current segment is empty */
3935+
3936+ /* Start the new segment. */
3937+ Assert(!(uRvaSeg & PAGE_OFFSET_MASK));
3938+ pArgs->fProt = fProt;
3939+ pArgs->uStartRva = uRvaSeg;
3940+ pArgs->uEndRva = uRvaSeg + cbMapped;
3941+ return VINF_SUCCESS;
3942+}
3943+
3944+
3945+/**
3946+ * Worker for supLoadModule().
3947+ */
3948+static int supLoadModuleInner(RTLDRMOD hLdrMod, PSUPLDRLOAD pLoadReq, uint32_t cbImageWithEverything,
3949+ RTR0PTR uImageBase, size_t cbImage, const char *pszModule, const char *pszFilename,
3950+ bool fNativeLoader, bool fIsVMMR0, const char *pszSrvReqHandler,
3951+ uint32_t offSymTab, uint32_t cSymbols,
3952+ uint32_t offStrTab, size_t cbStrTab,
3953+ uint32_t offSegTab, uint32_t cSegments,
3954+ PRTERRINFO pErrInfo)
3955+{
3956+ /*
3957+ * Get the image bits.
3958+ */
3959+ SUPLDRRESIMPARGS Args = { pszModule, pErrInfo };
3960+ int rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase, supLoadModuleResolveImport, &Args);
3961+ if (RT_FAILURE(rc))
3962+ {
3963+ LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
3964+ if (!RTErrInfoIsSet(pErrInfo))
3965+ RTErrInfoSetF(pErrInfo, rc, "RTLdrGetBits failed");
3966+ return rc;
3967+ }
3968+
3969+ /*
3970+ * Get the entry points.
3971+ */
3972+ RTUINTPTR VMMR0EntryFast = 0;
3973+ RTUINTPTR VMMR0EntryEx = 0;
3974+ RTUINTPTR SrvReqHandler = 0;
3975+ RTUINTPTR ModuleInit = 0;
3976+ RTUINTPTR ModuleTerm = 0;
3977+ const char *pszEp = NULL;
3978+ if (fIsVMMR0)
3979+ {
3980+ rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase,
3981+ UINT32_MAX, pszEp = "VMMR0EntryFast", &VMMR0EntryFast);
3982+ if (RT_SUCCESS(rc))
3983+ rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase,
3984+ UINT32_MAX, pszEp = "VMMR0EntryEx", &VMMR0EntryEx);
3985+ }
3986+ else if (pszSrvReqHandler)
3987+ rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase,
3988+ UINT32_MAX, pszEp = pszSrvReqHandler, &SrvReqHandler);
3989+ if (RT_SUCCESS(rc))
3990+ {
3991+ int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase,
3992+ UINT32_MAX, pszEp = "ModuleInit", &ModuleInit);
3993+ if (RT_FAILURE(rc2))
3994+ ModuleInit = 0;
3995+
3996+ rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase,
3997+ UINT32_MAX, pszEp = "ModuleTerm", &ModuleTerm);
3998+ if (RT_FAILURE(rc2))
3999+ ModuleTerm = 0;
4000+ }
4001+ if (RT_FAILURE(rc))
4002+ {
4003+ LogRel(("SUP: Failed to get entry point '%s' for %s (%s) rc=%Rrc\n", pszEp, pszModule, pszFilename, rc));
4004+ return RTErrInfoSetF(pErrInfo, rc, "Failed to resolve entry point '%s'", pszEp);
4005+ }
4006+
4007+ /*
4008+ * Create the symbol and string tables.
4009+ */
4010+ SUPLDRCREATETABSARGS CreateArgs;
4011+ CreateArgs.cbImage = cbImage;
4012+ CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
4013+ CreateArgs.pszBase = (char *)&pLoadReq->u.In.abImage[offStrTab];
4014+ CreateArgs.psz = CreateArgs.pszBase;
4015+ rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
4016+ if (RT_FAILURE(rc))
4017+ {
4018+ LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
4019+ return RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSymbols #2 failed");
4020+ }
4021+ AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= cbStrTab);
4022+ AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= cSymbols);
4023+
4024+ /*
4025+ * Create the segment table.
4026+ */
4027+ SUPLDRCOMPSEGTABARGS SegArgs;
4028+ SegArgs.uStartRva = 0;
4029+ SegArgs.uEndRva = 0;
4030+ SegArgs.fProt = RTMEM_PROT_READ;
4031+ SegArgs.iSegs = 0;
4032+ SegArgs.cSegsAlloc = cSegments;
4033+ SegArgs.paSegs = (PSUPLDRSEG)&pLoadReq->u.In.abImage[offSegTab];
4034+ SegArgs.pErrInfo = pErrInfo;
4035+ rc = RTLdrEnumSegments(hLdrMod, supLoadModuleCompileSegmentsCB, &SegArgs);
4036+ if (RT_FAILURE(rc))
4037+ {
4038+ LogRel(("SUP: RTLdrEnumSegments failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
4039+ return RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSegments #2 failed");
4040+ }
4041+ SegArgs.uEndRva = cbImage;
4042+ if (SegArgs.uEndRva > SegArgs.uStartRva)
4043+ {
4044+ SegArgs.paSegs[SegArgs.iSegs].off = SegArgs.uStartRva;
4045+ SegArgs.paSegs[SegArgs.iSegs].cb = SegArgs.uEndRva - SegArgs.uStartRva;
4046+ SegArgs.paSegs[SegArgs.iSegs].fProt = SegArgs.fProt;
4047+ SegArgs.iSegs++;
4048+ }
4049+ for (uint32_t i = 0; i < SegArgs.iSegs; i++)
4050+ LogRel(("SUP: seg #%u: %c%c%c %#010RX32 LB %#010RX32\n", i, /** @todo LogRel2 */
4051+ SegArgs.paSegs[i].fProt & SUPLDR_PROT_READ ? 'R' : ' ',
4052+ SegArgs.paSegs[i].fProt & SUPLDR_PROT_WRITE ? 'W' : ' ',
4053+ SegArgs.paSegs[i].fProt & SUPLDR_PROT_EXEC ? 'X' : ' ',
4054+ SegArgs.paSegs[i].off, SegArgs.paSegs[i].cb));
4055+ AssertRelease(SegArgs.iSegs == cSegments);
4056+ AssertRelease(SegArgs.cSegsAlloc == cSegments);
4057+
4058+ /*
4059+ * Upload the image.
4060+ */
4061+ pLoadReq->Hdr.u32Cookie = g_u32Cookie;
4062+ pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
4063+ pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithEverything);
4064+ pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
4065+ pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
4066+ pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
4067+
4068+ pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
4069+ pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
4070+ if (fIsVMMR0)
4071+ {
4072+ pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
4073+ pLoadReq->u.In.EP.VMMR0.pvVMMR0 = uImageBase;
4074+ pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
4075+ pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
4076+ }
4077+ else if (pszSrvReqHandler)
4078+ {
4079+ pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
4080+ pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
4081+ pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
4082+ pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
4083+ pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
4084+ }
4085+ else
4086+ pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
4087+ pLoadReq->u.In.offStrTab = offStrTab;
4088+ pLoadReq->u.In.cbStrTab = (uint32_t)cbStrTab;
4089+ AssertRelease(pLoadReq->u.In.cbStrTab == cbStrTab);
4090+ pLoadReq->u.In.cbImageBits = (uint32_t)cbImage;
4091+ pLoadReq->u.In.offSymbols = offSymTab;
4092+ pLoadReq->u.In.cSymbols = cSymbols;
4093+ pLoadReq->u.In.offSegments = offSegTab;
4094+ pLoadReq->u.In.cSegments = cSegments;
4095+ pLoadReq->u.In.cbImageWithEverything = cbImageWithEverything;
4096+ pLoadReq->u.In.pvImageBase = uImageBase;
4097+ if (!g_uSupFakeMode)
4098+ {
4099+ rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithEverything));
4100+ if (RT_SUCCESS(rc))
4101+ rc = pLoadReq->Hdr.rc;
4102+ else
4103+ LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
4104+ }
4105+ else
4106+ rc = VINF_SUCCESS;
4107+ if ( RT_SUCCESS(rc)
4108+ || rc == VERR_ALREADY_LOADED /* A competing process. */
4109+ )
4110+ {
4111+ LogRel(("SUP: Loaded %s (%s) at %#RKv - ModuleInit at %RKv and ModuleTerm at %RKv%s\n",
4112+ pszModule, pszFilename, uImageBase, (RTR0PTR)ModuleInit, (RTR0PTR)ModuleTerm,
4113+ fNativeLoader ? " using the native ring-0 loader" : ""));
4114+ if (fIsVMMR0)
4115+ {
4116+ g_pvVMMR0 = uImageBase;
4117+ LogRel(("SUP: VMMR0EntryEx located at %RKv and VMMR0EntryFast at %RKv\n", (RTR0PTR)VMMR0EntryEx, (RTR0PTR)VMMR0EntryFast));
4118+ }
4119+#ifdef RT_OS_WINDOWS
4120+ LogRel(("SUP: windbg> .reload /f %s=%#RKv\n", pszFilename, uImageBase));
4121+#endif
4122+ return VINF_SUCCESS;
4123+ }
4124+
4125+ /*
4126+ * Failed, bail out.
4127+ */
4128+ LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
4129+ if ( pLoadReq->u.Out.uErrorMagic == SUPLDRLOAD_ERROR_MAGIC
4130+ && pLoadReq->u.Out.szError[0] != '\0')
4131+ {
4132+ LogRel(("SUP: %s\n", pLoadReq->u.Out.szError));
4133+ return RTErrInfoSet(pErrInfo, rc, pLoadReq->u.Out.szError);
4134+ }
4135+ return RTErrInfoSet(pErrInfo, rc, "SUP_IOCTL_LDR_LOAD failed");
4136+}
4137+
4138+
4139+/**
4140 * Worker for SUPR3LoadModule().
4141 *
4142 * @returns VBox status code.
4143@@ -356,6 +713,7 @@
4144 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
4145 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
4146 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
4147+ /** @todo abspath it right into SUPLDROPEN */
4148 AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
4149 char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
4150 rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
4151@@ -371,8 +729,8 @@
4152 * Open image file and figure its size.
4153 */
4154 RTLDRMOD hLdrMod;
4155- rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
4156- if (!RT_SUCCESS(rc))
4157+ rc = RTLdrOpenEx(pszFilename, 0 /*fFlags*/, RTLDRARCH_HOST, &hLdrMod, pErrInfo);
4158+ if (RT_FAILURE(rc))
4159 {
4160 LogRel(("SUP: RTLdrOpen failed for %s (%s) %Rrc\n", pszModule, pszFilename, rc));
4161 return rc;
4162@@ -385,230 +743,105 @@
4163 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
4164 if (RT_SUCCESS(rc))
4165 {
4166- const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
4167- const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
4168- const uint32_t cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
4169-
4170 /*
4171- * Open the R0 image.
4172+ * Figure out the number of segments needed first.
4173 */
4174- SUPLDROPEN OpenReq;
4175- OpenReq.Hdr.u32Cookie = g_u32Cookie;
4176- OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
4177- OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
4178- OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
4179- OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
4180- OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
4181- OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
4182- OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
4183- strcpy(OpenReq.u.In.szName, pszModule);
4184- strcpy(OpenReq.u.In.szFilename, pszFilename);
4185- if (!g_uSupFakeMode)
4186+ SUPLDRCOMPSEGTABARGS SegArgs;
4187+ SegArgs.uStartRva = 0;
4188+ SegArgs.uEndRva = 0;
4189+ SegArgs.fProt = RTMEM_PROT_READ;
4190+ SegArgs.iSegs = 0;
4191+ SegArgs.cSegsAlloc = 0;
4192+ SegArgs.paSegs = NULL;
4193+ SegArgs.pErrInfo = pErrInfo;
4194+ rc = RTLdrEnumSegments(hLdrMod, supLoadModuleCompileSegmentsCB, &SegArgs);
4195+ if (RT_SUCCESS(rc))
4196 {
4197- rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
4198- if (RT_SUCCESS(rc))
4199- rc = OpenReq.Hdr.rc;
4200- }
4201- else
4202- {
4203- OpenReq.u.Out.fNeedsLoading = true;
4204- OpenReq.u.Out.pvImageBase = 0xef423420;
4205- }
4206- *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
4207- if ( RT_SUCCESS(rc)
4208- && OpenReq.u.Out.fNeedsLoading)
4209- {
4210+ Assert(SegArgs.uEndRva <= RTLdrSize(hLdrMod));
4211+ SegArgs.uEndRva = RTLdrSize(hLdrMod);
4212+ if (SegArgs.uEndRva > SegArgs.uStartRva)
4213+ SegArgs.iSegs++;
4214+
4215+ const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
4216+ const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
4217+ const uint32_t offSegTab = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
4218+ const uint32_t cbImageWithEverything = RT_ALIGN_32(offSegTab + sizeof(SUPLDRSEG) * SegArgs.iSegs, 8);
4219+
4220 /*
4221- * We need to load it.
4222- * Allocate memory for the image bits.
4223+ * Open the R0 image.
4224 */
4225- PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
4226- if (pLoadReq)
4227+ SUPLDROPEN OpenReq;
4228+ OpenReq.Hdr.u32Cookie = g_u32Cookie;
4229+ OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
4230+ OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
4231+ OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
4232+ OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
4233+ OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
4234+ OpenReq.u.In.cbImageWithEverything = cbImageWithEverything;
4235+ OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
4236+ strcpy(OpenReq.u.In.szName, pszModule);
4237+ strcpy(OpenReq.u.In.szFilename, pszFilename);
4238+ if (!g_uSupFakeMode)
4239 {
4240+ rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
4241+ if (RT_SUCCESS(rc))
4242+ rc = OpenReq.Hdr.rc;
4243+ }
4244+ else
4245+ {
4246+ OpenReq.u.Out.fNeedsLoading = true;
4247+ OpenReq.u.Out.pvImageBase = 0xef423420;
4248+ }
4249+ *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
4250+ if ( RT_SUCCESS(rc)
4251+ && OpenReq.u.Out.fNeedsLoading)
4252+ {
4253 /*
4254- * Get the image bits.
4255+ * We need to load it.
4256+ *
4257+ * Allocate the request and pass it to an inner work function
4258+ * that populates it and sends it off to the driver.
4259 */
4260-
4261- SUPLDRRESIMPARGS Args = { pszModule, pErrInfo };
4262- rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4263- supLoadModuleResolveImport, &Args);
4264-
4265- if (RT_SUCCESS(rc))
4266+ const uint32_t cbLoadReq = SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithEverything);
4267+ PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(cbLoadReq);
4268+ if (pLoadReq)
4269 {
4270- /*
4271- * Get the entry points.
4272- */
4273- RTUINTPTR VMMR0EntryFast = 0;
4274- RTUINTPTR VMMR0EntryEx = 0;
4275- RTUINTPTR SrvReqHandler = 0;
4276- RTUINTPTR ModuleInit = 0;
4277- RTUINTPTR ModuleTerm = 0;
4278- const char *pszEp = NULL;
4279- if (fIsVMMR0)
4280- {
4281- rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4282- UINT32_MAX, pszEp = "VMMR0EntryFast", &VMMR0EntryFast);
4283- if (RT_SUCCESS(rc))
4284- rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4285- UINT32_MAX, pszEp = "VMMR0EntryEx", &VMMR0EntryEx);
4286- }
4287- else if (pszSrvReqHandler)
4288- rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4289- UINT32_MAX, pszEp = pszSrvReqHandler, &SrvReqHandler);
4290- if (RT_SUCCESS(rc))
4291- {
4292- int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4293- UINT32_MAX, pszEp = "ModuleInit", &ModuleInit);
4294- if (RT_FAILURE(rc2))
4295- ModuleInit = 0;
4296-
4297- rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
4298- UINT32_MAX, pszEp = "ModuleTerm", &ModuleTerm);
4299- if (RT_FAILURE(rc2))
4300- ModuleTerm = 0;
4301- }
4302- if (RT_SUCCESS(rc))
4303- {
4304- /*
4305- * Create the symbol and string tables.
4306- */
4307- SUPLDRCREATETABSARGS CreateArgs;
4308- CreateArgs.cbImage = CalcArgs.cbImage;
4309- CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
4310- CreateArgs.pszBase = (char *)&pLoadReq->u.In.abImage[offStrTab];
4311- CreateArgs.psz = CreateArgs.pszBase;
4312- rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
4313- if (RT_SUCCESS(rc))
4314- {
4315- AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
4316- AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
4317-
4318- /*
4319- * Upload the image.
4320- */
4321- pLoadReq->Hdr.u32Cookie = g_u32Cookie;
4322- pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
4323- pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
4324- pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
4325- pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
4326- pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
4327-
4328- pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;
4329- pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;
4330- if (fIsVMMR0)
4331- {
4332- pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;
4333- pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;
4334- pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
4335- pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;
4336- }
4337- else if (pszSrvReqHandler)
4338- {
4339- pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;
4340- pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
4341- pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
4342- pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
4343- pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
4344- }
4345- else
4346- pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;
4347- pLoadReq->u.In.offStrTab = offStrTab;
4348- pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;
4349- AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
4350- pLoadReq->u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
4351- pLoadReq->u.In.offSymbols = offSymTab;
4352- pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;
4353- pLoadReq->u.In.cbImageWithTabs = cbImageWithTabs;
4354- pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;
4355- if (!g_uSupFakeMode)
4356- {
4357- rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
4358- if (RT_SUCCESS(rc))
4359- rc = pLoadReq->Hdr.rc;
4360- else
4361- LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
4362- }
4363- else
4364- rc = VINF_SUCCESS;
4365- if ( RT_SUCCESS(rc)
4366- || rc == VERR_ALREADY_LOADED /* A competing process. */
4367- )
4368- {
4369- LogRel(("SUP: Loaded %s (%s) at %#RKv - ModuleInit at %RKv and ModuleTerm at %RKv%s\n",
4370- pszModule, pszFilename, OpenReq.u.Out.pvImageBase, (RTR0PTR)ModuleInit, (RTR0PTR)ModuleTerm,
4371- OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
4372- if (fIsVMMR0)
4373- {
4374- g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
4375- LogRel(("SUP: VMMR0EntryEx located at %RKv and VMMR0EntryFast at %RKv\n", (RTR0PTR)VMMR0EntryEx, (RTR0PTR)VMMR0EntryFast));
4376- }
4377-#ifdef RT_OS_WINDOWS
4378- LogRel(("SUP: windbg> .reload /f %s=%#RKv\n", pszFilename, OpenReq.u.Out.pvImageBase));
4379-#endif
4380-
4381- RTMemTmpFree(pLoadReq);
4382- RTLdrClose(hLdrMod);
4383- return VINF_SUCCESS;
4384- }
4385-
4386- /*
4387- * Failed, bail out.
4388- */
4389- LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
4390- if ( pLoadReq->u.Out.uErrorMagic == SUPLDRLOAD_ERROR_MAGIC
4391- && pLoadReq->u.Out.szError[0] != '\0')
4392- {
4393- LogRel(("SUP: %s\n", pLoadReq->u.Out.szError));
4394- RTErrInfoSet(pErrInfo, rc, pLoadReq->u.Out.szError);
4395- }
4396- else
4397- RTErrInfoSet(pErrInfo, rc, "SUP_IOCTL_LDR_LOAD failed");
4398- }
4399- else
4400- {
4401- LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
4402- RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSymbols #2 failed");
4403- }
4404- }
4405- else
4406- {
4407- LogRel(("SUP: Failed to get entry point '%s' for %s (%s) rc=%Rrc\n", pszEp, pszModule, pszFilename, rc));
4408- RTErrInfoSetF(pErrInfo, rc, "Failed to resolve entry point '%s'", pszEp);
4409- }
4410+ rc = supLoadModuleInner(hLdrMod, pLoadReq, cbImageWithEverything, OpenReq.u.Out.pvImageBase, CalcArgs.cbImage,
4411+ pszModule, pszFilename, OpenReq.u.Out.fNativeLoader, fIsVMMR0, pszSrvReqHandler,
4412+ offSymTab, CalcArgs.cSymbols,
4413+ offStrTab, CalcArgs.cbStrings,
4414+ offSegTab, SegArgs.iSegs,
4415+ pErrInfo);
4416+ RTMemTmpFree(pLoadReq);
4417 }
4418 else
4419 {
4420- LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
4421- if (!RTErrInfoIsSet(pErrInfo))
4422- RTErrInfoSetF(pErrInfo, rc, "RTLdrGetBits failed");
4423+ AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithEverything)));
4424+ rc = RTErrInfoSetF(pErrInfo, VERR_NO_TMP_MEMORY, "Failed to allocate %u bytes for the load request",
4425+ SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithEverything));
4426 }
4427- RTMemTmpFree(pLoadReq);
4428 }
4429- else
4430+ /*
4431+ * Already loaded?
4432+ */
4433+ else if (RT_SUCCESS(rc))
4434 {
4435- AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
4436- rc = VERR_NO_TMP_MEMORY;
4437- RTErrInfoSetF(pErrInfo, rc, "Failed to allocate %u bytes for the load request", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
4438- }
4439- }
4440- /*
4441- * Already loaded?
4442- */
4443- else if (RT_SUCCESS(rc))
4444- {
4445- if (fIsVMMR0)
4446- g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
4447- LogRel(("SUP: Opened %s (%s) at %#RKv%s.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
4448- OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
4449+ if (fIsVMMR0)
4450+ g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
4451+ LogRel(("SUP: Opened %s (%s) at %#RKv%s.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
4452+ OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
4453 #ifdef RT_OS_WINDOWS
4454- LogRel(("SUP: windbg> .reload /f %s=%#RKv\n", pszFilename, OpenReq.u.Out.pvImageBase));
4455+ LogRel(("SUP: windbg> .reload /f %s=%#RKv\n", pszFilename, OpenReq.u.Out.pvImageBase));
4456 #endif
4457+ }
4458+ /*
4459+ * No, failed.
4460+ */
4461+ else
4462+ RTErrInfoSet(pErrInfo, rc, "SUP_IOCTL_LDR_OPEN failed");
4463 }
4464- /*
4465- * No, failed.
4466- */
4467- else
4468- RTErrInfoSet(pErrInfo, rc, "SUP_IOCTL_LDR_OPEN failed");
4469+ else if (!RTErrInfoIsSet(pErrInfo) && pErrInfo)
4470+ RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSegments #1 failed");
4471 }
4472 else
4473 RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSymbols #1 failed");
4474Index: src/VBox/HostDrivers/Support/SUPDrvIOC.h
4475===================================================================
4476diff --git a/src/VBox/HostDrivers/Support/SUPDrvIOC.h b/src/VBox/HostDrivers/Support/SUPDrvIOC.h
4477--- a/src/VBox/HostDrivers/Support/SUPDrvIOC.h (revision 85506)
4478+++ b/src/VBox/HostDrivers/Support/SUPDrvIOC.h (revision 85507)
4479@@ -220,9 +220,9 @@
4480 * -# When increment the major number, execute all pending work.
4481 *
4482 * @todo Pending work on next major version change:
4483- * - Move SUP_IOCTL_FAST_DO_NOP and SUP_VMMR0_DO_NEM_RUN after NEM.
4484+ * - Nothing.
4485 */
4486-#define SUPDRV_IOC_VERSION 0x002d0001
4487+#define SUPDRV_IOC_VERSION 0x002e0000
4488
4489 /** SUP_IOCTL_COOKIE. */
4490 typedef struct SUPCOOKIE
4491@@ -314,8 +314,8 @@
4492 {
4493 struct
4494 {
4495- /** Size of the image we'll be loading (including tables). */
4496- uint32_t cbImageWithTabs;
4497+ /** Size of the image we'll be loading (including all tables). */
4498+ uint32_t cbImageWithEverything;
4499 /** The size of the image bits. (Less or equal to cbImageWithTabs.) */
4500 uint32_t cbImageBits;
4501 /** Image name.
4502@@ -390,7 +390,30 @@
4503 /** Pointer to a const symbol table entry. */
4504 typedef SUPLDRSYM const *PCSUPLDRSYM;
4505
4506+#define SUPLDR_PROT_READ 1 /**< Grant read access (RTMEM_PROT_READ). */
4507+#define SUPLDR_PROT_WRITE 2 /**< Grant write access (RTMEM_PROT_WRITE). */
4508+#define SUPLDR_PROT_EXEC 4 /**< Grant execute access (RTMEM_PROT_EXEC). */
4509+
4510 /**
4511+ * A segment table entry - chiefly for conveying memory protection.
4512+ */
4513+typedef struct SUPLDRSEG
4514+{
4515+ /** The RVA of the segment. */
4516+ uint32_t off;
4517+ /** The size of the segment. */
4518+ uint32_t cb : 28;
4519+ /** The segment protection (SUPLDR_PROT_XXX). */
4520+ uint32_t fProt : 3;
4521+ /** MBZ. */
4522+ uint32_t fUnused;
4523+} SUPLDRSEG;
4524+/** Pointer to a segment table entry. */
4525+typedef SUPLDRSEG *PSUPLDRSEG;
4526+/** Pointer to a const segment table entry. */
4527+typedef SUPLDRSEG const *PCSUPLDRSEG;
4528+
4529+/**
4530 * SUPLDRLOAD::u::In::EP type.
4531 */
4532 typedef enum SUPLDRLOADEP
4533@@ -443,7 +466,7 @@
4534 /** The size of the image bits (starting at offset 0 and
4535 * approaching offSymbols). */
4536 uint32_t cbImageBits;
4537- /** The offset of the symbol table. */
4538+ /** The offset of the symbol table (SUPLDRSYM array). */
4539 uint32_t offSymbols;
4540 /** The number of entries in the symbol table. */
4541 uint32_t cSymbols;
4542@@ -451,8 +474,12 @@
4543 uint32_t offStrTab;
4544 /** Size of the string table. */
4545 uint32_t cbStrTab;
4546+ /** Offset to the segment table (SUPLDRSEG array). */
4547+ uint32_t offSegments;
4548+ /** Number of segments. */
4549+ uint32_t cSegments;
4550 /** Size of image data in achImage. */
4551- uint32_t cbImageWithTabs;
4552+ uint32_t cbImageWithEverything;
4553 /** The image data. */
4554 uint8_t abImage[1];
4555 } In;
4556Index: src/VBox/HostDrivers/Support/SUPDrvInternal.h
4557===================================================================
4558diff --git a/src/VBox/HostDrivers/Support/SUPDrvInternal.h b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
4559--- a/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85506)
4560+++ b/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85507)
4561@@ -146,6 +146,13 @@
4562 #endif
4563
4564
4565+#if 0 /*def RT_OS_LINUX*/
4566+/** Use the RTR0MemObj API rather than the RTMemExecAlloc for the images.
4567+ * This is a good idea in general, but a necessity for @bugref{9801}. */
4568+# define SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
4569+#endif
4570+
4571+
4572 /**
4573 * OS debug print macro.
4574 */
4575@@ -326,15 +333,20 @@
4576 struct SUPDRVLDRIMAGE * volatile pNext;
4577 /** Pointer to the image. */
4578 void *pvImage;
4579+#ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
4580+ /** The memory object for the module allocation. */
4581+ RTR0MEMOBJ hMemObjImage;
4582+#else
4583 /** Pointer to the allocated image buffer.
4584 * pvImage is 32-byte aligned or it may governed by the native loader (this
4585 * member is NULL then). */
4586 void *pvImageAlloc;
4587+#endif
4588 /** Magic value (SUPDRVLDRIMAGE_MAGIC). */
4589 uint32_t uMagic;
4590 /** Size of the image including the tables. This is mainly for verification
4591 * of the load request. */
4592- uint32_t cbImageWithTabs;
4593+ uint32_t cbImageWithEverything;
4594 /** Size of the image. */
4595 uint32_t cbImageBits;
4596 /** The number of entries in the symbol table. */
4597@@ -345,6 +357,10 @@
4598 char *pachStrTab;
4599 /** Size of the string table. */
4600 uint32_t cbStrTab;
4601+ /** Number of segments. */
4602+ uint32_t cSegments;
4603+ /** Segments (for memory protection). */
4604+ PSUPLDRSEG paSegments;
4605 /** Pointer to the optional module initialization callback. */
4606 PFNR0MODULEINIT pfnModuleInit;
4607 /** Pointer to the optional module termination callback. */
4608Index: src/VBox/HostDrivers/Support/SUPDrv.cpp
4609===================================================================
4610diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp
4611--- a/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85506)
4612+++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85507)
4613@@ -1732,11 +1732,10 @@
4614 /* validate */
4615 PSUPLDROPEN pReq = (PSUPLDROPEN)pReqHdr;
4616 REQ_CHECK_SIZES(SUP_IOCTL_LDR_OPEN);
4617- REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageWithTabs > 0);
4618- REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageWithTabs < 16*_1M);
4619+ REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageWithEverything > 0);
4620+ REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageWithEverything < 16*_1M);
4621 REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageBits > 0);
4622- REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageBits > 0);
4623- REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageBits < pReq->u.In.cbImageWithTabs);
4624+ REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.cbImageBits < pReq->u.In.cbImageWithEverything);
4625 REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, pReq->u.In.szName[0]);
4626 REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, RTStrEnd(pReq->u.In.szName, sizeof(pReq->u.In.szName)));
4627 REQ_CHECK_EXPR(SUP_IOCTL_LDR_OPEN, supdrvIsLdrModuleNameValid(pReq->u.In.szName));
4628@@ -1752,19 +1751,29 @@
4629 /* validate */
4630 PSUPLDRLOAD pReq = (PSUPLDRLOAD)pReqHdr;
4631 REQ_CHECK_EXPR(Name, pReq->Hdr.cbIn >= SUP_IOCTL_LDR_LOAD_SIZE_IN(32));
4632- REQ_CHECK_SIZES_EX(SUP_IOCTL_LDR_LOAD, SUP_IOCTL_LDR_LOAD_SIZE_IN(pReq->u.In.cbImageWithTabs), SUP_IOCTL_LDR_LOAD_SIZE_OUT);
4633- REQ_CHECK_EXPR(SUP_IOCTL_LDR_LOAD, pReq->u.In.cSymbols <= 16384);
4634+ REQ_CHECK_SIZES_EX(SUP_IOCTL_LDR_LOAD, SUP_IOCTL_LDR_LOAD_SIZE_IN(pReq->u.In.cbImageWithEverything), SUP_IOCTL_LDR_LOAD_SIZE_OUT);
4635 REQ_CHECK_EXPR_FMT( !pReq->u.In.cSymbols
4636- || ( pReq->u.In.offSymbols < pReq->u.In.cbImageWithTabs
4637- && pReq->u.In.offSymbols + pReq->u.In.cSymbols * sizeof(SUPLDRSYM) <= pReq->u.In.cbImageWithTabs),
4638- ("SUP_IOCTL_LDR_LOAD: offSymbols=%#lx cSymbols=%#lx cbImageWithTabs=%#lx\n", (long)pReq->u.In.offSymbols,
4639- (long)pReq->u.In.cSymbols, (long)pReq->u.In.cbImageWithTabs));
4640+ || ( pReq->u.In.cSymbols <= 16384
4641+ && pReq->u.In.offSymbols >= pReq->u.In.cbImageBits
4642+ && pReq->u.In.offSymbols < pReq->u.In.cbImageWithEverything
4643+ && pReq->u.In.offSymbols + pReq->u.In.cSymbols * sizeof(SUPLDRSYM) <= pReq->u.In.cbImageWithEverything),
4644+ ("SUP_IOCTL_LDR_LOAD: offSymbols=%#lx cSymbols=%#lx cbImageWithEverything=%#lx\n", (long)pReq->u.In.offSymbols,
4645+ (long)pReq->u.In.cSymbols, (long)pReq->u.In.cbImageWithEverything));
4646 REQ_CHECK_EXPR_FMT( !pReq->u.In.cbStrTab
4647- || ( pReq->u.In.offStrTab < pReq->u.In.cbImageWithTabs
4648- && pReq->u.In.offStrTab + pReq->u.In.cbStrTab <= pReq->u.In.cbImageWithTabs
4649- && pReq->u.In.cbStrTab <= pReq->u.In.cbImageWithTabs),
4650- ("SUP_IOCTL_LDR_LOAD: offStrTab=%#lx cbStrTab=%#lx cbImageWithTabs=%#lx\n", (long)pReq->u.In.offStrTab,
4651- (long)pReq->u.In.cbStrTab, (long)pReq->u.In.cbImageWithTabs));
4652+ || ( pReq->u.In.offStrTab < pReq->u.In.cbImageWithEverything
4653+ && pReq->u.In.offStrTab >= pReq->u.In.cbImageBits
4654+ && pReq->u.In.offStrTab + pReq->u.In.cbStrTab <= pReq->u.In.cbImageWithEverything
4655+ && pReq->u.In.cbStrTab <= pReq->u.In.cbImageWithEverything),
4656+ ("SUP_IOCTL_LDR_LOAD: offStrTab=%#lx cbStrTab=%#lx cbImageWithEverything=%#lx\n", (long)pReq->u.In.offStrTab,
4657+ (long)pReq->u.In.cbStrTab, (long)pReq->u.In.cbImageWithEverything));
4658+ REQ_CHECK_EXPR_FMT( pReq->u.In.cSegments >= 1
4659+ && pReq->u.In.cSegments <= 128
4660+ && pReq->u.In.cSegments <= pReq->u.In.cbImageBits / PAGE_SIZE
4661+ && pReq->u.In.offSegments >= pReq->u.In.cbImageBits
4662+ && pReq->u.In.offSegments < pReq->u.In.cbImageWithEverything
4663+ && pReq->u.In.offSegments + pReq->u.In.cSegments * sizeof(SUPLDRSEG) <= pReq->u.In.cbImageWithEverything,
4664+ ("SUP_IOCTL_LDR_LOAD: offSegments=%#lx cSegments=%#lx cbImageWithEverything=%#lx\n", (long)pReq->u.In.offSegments,
4665+ (long)pReq->u.In.cSegments, (long)pReq->u.In.cbImageWithEverything));
4666
4667 if (pReq->u.In.cSymbols)
4668 {
4669@@ -1772,15 +1781,37 @@
4670 PSUPLDRSYM paSyms = (PSUPLDRSYM)&pReq->u.In.abImage[pReq->u.In.offSymbols];
4671 for (i = 0; i < pReq->u.In.cSymbols; i++)
4672 {
4673- REQ_CHECK_EXPR_FMT(paSyms[i].offSymbol < pReq->u.In.cbImageWithTabs,
4674- ("SUP_IOCTL_LDR_LOAD: sym #%ld: symb off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offSymbol, (long)pReq->u.In.cbImageWithTabs));
4675+ REQ_CHECK_EXPR_FMT(paSyms[i].offSymbol < pReq->u.In.cbImageWithEverything,
4676+ ("SUP_IOCTL_LDR_LOAD: sym #%ld: symb off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offSymbol, (long)pReq->u.In.cbImageWithEverything));
4677 REQ_CHECK_EXPR_FMT(paSyms[i].offName < pReq->u.In.cbStrTab,
4678- ("SUP_IOCTL_LDR_LOAD: sym #%ld: name off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithTabs));
4679+ ("SUP_IOCTL_LDR_LOAD: sym #%ld: name off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithEverything));
4680 REQ_CHECK_EXPR_FMT(RTStrEnd((char const *)&pReq->u.In.abImage[pReq->u.In.offStrTab + paSyms[i].offName],
4681 pReq->u.In.cbStrTab - paSyms[i].offName),
4682- ("SUP_IOCTL_LDR_LOAD: sym #%ld: unterminated name! (%#lx / %#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithTabs));
4683+ ("SUP_IOCTL_LDR_LOAD: sym #%ld: unterminated name! (%#lx / %#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithEverything));
4684 }
4685 }
4686+ {
4687+ uint32_t i;
4688+ uint32_t offPrevEnd = 0;
4689+ PSUPLDRSEG paSegs = (PSUPLDRSEG)&pReq->u.In.abImage[pReq->u.In.offSegments];
4690+ for (i = 0; i < pReq->u.In.cSegments; i++)
4691+ {
4692+ REQ_CHECK_EXPR_FMT(paSegs[i].off < pReq->u.In.cbImageBits && !(paSegs[i].off & PAGE_OFFSET_MASK),
4693+ ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx (max=%#lx)\n", (long)i, (long)paSegs[i].off, (long)pReq->u.In.cbImageBits));
4694+ REQ_CHECK_EXPR_FMT(paSegs[i].cb <= pReq->u.In.cbImageBits,
4695+ ("SUP_IOCTL_LDR_LOAD: seg #%ld: cb %#lx (max=%#lx)\n", (long)i, (long)paSegs[i].cb, (long)pReq->u.In.cbImageBits));
4696+ REQ_CHECK_EXPR_FMT(paSegs[i].off + paSegs[i].cb <= pReq->u.In.cbImageBits,
4697+ ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx + cb %#lx = %#lx (max=%#lx)\n", (long)i, (long)paSegs[i].off, (long)paSegs[i].cb, (long)(paSegs[i].off + paSegs[i].cb), (long)pReq->u.In.cbImageBits));
4698+ REQ_CHECK_EXPR_FMT(paSegs[i].fProt != 0,
4699+ ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx + cb %#lx\n", (long)i, (long)paSegs[i].off, (long)paSegs[i].cb));
4700+ REQ_CHECK_EXPR_FMT(paSegs[i].fUnused == 0, ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx\n", (long)i, (long)paSegs[i].off));
4701+ REQ_CHECK_EXPR_FMT(offPrevEnd == paSegs[i].off,
4702+ ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx offPrevEnd %#lx\n", (long)i, (long)paSegs[i].off, (long)offPrevEnd));
4703+ offPrevEnd = paSegs[i].off + paSegs[i].cb;
4704+ }
4705+ REQ_CHECK_EXPR_FMT(offPrevEnd == pReq->u.In.cbImageBits,
4706+ ("SUP_IOCTL_LDR_LOAD: offPrevEnd %#lx cbImageBits %#lx\n", (long)i, (long)offPrevEnd, (long)pReq->u.In.cbImageBits));
4707+ }
4708
4709 /* execute */
4710 pReq->Hdr.rc = supdrvIOCtl_LdrLoad(pDevExt, pSession, pReq);
4711@@ -5023,7 +5054,7 @@
4712 size_t cchName = strlen(pReq->u.In.szName); /* (caller checked < 32). */
4713 SUPDRV_CHECK_SMAP_SETUP();
4714 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
4715- LogFlow(("supdrvIOCtl_LdrOpen: szName=%s cbImageWithTabs=%d\n", pReq->u.In.szName, pReq->u.In.cbImageWithTabs));
4716+ LogFlow(("supdrvIOCtl_LdrOpen: szName=%s cbImageWithEverything=%d\n", pReq->u.In.szName, pReq->u.In.cbImageWithEverything));
4717
4718 /*
4719 * Check if we got an instance of the image already.
4720@@ -5037,7 +5068,8 @@
4721 {
4722 if (RT_LIKELY(pImage->cUsage < UINT32_MAX / 2U))
4723 {
4724- /** @todo check cbImageBits and cbImageWithTabs here, if they differs that indicates that the images are different. */
4725+ /** @todo check cbImageBits and cbImageWithEverything here, if they differs
4726+ * that indicates that the images are different. */
4727 pImage->cUsage++;
4728 pReq->u.Out.pvImageBase = pImage->pvImage;
4729 pReq->u.Out.fNeedsLoading = pImage->uState == SUP_IOCTL_LDR_OPEN;
4730@@ -5080,13 +5112,19 @@
4731 */
4732 pImage = (PSUPDRVLDRIMAGE)pv;
4733 pImage->pvImage = NULL;
4734+#ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
4735+ pImage->hMemObjImage = NIL_RTR0MEMOBJ;
4736+#else
4737 pImage->pvImageAlloc = NULL;
4738- pImage->cbImageWithTabs = pReq->u.In.cbImageWithTabs;
4739+#endif
4740+ pImage->cbImageWithEverything = pReq->u.In.cbImageWithEverything;
4741 pImage->cbImageBits = pReq->u.In.cbImageBits;
4742 pImage->cSymbols = 0;
4743 pImage->paSymbols = NULL;
4744 pImage->pachStrTab = NULL;
4745 pImage->cbStrTab = 0;
4746+ pImage->cSegments = 0;
4747+ pImage->paSegments = NULL;
4748 pImage->pfnModuleInit = NULL;
4749 pImage->pfnModuleTerm = NULL;
4750 pImage->pfnServiceReqHandler = NULL;
4751@@ -5104,10 +5142,19 @@
4752 rc = supdrvOSLdrOpen(pDevExt, pImage, pReq->u.In.szFilename);
4753 if (rc == VERR_NOT_SUPPORTED)
4754 {
4755+#ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
4756+ rc = RTR0MemObjAllocPage(&pImage->hMemObjImage, pImage->cbImageBits, true /*fExecutable*/);
4757+ if (RT_SUCCESS(rc))
4758+ {
4759+ pImage->pvImage = RTR0MemObjAddress(pImage->hMemObjImage);
4760+ pImage->fNative = false;
4761+ }
4762+#else
4763 pImage->pvImageAlloc = RTMemExecAlloc(pImage->cbImageBits + 31);
4764 pImage->pvImage = RT_ALIGN_P(pImage->pvImageAlloc, 32);
4765 pImage->fNative = false;
4766 rc = pImage->pvImageAlloc ? VINF_SUCCESS : VERR_NO_EXEC_MEMORY;
4767+#endif
4768 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
4769 }
4770 if (RT_FAILURE(rc))
4771@@ -5140,41 +5187,83 @@
4772
4773
4774 /**
4775+ * Formats a load error message.
4776+ *
4777+ * @returns @a rc
4778+ * @param rc Return code.
4779+ * @param pReq The request.
4780+ * @param pszFormat The error message format string.
4781+ * @param ... Argument to the format string.
4782+ */
4783+int VBOXCALL supdrvLdrLoadError(int rc, PSUPLDRLOAD pReq, const char *pszFormat, ...)
4784+{
4785+ va_list va;
4786+ va_start(va, pszFormat);
4787+ pReq->u.Out.uErrorMagic = SUPLDRLOAD_ERROR_MAGIC;
4788+ RTStrPrintfV(pReq->u.Out.szError, sizeof(pReq->u.Out.szError), pszFormat, va);
4789+ va_end(va);
4790+ Log(("SUP_IOCTL_LDR_LOAD: %s [rc=%Rrc]\n", pReq->u.Out.szError, rc));
4791+ return rc;
4792+}
4793+
4794+
4795+/**
4796 * Worker that validates a pointer to an image entrypoint.
4797 *
4798+ * Calls supdrvLdrLoadError on error.
4799+ *
4800 * @returns IPRT status code.
4801 * @param pDevExt The device globals.
4802 * @param pImage The loader image.
4803 * @param pv The pointer into the image.
4804 * @param fMayBeNull Whether it may be NULL.
4805- * @param fCheckNative Whether to check with the native loaders.
4806- * @param pszSymbol The entrypoint name or log name. If the symbol
4807+ * @param pszSymbol The entrypoint name or log name. If the symbol is
4808 * capitalized it signifies a specific symbol, otherwise it
4809 * for logging.
4810 * @param pbImageBits The image bits prepared by ring-3.
4811+ * @param pReq The request for passing to supdrvLdrLoadError.
4812 *
4813- * @remarks Will leave the lock on failure.
4814+ * @note Will leave the loader lock on failure!
4815 */
4816 static int supdrvLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, bool fMayBeNull,
4817- bool fCheckNative, const uint8_t *pbImageBits, const char *pszSymbol)
4818+ const uint8_t *pbImageBits, const char *pszSymbol, PSUPLDRLOAD pReq)
4819 {
4820 if (!fMayBeNull || pv)
4821 {
4822- if ((uintptr_t)pv - (uintptr_t)pImage->pvImage >= pImage->cbImageBits)
4823+ uint32_t iSeg;
4824+
4825+ /* Must be within the image bits: */
4826+ uintptr_t const uRva = (uintptr_t)pv - (uintptr_t)pImage->pvImage;
4827+ if (uRva >= pImage->cbImageBits)
4828 {
4829 supdrvLdrUnlock(pDevExt);
4830- Log(("Out of range (%p LB %#x): %s=%p\n", pImage->pvImage, pImage->cbImageBits, pszSymbol, pv));
4831- return VERR_INVALID_PARAMETER;
4832+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq,
4833+ "Invalid entry point address %p given for %s: RVA %#zx, image size %#zx",
4834+ pv, pszSymbol, uRva, pImage->cbImageBits);
4835 }
4836
4837- if (pImage->fNative && fCheckNative)
4838+ /* Must be in an executable segment: */
4839+ for (iSeg = 0; iSeg < pImage->cSegments; iSeg++)
4840+ if (uRva - pImage->paSegments[iSeg].off < (uintptr_t)pImage->paSegments[iSeg].cb)
4841+ {
4842+ if (pImage->paSegments[iSeg].fProt & SUPLDR_PROT_EXEC)
4843+ break;
4844+ supdrvLdrUnlock(pDevExt);
4845+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq,
4846+ "Bad entry point %p given for %s: not executable (seg #%u: %#RX32 LB %#RX32 prot %#x)",
4847+ pv, pszSymbol, iSeg, pImage->paSegments[iSeg].off, pImage->paSegments[iSeg].cb,
4848+ pImage->paSegments[iSeg].fProt);
4849+ }
4850+
4851+ if (pImage->fNative)
4852 {
4853+ /** @todo pass pReq along to the native code. */
4854 int rc = supdrvOSLdrValidatePointer(pDevExt, pImage, pv, pbImageBits, pszSymbol);
4855 if (RT_FAILURE(rc))
4856 {
4857 supdrvLdrUnlock(pDevExt);
4858- Log(("Bad entry point address: %s=%p (rc=%Rrc)\n", pszSymbol, pv, rc));
4859- return rc;
4860+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq,
4861+ "Bad entry point address %p for %s: rc=%Rrc\n", pv, pszSymbol, rc);
4862 }
4863 }
4864 }
4865@@ -5183,27 +5272,6 @@
4866
4867
4868 /**
4869- * Formats a load error message.
4870- *
4871- * @returns @a rc
4872- * @param rc Return code.
4873- * @param pReq The request.
4874- * @param pszFormat The error message format string.
4875- * @param ... Argument to the format string.
4876- */
4877-int VBOXCALL supdrvLdrLoadError(int rc, PSUPLDRLOAD pReq, const char *pszFormat, ...)
4878-{
4879- va_list va;
4880- va_start(va, pszFormat);
4881- pReq->u.Out.uErrorMagic = SUPLDRLOAD_ERROR_MAGIC;
4882- RTStrPrintfV(pReq->u.Out.szError, sizeof(pReq->u.Out.szError), pszFormat, va);
4883- va_end(va);
4884- Log(("SUP_IOCTL_LDR_LOAD: %s [rc=%Rrc]\n", pReq->u.Out.szError, rc));
4885- return rc;
4886-}
4887-
4888-
4889-/**
4890 * Loads the image bits.
4891 *
4892 * This is the 2nd step of the loading.
4893@@ -5219,7 +5287,7 @@
4894 PSUPDRVLDRIMAGE pImage;
4895 int rc;
4896 SUPDRV_CHECK_SMAP_SETUP();
4897- LogFlow(("supdrvIOCtl_LdrLoad: pvImageBase=%p cbImageWithBits=%d\n", pReq->u.In.pvImageBase, pReq->u.In.cbImageWithTabs));
4898+ LogFlow(("supdrvIOCtl_LdrLoad: pvImageBase=%p cbImageWithEverything=%d\n", pReq->u.In.pvImageBase, pReq->u.In.cbImageWithEverything));
4899 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
4900
4901 /*
4902@@ -5241,12 +5309,12 @@
4903 /*
4904 * Validate input.
4905 */
4906- if ( pImage->cbImageWithTabs != pReq->u.In.cbImageWithTabs
4907- || pImage->cbImageBits != pReq->u.In.cbImageBits)
4908+ if ( pImage->cbImageWithEverything != pReq->u.In.cbImageWithEverything
4909+ || pImage->cbImageBits != pReq->u.In.cbImageBits)
4910 {
4911 supdrvLdrUnlock(pDevExt);
4912- return supdrvLdrLoadError(VERR_INVALID_HANDLE, pReq, "Image size mismatch found: %d(prep) != %d(load) or %d != %d",
4913- pImage->cbImageWithTabs, pReq->u.In.cbImageWithTabs, pImage->cbImageBits, pReq->u.In.cbImageBits);
4914+ return supdrvLdrLoadError(VERR_INVALID_HANDLE, pReq, "Image size mismatch found: %u(prep) != %u(load) or %u != %u",
4915+ pImage->cbImageWithEverything, pReq->u.In.cbImageWithEverything, pImage->cbImageBits, pReq->u.In.cbImageBits);
4916 }
4917
4918 if (pImage->uState != SUP_IOCTL_LDR_OPEN)
4919@@ -5272,29 +5340,30 @@
4920 break;
4921
4922 case SUPLDRLOADEP_VMMR0:
4923- rc = supdrvLdrValidatePointer( pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0, false, false, pReq->u.In.abImage, "pvVMMR0");
4924- if (RT_SUCCESS(rc))
4925- rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0EntryFast, false, true, pReq->u.In.abImage, "VMMR0EntryFast");
4926- if (RT_SUCCESS(rc))
4927- rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0EntryEx, false, true, pReq->u.In.abImage, "VMMR0EntryEx");
4928+ if (pReq->u.In.EP.VMMR0.pvVMMR0 != pImage->pvImage)
4929+ {
4930+ supdrvLdrUnlock(pDevExt);
4931+ return supdrvLdrLoadError(rc, pReq, "Invalid pvVMMR0 pointer: %p, expected %p", pReq->u.In.EP.VMMR0.pvVMMR0, pImage->pvImage);
4932+ }
4933+ rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0EntryFast, false, pReq->u.In.abImage, "VMMR0EntryFast", pReq);
4934 if (RT_FAILURE(rc))
4935- return supdrvLdrLoadError(rc, pReq, "Invalid VMMR0 pointer");
4936+ return rc;
4937+ rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0EntryEx, false, pReq->u.In.abImage, "VMMR0EntryEx", pReq);
4938+ if (RT_FAILURE(rc))
4939+ return rc;
4940 break;
4941
4942 case SUPLDRLOADEP_SERVICE:
4943- rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.Service.pfnServiceReq, false, true, pReq->u.In.abImage, "pfnServiceReq");
4944+ rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.Service.pfnServiceReq, false, pReq->u.In.abImage, "pfnServiceReq", pReq);
4945 if (RT_FAILURE(rc))
4946- return supdrvLdrLoadError(rc, pReq, "Invalid pfnServiceReq pointer: %p", pReq->u.In.EP.Service.pfnServiceReq);
4947+ return rc;
4948 if ( pReq->u.In.EP.Service.apvReserved[0] != NIL_RTR0PTR
4949 || pReq->u.In.EP.Service.apvReserved[1] != NIL_RTR0PTR
4950 || pReq->u.In.EP.Service.apvReserved[2] != NIL_RTR0PTR)
4951 {
4952 supdrvLdrUnlock(pDevExt);
4953- return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq,
4954- "Out of range (%p LB %#x): apvReserved={%p,%p,%p} MBZ!",
4955- pImage->pvImage, pReq->u.In.cbImageWithTabs,
4956- pReq->u.In.EP.Service.apvReserved[0],
4957- pReq->u.In.EP.Service.apvReserved[1],
4958+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq, "apvReserved={%p,%p,%p} MBZ!",
4959+ pReq->u.In.EP.Service.apvReserved[0], pReq->u.In.EP.Service.apvReserved[1],
4960 pReq->u.In.EP.Service.apvReserved[2]);
4961 }
4962 break;
4963@@ -5304,12 +5373,12 @@
4964 return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq, "Invalid eEPType=%d", pReq->u.In.eEPType);
4965 }
4966
4967- rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.pfnModuleInit, true, true, pReq->u.In.abImage, "ModuleInit");
4968+ rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.pfnModuleInit, true, pReq->u.In.abImage, "ModuleInit", pReq);
4969 if (RT_FAILURE(rc))
4970- return supdrvLdrLoadError(rc, pReq, "Invalid pfnModuleInit pointer: %p", pReq->u.In.pfnModuleInit);
4971- rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.pfnModuleTerm, true, true, pReq->u.In.abImage, "ModuleTerm");
4972+ return rc;
4973+ rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.pfnModuleTerm, true, pReq->u.In.abImage, "ModuleTerm", pReq);
4974 if (RT_FAILURE(rc))
4975- return supdrvLdrLoadError(rc, pReq, "Invalid pfnModuleTerm pointer: %p", pReq->u.In.pfnModuleTerm);
4976+ return rc;
4977 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
4978
4979 /*
4980@@ -5321,10 +5390,8 @@
4981 pImage->cbStrTab = pReq->u.In.cbStrTab;
4982 if (pImage->cbStrTab)
4983 {
4984- pImage->pachStrTab = (char *)RTMemAlloc(pImage->cbStrTab);
4985- if (pImage->pachStrTab)
4986- memcpy(pImage->pachStrTab, &pReq->u.In.abImage[pReq->u.In.offStrTab], pImage->cbStrTab);
4987- else
4988+ pImage->pachStrTab = (char *)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offStrTab], pImage->cbStrTab);
4989+ if (!pImage->pachStrTab)
4990 rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for string table: %#x", pImage->cbStrTab);
4991 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
4992 }
4993@@ -5333,17 +5400,27 @@
4994 if (RT_SUCCESS(rc) && pImage->cSymbols)
4995 {
4996 size_t cbSymbols = pImage->cSymbols * sizeof(SUPLDRSYM);
4997- pImage->paSymbols = (PSUPLDRSYM)RTMemAlloc(cbSymbols);
4998- if (pImage->paSymbols)
4999- memcpy(pImage->paSymbols, &pReq->u.In.abImage[pReq->u.In.offSymbols], cbSymbols);
5000- else
5001+ pImage->paSymbols = (PSUPLDRSYM)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSymbols], cbSymbols);
5002+ if (!pImage->paSymbols)
5003 rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for symbol table: %#x", cbSymbols);
5004 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5005 }
5006+
5007+ pImage->cSegments = pReq->u.In.cSegments;
5008+ if (RT_SUCCESS(rc))
5009+ {
5010+ size_t cbSegments = pImage->cSegments * sizeof(SUPLDRSEG);
5011+ pImage->paSegments = (PSUPLDRSEG)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSegments], cbSegments);
5012+ if (pImage->paSegments) /* Align the last segment size to avoid upsetting RTR0MemObjProtect. */ /** @todo relax RTR0MemObjProtect */
5013+ pImage->paSegments[pImage->cSegments - 1].cb = RT_ALIGN_32(pImage->paSegments[pImage->cSegments - 1].cb, PAGE_SIZE);
5014+ else
5015+ rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for segment table: %#x", cbSegments);
5016+ SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5017+ }
5018 }
5019
5020 /*
5021- * Copy the bits / complete native loading.
5022+ * Copy the bits and apply permissions / complete native loading.
5023 */
5024 if (RT_SUCCESS(rc))
5025 {
5026@@ -5355,7 +5432,26 @@
5027 rc = supdrvOSLdrLoad(pDevExt, pImage, pReq->u.In.abImage, pReq);
5028 else
5029 {
5030+#ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
5031+ uint32_t i;
5032 memcpy(pImage->pvImage, &pReq->u.In.abImage[0], pImage->cbImageBits);
5033+
5034+ for (i = 0; i < pImage->cSegments; i++)
5035+ {
5036+ rc = RTR0MemObjProtect(pImage->hMemObjImage, pImage->paSegments[i].off, pImage->paSegments[i].cb,
5037+ pImage->paSegments[i].fProt);
5038+ if (RT_SUCCESS(rc))
5039+ continue;
5040+ if (rc == VERR_NOT_SUPPORTED)
5041+ rc = VINF_SUCCESS;
5042+ else
5043+ rc = supdrvLdrLoadError(rc, pReq, "RTR0MemObjProtect failed on seg#%u %#RX32 LB %#RX32 fProt=%#x",
5044+ i, pImage->paSegments[i].off, pImage->paSegments[i].cb, pImage->paSegments[i].fProt);
5045+ break;
5046+ }
5047+#else
5048+ memcpy(pImage->pvImage, &pReq->u.In.abImage[0], pImage->cbImageBits);
5049+#endif
5050 Log(("vboxdrv: Loaded '%s' at %p\n", pImage->szName, pImage->pvImage));
5051 }
5052 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5053@@ -5950,12 +6046,20 @@
5054 pImage->pDevExt = NULL;
5055 pImage->pNext = NULL;
5056 pImage->uState = SUP_IOCTL_LDR_FREE;
5057+#ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
5058+ RTR0MemObjFree(pImage->hMemObjImage, true /*fMappings*/);
5059+ pImage->hMemObjImage = NIL_RTR0MEMOBJ;
5060+#else
5061 RTMemExecFree(pImage->pvImageAlloc, pImage->cbImageBits + 31);
5062 pImage->pvImageAlloc = NULL;
5063+#endif
5064+ pImage->pvImage = NULL;
5065 RTMemFree(pImage->pachStrTab);
5066 pImage->pachStrTab = NULL;
5067 RTMemFree(pImage->paSymbols);
5068 pImage->paSymbols = NULL;
5069+ RTMemFree(pImage->paSegments);
5070+ pImage->paSegments = NULL;
5071 RTMemFree(pImage);
5072 }
5073
5074Index: include/VBox/sup.h
5075===================================================================
5076diff --git a/include/VBox/sup.h b/include/VBox/sup.h
5077--- a/include/VBox/sup.h (revision 85508)
5078+++ b/include/VBox/sup.h (revision 85509)
5079@@ -1555,6 +1555,7 @@
5080 *
5081 * @returns VBox status code.
5082 * @deprecated Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
5083+ * @param pszFilename Full path to the VMMR0.r0 file (silly).
5084 * @param pErrInfo Where to return extended error information.
5085 * Optional.
5086 */
5087Index: src/VBox/HostDrivers/Support/SUPDrv.cpp
5088===================================================================
5089diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp
5090--- a/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85509)
5091+++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85510)
5092@@ -5343,7 +5343,7 @@
5093 if (pReq->u.In.EP.VMMR0.pvVMMR0 != pImage->pvImage)
5094 {
5095 supdrvLdrUnlock(pDevExt);
5096- return supdrvLdrLoadError(rc, pReq, "Invalid pvVMMR0 pointer: %p, expected %p", pReq->u.In.EP.VMMR0.pvVMMR0, pImage->pvImage);
5097+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq, "Invalid pvVMMR0 pointer: %p, expected %p", pReq->u.In.EP.VMMR0.pvVMMR0, pImage->pvImage);
5098 }
5099 rc = supdrvLdrValidatePointer(pDevExt, pImage, pReq->u.In.EP.VMMR0.pvVMMR0EntryFast, false, pReq->u.In.abImage, "VMMR0EntryFast", pReq);
5100 if (RT_FAILURE(rc))
5101Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5102===================================================================
5103diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5104--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85510)
5105+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85511)
5106@@ -593,7 +593,8 @@
5107 LogRel(("SUP: RTLdrEnumSegments failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
5108 return RTErrInfoSetF(pErrInfo, rc, "RTLdrEnumSegments #2 failed");
5109 }
5110- SegArgs.uEndRva = cbImage;
5111+ SegArgs.uEndRva = (uint32_t)cbImage;
5112+ AssertReturn(SegArgs.uEndRva == cbImage, VERR_OUT_OF_RANGE);
5113 if (SegArgs.uEndRva > SegArgs.uStartRva)
5114 {
5115 SegArgs.paSegs[SegArgs.iSegs].off = SegArgs.uStartRva;
5116@@ -758,7 +759,7 @@
5117 if (RT_SUCCESS(rc))
5118 {
5119 Assert(SegArgs.uEndRva <= RTLdrSize(hLdrMod));
5120- SegArgs.uEndRva = RTLdrSize(hLdrMod);
5121+ SegArgs.uEndRva = (uint32_t)CalcArgs.cbImage; /* overflow is checked later */
5122 if (SegArgs.uEndRva > SegArgs.uStartRva)
5123 SegArgs.iSegs++;
5124
5125Index: src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
5126===================================================================
5127diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
5128--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85513)
5129+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85514)
5130@@ -52,6 +52,13 @@
5131 # define PAGE_READONLY_EXEC PAGE_READONLY
5132 #endif
5133
5134+/** @def IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5135+ * Whether we use alloc_vm_area (3.2+) for executable memory.
5136+ * This is a must for 5.8+, but we'll enable it for earlier kernels later. */
5137+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || defined(DOXYGEN_RUNNING)
5138+# define IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5139+#endif
5140+
5141 /*
5142 * 2.6.29+ kernels don't work with remap_pfn_range() anymore because
5143 * track_pfn_vma_new() is apparently not defined for non-RAM pages.
5144@@ -105,7 +112,7 @@
5145 bool fExecutable;
5146 /** Set if we've vmap'ed the memory into ring-0. */
5147 bool fMappedToRing0;
5148-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
5149+#ifdef IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5150 /** Return from alloc_vm_area() that we now need to use for executable
5151 * memory. */
5152 struct vm_struct *pArea;
5153@@ -544,7 +551,7 @@
5154 pgprot_val(fPg) |= _PAGE_NX;
5155 # endif
5156
5157-# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
5158+# ifdef IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5159 if (fExecutable)
5160 {
5161 pte_t **papPtes = (pte_t **)kmalloc_array(pMemLnx->cPages, sizeof(papPtes[0]), GFP_KERNEL);
5162@@ -612,7 +619,7 @@
5163 static void rtR0MemObjLinuxVUnmap(PRTR0MEMOBJLNX pMemLnx)
5164 {
5165 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
5166-# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
5167+# ifdef IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5168 if (pMemLnx->pArea)
5169 {
5170 # if 0
5171@@ -1828,7 +1835,7 @@
5172
5173 DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
5174 {
5175-# if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
5176+# ifdef IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5177 /*
5178 * Currently only supported when we've got addresses PTEs from the kernel.
5179 */
5180Index: src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
5181===================================================================
5182diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
5183--- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85515)
5184+++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c (revision 85516)
5185@@ -54,8 +54,9 @@
5186
5187 /** @def IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5188 * Whether we use alloc_vm_area (3.2+) for executable memory.
5189- * This is a must for 5.8+, but we'll enable it for earlier kernels later. */
5190-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) || defined(DOXYGEN_RUNNING)
5191+ * This is a must for 5.8+, but we enable it all the way back to 3.2.x for
5192+ * better W^R compliance (fExecutable flag). */
5193+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || defined(DOXYGEN_RUNNING)
5194 # define IPRT_USE_ALLOC_VM_AREA_FOR_EXEC
5195 #endif
5196
5197Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5198===================================================================
5199diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5200--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85516)
5201+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85517)
5202@@ -497,7 +497,7 @@
5203 }
5204
5205
5206-/**
5207+/**
5208 * Worker for supLoadModule().
5209 */
5210 static int supLoadModuleInner(RTLDRMOD hLdrMod, PSUPLDRLOAD pLoadReq, uint32_t cbImageWithEverything,
5211Index: src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
5212===================================================================
5213diff --git a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
5214--- a/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h (revision 85517)
5215+++ b/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h (revision 85518)
5216@@ -176,6 +176,11 @@
5217 # include <asm/set_memory.h>
5218 #endif
5219
5220+/* for __flush_tlb_all() */
5221+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
5222+# include <asm/tlbflush.h>
5223+#endif
5224+
5225 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
5226 # include <asm/smap.h>
5227 #else
5228Index: src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5229===================================================================
5230diff --git a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5231--- a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85524)
5232+++ b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85525)
5233@@ -133,6 +133,8 @@
5234 /** Base section number, either 1 or zero depending on whether we've
5235 * re-used the NULL entry for .elf.headers in ET_EXEC/ET_DYN. */
5236 unsigned iFirstSect;
5237+ /** Set if the SHF_ALLOC section headers are in order of sh_addr. */
5238+ bool fShdrInOrder;
5239 /** The size of the loaded image. */
5240 size_t cbImage;
5241
5242@@ -1376,6 +1378,45 @@
5243 return NULL;
5244 }
5245
5246+/**
5247+ * Helper that locates the next allocated section logically by RVA (sh_addr).
5248+ *
5249+ * @returns Pointer to the section header if found, NULL if none.
5250+ * @param pModElf The module instance.
5251+ * @param iCur The current section header.
5252+ */
5253+static const Elf_Shdr *RTLDRELF_NAME(GetNextAllocatedSection)(PRTLDRMODELF pModElf, unsigned iCur)
5254+{
5255+ unsigned const cShdrs = pModElf->Ehdr.e_shnum;
5256+ const Elf_Shdr * const paShdrs = pModElf->paShdrs;
5257+ if (pModElf->fShdrInOrder)
5258+ {
5259+ for (; iCur < cShdrs; iCur++)
5260+ if (paShdrs[iCur].sh_flags & SHF_ALLOC)
5261+ return &paShdrs[iCur];
5262+ }
5263+ else
5264+ {
5265+ Elf_Addr const uEndCur = paShdrs[iCur].sh_addr + paShdrs[iCur].sh_size;
5266+ Elf_Addr offBest = ~(Elf_Addr)0;
5267+ unsigned iBest = cShdrs;
5268+ for (iCur = pModElf->iFirstSect; iCur < cShdrs; iCur++)
5269+ if (paShdrs[iCur].sh_flags & SHF_ALLOC)
5270+ {
5271+ Elf_Addr const offDelta = paShdrs[iCur].sh_addr - uEndCur;
5272+ if ( offDelta < offBest
5273+ && paShdrs[iCur].sh_addr >= uEndCur)
5274+ {
5275+ offBest = offDelta;
5276+ iBest = iCur;
5277+ }
5278+ }
5279+ if (iBest < cShdrs)
5280+ return &paShdrs[iBest];
5281+ }
5282+ return NULL;
5283+}
5284+
5285 /** @copydoc RTLDROPS::pfnEnumSegments. */
5286 static DECLCALLBACK(int) RTLDRELF_NAME(EnumSegments)(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
5287 {
5288@@ -1427,14 +1468,11 @@
5289 {
5290 Seg.LinkAddress = paOrgShdrs[iShdr].sh_addr;
5291 Seg.RVA = paShdrs[iShdr].sh_addr;
5292- const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&paShdrs[iShdr + 1],
5293- pModElf->Ehdr.e_shnum - iShdr - 1);
5294- if ( pShdr2
5295- && pShdr2->sh_addr >= paShdrs[iShdr].sh_addr
5296- && Seg.RVA >= uPrevMappedRva)
5297+ const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetNextAllocatedSection)(pModElf, iShdr);
5298+ if (pShdr2)
5299 Seg.cbMapped = pShdr2->sh_addr - paShdrs[iShdr].sh_addr;
5300 else
5301- Seg.cbMapped = RT_MAX(paShdrs[iShdr].sh_size, paShdrs[iShdr].sh_addralign);
5302+ Seg.cbMapped = pModElf->cbImage - paShdrs[iShdr].sh_addr;
5303 uPrevMappedRva = Seg.RVA;
5304 }
5305 else
5306@@ -2837,6 +2875,7 @@
5307 //pModElf->Dyn.cbStr = 0;
5308 //pModElf->Dyn.pStr = NULL;
5309 //pModElf->iFirstSect = 0;
5310+ //pModElf->fShdrInOrder = false;
5311 //pModElf->cbImage = 0;
5312 pModElf->LinkAddress = ~(Elf_Addr)0;
5313 //pModElf->cbShStr = 0;
5314@@ -2939,9 +2978,27 @@
5315 }
5316 }
5317
5318- Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
5319+ /*
5320+ * Check if the sections are in order by address, as that will simplify
5321+ * enumeration and address translation.
5322+ */
5323+ pModElf->fShdrInOrder = true;
5324+ Elf_Addr uEndAddr = 0;
5325+ for (unsigned i = pModElf->iFirstSect; i < pModElf->Ehdr.e_shnum; i++)
5326+ if (paShdrs[i].sh_flags & SHF_ALLOC)
5327+ {
5328+ if (uEndAddr <= paShdrs[i].sh_addr)
5329+ uEndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
5330+ else
5331+ {
5332+ pModElf->fShdrInOrder = false;
5333+ break;
5334+ }
5335+ }
5336+
5337+ Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR " fShdrInOrder=%RTbool\n",
5338 pModElf->Rel.iSymSh, pModElf->Rel.cSyms, pModElf->Rel.iStrSh, pModElf->Rel.cbStr, rc,
5339- pModElf->cbImage, pModElf->LinkAddress));
5340+ pModElf->cbImage, pModElf->LinkAddress, pModElf->fShdrInOrder));
5341 if (RT_SUCCESS(rc))
5342 {
5343 pModElf->Core.pOps = &RTLDRELF_MID(s_rtldrElf,Ops);
5344Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5345===================================================================
5346diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5347--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85524)
5348+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85525)
5349@@ -373,8 +373,8 @@
5350 uint32_t cbMapped = (uint32_t)pSeg->cbMapped;
5351 AssertReturn(pSeg->RVA < _1G, VERR_INTERNAL_ERROR_3);
5352 uint32_t uRvaSeg = (uint32_t)pSeg->RVA;
5353- Log2(("supLoadModuleCompileSegmentsCB: %RTptr/%RTptr LB %RTptr prot %#x %s\n",
5354- pSeg->LinkAddress, pSeg->RVA, pSeg->cbMapped, pSeg->fProt, pSeg->pszName));
5355+ Log2(("supLoadModuleCompileSegmentsCB: %RTptr/%RTptr LB %RTptr/%RTptr prot %#x %s\n",
5356+ pSeg->LinkAddress, pSeg->RVA, pSeg->cbMapped, pSeg->cb, pSeg->fProt, pSeg->pszName));
5357
5358 /*
5359 * If the protection is the same as the previous segment,
5360Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5361===================================================================
5362diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5363--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85525)
5364+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85526)
5365@@ -450,9 +450,10 @@
5366 if (pArgs->paSegs)
5367 {
5368 AssertReturn(pArgs->iSegs < pArgs->cSegsAlloc, VERR_INTERNAL_ERROR_5);
5369- pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
5370- pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
5371- pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
5372+ pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
5373+ pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
5374+ pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
5375+ pArgs->paSegs[pArgs->iSegs].fUnused = 0;
5376 }
5377 pArgs->iSegs++;
5378 pArgs->uStartRva = pArgs->uEndRva;
5379@@ -480,9 +481,10 @@
5380 if (pArgs->paSegs)
5381 {
5382 AssertReturn(pArgs->iSegs < pArgs->cSegsAlloc, VERR_INTERNAL_ERROR_5);
5383- pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
5384- pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
5385- pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
5386+ pArgs->paSegs[pArgs->iSegs].off = pArgs->uStartRva;
5387+ pArgs->paSegs[pArgs->iSegs].cb = pArgs->uEndRva - pArgs->uStartRva;
5388+ pArgs->paSegs[pArgs->iSegs].fProt = pArgs->fProt;
5389+ pArgs->paSegs[pArgs->iSegs].fUnused = 0;
5390 }
5391 pArgs->iSegs++;
5392 }
5393@@ -597,9 +599,10 @@
5394 AssertReturn(SegArgs.uEndRva == cbImage, VERR_OUT_OF_RANGE);
5395 if (SegArgs.uEndRva > SegArgs.uStartRva)
5396 {
5397- SegArgs.paSegs[SegArgs.iSegs].off = SegArgs.uStartRva;
5398- SegArgs.paSegs[SegArgs.iSegs].cb = SegArgs.uEndRva - SegArgs.uStartRva;
5399- SegArgs.paSegs[SegArgs.iSegs].fProt = SegArgs.fProt;
5400+ SegArgs.paSegs[SegArgs.iSegs].off = SegArgs.uStartRva;
5401+ SegArgs.paSegs[SegArgs.iSegs].cb = SegArgs.uEndRva - SegArgs.uStartRva;
5402+ SegArgs.paSegs[SegArgs.iSegs].fProt = SegArgs.fProt;
5403+ SegArgs.paSegs[SegArgs.iSegs].fUnused = 0;
5404 SegArgs.iSegs++;
5405 }
5406 for (uint32_t i = 0; i < SegArgs.iSegs; i++)
5407Index: src/VBox/HostDrivers/Support/SUPDrv.cpp
5408===================================================================
5409diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp
5410--- a/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85526)
5411+++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85527)
5412@@ -1804,7 +1804,7 @@
5413 ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx + cb %#lx = %#lx (max=%#lx)\n", (long)i, (long)paSegs[i].off, (long)paSegs[i].cb, (long)(paSegs[i].off + paSegs[i].cb), (long)pReq->u.In.cbImageBits));
5414 REQ_CHECK_EXPR_FMT(paSegs[i].fProt != 0,
5415 ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx + cb %#lx\n", (long)i, (long)paSegs[i].off, (long)paSegs[i].cb));
5416- REQ_CHECK_EXPR_FMT(paSegs[i].fUnused == 0, ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx\n", (long)i, (long)paSegs[i].off));
5417+ REQ_CHECK_EXPR_FMT(paSegs[i].fUnused == 0, ("SUP_IOCTL_LDR_LOAD: seg #%ld: fUnused=1\n", (long)i));
5418 REQ_CHECK_EXPR_FMT(offPrevEnd == paSegs[i].off,
5419 ("SUP_IOCTL_LDR_LOAD: seg #%ld: off %#lx offPrevEnd %#lx\n", (long)i, (long)paSegs[i].off, (long)offPrevEnd));
5420 offPrevEnd = paSegs[i].off + paSegs[i].cb;
5421Index: Config.kmk
5422===================================================================
5423diff --git a/Config.kmk b/Config.kmk
5424--- a/Config.kmk (revision 85532)
5425+++ b/Config.kmk (revision 85533)
5426@@ -4651,7 +4651,7 @@
5427 ## @todo WTF doesn't the globals work? Debug info is supposed to be split everywhere. GRR
5428 TEMPLATE_VBoxR0_LD_DEBUG = split
5429 endif
5430- if 0 #1of ($(KBUILD_TARGET), linux)
5431+ if1of ($(KBUILD_TARGET), linux)
5432 VBOX_WITH_VBOXR0_AS_DLL = 1
5433 TEMPLATE_VBoxR0_DLLSUFF = .r0
5434 TEMPLATE_VBoxR0_CFLAGS += -fPIC
5435Index: src/VBox/HostDrivers/Support/SUPDrvInternal.h
5436===================================================================
5437diff --git a/src/VBox/HostDrivers/Support/SUPDrvInternal.h b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
5438--- a/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85532)
5439+++ b/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85533)
5440@@ -145,8 +145,7 @@
5441 # define SUPDRV_USE_MUTEX_FOR_GIP
5442 #endif
5443
5444-
5445-#if 0 /*def RT_OS_LINUX*/
5446+#if defined(RT_OS_LINUX) /** @todo make everyone do this */
5447 /** Use the RTR0MemObj API rather than the RTMemExecAlloc for the images.
5448 * This is a good idea in general, but a necessity for @bugref{9801}. */
5449 # define SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
5450Index: src/VBox/HostDrivers/Support/SUPDrvInternal.h
5451===================================================================
5452diff --git a/src/VBox/HostDrivers/Support/SUPDrvInternal.h b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
5453--- a/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85533)
5454+++ b/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85534)
5455@@ -145,7 +145,7 @@
5456 # define SUPDRV_USE_MUTEX_FOR_GIP
5457 #endif
5458
5459-#if defined(RT_OS_LINUX) /** @todo make everyone do this */
5460+#if 0 /*defined(RT_OS_LINUX)*/ /** @todo make everyone do this */
5461 /** Use the RTR0MemObj API rather than the RTMemExecAlloc for the images.
5462 * This is a good idea in general, but a necessity for @bugref{9801}. */
5463 # define SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
5464Index: src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5465===================================================================
5466diff --git a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5467--- a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85539)
5468+++ b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85540)
5469@@ -1361,54 +1361,38 @@
5470
5471
5472 /**
5473- * Helper that locates the first allocated section.
5474+ * Locate the next allocated section by RVA (sh_addr).
5475 *
5476- * @returns Pointer to the section header if found, NULL if none.
5477- * @param pShdr The section header to start searching at.
5478- * @param cLeft The number of section headers left to search. Can be 0.
5479- */
5480-static const Elf_Shdr *RTLDRELF_NAME(GetFirstAllocatedSection)(const Elf_Shdr *pShdr, unsigned cLeft)
5481-{
5482- while (cLeft-- > 0)
5483- {
5484- if (pShdr->sh_flags & SHF_ALLOC)
5485- return pShdr;
5486- pShdr++;
5487- }
5488- return NULL;
5489-}
5490-
5491-/**
5492- * Helper that locates the next allocated section logically by RVA (sh_addr).
5493+ * This is a helper for EnumSegments and SegOffsetToRva.
5494 *
5495 * @returns Pointer to the section header if found, NULL if none.
5496- * @param pModElf The module instance.
5497- * @param iCur The current section header.
5498+ * @param pModElf The module instance.
5499+ * @param iShdrCur The current section header.
5500 */
5501-static const Elf_Shdr *RTLDRELF_NAME(GetNextAllocatedSection)(PRTLDRMODELF pModElf, unsigned iCur)
5502+static const Elf_Shdr *RTLDRELF_NAME(GetNextAllocatedSection)(PRTLDRMODELF pModElf, unsigned iShdrCur)
5503 {
5504 unsigned const cShdrs = pModElf->Ehdr.e_shnum;
5505 const Elf_Shdr * const paShdrs = pModElf->paShdrs;
5506 if (pModElf->fShdrInOrder)
5507 {
5508- for (; iCur < cShdrs; iCur++)
5509- if (paShdrs[iCur].sh_flags & SHF_ALLOC)
5510- return &paShdrs[iCur];
5511+ for (unsigned iShdr = iShdrCur + 1; iShdr < cShdrs; iShdr++)
5512+ if (paShdrs[iShdr].sh_flags & SHF_ALLOC)
5513+ return &paShdrs[iShdr];
5514 }
5515 else
5516 {
5517- Elf_Addr const uEndCur = paShdrs[iCur].sh_addr + paShdrs[iCur].sh_size;
5518+ Elf_Addr const uEndCur = paShdrs[iShdrCur].sh_addr + paShdrs[iShdrCur].sh_size;
5519 Elf_Addr offBest = ~(Elf_Addr)0;
5520 unsigned iBest = cShdrs;
5521- for (iCur = pModElf->iFirstSect; iCur < cShdrs; iCur++)
5522- if (paShdrs[iCur].sh_flags & SHF_ALLOC)
5523+ for (unsigned iShdr = pModElf->iFirstSect; iShdr < cShdrs; iShdr++)
5524+ if ((paShdrs[iShdr].sh_flags & SHF_ALLOC) && iShdr != iShdrCur)
5525 {
5526- Elf_Addr const offDelta = paShdrs[iCur].sh_addr - uEndCur;
5527+ Elf_Addr const offDelta = paShdrs[iShdr].sh_addr - uEndCur;
5528 if ( offDelta < offBest
5529- && paShdrs[iCur].sh_addr >= uEndCur)
5530+ && paShdrs[iShdr].sh_addr >= uEndCur)
5531 {
5532 offBest = offDelta;
5533- iBest = iCur;
5534+ iBest = iShdr;
5535 }
5536 }
5537 if (iBest < cShdrs)
5538@@ -1417,6 +1401,7 @@
5539 return NULL;
5540 }
5541
5542+
5543 /** @copydoc RTLDROPS::pfnEnumSegments. */
5544 static DECLCALLBACK(int) RTLDRELF_NAME(EnumSegments)(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser)
5545 {
5546@@ -1562,8 +1547,7 @@
5547 iSeg += pModElf->iFirstSect; /* skip section 0 if not used */
5548 if (offSeg > pModElf->paShdrs[iSeg].sh_size)
5549 {
5550- const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetFirstAllocatedSection)(&pModElf->paShdrs[iSeg + 1],
5551- pModElf->Ehdr.e_shnum - iSeg - 1);
5552+ const Elf_Shdr *pShdr2 = RTLDRELF_NAME(GetNextAllocatedSection)(pModElf, iSeg);
5553 if ( !pShdr2
5554 || offSeg > (pShdr2->sh_addr - pModElf->paShdrs[iSeg].sh_addr))
5555 return VERR_LDR_INVALID_SEG_OFFSET;
5556Index: src/VBox/Runtime/testcase/tstLdr-4.cpp
5557===================================================================
5558diff --git a/src/VBox/Runtime/testcase/tstLdr-4.cpp b/src/VBox/Runtime/testcase/tstLdr-4.cpp
5559--- a/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85540)
5560+++ b/src/VBox/Runtime/testcase/tstLdr-4.cpp (revision 85541)
5561@@ -60,6 +60,16 @@
5562 , *piSeg, pSeg->RVA, pSeg->cbMapped, pSeg->pszName,
5563 pSeg->LinkAddress, pSeg->cb, pSeg->Alignment, pSeg->fProt, pSeg->offFile);
5564
5565+ if (pSeg->RVA != NIL_RTLDRADDR)
5566+ {
5567+ RTTESTI_CHECK(pSeg->cbMapped != NIL_RTLDRADDR);
5568+ RTTESTI_CHECK(pSeg->cbMapped >= pSeg->cb);
5569+ }
5570+ else
5571+ {
5572+ RTTESTI_CHECK(pSeg->cbMapped == NIL_RTLDRADDR);
5573+ }
5574+
5575 /*
5576 * Do some address conversion tests:
5577 */
5578Index: src/VBox/HostDrivers/Support/SUPDrv.cpp
5579===================================================================
5580diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp
5581--- a/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85544)
5582+++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp (revision 85545)
5583@@ -5254,6 +5254,13 @@
5584 pv, pszSymbol, iSeg, pImage->paSegments[iSeg].off, pImage->paSegments[iSeg].cb,
5585 pImage->paSegments[iSeg].fProt);
5586 }
5587+ if (iSeg >= pImage->cSegments)
5588+ {
5589+ supdrvLdrUnlock(pDevExt);
5590+ return supdrvLdrLoadError(VERR_INVALID_PARAMETER, pReq,
5591+ "Bad entry point %p given for %s: no matching segment found (RVA %#zx)!",
5592+ pv, pszSymbol, uRva);
5593+ }
5594
5595 if (pImage->fNative)
5596 {
5597@@ -5334,6 +5341,26 @@
5598 return supdrvLdrLoadError(VERR_PERMISSION_DENIED, pReq, "Loader is locked down");
5599 }
5600
5601+ /*
5602+ * Copy the segments before we start using supdrvLdrValidatePointer for entrypoint validation.
5603+ */
5604+ pImage->cSegments = pReq->u.In.cSegments;
5605+ {
5606+ size_t cbSegments = pImage->cSegments * sizeof(SUPLDRSEG);
5607+ pImage->paSegments = (PSUPLDRSEG)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSegments], cbSegments);
5608+ if (pImage->paSegments) /* Align the last segment size to avoid upsetting RTR0MemObjProtect. */ /** @todo relax RTR0MemObjProtect */
5609+ pImage->paSegments[pImage->cSegments - 1].cb = RT_ALIGN_32(pImage->paSegments[pImage->cSegments - 1].cb, PAGE_SIZE);
5610+ else
5611+ {
5612+ supdrvLdrUnlock(pDevExt);
5613+ return supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for segment table: %#x", cbSegments);
5614+ }
5615+ SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5616+ }
5617+
5618+ /*
5619+ * Validate entrypoints.
5620+ */
5621 switch (pReq->u.In.eEPType)
5622 {
5623 case SUPLDRLOADEP_NOTHING:
5624@@ -5405,18 +5432,6 @@
5625 rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for symbol table: %#x", cbSymbols);
5626 SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5627 }
5628-
5629- pImage->cSegments = pReq->u.In.cSegments;
5630- if (RT_SUCCESS(rc))
5631- {
5632- size_t cbSegments = pImage->cSegments * sizeof(SUPLDRSEG);
5633- pImage->paSegments = (PSUPLDRSEG)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSegments], cbSegments);
5634- if (pImage->paSegments) /* Align the last segment size to avoid upsetting RTR0MemObjProtect. */ /** @todo relax RTR0MemObjProtect */
5635- pImage->paSegments[pImage->cSegments - 1].cb = RT_ALIGN_32(pImage->paSegments[pImage->cSegments - 1].cb, PAGE_SIZE);
5636- else
5637- rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for segment table: %#x", cbSegments);
5638- SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING);
5639- }
5640 }
5641
5642 /*
5643Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5644===================================================================
5645diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5646--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85545)
5647+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85546)
5648@@ -358,9 +358,15 @@
5649 AssertCompile(RTMEM_PROT_EXEC == SUPLDR_PROT_EXEC);
5650 RT_NOREF(hLdrMod);
5651
5652+ Log2(("supLoadModuleCompileSegmentsCB: %RTptr/%RTptr LB %RTptr/%RTptr prot %#x %s\n",
5653+ pSeg->LinkAddress, pSeg->RVA, pSeg->cbMapped, pSeg->cb, pSeg->fProt, pSeg->pszName));
5654+
5655 /* Ignore segments not part of the loaded image. */
5656 if (pSeg->RVA == NIL_RTLDRADDR || pSeg->cbMapped == 0)
5657+ {
5658+ Log2(("supLoadModuleCompileSegmentsCB: -> skipped\n"));
5659 return VINF_SUCCESS;
5660+ }
5661
5662 /* We currently ASSUME that all relevant segments are in ascending RVA order. */
5663 AssertReturn(pSeg->RVA >= pArgs->uEndRva,
5664@@ -373,8 +379,6 @@
5665 uint32_t cbMapped = (uint32_t)pSeg->cbMapped;
5666 AssertReturn(pSeg->RVA < _1G, VERR_INTERNAL_ERROR_3);
5667 uint32_t uRvaSeg = (uint32_t)pSeg->RVA;
5668- Log2(("supLoadModuleCompileSegmentsCB: %RTptr/%RTptr LB %RTptr/%RTptr prot %#x %s\n",
5669- pSeg->LinkAddress, pSeg->RVA, pSeg->cbMapped, pSeg->cb, pSeg->fProt, pSeg->pszName));
5670
5671 /*
5672 * If the protection is the same as the previous segment,
5673Index: src/VBox/HostDrivers/Support/SUPDrvInternal.h
5674===================================================================
5675diff --git a/src/VBox/HostDrivers/Support/SUPDrvInternal.h b/src/VBox/HostDrivers/Support/SUPDrvInternal.h
5676--- a/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85551)
5677+++ b/src/VBox/HostDrivers/Support/SUPDrvInternal.h (revision 85552)
5678@@ -145,7 +145,7 @@
5679 # define SUPDRV_USE_MUTEX_FOR_GIP
5680 #endif
5681
5682-#if 0 /*defined(RT_OS_LINUX)*/ /** @todo make everyone do this */
5683+#if defined(RT_OS_LINUX) /** @todo make everyone do this */
5684 /** Use the RTR0MemObj API rather than the RTMemExecAlloc for the images.
5685 * This is a good idea in general, but a necessity for @bugref{9801}. */
5686 # define SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
5687Index: src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5688===================================================================
5689diff --git a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
5690--- a/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85554)
5691+++ b/src/VBox/HostDrivers/Support/SUPLibLdr.cpp (revision 85555)
5692@@ -392,7 +392,7 @@
5693 if (pSeg->fProt == pArgs->fProt)
5694 {
5695 pArgs->uEndRva = uRvaSeg + cbMapped;
5696- Log2(("supLoadModuleCompileSegmentsCB: -> merged\n"));
5697+ Log2(("supLoadModuleCompileSegmentsCB: -> merged, end %#x\n", pArgs->uEndRva));
5698 return VINF_SUCCESS;
5699 }
5700
5701@@ -419,7 +419,8 @@
5702 if (cbCommon >= cbMapped)
5703 {
5704 pArgs->uEndRva = uRvaSeg + cbMapped;
5705- Log2(("supLoadModuleCompileSegmentsCB: -> merge, %#x common, upgrading prot to %#x\n", cbCommon, pArgs->fProt));
5706+ Log2(("supLoadModuleCompileSegmentsCB: -> merge, %#x common, upgrading prot to %#x, end %#x\n",
5707+ cbCommon, pArgs->fProt, pArgs->uEndRva));
5708 return VINF_SUCCESS; /* New segment was smaller than a page. */
5709 }
5710 cbMapped -= cbCommon;
5711@@ -437,7 +438,7 @@
5712 {
5713 pArgs->fProt = fProt;
5714 pArgs->uEndRva = uRvaSeg + cbMapped;
5715- Log2(("supLoadModuleCompileSegmentsCB: -> upgrade current protection\n"));
5716+ Log2(("supLoadModuleCompileSegmentsCB: -> upgrade current protection, end %#x\n", pArgs->uEndRva));
5717 return VINF_SUCCESS; /* Current segment was smaller than a page. */
5718 }
5719 Log2(("supLoadModuleCompileSegmentsCB: -> new, %#x common into new\n", (uint32_t)(pSeg->RVA & PAGE_OFFSET_MASK)));
5720@@ -445,7 +446,7 @@
5721 else
5722 {
5723 /* Create a new segment for the common page with the combined protection. */
5724- Log2(("supLoadModuleCompileSegmentsCB: -> its complicated...\n"));
5725+ Log2(("supLoadModuleCompileSegmentsCB: -> it's complicated...\n"));
5726 pArgs->uEndRva &= ~(uint32_t)PAGE_OFFSET_MASK;
5727 if (pArgs->uEndRva > pArgs->uStartRva)
5728 {
5729@@ -465,7 +466,7 @@
5730 pArgs->fProt |= fProt;
5731
5732 uint32_t const cbCommon = PAGE_SIZE - (uRvaSeg & PAGE_OFFSET_MASK);
5733- if (cbCommon <= cbMapped)
5734+ if (cbCommon >= cbMapped)
5735 {
5736 fProt |= pArgs->fProt;
5737 pArgs->uEndRva = uRvaSeg + cbMapped;
5738@@ -768,7 +769,11 @@
5739 Assert(SegArgs.uEndRva <= RTLdrSize(hLdrMod));
5740 SegArgs.uEndRva = (uint32_t)CalcArgs.cbImage; /* overflow is checked later */
5741 if (SegArgs.uEndRva > SegArgs.uStartRva)
5742+ {
5743+ Log2(("supLoadModule: SUP Seg #%u: %#x LB %#x prot %#x\n",
5744+ SegArgs.iSegs, SegArgs.uStartRva, SegArgs.uEndRva - SegArgs.uStartRva, SegArgs.fProt));
5745 SegArgs.iSegs++;
5746+ }
5747
5748 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
5749 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
5750Index: src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5751===================================================================
5752diff --git a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h
5753--- a/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85555)
5754+++ b/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h (revision 85556)
5755@@ -2858,7 +2858,7 @@
5756 pModElf->Dyn.iStrSh = ~0U;
5757 //pModElf->Dyn.cbStr = 0;
5758 //pModElf->Dyn.pStr = NULL;
5759- //pModElf->iFirstSect = 0;
5760+ pModElf->iFirstSect = 1;
5761 //pModElf->fShdrInOrder = false;
5762 //pModElf->cbImage = 0;
5763 pModElf->LinkAddress = ~(Elf_Addr)0;
5764Index: src/VBox/HostDrivers/Support/SUPDrvIOC.h
5765===================================================================
5766diff --git a/src/VBox/HostDrivers/Support/SUPDrvIOC.h b/src/VBox/HostDrivers/Support/SUPDrvIOC.h
5767--- a/src/VBox/HostDrivers/Support/SUPDrvIOC.h (revision 85589)
5768+++ b/src/VBox/HostDrivers/Support/SUPDrvIOC.h (revision 85590)
5769@@ -221,6 +221,7 @@
5770 *
5771 * @todo Pending work on next major version change:
5772 * - Nothing.
5773+ * @note 0x002f0000 is used by 6.0. The next version number must be 0x00300000.
5774 */
5775 #define SUPDRV_IOC_VERSION 0x002e0000
5776
This page took 0.810891 seconds and 4 git commands to generate.