VirtualBox

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

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

DBGFPlugInOS2: Added some code for walking the MTE list. (Though this was done a while ago,)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.6 KB
Line 
1/* $Id: DBGPlugInOS2.cpp 75166 2018-10-29 21:01: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 * 32-bit OS/2 loader module table entry.
76 */
77typedef struct LDRMTE
78{
79 uint16_t mte_flags2;
80 uint16_t mte_handle;
81 uint32_t mte_swapmte; /**< Pointer to LDRSMTE. */
82 uint32_t mte_link; /**< Pointer to next LDRMTE. */
83 uint32_t mte_flags1;
84 uint32_t mte_impmodcnt;
85 uint16_t mte_sfn;
86 uint16_t mte_usecnt;
87 char mte_modname[8];
88 uint32_t mte_RAS; /**< added later */
89 uint32_t mte_modver; /**< added even later. */
90} LDRMTE;
91
92/**
93 * 32-bit OS/2 swappable module table entry.
94 */
95typedef struct LDRSMTE
96{
97 uint32_t smte_mpages; /**< module page count. */
98 uint32_t smte_startobj; /**< Entrypoint segment number. */
99 uint32_t smte_eip; /**< Entrypoint offset value. */
100 uint32_t smte_stackobj; /**< Stack segment number. */
101 uint32_t smte_esp; /**< Stack offset value*/
102 uint32_t smte_pageshift; /**< Page shift value. */
103 uint32_t smte_fixupsize; /**< Size of the fixup section. */
104 uint32_t smte_objtab; /**< Pointer to LDROTE array. */
105 uint32_t smte_objcnt; /**< Number of segments. */
106 uint32_t smte_objmap; /**< Address of the object page map. */
107 uint32_t smte_itermap; /**< File offset of the iterated data map*/
108 uint32_t smte_rsrctab; /**< Pointer to resource table? */
109 uint32_t smte_rsrccnt; /**< Number of resource table entries. */
110 uint32_t smte_restab; /**< Pointer to the resident name table. */
111 uint32_t smte_enttab; /**< Possibly entry point table address, if not file offset. */
112 uint32_t smte_fpagetab; /* Offset of Fixup Page Table */
113 uint32_t smte_frectab; /* Offset of Fixup Record Table */
114 uint32_t smte_impmod;
115 uint32_t smte_impproc;
116 uint32_t smte_datapage;
117 uint32_t smte_nrestab;
118 uint32_t smte_cbnrestab;
119 uint32_t smte_autods;
120 uint32_t smte_debuginfo; /* Offset of the debugging info */
121 uint32_t smte_debuglen; /* The len of the debug info in bytes */
122 uint32_t smte_heapsize;
123 uint32_t smte_path; /**< Address of full name string. */
124 uint16_t smte_semcount;
125 uint16_t smte_semowner;
126 uint32_t smte_pfilecache; /** Address of cached data if replace-module is used. */
127 uint32_t smte_stacksize; /**< Stack size for .exe thread 1. */
128 uint16_t smte_alignshift;
129 uint16_t smte_NEexpver;
130 uint16_t smte_pathlen; /**< Length of smte_path */
131 uint16_t smte_NEexetype;
132 uint16_t smte_csegpack;
133 uint8_t smte_major_os; /**< added later to lie about OS version */
134 uint8_t smte_minor_os; /**< added later to lie about OS version */
135} LDRSMTE;
136
137typedef struct LDROTE
138{
139 uint32_t ote_size;
140 uint32_t ote_base;
141 uint32_t ote_flags;
142 uint32_t ote_pagemap;
143 uint32_t ote_mapsize;
144 union
145 {
146 uint32_t ote_vddaddr;
147 uint32_t ote_krnaddr;
148 struct
149 {
150 uint16_t ote_selector;
151 uint16_t ote_handle;
152 } s;
153 };
154} LDROTE;
155AssertCompileSize(LDROTE, 24);
156
157
158/**
159 * 32-bit system anchor block segment header.
160 */
161typedef struct SAS
162{
163 uint8_t SAS_signature[4];
164 uint16_t SAS_tables_data; /**< Offset to SASTABLES. */
165 uint16_t SAS_flat_sel; /**< 32-bit kernel DS (flat). */
166 uint16_t SAS_config_data; /**< Offset to SASCONFIG. */
167 uint16_t SAS_dd_data; /**< Offset to SASDD. */
168 uint16_t SAS_vm_data; /**< Offset to SASVM. */
169 uint16_t SAS_task_data; /**< Offset to SASTASK. */
170 uint16_t SAS_RAS_data; /**< Offset to SASRAS. */
171 uint16_t SAS_file_data; /**< Offset to SASFILE. */
172 uint16_t SAS_info_data; /**< Offset to SASINFO. */
173 uint16_t SAS_mp_data; /**< Offset to SASMP. SMP only. */
174} SAS;
175#define SAS_SIGNATURE "SAS "
176
177typedef struct SASTABLES
178{
179 uint16_t SAS_tbl_GDT;
180 uint16_t SAS_tbl_LDT;
181 uint16_t SAS_tbl_IDT;
182 uint16_t SAS_tbl_GDTPOOL;
183} SASTABLES;
184
185typedef struct SASCONFIG
186{
187 uint16_t SAS_config_table;
188} SASCONFIG;
189
190typedef struct SASDD
191{
192 uint16_t SAS_dd_bimodal_chain;
193 uint16_t SAS_dd_real_chain;
194 uint16_t SAS_dd_DPB_segment;
195 uint16_t SAS_dd_CDA_anchor_p;
196 uint16_t SAS_dd_CDA_anchor_r;
197 uint16_t SAS_dd_FSC;
198} SASDD;
199
200typedef struct SASVM
201{
202 uint32_t SAS_vm_arena;
203 uint32_t SAS_vm_object;
204 uint32_t SAS_vm_context;
205 uint32_t SAS_vm_krnl_mte; /**< Flat address of kernel MTE. */
206 uint32_t SAS_vm_glbl_mte; /**< Flat address of global MTE list head pointer variable. */
207 uint32_t SAS_vm_pft;
208 uint32_t SAS_vm_prt;
209 uint32_t SAS_vm_swap;
210 uint32_t SAS_vm_idle_head;
211 uint32_t SAS_vm_free_head;
212 uint32_t SAS_vm_heap_info;
213 uint32_t SAS_vm_all_mte; /**< Flat address of global MTE list head pointer variable. */
214} SASVM;
215
216
217#pragma pack(1)
218typedef struct SASTASK
219{
220 uint16_t SAS_task_PTDA; /**< Current PTDA selector. */
221 uint32_t SAS_task_ptdaptrs; /**< Flat address of process tree root. */
222 uint32_t SAS_task_threadptrs; /**< Flat address array of thread pointer array. */
223 uint32_t SAS_task_tasknumber; /**< Flat address of the TaskNumber variable. */
224 uint32_t SAS_task_threadcount; /**< Flat address of the ThreadCount variable. */
225} SASTASK;
226#pragma pack()
227
228
229#pragma pack(1)
230typedef struct SASRAS
231{
232 uint16_t SAS_RAS_STDA_p;
233 uint16_t SAS_RAS_STDA_r;
234 uint16_t SAS_RAS_event_mask;
235 uint32_t SAS_RAS_Perf_Buff;
236} SASRAS;
237#pragma pack()
238
239typedef struct SASFILE
240{
241 uint32_t SAS_file_MFT; /**< Handle. */
242 uint16_t SAS_file_SFT; /**< Selector. */
243 uint16_t SAS_file_VPB; /**< Selector. */
244 uint16_t SAS_file_CDS; /**< Selector. */
245 uint16_t SAS_file_buffers; /**< Selector. */
246} SASFILE;
247
248#pragma pack(1)
249typedef struct SASINFO
250{
251 uint16_t SAS_info_global; /**< GIS selector. */
252 uint32_t SAS_info_local; /**< Flat address of LIS for current task. */
253 uint32_t SAS_info_localRM;
254 uint16_t SAS_info_CDIB; /**< Selector. */
255} SASINFO;
256#pragma pack()
257
258typedef struct SASMP
259{
260 uint32_t SAS_mp_PCBFirst; /**< Flat address of PCB head. */
261 uint32_t SAS_mp_pLockHandles; /**< Flat address of lock handles. */
262 uint32_t SAS_mp_cProcessors; /**< Flat address of CPU count variable. */
263 uint32_t SAS_mp_pIPCInfo; /**< Flat address of IPC info pointer variable. */
264 uint32_t SAS_mp_pIPCHistory; /**< Flat address of IPC history pointer. */
265 uint32_t SAS_mp_IPCHistoryIdx; /**< Flat address of IPC history index variable. */
266 uint32_t SAS_mp_pFirstPSA; /**< Flat address of PSA. Added later. */
267 uint32_t SAS_mp_pPSAPages; /**< Flat address of PSA pages. */
268} SASMP;
269
270
271
272/*********************************************************************************************************************************
273* Defined Constants And Macros *
274*********************************************************************************************************************************/
275/** The 'SAS ' signature. */
276#define DIG_OS2_SAS_SIG RT_MAKE_U32_FROM_U8('S','A','S',' ')
277
278/** OS/2Warp on little endian ASCII systems. */
279#define DIG_OS2_MOD_TAG UINT64_C(0x43532f3257617270)
280
281
282/*********************************************************************************************************************************
283* Internal Functions *
284*********************************************************************************************************************************/
285static DECLCALLBACK(int) dbgDiggerOS2Init(PUVM pUVM, void *pvData);
286
287
288
289#if 0 /* unused */
290/**
291 * Process a PE image found in guest memory.
292 *
293 * @param pThis The instance data.
294 * @param pUVM The user mode VM handle.
295 * @param pszName The image name.
296 * @param pImageAddr The image address.
297 * @param cbImage The size of the image.
298 * @param pbBuf Scratch buffer containing the first
299 * RT_MIN(cbBuf, cbImage) bytes of the image.
300 * @param cbBuf The scratch buffer size.
301 */
302static void dbgDiggerOS2ProcessImage(PDBGDIGGEROS2 pThis, PUVM pUVM, const char *pszName,
303 PCDBGFADDRESS pImageAddr, uint32_t cbImage,
304 uint8_t *pbBuf, size_t cbBuf)
305{
306 RT_NOREF7(pThis, pUVM, pszName, pImageAddr, cbImage, pbBuf, cbBuf);
307 LogFlow(("DigOS2: %RGp %#x %s\n", pImageAddr->FlatPtr, cbImage, pszName));
308
309 /* To be implemented.*/
310}
311#endif
312
313
314/**
315 * @copydoc DBGFOSREG::pfnStackUnwindAssist
316 */
317static DECLCALLBACK(int) dbgDiggerOS2StackUnwindAssist(PUVM pUVM, void *pvData, VMCPUID idCpu, PDBGFSTACKFRAME pFrame,
318 PRTDBGUNWINDSTATE pState, PCCPUMCTX pInitialCtx, RTDBGAS hAs,
319 uint64_t *puScratch)
320{
321 RT_NOREF(pUVM, pvData, idCpu, pFrame, pState, pInitialCtx, hAs, puScratch);
322 return VINF_SUCCESS;
323}
324
325
326/**
327 * @copydoc DBGFOSREG::pfnQueryInterface
328 */
329static DECLCALLBACK(void *) dbgDiggerOS2QueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
330{
331 RT_NOREF3(pUVM, pvData, enmIf);
332 return NULL;
333}
334
335
336/**
337 * @copydoc DBGFOSREG::pfnQueryVersion
338 */
339static DECLCALLBACK(int) dbgDiggerOS2QueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
340{
341 RT_NOREF1(pUVM);
342 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
343 Assert(pThis->fValid);
344 char *achOS2ProductType[32];
345 char *pszOS2ProductType = (char *)achOS2ProductType;
346
347 if (pThis->OS2MajorVersion == 10)
348 {
349 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 1.%02d", pThis->OS2MinorVersion);
350 pThis->enmVer = DBGDIGGEROS2VER_1_x;
351 }
352 else if (pThis->OS2MajorVersion == 20)
353 {
354 if (pThis->OS2MinorVersion < 30)
355 {
356 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 2.%02d", pThis->OS2MinorVersion);
357 pThis->enmVer = DBGDIGGEROS2VER_2_x;
358 }
359 else if (pThis->OS2MinorVersion < 40)
360 {
361 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp");
362 pThis->enmVer = DBGDIGGEROS2VER_3_0;
363 }
364 else if (pThis->OS2MinorVersion == 40)
365 {
366 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp 4");
367 pThis->enmVer = DBGDIGGEROS2VER_4_0;
368 }
369 else
370 {
371 RTStrPrintf(pszOS2ProductType, sizeof(achOS2ProductType), "OS/2 Warp %d.%d",
372 pThis->OS2MinorVersion / 10, pThis->OS2MinorVersion % 10);
373 pThis->enmVer = DBGDIGGEROS2VER_4_5;
374 }
375 }
376 RTStrPrintf(pszVersion, cchVersion, "%u.%u (%s)", pThis->OS2MajorVersion, pThis->OS2MinorVersion, pszOS2ProductType);
377 return VINF_SUCCESS;
378}
379
380
381/**
382 * @copydoc DBGFOSREG::pfnTerm
383 */
384static DECLCALLBACK(void) dbgDiggerOS2Term(PUVM pUVM, void *pvData)
385{
386 RT_NOREF1(pUVM);
387 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
388 Assert(pThis->fValid);
389
390 pThis->fValid = false;
391}
392
393
394/**
395 * @copydoc DBGFOSREG::pfnRefresh
396 */
397static DECLCALLBACK(int) dbgDiggerOS2Refresh(PUVM pUVM, void *pvData)
398{
399 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
400 NOREF(pThis);
401 Assert(pThis->fValid);
402
403 /*
404 * For now we'll flush and reload everything.
405 */
406 RTDBGAS hDbgAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
407 if (hDbgAs != NIL_RTDBGAS)
408 {
409 uint32_t iMod = RTDbgAsModuleCount(hDbgAs);
410 while (iMod-- > 0)
411 {
412 RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);
413 if (hMod != NIL_RTDBGMOD)
414 {
415 if (RTDbgModGetTag(hMod) == DIG_OS2_MOD_TAG)
416 {
417 int rc = RTDbgAsModuleUnlink(hDbgAs, hMod);
418 AssertRC(rc);
419 }
420 RTDbgModRelease(hMod);
421 }
422 }
423 RTDbgAsRelease(hDbgAs);
424 }
425
426 dbgDiggerOS2Term(pUVM, pvData);
427 return dbgDiggerOS2Init(pUVM, pvData);
428}
429
430/** Buffer shared by dbgdiggerOS2ProcessModule and dbgDiggerOS2Init.*/
431typedef union DBGDIGGEROS2BUF
432{
433 uint8_t au8[0x2000];
434 uint16_t au16[0x2000/2];
435 uint32_t au32[0x2000/4];
436 RTUTF16 wsz[0x2000/2];
437 char ach[0x2000];
438 LDROTE aOtes[0x2000 / sizeof(LDROTE)];
439 SAS sas;
440 SASVM sasvm;
441 LDRMTE mte;
442 LDRSMTE smte;
443 LDROTE ote;
444} DBGDIGGEROS2BUF;
445
446
447static void dbgdiggerOS2ProcessModule(PUVM pUVM, PDBGDIGGEROS2 pThis, DBGDIGGEROS2BUF *pBuf)
448{
449 RT_NOREF(pThis);
450
451 /*
452 * Save the MTE.
453 */
454 LDRMTE const Mte = pBuf->mte;
455
456 /*
457 * Try read the swappable MTE. Save it too.
458 */
459 DBGFADDRESS Addr;
460 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, Mte.mte_swapmte), &pBuf->smte, sizeof(pBuf->smte));
461 if (RT_FAILURE(rc))
462 {
463 LogRel(("DbgDiggerOs2: Error reading swap mte @ %RX32: %Rrc\n", Mte.mte_swapmte, rc));
464 return;
465 }
466 LDRSMTE const SwapMte = pBuf->smte;
467
468 /* Ignore empty modules or modules with too many segments. */
469 if (SwapMte.smte_objcnt == 0 || SwapMte.smte_objcnt > RT_ELEMENTS(pBuf->aOtes))
470 {
471 LogRel(("DbgDiggerOs2: Skipping: smte_objcnt= %#RX32\n", SwapMte.smte_objcnt));
472 return;
473 }
474
475#if 0
476 /*
477 * Try read the path name, falling back on module name.
478 */
479 rc = VERR_NOT_AVAILABLE;
480 if (SwapMte.smte_path != 0 && SwapMte.smte_pathlen > 0)
481 {
482 uint32_t cbToRead = RT_MIN(SwapMte.smte_path, sizeof(*pBuf) - 1);
483 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, SwapMte.smte_path), pBuf->ach, cbToRead);
484 pBuf->ach[cbToRead] = '\0';
485 }
486 if (RT_FAILURE(rc))
487 {
488 memcpy(pBuf->ach, Mte.mte_modname, sizeof(Mte.mte_modname));
489 pBuf->ach[sizeof(Mte.mte_modname)] = '\0';
490 RTStrStripR(pBuf->ach);
491 }
492#endif
493
494 /*
495 * Create a simple module.
496 */
497 memcpy(pBuf->ach, Mte.mte_modname, sizeof(Mte.mte_modname));
498 pBuf->ach[sizeof(Mte.mte_modname)] = '\0';
499 RTStrStripR(pBuf->ach);
500
501 RTDBGMOD hDbgMod;
502 rc = RTDbgModCreate(&hDbgMod, pBuf->ach, 0 /*cbSeg*/, 0 /*fFlags*/);
503 if (RT_FAILURE(rc))
504 {
505 LogRel(("DbgDiggerOs2: RTDbgModCreate failed: %Rrc\n", rc));
506 return;
507 }
508 rc = RTDbgModSetTag(hDbgMod, DIG_OS2_MOD_TAG);
509 if (RT_SUCCESS(rc))
510 {
511 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
512 if (hAs != NIL_RTDBGAS)
513 {
514 /*
515 * Read the object table and do the linking of each of them.
516 */
517 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, SwapMte.smte_objtab),
518 &pBuf->aOtes[0], sizeof(pBuf->aOtes[0]) * SwapMte.smte_objcnt);
519 if (RT_SUCCESS(rc))
520 {
521 uint32_t uRva = 0;
522 for (uint32_t i = 0; i < SwapMte.smte_objcnt; i++)
523 {
524 char szSegNm[16];
525 RTStrPrintf(szSegNm, sizeof(szSegNm), "seg%u", i);
526 rc = RTDbgModSegmentAdd(hDbgMod, uRva, pBuf->aOtes[i].ote_size, szSegNm, 0 /*fFlags*/, NULL);
527 if (RT_FAILURE(rc))
528 {
529 LogRel(("DbgDiggerOs2: RTDbgModSegmentAdd failed (i=%u, ote_size=%#x): %Rrc\n",
530 i, pBuf->aOtes[i].ote_size, rc));
531 break;
532 }
533 rc = RTDbgAsModuleLinkSeg(hAs, hDbgMod, i, pBuf->aOtes[i].ote_base, RTDBGASLINK_FLAGS_REPLACE /*fFlags*/);
534 if (RT_FAILURE(rc))
535 LogRel(("DbgDiggerOs2: RTDbgAsModuleLinkSeg failed (i=%u, ote_base=%#x): %Rrc\n",
536 i, pBuf->aOtes[i].ote_base, rc));
537 uRva += RT_ALIGN_32(pBuf->aOtes[i].ote_size, _4K);
538 }
539 }
540 else
541 LogRel(("DbgDiggerOs2: Error reading object table @ %#RX32 LB %#zx: %Rrc\n",
542 SwapMte.smte_objtab, sizeof(pBuf->aOtes[0]) * SwapMte.smte_objcnt, rc));
543 }
544 else
545 LogRel(("DbgDiggerOs2: DBGFR3AsResolveAndRetain failed\n"));
546 RTDbgAsRelease(hAs);
547 }
548 else
549 LogRel(("DbgDiggerOs2: RTDbgModSetTag failed: %Rrc\n", rc));
550 RTDbgModRelease(hDbgMod);
551
552}
553
554
555/**
556 * @copydoc DBGFOSREG::pfnInit
557 */
558static DECLCALLBACK(int) dbgDiggerOS2Init(PUVM pUVM, void *pvData)
559{
560 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
561 Assert(!pThis->fValid);
562
563 DBGDIGGEROS2BUF uBuf;
564 DBGFADDRESS Addr;
565 int rc;
566
567 /*
568 * Determine the OS/2 version.
569 */
570 /* Version info is at GIS:15h (major/minor/revision). */
571 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, pThis->selGIS, 0x15);
572 if (RT_FAILURE(rc))
573 return VERR_NOT_SUPPORTED;
574 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, uBuf.au32, sizeof(uint32_t));
575 if (RT_FAILURE(rc))
576 return VERR_NOT_SUPPORTED;
577
578 pThis->OS2MajorVersion = uBuf.au8[0];
579 pThis->OS2MinorVersion = uBuf.au8[1];
580
581 pThis->fValid = true;
582
583 /*
584 * Try use SAS to find the module list.
585 */
586 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, 0x70, 0x00);
587 if (RT_SUCCESS(rc))
588 {
589 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &uBuf.sas, sizeof(uBuf.sas));
590 if (RT_SUCCESS(rc))
591 {
592 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, 0x70, uBuf.sas.SAS_vm_data);
593 if (RT_SUCCESS(rc))
594 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &uBuf.sasvm, sizeof(uBuf.sasvm));
595 if (RT_SUCCESS(rc))
596 {
597 /*
598 * Work the module list.
599 */
600 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, uBuf.sasvm.SAS_vm_all_mte),
601 &uBuf.au32[0], sizeof(uBuf.au32[0]));
602 if (RT_SUCCESS(rc))
603 {
604 DBGFR3AddrFromFlat(pUVM, &Addr, uBuf.au32[0]);
605 while (Addr.FlatPtr != 0 && Addr.FlatPtr != UINT32_MAX)
606 {
607 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &uBuf.mte, sizeof(uBuf.mte));
608 if (RT_FAILURE(rc))
609 break;
610 LogRel(("DbgDiggerOs2: Module @ %#010RX32: %.8s %#x %#x\n", (uint32_t)Addr.FlatPtr,
611 uBuf.mte.mte_modname, uBuf.mte.mte_flags1, uBuf.mte.mte_flags2));
612
613 DBGFR3AddrFromFlat(pUVM, &Addr, uBuf.mte.mte_link);
614 dbgdiggerOS2ProcessModule(pUVM, pThis, &uBuf);
615 }
616 }
617 }
618 }
619 }
620
621 return VINF_SUCCESS;
622}
623
624
625/**
626 * @copydoc DBGFOSREG::pfnProbe
627 */
628static DECLCALLBACK(bool) dbgDiggerOS2Probe(PUVM pUVM, void *pvData)
629{
630 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
631 DBGFADDRESS Addr;
632 int rc;
633 uint16_t offInfo;
634 union
635 {
636 uint8_t au8[8192];
637 uint16_t au16[8192/2];
638 uint32_t au32[8192/4];
639 RTUTF16 wsz[8192/2];
640 } u;
641
642 /*
643 * If the DWORD at 70:0 contains 'SAS ' it's quite unlikely that this wouldn't be OS/2.
644 * Note: The SAS layout is similar between 16-bit and 32-bit OS/2, but not identical.
645 * 32-bit OS/2 will have the flat kernel data selector at SAS:06. The selector is 168h
646 * or similar. For 16-bit OS/2 the field contains a table offset into the SAS which will
647 * be much smaller. Fun fact: The global infoseg selector in the SAS is bimodal in 16-bit
648 * OS/2 and will work in real mode as well.
649 */
650 do {
651 rc = DBGFR3AddrFromSelOff(pUVM, 0 /*idCpu*/, &Addr, 0x70, 0x00);
652 if (RT_FAILURE(rc))
653 break;
654 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, u.au32, 256);
655 if (RT_FAILURE(rc))
656 break;
657 if (u.au32[0] != DIG_OS2_SAS_SIG)
658 break;
659
660 /* This sure looks like OS/2, but a bit of paranoia won't hurt. */
661 if (u.au16[2] >= u.au16[4])
662 break;
663
664 /* If 4th word is bigger than 5th, it's the flat kernel mode selector. */
665 if (u.au16[3] > u.au16[4])
666 pThis->f32Bit = true;
667
668 /* Offset into info table is either at SAS:14h or SAS:16h. */
669 if (pThis->f32Bit)
670 offInfo = u.au16[0x14/2];
671 else
672 offInfo = u.au16[0x16/2];
673
674 /* The global infoseg selector is the first entry in the info table. */
675 pThis->selGIS = u.au16[offInfo/2];
676 return true;
677 } while (0);
678
679 return false;
680}
681
682
683/**
684 * @copydoc DBGFOSREG::pfnDestruct
685 */
686static DECLCALLBACK(void) dbgDiggerOS2Destruct(PUVM pUVM, void *pvData)
687{
688 RT_NOREF2(pUVM, pvData);
689}
690
691
692/**
693 * @copydoc DBGFOSREG::pfnConstruct
694 */
695static DECLCALLBACK(int) dbgDiggerOS2Construct(PUVM pUVM, void *pvData)
696{
697 RT_NOREF1(pUVM);
698 PDBGDIGGEROS2 pThis = (PDBGDIGGEROS2)pvData;
699 pThis->fValid = false;
700 pThis->f32Bit = false;
701 pThis->enmVer = DBGDIGGEROS2VER_UNKNOWN;
702 return VINF_SUCCESS;
703}
704
705
706const DBGFOSREG g_DBGDiggerOS2 =
707{
708 /* .u32Magic = */ DBGFOSREG_MAGIC,
709 /* .fFlags = */ 0,
710 /* .cbData = */ sizeof(DBGDIGGEROS2),
711 /* .szName = */ "OS/2",
712 /* .pfnConstruct = */ dbgDiggerOS2Construct,
713 /* .pfnDestruct = */ dbgDiggerOS2Destruct,
714 /* .pfnProbe = */ dbgDiggerOS2Probe,
715 /* .pfnInit = */ dbgDiggerOS2Init,
716 /* .pfnRefresh = */ dbgDiggerOS2Refresh,
717 /* .pfnTerm = */ dbgDiggerOS2Term,
718 /* .pfnQueryVersion = */ dbgDiggerOS2QueryVersion,
719 /* .pfnQueryInterface = */ dbgDiggerOS2QueryInterface,
720 /* .pfnStackUnwindAssist = */ dbgDiggerOS2StackUnwindAssist,
721 /* .u32EndMagic = */ DBGFOSREG_MAGIC
722};
Note: See TracBrowser for help on using the repository browser.

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