VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/nocrt-startup-common-win.cpp@ 105155

Last change on this file since 105155 was 105155, checked in by vboxsync, 6 months ago

IPRT/nocrt-startup-*win.cpp: Avoid a couple of ntdll function so as to not trigger silly AV heuristics.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: nocrt-startup-common-win.cpp 105155 2024-07-05 02:44:07Z vboxsync $ */
2/** @file
3 * IPRT - No-CRT - Common Windows startup code.
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 "internal/nocrt.h"
42#include "internal/process.h"
43
44#include <iprt/nt/nt-and-windows.h>
45#ifndef IPRT_NOCRT_WITHOUT_FATAL_WRITE
46# include <iprt/assert.h>
47#endif
48#include <iprt/getopt.h>
49#include <iprt/message.h>
50#include <iprt/path.h>
51#include <iprt/string.h>
52#include <iprt/utf16.h>
53
54#include "internal/compiler-vcc.h"
55#include "internal/process.h"
56
57
58#ifdef RT_ARCH_X86
59/**
60 * NT 3.1 does not know about the IMAGE_SECTION_HEADER::Misc.VirtualSize field
61 * and will therefore not handle merging initialized and uninitialized data into
62 * the same section.
63 *
64 * We work around this by manually zeroing the uninitialized data before any
65 * other code has been executed.
66 */
67void rtVccWinInitBssOnNt3(void *pvImageBase)
68{
69 /* We are called really early on, so we must figure out the NT version
70 on our own. It doesn't have to be all that accurate, though, as only
71 NT 3.10 is affected (3.50 isn't). */
72 DWORD const dwRawVer = GetVersion();
73 DWORD const uMajorVer = RT_BYTE1(dwRawVer);
74 DWORD const uMinorVer = RT_BYTE2(dwRawVer);
75 if (uMajorVer != 3 || uMinorVer >= 50)
76 return;
77
78 /*
79 * Locate the NT headers.
80 */
81 PIMAGE_NT_HEADERS pNtHdrs;
82 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)pvImageBase;
83 if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
84 pNtHdrs = (PIMAGE_NT_HEADERS)((uintptr_t)pvImageBase + pDosHdr->e_lfanew);
85 else
86 pNtHdrs = (PIMAGE_NT_HEADERS)pvImageBase;
87 if (pNtHdrs->Signature == IMAGE_NT_SIGNATURE)
88 {
89 /*
90 * Locate the section table and walk thru it, memsetting anything that
91 * wasn't loaded from the file.
92 */
93 PIMAGE_SECTION_HEADER paSHdrs = (PIMAGE_SECTION_HEADER)( (uintptr_t)&pNtHdrs->OptionalHeader
94 + pNtHdrs->FileHeader.SizeOfOptionalHeader);
95 uint32_t const cSections = pNtHdrs->FileHeader.NumberOfSections;
96 for (uint32_t i = 0; i < cSections; i++)
97 {
98 if (paSHdrs[i].Misc.VirtualSize > paSHdrs[i].SizeOfRawData)
99 {
100 /* ASSUMES VirtualAddress is still an RVAs */
101 uint8_t *pbToZero = (uint8_t *)pvImageBase + paSHdrs[i].VirtualAddress + paSHdrs[i].SizeOfRawData;
102 uint32_t const cbToZero = paSHdrs[i].Misc.VirtualSize - paSHdrs[i].SizeOfRawData;
103
104# if 0 /* very very crude debugging */
105 const char *pszHex = "0123456789abcdef";
106 char szMsg[128];
107 char *psz = szMsg;
108 *psz++ = 'd'; *psz++ = 'b'; *psz++ = 'g'; *psz++ = ':'; *psz++ = ' ';
109 for (uint32_t q = 0, u = i; q < 8; q++, u >>= 4)
110 psz[7 - q] = pszHex[u & 0xf];
111 psz += 8;
112 *psz++ = ':';
113 *psz++ = ' ';
114 for (uint32_t q = 0, u = (uint32_t)pbToZero; q < 8; q++, u >>= 4)
115 psz[7 - q] = pszHex[u & 0xf];
116 psz += 8;
117 *psz++ = ' ';
118 *psz++ = 'L';
119 *psz++ = 'B';
120 *psz++ = ' ';
121 for (uint32_t q = 0, u = cbToZero; q < 8; q++, u >>= 4)
122 psz[7 - q] = pszHex[u & 0xf];
123 psz += 8;
124 *psz++ = ' ';
125 for (uint32_t q = 0; q < 8; q++)
126 *psz++ = paSHdrs[i].Name[q] ? paSHdrs[i].Name[q] : ' ';
127 *psz++ = ' '; *psz++ = '/'; *psz++ = ' '; *psz++ = 'v'; *psz++ = 'e'; *psz++ = 'r'; *psz++ = ' ';
128 *psz++ = pszHex[(uMajorVer >> 4) & 0xf];
129 *psz++ = pszHex[uMajorVer & 0xf];
130 *psz++ = '.';
131 *psz++ = pszHex[(uMinorVer >> 4) & 0xf];
132 *psz++ = pszHex[uMinorVer & 0xf];
133 *psz++ = '\r'; *psz++ = '\n';
134 *psz = '\0';
135 DWORD cbIgn;
136 HANDLE hOut = RTNtCurrentPeb()->ProcessParameters->StandardOutput;
137 if (hOut == NULL || hOut == INVALID_HANDLE_VALUE)
138 hOut = RTNtCurrentPeb()->ProcessParameters->StandardError;
139 if (hOut == NULL || hOut == INVALID_HANDLE_VALUE)
140 hOut = RTNtCurrentPeb()->ProcessParameters->ConsoleHandle;
141 if (hOut == NULL || hOut == INVALID_HANDLE_VALUE)
142 hOut = GetStdHandle(STD_OUTPUT_HANDLE);
143 WriteFile(hOut, szMsg, psz - szMsg, &cbIgn, NULL);
144# endif
145
146 if (paSHdrs[i].Characteristics & IMAGE_SCN_MEM_WRITE)
147 memset(pbToZero, 0, cbToZero);
148 else
149 {
150# if 1 /* This dynamic stupidity is because of stupid AV heuristics. */
151 static decltype(NtProtectVirtualMemory) *s_pfnNtProtectVirtualMemory = NULL;
152 if (!s_pfnNtProtectVirtualMemory)
153 s_pfnNtProtectVirtualMemory
154 = (decltype(NtProtectVirtualMemory) *)GetProcAddress(GetModuleHandleW(L"ntdll.dll"),
155 "NtProtectVirtualMemory");
156 if (!s_pfnNtProtectVirtualMemory)
157 {
158 RT_BREAKPOINT();
159 continue;
160 }
161# else
162# define s_pfnNtProtectVirtualMemory NtProtectVirtualMemory
163# endif
164
165 /* The section is not writable, so temporarily make it writable. */
166 PVOID pvAligned = pbToZero - ((uintptr_t)pbToZero & PAGE_OFFSET_MASK);
167 ULONG cbAligned = RT_ALIGN_32(cbToZero + ((uintptr_t)pbToZero & PAGE_OFFSET_MASK), PAGE_SIZE);
168 ULONG fNewProt = paSHdrs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE
169 ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
170 ULONG fOldProt = fNewProt;
171 NTSTATUS rcNt = s_pfnNtProtectVirtualMemory(NtCurrentProcess(), &pvAligned, &cbAligned, fNewProt, &fOldProt);
172 if (NT_SUCCESS(rcNt))
173 {
174 memset(pbToZero, 0, cbToZero);
175
176 rcNt = s_pfnNtProtectVirtualMemory(NtCurrentProcess(), &pvAligned, &cbAligned, fOldProt, &fNewProt);
177 }
178 else
179 RT_BREAKPOINT();
180 }
181 }
182 }
183 }
184 else
185 RT_BREAKPOINT();
186}
187#endif
188
189
190void rtVccWinInitProcExecPath(void)
191{
192 WCHAR wszPath[RTPATH_MAX];
193 UINT cwcPath = GetModuleFileNameW(NULL, wszPath, RT_ELEMENTS(wszPath));
194 if (cwcPath)
195 {
196 char *pszDst = g_szrtProcExePath;
197 int rc = RTUtf16ToUtf8Ex(wszPath, cwcPath, &pszDst, sizeof(g_szrtProcExePath), &g_cchrtProcExePath);
198 if (RT_SUCCESS(rc))
199 {
200 g_cchrtProcExeDir = g_offrtProcName = RTPathFilename(pszDst) - g_szrtProcExePath;
201 while ( g_cchrtProcExeDir >= 2
202 && RTPATH_IS_SLASH(g_szrtProcExePath[g_cchrtProcExeDir - 1])
203 && g_szrtProcExePath[g_cchrtProcExeDir - 2] != ':')
204 g_cchrtProcExeDir--;
205 }
206 else
207 {
208#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
209 RTMsgError("initProcExecPath: RTUtf16ToUtf8Ex failed: %Rrc\n", rc);
210#else
211 rtNoCrtFatalMsgWithRc(RT_STR_TUPLE("initProcExecPath: RTUtf16ToUtf8Ex failed: "), rc);
212#endif
213 }
214 }
215 else
216 {
217#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
218 RTMsgError("initProcExecPath: GetModuleFileNameW failed: %Rhrc\n", GetLastError());
219#else
220 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("initProcExecPath: GetModuleFileNameW failed: "));
221 rtNoCrtFatalWriteWinRc(GetLastError());
222 rtNoCrtFatalWrite(RT_STR_TUPLE("\r\n"));
223#endif
224 }
225}
226
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