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