VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstLdr-2.cpp@ 102792

Last change on this file since 102792 was 99775, checked in by vboxsync, 18 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.1 KB
Line 
1/* $Id: tstLdr-2.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * IPRT - Testcase for parts of RTLdr*, manual inspection.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/ldr.h>
42#include <iprt/alloc.h>
43#include <iprt/stream.h>
44#include <iprt/assert.h>
45#include <iprt/initterm.h>
46#include <VBox/dis.h>
47#include <iprt/errcore.h>
48#include <iprt/string.h>
49
50
51static bool MyDisBlock(uint8_t const *pbCodeBlock, int32_t cbMax)
52{
53 DISSTATE Dis;
54 int32_t i = 0;
55 while (i < cbMax)
56 {
57 char szOutput[256];
58 uint32_t cbInstr;
59 if (RT_FAILURE(DISInstrToStr(pbCodeBlock + i, DISCPUMODE_32BIT, &Dis, &cbInstr, szOutput, sizeof(szOutput))))
60 return false;
61
62 RTPrintf("%s", szOutput);
63
64 /* next */
65 i += cbInstr;
66 }
67 return true;
68}
69
70
71
72/**
73 * Resolve an external symbol during RTLdrGetBits().
74 *
75 * @returns iprt status code.
76 * @param hLdrMod The loader module handle.
77 * @param pszModule Module name.
78 * @param pszSymbol Symbol name, NULL if uSymbol should be used.
79 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
80 * @param pValue Where to store the symbol value (address).
81 * @param pvUser User argument.
82 */
83static DECLCALLBACK(int) testGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol,
84 RTUINTPTR *pValue, void *pvUser)
85{
86 RT_NOREF5(hLdrMod, pszModule, pszSymbol, uSymbol, pvUser);
87 /* check the name format and only permit certain names */
88 *pValue = 0xf0f0f0f0;
89 return VINF_SUCCESS;
90}
91
92
93/**
94 * One test iteration with one file.
95 *
96 * The test is very simple, we load the file three times
97 * into two different regions. The first two into each of the
98 * regions the for compare usage. The third is loaded into one
99 * and then relocated between the two and other locations a few times.
100 *
101 * @returns number of errors.
102 * @param pszFilename The file to load the mess with.
103 */
104static int testLdrOne(const char *pszFilename)
105{
106 RTERRINFOSTATIC ErrInfo;
107 RTLDRMOD hLdrMod;
108 int rc = RTLdrOpenEx(pszFilename, 0, RTLDRARCH_WHATEVER, &hLdrMod, RTErrInfoInitStatic(&ErrInfo));
109 if (RT_FAILURE(rc))
110 {
111 RTPrintf("tstLdr: Failed to open '%s', rc=%Rrc. aborting test.\n", pszFilename, rc);
112 if (ErrInfo.szMsg[0])
113 RTPrintf("tstLdr: %s\n", ErrInfo.szMsg);
114 Assert(hLdrMod == NIL_RTLDRMOD);
115 return 1;
116 }
117
118 int rcRet = 1;
119 size_t cb = RTLdrSize(hLdrMod);
120 if (cb > 100)
121 {
122 void *pvBits = RTMemAlloc(cb);
123 if (pvBits)
124 {
125 RTUINTPTR Addr = 0xc0000000;
126 rc = RTLdrGetBits(hLdrMod, pvBits, Addr, testGetImport, NULL);
127 if (RT_SUCCESS(rc))
128 {
129 RTUINTPTR Value;
130 rc = RTLdrGetSymbolEx(hLdrMod, pvBits, Addr, UINT32_MAX, "Entrypoint", &Value);
131 if (RT_SUCCESS(rc))
132 {
133 unsigned off = Value - Addr;
134 if (off < cb)
135 {
136 if (MyDisBlock((uint8_t *)pvBits + off, Addr - (uintptr_t)pvBits))
137 {
138 RTUINTPTR Addr2 = 0xd0000000;
139 rc = RTLdrRelocate(hLdrMod, pvBits, Addr2, Addr, testGetImport, NULL);
140 if (RT_SUCCESS(rc))
141 {
142 if (MyDisBlock((uint8_t *)pvBits + off, Addr2 - (uintptr_t)pvBits))
143 rcRet = 0;
144 else
145 RTPrintf("tstLdr: Disassembly failed!\n");
146 }
147 else
148 RTPrintf("tstLdr: Relocate of '%s' from %#x to %#x failed, rc=%Rrc. Aborting test.\n",
149 pszFilename, Addr2, Addr, rc);
150 }
151 else
152 RTPrintf("tstLdr: Disassembly failed!\n");
153 }
154 else
155 RTPrintf("tstLdr: Invalid value for symbol '%s' in '%s'. off=%#x Value=%#x\n",
156 "Entrypoint", pszFilename, off, Value);
157 }
158 else
159 RTPrintf("tstLdr: Failed to resolve symbol '%s' in '%s', rc=%Rrc.\n", "Entrypoint", pszFilename, rc);
160 }
161 else
162 RTPrintf("tstLdr: Failed to get bits for '%s', rc=%Rrc. aborting test\n", pszFilename, rc);
163 RTMemFree(pvBits);
164 }
165 else
166 RTPrintf("tstLdr: Out of memory '%s' cb=%d. aborting test.\n", pszFilename, cb);
167 }
168 else
169 RTPrintf("tstLdr: Size is odd, '%s'. aborting test.\n", pszFilename);
170
171
172 /* cleanup */
173 rc = RTLdrClose(hLdrMod);
174 if (RT_FAILURE(rc))
175 {
176 RTPrintf("tstLdr: Failed to close '%s', rc=%Rrc.\n", pszFilename, rc);
177 rcRet++;
178 }
179
180 return rcRet;
181}
182
183
184
185int main(int argc, char **argv)
186{
187 RTR3InitExe(argc, &argv, 0);
188
189 int rcRet = 0;
190 if (argc <= 1)
191 {
192 RTPrintf("usage: %s <module> [more modules]\n", argv[0]);
193 return 1;
194 }
195
196 /*
197 * Iterate the files.
198 */
199 for (int argi = 1; argi < argc; argi++)
200 {
201 RTPrintf("tstLdr: TESTING '%s'...\n", argv[argi]);
202 rcRet += testLdrOne(argv[argi]);
203 }
204
205 /*
206 * Test result summary.
207 */
208 if (!rcRet)
209 RTPrintf("tstLdr: SUCCESS\n");
210 else
211 RTPrintf("tstLdr: FAILURE - %d errors\n", rcRet);
212 return !!rcRet;
213}
Note: See TracBrowser for help on using the repository browser.

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