VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: nocrt-startup-common-win.cpp 98103 2023-01-17 14:15:46Z 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 /* The section is not writable, so temporarily make it writable. */
151 PVOID pvAligned = pbToZero - ((uintptr_t)pbToZero & PAGE_OFFSET_MASK);
152 ULONG cbAligned = RT_ALIGN_32(cbToZero + ((uintptr_t)pbToZero & PAGE_OFFSET_MASK), PAGE_SIZE);
153 ULONG fNewProt = paSHdrs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE
154 ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
155 ULONG fOldProt = fNewProt;
156 NTSTATUS rcNt = NtProtectVirtualMemory(NtCurrentProcess(), &pvAligned, &cbAligned, fNewProt, &fOldProt);
157 if (NT_SUCCESS(rcNt))
158 {
159 memset(pbToZero, 0, cbToZero);
160
161 rcNt = NtProtectVirtualMemory(NtCurrentProcess(), &pvAligned, &cbAligned, fOldProt, &fNewProt);
162 }
163 else
164 RT_BREAKPOINT();
165 }
166 }
167 }
168 }
169 else
170 RT_BREAKPOINT();
171}
172#endif
173
174
175void rtVccWinInitProcExecPath(void)
176{
177 WCHAR wszPath[RTPATH_MAX];
178 UINT cwcPath = GetModuleFileNameW(NULL, wszPath, RT_ELEMENTS(wszPath));
179 if (cwcPath)
180 {
181 char *pszDst = g_szrtProcExePath;
182 int rc = RTUtf16ToUtf8Ex(wszPath, cwcPath, &pszDst, sizeof(g_szrtProcExePath), &g_cchrtProcExePath);
183 if (RT_SUCCESS(rc))
184 {
185 g_cchrtProcExeDir = g_offrtProcName = RTPathFilename(pszDst) - g_szrtProcExePath;
186 while ( g_cchrtProcExeDir >= 2
187 && RTPATH_IS_SLASH(g_szrtProcExePath[g_cchrtProcExeDir - 1])
188 && g_szrtProcExePath[g_cchrtProcExeDir - 2] != ':')
189 g_cchrtProcExeDir--;
190 }
191 else
192 {
193#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
194 RTMsgError("initProcExecPath: RTUtf16ToUtf8Ex failed: %Rrc\n", rc);
195#else
196 rtNoCrtFatalMsgWithRc(RT_STR_TUPLE("initProcExecPath: RTUtf16ToUtf8Ex failed: "), rc);
197#endif
198 }
199 }
200 else
201 {
202#ifdef IPRT_NOCRT_WITHOUT_FATAL_WRITE
203 RTMsgError("initProcExecPath: GetModuleFileNameW failed: %Rhrc\n", GetLastError());
204#else
205 rtNoCrtFatalWriteBegin(RT_STR_TUPLE("initProcExecPath: GetModuleFileNameW failed: "));
206 rtNoCrtFatalWriteWinRc(GetLastError());
207 rtNoCrtFatalWrite(RT_STR_TUPLE("\r\n"));
208#endif
209 }
210}
211
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use