VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGPlugInOS2.cpp@ 74888

Last change on this file since 74888 was 73460, checked in by vboxsync, 6 years ago

IPRT,DBGF,Diggers: Moved DBGFRETURNTYPE and the unwind state structure to IPRT (dbg.h) in prep for debug module interface and more. Added stack unwind assist callback for the OS diggers so they can identify special stack frames and supply more info via the sure-register-value array and frame flags. Identify and decode NT/AMD64 trap frames.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/* $Id: DBGPlugInOS2.cpp 73460 2018-08-02 21:06:59Z vboxsync $ */
2/** @file
3 * DBGPlugInOS2 - Debugger and Guest OS Digger Plugin For OS/2.
4 */
5
6/*
7 * Copyright (C) 2009-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF /// @todo add new log group.
23#include "DBGPlugIns.h"
24#include <VBox/vmm/dbgf.h>
25#include <VBox/err.h>
26#include <VBox/param.h>
27#include <iprt/string.h>
28#include <iprt/mem.h>
29#include <iprt/stream.h>
30
31
32/*********************************************************************************************************************************
33* Structures and Typedefs *
34*********************************************************************************************************************************/
35
36/** @name Internal OS/2 structures */
37
38/** @} */
39
40
41typedef enum DBGDIGGEROS2VER
42{
43 DBGDIGGEROS2VER_UNKNOWN,
44 DBGDIGGEROS2VER_1_x,
45 DBGDIGGEROS2VER_2_x,
46 DBGDIGGEROS2VER_3_0,
47 DBGDIGGEROS2VER_4_0,
48 DBGDIGGEROS2VER_4_5
49} DBGDIGGEROS2VER;
50
51/**
52 * OS/2 guest OS digger instance data.
53 */
54typedef struct DBGDIGGEROS2
55{
56 /** Whether the information is valid or not.
57 * (For fending off illegal interface method calls.) */
58 bool fValid;
59 /** 32-bit (true) or 16-bit (false) */
60 bool f32Bit;
61
62 /** The OS/2 guest version. */
63 DBGDIGGEROS2VER enmVer;
64 uint8_t OS2MajorVersion;
65 uint8_t OS2MinorVersion;
66
67 /** Guest's Global Info Segment selector. */
68 uint16_t selGIS;
69
70} DBGDIGGEROS2;
71/** Pointer to the OS/2 guest OS digger instance data. */
72typedef DBGDIGGEROS2 *PDBGDIGGEROS2;
73
74
75/*********************************************************************************************************************************
76* Defined Constants And Macros *
77*********************************************************************************************************************************/
78/** The 'SAS ' signature. */
79#define DIG_OS2_SAS_SIG RT_MAKE_U32_FROM_U8('S','A','S',' ')
80
81/** OS/2Warp on little endian ASCII systems. */
82#define DIG_OS2_MOD_TAG UINT64_C(0x43532f3257617270)
83
84
85/*********************************************************************************************************************************
86* Internal Functions *
87*********************************************************************************************************************************/
88static DECLCALLBACK(int) dbgDiggerOS2Init(PUVM pUVM, void *pvData);
89
90
91
92#if 0 /* unused */
93/**
94 * Process a PE image found in guest memory.
95 *
96 * @param pThis The instance data.
97 * @param pUVM The user mode VM handle.
98 * @param pszName The image name.
99 * @param pImageAddr The image address.
100 * @param cbImage The size of the image.
101 * @param pbBuf Scratch buffer containing the first
102 * RT_MIN(cbBuf, cbImage) bytes of the image.
103 * @param cbBuf The scratch buffer size.
104 */
105static void dbgDiggerOS2ProcessImage(PDBGDIGGEROS2 pThis, PUVM pUVM, const char *pszName,
106 PCDBGFADDRESS pImageAddr, uint32_t cbImage,
107 uint8_t *pbBuf, size_t cbBuf)
108{
109 RT_NOREF7(pThis, pUVM, pszName, pImageAddr, cbImage, pbBuf, cbBuf);
110 LogFlow(("DigOS2: %RGp %#x %s\n", pImageAddr->FlatPtr, cbImage, pszName));
111
112 /* To be implemented.*/
113}
114#endif
115
116
117/**
118 * @copydoc DBGFOSREG::pfnStackUnwindAssist
119 */
120static DECLCALLBACK(int) dbgDiggerOS2StackUnwindAssist(PUVM pUVM, void *pvData, VMCPUID idCpu, PDBGFSTACKFRAME pFrame,
121 PRTDBGUNWINDSTATE pState, PCCPUMCTX pInitialCtx, RTDBGAS hAs,
122 uint64_t *puScratch)
123{
124 RT_NOREF(pUVM, pvData, idCpu, pFrame, pState, pInitialCtx, hAs, puScratch);
125 return VINF_SUCCESS;
126}
127
128
129/**
130 * @copydoc DBGFOSREG::pfnQueryInterface
131 */
132static DECLCALLBACK(void *) dbgDiggerOS2QueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
133{
134 RT_NOREF3(pUVM, pvData, enmIf);
135 return NULL;
136}
137
138
139/**
140 * @copydoc DBGFOSREG::pfnQueryVersion
141 */
142static DECLCALLBACK(int) dbgDiggerOS2QueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
143{
144 RT_NOREF1(pUVM);
145 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
146 Assert(pThis->fValid);
147 char *achOS2ProductType[32];
148 char *pszOS2ProductType = (char *)achOS2ProductType;
149
150 if (pThis->OS2MajorVersion == 10)
151 {
152 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 1.%02d", pThis->OS2MinorVersion);
153 pThis->enmVer = DBGDIGGEROS2VER_1_x;
154 }
155 else if (pThis->OS2MajorVersion == 20)
156 {
157 if (pThis->OS2MinorVersion < 30)
158 {
159 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 2.%02d", pThis->OS2MinorVersion);
160 pThis->enmVer = DBGDIGGEROS2VER_2_x;
161 }
162 else if (pThis->OS2MinorVersion < 40)
163 {
164 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp");
165 pThis->enmVer = DBGDIGGEROS2VER_3_0;
166 }
167 else if (pThis->OS2MinorVersion == 40)
168 {
169 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp 4");
170 pThis->enmVer = DBGDIGGEROS2VER_4_0;
171 }
172 else
173 {
174 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp %d.%d",
175 pThis->OS2MinorVersion / 10, pThis->OS2MinorVersion % 10);
176 pThis->enmVer = DBGDIGGEROS2VER_4_5;
177 }
178 }
179 RTStrPrintf(pszVersion, cchVersion, "%u.%u (%s)", pThis->OS2MajorVersion, pThis->OS2MinorVersion, pszOS2ProductType);
180 return VINF_SUCCESS;
181}
182
183
184/**
185 * @copydoc DBGFOSREG::pfnTerm
186 */
187static DECLCALLBACK(void) dbgDiggerOS2Term(PUVM pUVM, void *pvData)
188{
189 RT_NOREF1(pUVM);
190 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
191 Assert(pThis->fValid);
192
193 pThis->fValid = false;
194}
195
196
197/**
198 * @copydoc DBGFOSREG::pfnRefresh
199 */
200static DECLCALLBACK(int) dbgDiggerOS2Refresh(PUVM pUVM, void *pvData)
201{
202 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
203 NOREF(pThis);
204 Assert(pThis->fValid);
205
206 /*
207 * For now we'll flush and reload everything.
208 */
209 RTDBGAS hDbgAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
210 if (hDbgAs != NIL_RTDBGAS)
211 {
212 uint32_t iMod = RTDbgAsModuleCount(hDbgAs);
213 while (iMod-- > 0)
214 {
215 RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);
216 if (hMod != NIL_RTDBGMOD)
217 {
218 if (RTDbgModGetTag(hMod) == DIG_OS2_MOD_TAG)
219 {
220 int rc = RTDbgAsModuleUnlink(hDbgAs, hMod);
221 AssertRC(rc);
222 }
223 RTDbgModRelease(hMod);
224 }
225 }
226 RTDbgAsRelease(hDbgAs);
227 }
228
229 dbgDiggerOS2Term(pUVM, pvData);
230 return dbgDiggerOS2Init(pUVM, pvData);
231}
232
233
234/**
235 * @copydoc DBGFOSREG::pfnInit
236 */
237static DECLCALLBACK(int) dbgDiggerOS2Init(PUVM pUVM, void *pvData)
238{
239 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
240 Assert(!pThis->fValid);
241
242 union
243 {
244 uint8_t au8[0x2000];
245 uint16_t au16[0x2000/2];
246 uint32_t au32[0x2000/4];
247 RTUTF16 wsz[0x2000/2];
248 } u;
249 DBGFADDRESS Addr;
250 int rc;
251
252 /*
253 * Determine the OS/2 version.
254 */
255 do {
256 /* Version info is at GIS:15h (major/minor/revision). */
257 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, pThis->selGIS, 0x15);
258 if (RT_FAILURE(rc))
259 break;
260 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, u.au32, sizeof(uint32_t));
261 if (RT_FAILURE(rc))
262 break;
263
264 pThis->OS2MajorVersion = u.au8[0];
265 pThis->OS2MinorVersion = u.au8[1];
266
267 pThis->fValid = true;
268 return VINF_SUCCESS;
269 } while (0);
270 return VERR_NOT_SUPPORTED;
271}
272
273
274/**
275 * @copydoc DBGFOSREG::pfnProbe
276 */
277static DECLCALLBACK(bool) dbgDiggerOS2Probe(PUVM pUVM, void *pvData)
278{
279 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
280 DBGFADDRESS Addr;
281 int rc;
282 uint16_t offInfo;
283 union
284 {
285 uint8_t au8[8192];
286 uint16_t au16[8192/2];
287 uint32_t au32[8192/4];
288 RTUTF16 wsz[8192/2];
289 } u;
290
291 /*
292 * If the DWORD at 70:0 contains 'SAS ' it's quite unlikely that this wouldn't be OS/2.
293 * Note: The SAS layout is similar between 16-bit and 32-bit OS/2, but not identical.
294 * 32-bit OS/2 will have the flat kernel data selector at SAS:06. The selector is 168h
295 * or similar. For 16-bit OS/2 the field contains a table offset into the SAS which will
296 * be much smaller. Fun fact: The global infoseg selector in the SAS is bimodal in 16-bit
297 * OS/2 and will work in real mode as well.
298 */
299 do {
300 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, 0x70, 0x00);
301 if (RT_FAILURE(rc))
302 break;
303 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, u.au32, 256);
304 if (RT_FAILURE(rc))
305 break;
306 if (u.au32[0] != DIG_OS2_SAS_SIG)
307 break;
308
309 /* This sure looks like OS/2, but a bit of paranoia won't hurt. */
310 if (u.au16[2] >= u.au16[4])
311 break;
312
313 /* If 4th word is bigger than 5th, it's the flat kernel mode selector. */
314 if (u.au16[3] > u.au16[4])
315 pThis->f32Bit = true;
316
317 /* Offset into info table is either at SAS:14h or SAS:16h. */
318 if (pThis->f32Bit)
319 offInfo = u.au16[0x14/2];
320 else
321 offInfo = u.au16[0x16/2];
322
323 /* The global infoseg selector is the first entry in the info table. */
324 pThis->selGIS = u.au16[offInfo/2];
325 return true;
326 } while (0);
327
328 return false;
329}
330
331
332/**
333 * @copydoc DBGFOSREG::pfnDestruct
334 */
335static DECLCALLBACK(void) dbgDiggerOS2Destruct(PUVM pUVM, void *pvData)
336{
337 RT_NOREF2(pUVM, pvData);
338}
339
340
341/**
342 * @copydoc DBGFOSREG::pfnConstruct
343 */
344static DECLCALLBACK(int) dbgDiggerOS2Construct(PUVM pUVM, void *pvData)
345{
346 RT_NOREF1(pUVM);
347 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
348 pThis->fValid = false;
349 pThis->f32Bit = false;
350 pThis->enmVer = DBGDIGGEROS2VER_UNKNOWN;
351 return VINF_SUCCESS;
352}
353
354
355const DBGFOSREG g_DBGDiggerOS2 =
356{
357 /* .u32Magic = */ DBGFOSREG_MAGIC,
358 /* .fFlags = */ 0,
359 /* .cbData = */ sizeof(DBGDIGGEROS2),
360 /* .szName = */ "OS/2",
361 /* .pfnConstruct = */ dbgDiggerOS2Construct,
362 /* .pfnDestruct = */ dbgDiggerOS2Destruct,
363 /* .pfnProbe = */ dbgDiggerOS2Probe,
364 /* .pfnInit = */ dbgDiggerOS2Init,
365 /* .pfnRefresh = */ dbgDiggerOS2Refresh,
366 /* .pfnTerm = */ dbgDiggerOS2Term,
367 /* .pfnQueryVersion = */ dbgDiggerOS2QueryVersion,
368 /* .pfnQueryInterface = */ dbgDiggerOS2QueryInterface,
369 /* .pfnStackUnwindAssist = */ dbgDiggerOS2StackUnwindAssist,
370 /* .u32EndMagic = */ DBGFOSREG_MAGIC
371};
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