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