VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGPlugInSolaris.cpp@ 94521

Last change on this file since 94521 was 93485, checked in by vboxsync, 2 years ago

Debugger,Main: Doxygen fixes. bugref:10074

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 46.5 KB
Line 
1/* $Id: DBGPlugInSolaris.cpp 93485 2022-01-29 12:32:20Z vboxsync $ */
2/** @file
3 * DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
4 */
5
6/*
7 * Copyright (C) 2008-2022 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 "DBGPlugInCommonELF.h"
25#include <VBox/vmm/dbgf.h>
26#include <VBox/vmm/vmmr3vtable.h>
27#include <iprt/asm.h>
28#include <iprt/err.h>
29#include <iprt/mem.h>
30#include <iprt/stream.h>
31#include <iprt/string.h>
32
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37/** Solaris on little endian ASCII systems. */
38#define DIG_SOL_MOD_TAG UINT64_C(0x00736972616c6f53)
39
40
41/*********************************************************************************************************************************
42* Structures and Typedefs *
43*********************************************************************************************************************************/
44
45/** @name InternalSolaris structures
46 * @{ */
47
48/** sys/modctl.h */
49typedef struct SOL32v11_modctl
50{
51 uint32_t mod_next; /**< 0 */
52 uint32_t mod_prev; /**< 4 */
53 int32_t mod_id; /**< 8 */
54 uint32_t mod_mp; /**< c Pointer to the kernel runtime loader bits. */
55 uint32_t mod_inprogress_thread; /**< 10 */
56 uint32_t mod_modinfo; /**< 14 */
57 uint32_t mod_linkage; /**< 18 */
58 uint32_t mod_filename; /**< 1c */
59 uint32_t mod_modname; /**< 20 */
60 int8_t mod_busy; /**< 24 */
61 int8_t mod_want; /**< 25 */
62 int8_t mod_prim; /**< 26 this is 1 for 'unix' and a few others. */
63 int8_t mod_unused_padding; /**< 27 */
64 int32_t mod_ref; /**< 28 */
65 int8_t mod_loaded; /**< 2c */
66 int8_t mod_installed; /**< 2d */
67 int8_t mod_loadflags; /**< 2e */
68 int8_t mod_delay_unload; /**< 2f */
69 uint32_t mod_requisites; /**< 30 */
70 uint32_t mod___unused; /**< 34 */
71 int32_t mod_loadcnt; /**< 38 */
72 int32_t mod_nenabled; /**< 3c */
73 uint32_t mod_text; /**< 40 */
74 uint32_t mod_text_size; /**< 44 */
75 int32_t mod_gencount; /**< 48 */
76 uint32_t mod_requisite_loading; /**< 4c */
77} SOL32v11_modctl_t;
78AssertCompileSize(SOL32v11_modctl_t, 0x50);
79
80typedef struct SOL64v11_modctl
81{
82 uint64_t mod_next; /**< 0 */
83 uint64_t mod_prev; /**< 8 */
84 int32_t mod_id; /**< 10 */
85 int32_t mod_padding0;
86 uint64_t mod_mp; /**< 18 Pointer to the kernel runtime loader bits. */
87 uint64_t mod_inprogress_thread; /**< 20 */
88 uint64_t mod_modinfo; /**< 28 */
89 uint64_t mod_linkage; /**< 30 */
90 uint64_t mod_filename; /**< 38 */
91 uint64_t mod_modname; /**< 40 */
92 int8_t mod_busy; /**< 48 */
93 int8_t mod_want; /**< 49 */
94 int8_t mod_prim; /**< 4a this is 1 for 'unix' and a few others. */
95 int8_t mod_unused_padding; /**< 4b */
96 int32_t mod_ref; /**< 4c */
97 int8_t mod_loaded; /**< 50 */
98 int8_t mod_installed; /**< 51 */
99 int8_t mod_loadflags; /**< 52 */
100 int8_t mod_delay_unload; /**< 53 */
101 int32_t mod_padding1;
102 uint64_t mod_requisites; /**< 58 */
103 uint64_t mod___unused; /**< 60 */
104 int32_t mod_loadcnt; /**< 68 */
105 int32_t mod_nenabled; /**< 6c */
106 uint64_t mod_text; /**< 70 */
107 uint64_t mod_text_size; /**< 78 */
108 int32_t mod_gencount; /**< 80 */
109 int32_t mod_padding2;
110 uint64_t mod_requisite_loading; /**< 88 */
111} SOL64v11_modctl_t;
112AssertCompileSize(SOL64v11_modctl_t, 0x90);
113
114typedef struct SOL32v9_modctl
115{
116 uint32_t mod_next; /**< 0 */
117 uint32_t mod_prev; /**< 4 */
118 int32_t mod_id; /**< 8 */
119 uint32_t mod_mp; /**< c Pointer to the kernel runtime loader bits. */
120 uint32_t mod_inprogress_thread; /**< 10 */
121 uint32_t mod_modinfo; /**< 14 */
122 uint32_t mod_linkage; /**< 18 */
123 uint32_t mod_filename; /**< 1c */
124 uint32_t mod_modname; /**< 20 */
125 int32_t mod_busy; /**< 24 */
126 int32_t mod_stub; /**< 28 DIFF 1 */
127 int8_t mod_loaded; /**< 2c */
128 int8_t mod_installed; /**< 2d */
129 int8_t mod_loadflags; /**< 2e */
130 int8_t mod_want; /**< 2f DIFF 2 */
131 uint32_t mod_requisites; /**< 30 */
132 uint32_t mod_dependents; /**< 34 DIFF 3 */
133 int32_t mod_loadcnt; /**< 38 */
134 /* DIFF 4: 4 bytes added in v11 */
135 uint32_t mod_text; /**< 3c */
136 uint32_t mod_text_size; /**< 40 */
137 /* DIFF 5: 8 bytes added in v11 */
138} SOL32v9_modctl_t;
139AssertCompileSize(SOL32v9_modctl_t, 0x44);
140
141typedef struct SOL64v9_modctl
142{
143 uint64_t mod_next; /**< 0 */
144 uint64_t mod_prev; /**< 8 */
145 int32_t mod_id; /**< 10 */
146 int32_t mod_padding0;
147 uint64_t mod_mp; /**< 18 Pointer to the kernel runtime loader bits. */
148 uint64_t mod_inprogress_thread; /**< 20 */
149 uint64_t mod_modinfo; /**< 28 */
150 uint64_t mod_linkage; /**< 30 */
151 uint64_t mod_filename; /**< 38 */
152 uint64_t mod_modname; /**< 40 */
153 int32_t mod_busy; /**< 48 */
154 int32_t mod_stub; /**< 4c DIFF 1 - is this a pointer? */
155 int8_t mod_loaded; /**< 50 */
156 int8_t mod_installed; /**< 51 */
157 int8_t mod_loadflags; /**< 52 */
158 int8_t mod_want; /**< 53 DIFF 2 */
159 int32_t mod_padding1;
160 uint64_t mod_requisites; /**< 58 */
161 uint64_t mod_dependencies; /**< 60 DIFF 3 */
162 int32_t mod_loadcnt; /**< 68 */
163 int32_t mod_padding3; /**< 6c DIFF 4 */
164 uint64_t mod_text; /**< 70 */
165 uint64_t mod_text_size; /**< 78 */
166 /* DIFF 5: 8 bytes added in v11 */
167} SOL64v9_modctl_t;
168AssertCompileSize(SOL64v9_modctl_t, 0x80);
169
170typedef union SOL_modctl
171{
172 SOL32v9_modctl_t v9_32;
173 SOL32v11_modctl_t v11_32;
174 SOL64v9_modctl_t v9_64;
175 SOL64v11_modctl_t v11_64;
176} SOL_modctl_t;
177
178/** sys/kobj.h */
179typedef struct SOL32_module
180{
181 int32_t total_allocated; /**< 0 */
182 Elf32_Ehdr hdr; /**< 4 Easy to validate */
183 uint32_t shdrs; /**< 38 */
184 uint32_t symhdr; /**< 3c */
185 uint32_t strhdr; /**< 40 */
186 uint32_t depends_on; /**< 44 */
187 uint32_t symsize; /**< 48 */
188 uint32_t symspace; /**< 4c */
189 int32_t flags; /**< 50 */
190 uint32_t text_size; /**< 54 */
191 uint32_t data_size; /**< 58 */
192 uint32_t text; /**< 5c */
193 uint32_t data; /**< 60 */
194 uint32_t symtbl_section; /**< 64 */
195 uint32_t symtbl; /**< 68 */
196 uint32_t strings; /**< 6c */
197 uint32_t hashsize; /**< 70 */
198 uint32_t buckets; /**< 74 */
199 uint32_t chains; /**< 78 */
200 uint32_t nsyms; /**< 7c */
201 uint32_t bss_align; /**< 80 */
202 uint32_t bss_size; /**< 84 */
203 uint32_t bss; /**< 88 */
204 uint32_t filename; /**< 8c */
205 uint32_t head; /**< 90 */
206 uint32_t tail; /**< 94 */
207 uint32_t destination; /**< 98 */
208 uint32_t machdata; /**< 9c */
209 uint32_t ctfdata; /**< a0 */
210 uint32_t ctfsize; /**< a4 */
211 uint32_t fbt_tab; /**< a8 */
212 uint32_t fbt_size; /**< ac */
213 uint32_t fbt_nentries; /**< b0 */
214 uint32_t textwin; /**< b4 */
215 uint32_t textwin_base; /**< b8 */
216 uint32_t sdt_probes; /**< bc */
217 uint32_t sdt_nprobes; /**< c0 */
218 uint32_t sdt_tab; /**< c4 */
219 uint32_t sdt_size; /**< c8 */
220 uint32_t sigdata; /**< cc */
221 uint32_t sigsize; /**< d0 */
222} SOL32_module_t;
223AssertCompileSize(Elf32_Ehdr, 0x34);
224AssertCompileSize(SOL32_module_t, 0xd4);
225
226typedef struct SOL64_module
227{
228 int32_t total_allocated; /**< 0 */
229 int32_t padding0;
230 Elf64_Ehdr hdr; /**< 8 Easy to validate */
231 uint64_t shdrs; /**< 48 */
232 uint64_t symhdr; /**< 50 */
233 uint64_t strhdr; /**< 58 */
234 uint64_t depends_on; /**< 60 */
235 uint64_t symsize; /**< 68 */
236 uint64_t symspace; /**< 70 */
237 int32_t flags; /**< 78 */
238 int32_t padding1;
239 uint64_t text_size; /**< 80 */
240 uint64_t data_size; /**< 88 */
241 uint64_t text; /**< 90 */
242 uint64_t data; /**< 98 */
243 uint32_t symtbl_section; /**< a0 */
244 int32_t padding2;
245 uint64_t symtbl; /**< a8 */
246 uint64_t strings; /**< b0 */
247 uint32_t hashsize; /**< b8 */
248 int32_t padding3;
249 uint64_t buckets; /**< c0 */
250 uint64_t chains; /**< c8 */
251 uint32_t nsyms; /**< d0 */
252 uint32_t bss_align; /**< d4 */
253 uint64_t bss_size; /**< d8 */
254 uint64_t bss; /**< e0 */
255 uint64_t filename; /**< e8 */
256 uint64_t head; /**< f0 */
257 uint64_t tail; /**< f8 */
258 uint64_t destination; /**< 100 */
259 uint64_t machdata; /**< 108 */
260 uint64_t ctfdata; /**< 110 */
261 uint64_t ctfsize; /**< 118 */
262 uint64_t fbt_tab; /**< 120 */
263 uint64_t fbt_size; /**< 128 */
264 uint64_t fbt_nentries; /**< 130 */
265 uint64_t textwin; /**< 138 */
266 uint64_t textwin_base; /**< 140 */
267 uint64_t sdt_probes; /**< 148 */
268 uint64_t sdt_nprobes; /**< 150 */
269 uint64_t sdt_tab; /**< 158 */
270 uint64_t sdt_size; /**< 160 */
271 uint64_t sigdata; /**< 168 */
272 uint64_t sigsize; /**< 170 */
273} SOL64_module_t;
274AssertCompileSize(Elf64_Ehdr, 0x40);
275AssertCompileSize(SOL64_module_t, 0x178);
276
277typedef struct SOL_utsname
278{
279 char sysname[257];
280 char nodename[257];
281 char release[257];
282 char version[257];
283 char machine[257];
284} SOL_utsname_t;
285AssertCompileSize(SOL_utsname_t, 5 * 257);
286
287/** @} */
288
289
290/**
291 * Solaris guest OS digger instance data.
292 */
293typedef struct DBGDIGGERSOLARIS
294{
295 /** Whether the information is valid or not.
296 * (For fending off illegal interface method calls.) */
297 bool fValid;
298
299 /** Address of the 'unix' text segment.
300 * This is set during probing. */
301 DBGFADDRESS AddrUnixText;
302 /** Address of the 'unix' text segment.
303 * This is set during probing. */
304 DBGFADDRESS AddrUnixData;
305 /** Address of the 'unix' modctl_t (aka modules). */
306 DBGFADDRESS AddrUnixModCtl;
307 /** modctl_t version number. */
308 int iModCtlVer;
309 /** 64-bit/32-bit indicator. */
310 bool f64Bit;
311
312} DBGDIGGERSOLARIS;
313/** Pointer to the solaris guest OS digger instance data. */
314typedef DBGDIGGERSOLARIS *PDBGDIGGERSOLARIS;
315
316
317/*********************************************************************************************************************************
318* Defined Constants And Macros *
319*********************************************************************************************************************************/
320/** Min kernel address. */
321#define SOL32_MIN_KRNL_ADDR UINT32_C(0x80000000)
322/** Max kernel address. */
323#define SOL32_MAX_KRNL_ADDR UINT32_C(0xfffff000)
324
325/** Min kernel address. */
326#define SOL64_MIN_KRNL_ADDR UINT64_C(0xFFFFC00000000000)
327/** Max kernel address. */
328#define SOL64_MAX_KRNL_ADDR UINT64_C(0xFFFFFFFFFFF00000)
329
330
331/** Validates a 32-bit solaris kernel address */
332#if 0 /* OpenSolaris, early boot have symspace at 0x27a2000 */
333# define SOL32_VALID_ADDRESS(Addr) ((Addr) > SOL32_MIN_KRNL_ADDR && (Addr) < SOL32_MAX_KRNL_ADDR)
334#else
335# define SOL32_VALID_ADDRESS(Addr) ( ((Addr) > SOL32_MIN_KRNL_ADDR && (Addr) < SOL32_MAX_KRNL_ADDR) \
336 || ((Addr) > UINT32_C(0x02000000) && (Addr) < UINT32_C(0x04000000)) /* boot */ )
337#endif
338
339/** Validates a 64-bit solaris kernel address */
340#define SOL64_VALID_ADDRESS(Addr) ( (Addr) > SOL64_MIN_KRNL_ADDR \
341 && (Addr) < SOL64_MAX_KRNL_ADDR)
342
343/** The max data segment size of the 'unix' module. */
344#define SOL_UNIX_MAX_DATA_SEG_SIZE 0x01000000
345
346/** The max code segment size of the 'unix' module.
347 * This is the same for both 64-bit and 32-bit. */
348#define SOL_UNIX_MAX_CODE_SEG_SIZE 0x00400000
349
350
351/*********************************************************************************************************************************
352* Internal Functions *
353*********************************************************************************************************************************/
354static DECLCALLBACK(int) dbgDiggerSolarisInit(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData);
355
356
357
358/**
359 * @copydoc DBGFOSREG::pfnStackUnwindAssist
360 */
361static DECLCALLBACK(int) dbgDiggerSolarisStackUnwindAssist(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData, VMCPUID idCpu,
362 PDBGFSTACKFRAME pFrame, PRTDBGUNWINDSTATE pState,
363 PCCPUMCTX pInitialCtx, RTDBGAS hAs, uint64_t *puScratch)
364{
365 RT_NOREF(pUVM, pVMM, pvData, idCpu, pFrame, pState, pInitialCtx, hAs, puScratch);
366 return VINF_SUCCESS;
367}
368
369
370/**
371 * @copydoc DBGFOSREG::pfnQueryInterface
372 */
373static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData, DBGFOSINTERFACE enmIf)
374{
375 RT_NOREF(pUVM, pVMM, pvData, enmIf);
376 return NULL;
377}
378
379
380/**
381 * @copydoc DBGFOSREG::pfnQueryVersion
382 */
383static DECLCALLBACK(int) dbgDiggerSolarisQueryVersion(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData,
384 char *pszVersion, size_t cchVersion)
385{
386 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
387 Assert(pThis->fValid);
388
389 /*
390 * It's all in the utsname symbol...
391 */
392 SOL_utsname_t UtsName;
393 RT_ZERO(UtsName); /* Make MSC happy. */
394 DBGFADDRESS Addr;
395 RTDBGSYMBOL SymUtsName;
396 int rc = pVMM->pfnDBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "utsname", &SymUtsName, NULL);
397 if (RT_SUCCESS(rc))
398 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, SymUtsName.Value),
399 &UtsName, sizeof(UtsName));
400 if (RT_FAILURE(rc))
401 {
402 /*
403 * Try searching by the name...
404 */
405 memset(&UtsName, '\0', sizeof(UtsName));
406 strcpy(&UtsName.sysname[0], "SunOS");
407 rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &pThis->AddrUnixData, SOL_UNIX_MAX_DATA_SEG_SIZE, 1,
408 &UtsName.sysname[0], sizeof(UtsName.sysname), &Addr);
409 if (RT_SUCCESS(rc))
410 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr,
411 Addr.FlatPtr - RT_OFFSETOF(SOL_utsname_t, sysname)),
412 &UtsName, sizeof(UtsName));
413 }
414
415 /*
416 * Copy out the result (if any).
417 */
418 if (RT_SUCCESS(rc))
419 {
420 if ( UtsName.sysname[sizeof(UtsName.sysname) - 1] != '\0'
421 || UtsName.nodename[sizeof(UtsName.nodename) - 1] != '\0'
422 || UtsName.release[sizeof(UtsName.release) - 1] != '\0'
423 || UtsName.version[sizeof(UtsName.version) - 1] != '\0'
424 || UtsName.machine[sizeof(UtsName.machine) - 1] != '\0')
425 {
426 //rc = VERR_DBGF_UNEXPECTED_OS_DATA;
427 rc = VERR_GENERAL_FAILURE;
428 RTStrPrintf(pszVersion, cchVersion, "failed - bogus utsname");
429 }
430 else
431 RTStrPrintf(pszVersion, cchVersion, "%s %s", UtsName.version, UtsName.release);
432 }
433 else
434 RTStrPrintf(pszVersion, cchVersion, "failed - %Rrc", rc);
435
436 return rc;
437}
438
439
440
441/**
442 * Processes a modctl_t.
443 *
444 * @param pUVM The user mode VM handle.
445 * @param pVMM The VMM function table.
446 * @param pThis Our instance data.
447 * @param pModCtl Pointer to the modctl structure.
448 */
449static void dbgDiggerSolarisProcessModCtl32(PUVM pUVM, PCVMMR3VTABLE pVMM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
450{
451 RT_NOREF1(pThis);
452
453 /* skip it if it's not loaded and installed */
454 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_loaded, v9_32.mod_loaded);
455 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_installed, v9_32.mod_installed);
456 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_id, v9_32.mod_id);
457 if ( ( !pModCtl->v9_32.mod_loaded
458 || !pModCtl->v9_32.mod_installed)
459 && pModCtl->v9_32.mod_id > 3)
460 return;
461
462 /*
463 * Read the module and file names first
464 */
465 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_modname, v9_32.mod_modname);
466 char szModName[64];
467 DBGFADDRESS Addr;
468 int rc = pVMM->pfnDBGFR3MemReadString(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_modname),
469 szModName, sizeof(szModName));
470 if (RT_FAILURE(rc))
471 return;
472 if (!RTStrEnd(szModName, sizeof(szModName)))
473 szModName[sizeof(szModName) - 1] = '\0';
474
475 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_filename, v9_32.mod_filename);
476 char szFilename[256];
477 rc = pVMM->pfnDBGFR3MemReadString(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_filename),
478 szFilename, sizeof(szFilename));
479 if (RT_FAILURE(rc))
480 strcpy(szFilename, szModName);
481 else if (!RTStrEnd(szFilename, sizeof(szFilename)))
482 szFilename[sizeof(szFilename) - 1] = '\0';
483
484 /*
485 * Then read the module struct and validate it.
486 */
487 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_mp, v9_32.mod_mp);
488 struct SOL32_module Module;
489 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_mp), &Module, sizeof(Module));
490 if (RT_FAILURE(rc))
491 return;
492
493 /* Basic validations of the elf header. */
494 if ( Module.hdr.e_ident[EI_MAG0] != ELFMAG0
495 || Module.hdr.e_ident[EI_MAG1] != ELFMAG1
496 || Module.hdr.e_ident[EI_MAG2] != ELFMAG2
497 || Module.hdr.e_ident[EI_MAG3] != ELFMAG3
498 || Module.hdr.e_ident[EI_CLASS] != ELFCLASS32
499 || Module.hdr.e_ident[EI_DATA] != ELFDATA2LSB
500 || Module.hdr.e_ident[EI_VERSION] != EV_CURRENT
501 || !ASMMemIsZero(&Module.hdr.e_ident[EI_PAD], EI_NIDENT - EI_PAD)
502 )
503 return;
504 if (Module.hdr.e_version != EV_CURRENT)
505 return;
506 if (Module.hdr.e_ehsize != sizeof(Module.hdr))
507 return;
508 if ( Module.hdr.e_type != ET_DYN
509 && Module.hdr.e_type != ET_REL
510 && Module.hdr.e_type != ET_EXEC) //??
511 return;
512 if ( Module.hdr.e_machine != EM_386
513 && Module.hdr.e_machine != EM_486)
514 return;
515 if ( Module.hdr.e_phentsize != sizeof(Elf32_Phdr)
516 && Module.hdr.e_phentsize) //??
517 return;
518 if (Module.hdr.e_shentsize != sizeof(Elf32_Shdr))
519 return;
520
521 if (Module.hdr.e_shentsize != sizeof(Elf32_Shdr))
522 return;
523
524 /* Basic validations of the rest of the stuff. */
525 if ( !SOL32_VALID_ADDRESS(Module.shdrs)
526 || !SOL32_VALID_ADDRESS(Module.symhdr)
527 || !SOL32_VALID_ADDRESS(Module.strhdr)
528 || (!SOL32_VALID_ADDRESS(Module.symspace) && Module.symspace)
529 || !SOL32_VALID_ADDRESS(Module.text)
530 || !SOL32_VALID_ADDRESS(Module.data)
531 || (!SOL32_VALID_ADDRESS(Module.symtbl) && Module.symtbl)
532 || (!SOL32_VALID_ADDRESS(Module.strings) && Module.strings)
533 || (!SOL32_VALID_ADDRESS(Module.head) && Module.head)
534 || (!SOL32_VALID_ADDRESS(Module.tail) && Module.tail)
535 || !SOL32_VALID_ADDRESS(Module.filename))
536 return;
537 if ( Module.symsize > _4M
538 || Module.hdr.e_shnum > 4096
539 || Module.nsyms > _256K)
540 return;
541
542 /* Ignore modules without symbols. */
543 if (!Module.symtbl || !Module.strings || !Module.symspace || !Module.symsize)
544 return;
545
546 /* Check that the symtbl and strings points inside the symspace. */
547 if (Module.strings - Module.symspace >= Module.symsize)
548 return;
549 if (Module.symtbl - Module.symspace >= Module.symsize)
550 return;
551
552 /*
553 * Read the section headers, symbol table and string tables.
554 */
555 size_t cb = Module.hdr.e_shnum * sizeof(Elf32_Shdr);
556 Elf32_Shdr *paShdrs = (Elf32_Shdr *)RTMemTmpAlloc(cb);
557 if (!paShdrs)
558 return;
559 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, Module.shdrs), paShdrs, cb);
560 if (RT_SUCCESS(rc))
561 {
562 void *pvSymSpace = RTMemTmpAlloc(Module.symsize + 1);
563 if (pvSymSpace)
564 {
565 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, Module.symspace),
566 pvSymSpace, Module.symsize);
567 if (RT_SUCCESS(rc))
568 {
569 ((uint8_t *)pvSymSpace)[Module.symsize] = 0;
570
571 /*
572 * Hand it over to the common ELF32 module parser.
573 */
574 char const *pbStrings = (char const *)pvSymSpace + (Module.strings - Module.symspace);
575 size_t cbMaxStrings = Module.symsize - (Module.strings - Module.symspace);
576
577 Elf32_Sym const *paSyms = (Elf32_Sym const *)((uintptr_t)pvSymSpace + (Module.symtbl - Module.symspace));
578 size_t cMaxSyms = (Module.symsize - (Module.symtbl - Module.symspace)) / sizeof(Elf32_Sym);
579 cMaxSyms = RT_MIN(cMaxSyms, Module.nsyms);
580
581 DBGDiggerCommonParseElf32Mod(pUVM, pVMM, szModName, szFilename, DBG_DIGGER_ELF_FUNNY_SHDRS,
582 &Module.hdr, paShdrs, paSyms, cMaxSyms, pbStrings, cbMaxStrings,
583 SOL32_MIN_KRNL_ADDR, SOL32_MAX_KRNL_ADDR - 1, DIG_SOL_MOD_TAG);
584 }
585 RTMemTmpFree(pvSymSpace);
586 }
587 }
588
589 RTMemTmpFree(paShdrs);
590 return;
591}
592
593
594/**
595 * Processes a modctl_t.
596 *
597 * @param pUVM The user mode VM handle.
598 * @param pVMM The VMM function table.
599 * @param pThis Our instance data.
600 * @param pModCtl Pointer to the modctl structure.
601 */
602static void dbgDiggerSolarisProcessModCtl64(PUVM pUVM, PCVMMR3VTABLE pVMM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
603{
604 RT_NOREF1(pThis);
605
606 /* skip it if it's not loaded and installed */
607 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_loaded, v9_64.mod_loaded);
608 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_installed, v9_64.mod_installed);
609 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_id, v9_64.mod_id);
610 if ( ( !pModCtl->v9_64.mod_loaded
611 || !pModCtl->v9_64.mod_installed)
612 && pModCtl->v9_64.mod_id > 3)
613 return;
614
615 /*
616 * Read the module and file names first
617 */
618 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_modname, v9_64.mod_modname);
619 char szModName[64];
620 DBGFADDRESS Addr;
621 int rc = pVMM->pfnDBGFR3MemReadString(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_modname),
622 szModName, sizeof(szModName));
623 if (RT_FAILURE(rc))
624 return;
625 if (!RTStrEnd(szModName, sizeof(szModName)))
626 szModName[sizeof(szModName) - 1] = '\0';
627
628 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_filename, v9_64.mod_filename);
629 char szFilename[256];
630 rc = pVMM->pfnDBGFR3MemReadString(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_filename),
631 szFilename, sizeof(szFilename));
632 if (RT_FAILURE(rc))
633 strcpy(szFilename, szModName);
634 else if (!RTStrEnd(szFilename, sizeof(szFilename)))
635 szFilename[sizeof(szFilename) - 1] = '\0';
636
637 /*
638 * Then read the module struct and validate it.
639 */
640 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_mp, v9_64.mod_mp);
641 struct SOL64_module Module;
642 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_mp), &Module, sizeof(Module));
643 if (RT_FAILURE(rc))
644 return;
645
646 /* Basic validations of the elf header. */
647 if ( Module.hdr.e_ident[EI_MAG0] != ELFMAG0
648 || Module.hdr.e_ident[EI_MAG1] != ELFMAG1
649 || Module.hdr.e_ident[EI_MAG2] != ELFMAG2
650 || Module.hdr.e_ident[EI_MAG3] != ELFMAG3
651 || Module.hdr.e_ident[EI_CLASS] != ELFCLASS64
652 || Module.hdr.e_ident[EI_DATA] != ELFDATA2LSB
653 || Module.hdr.e_ident[EI_VERSION] != EV_CURRENT
654 || !ASMMemIsZero(&Module.hdr.e_ident[EI_PAD], EI_NIDENT - EI_PAD)
655 )
656 return;
657 if (Module.hdr.e_version != EV_CURRENT)
658 return;
659 if (Module.hdr.e_ehsize != sizeof(Module.hdr))
660 return;
661 if ( Module.hdr.e_type != ET_DYN
662 && Module.hdr.e_type != ET_REL
663 && Module.hdr.e_type != ET_EXEC) //??
664 return;
665 if (Module.hdr.e_machine != EM_X86_64)
666 return;
667 if ( Module.hdr.e_phentsize != sizeof(Elf64_Phdr)
668 && Module.hdr.e_phentsize) //??
669 return;
670 if (Module.hdr.e_shentsize != sizeof(Elf64_Shdr))
671 return;
672
673 if (Module.hdr.e_shentsize != sizeof(Elf64_Shdr))
674 return;
675
676 /* Basic validations of the rest of the stuff. */
677 if ( !SOL64_VALID_ADDRESS(Module.shdrs)
678 || !SOL64_VALID_ADDRESS(Module.symhdr)
679 || !SOL64_VALID_ADDRESS(Module.strhdr)
680 || (!SOL64_VALID_ADDRESS(Module.symspace) && Module.symspace)
681 || !SOL64_VALID_ADDRESS(Module.text)
682 || !SOL64_VALID_ADDRESS(Module.data)
683 || (!SOL64_VALID_ADDRESS(Module.symtbl) && Module.symtbl)
684 || (!SOL64_VALID_ADDRESS(Module.strings) && Module.strings)
685 || (!SOL64_VALID_ADDRESS(Module.head) && Module.head)
686 || (!SOL64_VALID_ADDRESS(Module.tail) && Module.tail)
687 || !SOL64_VALID_ADDRESS(Module.filename))
688 return;
689 if ( Module.symsize > _4M
690 || Module.hdr.e_shnum > 4096
691 || Module.nsyms > _256K)
692 return;
693
694 /* Ignore modules without symbols. */
695 if (!Module.symtbl || !Module.strings || !Module.symspace || !Module.symsize)
696 return;
697
698 /* Check that the symtbl and strings points inside the symspace. */
699 if (Module.strings - Module.symspace >= Module.symsize)
700 return;
701 if (Module.symtbl - Module.symspace >= Module.symsize)
702 return;
703
704 /*
705 * Read the section headers, symbol table and string tables.
706 */
707 size_t cb = Module.hdr.e_shnum * sizeof(Elf64_Shdr);
708 Elf64_Shdr *paShdrs = (Elf64_Shdr *)RTMemTmpAlloc(cb);
709 if (!paShdrs)
710 return;
711 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, Module.shdrs), paShdrs, cb);
712 if (RT_SUCCESS(rc))
713 {
714 void *pvSymSpace = RTMemTmpAlloc(Module.symsize + 1);
715 if (pvSymSpace)
716 {
717 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, Module.symspace),
718 pvSymSpace, Module.symsize);
719 if (RT_SUCCESS(rc))
720 {
721 ((uint8_t *)pvSymSpace)[Module.symsize] = 0;
722
723 /*
724 * Hand it over to the common ELF64 module parser.
725 */
726 char const *pbStrings = (char const *)pvSymSpace + (Module.strings - Module.symspace);
727 size_t cbMaxStrings = Module.symsize - (Module.strings - Module.symspace);
728
729 Elf64_Sym const *paSyms = (Elf64_Sym const *)((uintptr_t)pvSymSpace + (uintptr_t)(Module.symtbl - Module.symspace));
730 size_t cMaxSyms = (Module.symsize - (Module.symtbl - Module.symspace)) / sizeof(Elf32_Sym);
731 cMaxSyms = RT_MIN(cMaxSyms, Module.nsyms);
732
733 DBGDiggerCommonParseElf64Mod(pUVM, pVMM, szModName, szFilename, DBG_DIGGER_ELF_FUNNY_SHDRS,
734 &Module.hdr, paShdrs, paSyms, cMaxSyms, pbStrings, cbMaxStrings,
735 SOL64_MIN_KRNL_ADDR, SOL64_MAX_KRNL_ADDR - 1, DIG_SOL_MOD_TAG);
736 }
737 RTMemTmpFree(pvSymSpace);
738 }
739 }
740
741 RTMemTmpFree(paShdrs);
742 return;
743}
744
745
746/**
747 * @copydoc DBGFOSREG::pfnTerm
748 */
749static DECLCALLBACK(void) dbgDiggerSolarisTerm(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
750{
751 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
752 RT_NOREF(pUVM, pVMM);
753 Assert(pThis->fValid);
754
755 pThis->fValid = false;
756}
757
758
759/**
760 * @copydoc DBGFOSREG::pfnRefresh
761 */
762static DECLCALLBACK(int) dbgDiggerSolarisRefresh(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
763{
764 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
765 RT_NOREF(pThis);
766 Assert(pThis->fValid);
767
768 /*
769 * For now we'll flush and reload everything.
770 */
771 RTDBGAS hDbgAs = pVMM->pfnDBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
772 if (hDbgAs != NIL_RTDBGAS)
773 {
774 uint32_t iMod = RTDbgAsModuleCount(hDbgAs);
775 while (iMod-- > 0)
776 {
777 RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);
778 if (hMod != NIL_RTDBGMOD)
779 {
780 if (RTDbgModGetTag(hMod) == DIG_SOL_MOD_TAG)
781 {
782 int rc = RTDbgAsModuleUnlink(hDbgAs, hMod);
783 AssertRC(rc);
784 }
785 RTDbgModRelease(hMod);
786 }
787 }
788 RTDbgAsRelease(hDbgAs);
789 }
790
791 dbgDiggerSolarisTerm(pUVM, pVMM, pvData);
792 return dbgDiggerSolarisInit(pUVM, pVMM, pvData);
793}
794
795
796/**
797 * @copydoc DBGFOSREG::pfnInit
798 */
799static DECLCALLBACK(int) dbgDiggerSolarisInit(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
800{
801 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
802 Assert(!pThis->fValid);
803 int rc;
804 size_t cbModCtl = 0;
805
806 /*
807 * On Solaris the kernel and is the global address space.
808 */
809 pVMM->pfnDBGFR3AsSetAlias(pUVM, DBGF_AS_KERNEL, DBGF_AS_GLOBAL);
810
811/** @todo Use debug_info, build 7x / S10U6. */
812
813 /*
814 * Find the 'unix' modctl_t structure (aka modules).
815 * We know it resides in the unix data segment.
816 */
817 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &pThis->AddrUnixModCtl, 0);
818
819 DBGFADDRESS CurAddr = pThis->AddrUnixData;
820 DBGFADDRESS MaxAddr;
821 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &MaxAddr, CurAddr.FlatPtr + SOL_UNIX_MAX_DATA_SEG_SIZE);
822 const uint8_t *pbExpr = (const uint8_t *)&pThis->AddrUnixText.FlatPtr;
823 const uint32_t cbExpr = pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t);
824 while ( CurAddr.FlatPtr < MaxAddr.FlatPtr
825 && CurAddr.FlatPtr >= pThis->AddrUnixData.FlatPtr)
826 {
827 DBGFADDRESS HitAddr;
828 rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &CurAddr, MaxAddr.FlatPtr - CurAddr.FlatPtr, 1, pbExpr, cbExpr, &HitAddr);
829 if (RT_FAILURE(rc))
830 break;
831
832 /*
833 * Read out the modctl_t structure.
834 */
835 DBGFADDRESS ModCtlAddr;
836
837 /* v11 */
838 if (pThis->f64Bit)
839 {
840 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v11_modctl_t, mod_text));
841 SOL64v11_modctl_t ModCtlv11;
842 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv11, sizeof(ModCtlv11));
843 if (RT_SUCCESS(rc))
844 {
845 if ( SOL64_VALID_ADDRESS(ModCtlv11.mod_next)
846 && SOL64_VALID_ADDRESS(ModCtlv11.mod_prev)
847 && ModCtlv11.mod_id == 0
848 && SOL64_VALID_ADDRESS(ModCtlv11.mod_mp)
849 && SOL64_VALID_ADDRESS(ModCtlv11.mod_filename)
850 && SOL64_VALID_ADDRESS(ModCtlv11.mod_modname)
851 && ModCtlv11.mod_prim == 1
852 && ModCtlv11.mod_loaded == 1
853 && ModCtlv11.mod_installed == 1
854 && ModCtlv11.mod_requisites == 0
855 && ModCtlv11.mod_loadcnt == 1
856 /*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
857 && ModCtlv11.mod_text_size < SOL_UNIX_MAX_CODE_SEG_SIZE
858 && ModCtlv11.mod_text_size >= _128K)
859 {
860 char szUnix[5];
861 DBGFADDRESS NameAddr;
862 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv11.mod_modname);
863 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
864 if (RT_SUCCESS(rc))
865 {
866 if (!strcmp(szUnix, "unix"))
867 {
868 pThis->AddrUnixModCtl = ModCtlAddr;
869 pThis->iModCtlVer = 11;
870 cbModCtl = sizeof(ModCtlv11);
871 break;
872 }
873 Log(("sol64 mod_name=%.*s v11\n", sizeof(szUnix), szUnix));
874 }
875 }
876 }
877 }
878 else
879 {
880 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v11_modctl_t, mod_text));
881 SOL32v11_modctl_t ModCtlv11;
882 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv11, sizeof(ModCtlv11));
883 if (RT_SUCCESS(rc))
884 {
885 if ( SOL32_VALID_ADDRESS(ModCtlv11.mod_next)
886 && SOL32_VALID_ADDRESS(ModCtlv11.mod_prev)
887 && ModCtlv11.mod_id == 0
888 && SOL32_VALID_ADDRESS(ModCtlv11.mod_mp)
889 && SOL32_VALID_ADDRESS(ModCtlv11.mod_filename)
890 && SOL32_VALID_ADDRESS(ModCtlv11.mod_modname)
891 && ModCtlv11.mod_prim == 1
892 && ModCtlv11.mod_loaded == 1
893 && ModCtlv11.mod_installed == 1
894 && ModCtlv11.mod_requisites == 0
895 && ModCtlv11.mod_loadcnt == 1
896 /*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
897 && ModCtlv11.mod_text_size < SOL_UNIX_MAX_CODE_SEG_SIZE
898 && ModCtlv11.mod_text_size >= _128K)
899 {
900 char szUnix[5];
901 DBGFADDRESS NameAddr;
902 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv11.mod_modname);
903 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
904 if (RT_SUCCESS(rc))
905 {
906 if (!strcmp(szUnix, "unix"))
907 {
908 pThis->AddrUnixModCtl = ModCtlAddr;
909 pThis->iModCtlVer = 11;
910 cbModCtl = sizeof(ModCtlv11);
911 break;
912 }
913 Log(("sol32 mod_name=%.*s v11\n", sizeof(szUnix), szUnix));
914 }
915 }
916 }
917 }
918
919 /* v9 */
920 if (pThis->f64Bit)
921 {
922 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL64v9_modctl_t, mod_text));
923 SOL64v9_modctl_t ModCtlv9;
924 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv9, sizeof(ModCtlv9));
925 if (RT_SUCCESS(rc))
926 {
927 if ( SOL64_VALID_ADDRESS(ModCtlv9.mod_next)
928 && SOL64_VALID_ADDRESS(ModCtlv9.mod_prev)
929 && ModCtlv9.mod_id == 0
930 && SOL64_VALID_ADDRESS(ModCtlv9.mod_mp)
931 && SOL64_VALID_ADDRESS(ModCtlv9.mod_filename)
932 && SOL64_VALID_ADDRESS(ModCtlv9.mod_modname)
933 && (ModCtlv9.mod_loaded == 1 || ModCtlv9.mod_loaded == 0)
934 && (ModCtlv9.mod_installed == 1 || ModCtlv9.mod_installed == 0)
935 && ModCtlv9.mod_requisites == 0
936 && (ModCtlv9.mod_loadcnt == 1 || ModCtlv9.mod_loadcnt == 0)
937 /*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
938 && ModCtlv9.mod_text_size < SOL_UNIX_MAX_CODE_SEG_SIZE)
939 {
940 char szUnix[5];
941 DBGFADDRESS NameAddr;
942 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv9.mod_modname);
943 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
944 if (RT_SUCCESS(rc))
945 {
946 if (!strcmp(szUnix, "unix"))
947 {
948 pThis->AddrUnixModCtl = ModCtlAddr;
949 pThis->iModCtlVer = 9;
950 cbModCtl = sizeof(ModCtlv9);
951 break;
952 }
953 Log(("sol64 mod_name=%.*s v9\n", sizeof(szUnix), szUnix));
954 }
955 }
956 }
957 }
958 else
959 {
960 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v9_modctl_t, mod_text));
961 SOL32v9_modctl_t ModCtlv9;
962 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv9, sizeof(ModCtlv9));
963 if (RT_SUCCESS(rc))
964 {
965 if ( SOL32_VALID_ADDRESS(ModCtlv9.mod_next)
966 && SOL32_VALID_ADDRESS(ModCtlv9.mod_prev)
967 && ModCtlv9.mod_id == 0
968 && SOL32_VALID_ADDRESS(ModCtlv9.mod_mp)
969 && SOL32_VALID_ADDRESS(ModCtlv9.mod_filename)
970 && SOL32_VALID_ADDRESS(ModCtlv9.mod_modname)
971 && (ModCtlv9.mod_loaded == 1 || ModCtlv9.mod_loaded == 0)
972 && (ModCtlv9.mod_installed == 1 || ModCtlv9.mod_installed == 0)
973 && ModCtlv9.mod_requisites == 0
974 && (ModCtlv9.mod_loadcnt == 1 || ModCtlv9.mod_loadcnt == 0)
975 /*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
976 && ModCtlv9.mod_text_size < SOL_UNIX_MAX_CODE_SEG_SIZE )
977 {
978 char szUnix[5];
979 DBGFADDRESS NameAddr;
980 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv9.mod_modname);
981 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
982 if (RT_SUCCESS(rc))
983 {
984 if (!strcmp(szUnix, "unix"))
985 {
986 pThis->AddrUnixModCtl = ModCtlAddr;
987 pThis->iModCtlVer = 9;
988 cbModCtl = sizeof(ModCtlv9);
989 break;
990 }
991 Log(("sol32 mod_name=%.*s v9\n", sizeof(szUnix), szUnix));
992 }
993 }
994 }
995 }
996
997 /* next */
998 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &CurAddr, HitAddr.FlatPtr + cbExpr);
999 }
1000
1001 /*
1002 * Walk the module chain and add the modules and their symbols.
1003 */
1004 if (pThis->AddrUnixModCtl.FlatPtr)
1005 {
1006 int iMod = 0;
1007 CurAddr = pThis->AddrUnixModCtl;
1008 do
1009 {
1010 /* read it */
1011 SOL_modctl_t ModCtl;
1012 rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, &CurAddr, &ModCtl, cbModCtl);
1013 if (RT_FAILURE(rc))
1014 {
1015 LogRel(("sol: bad modctl_t chain for module %d: %RGv - %Rrc\n", iMod, CurAddr.FlatPtr, rc));
1016 break;
1017 }
1018
1019 /* process it. */
1020 if (pThis->f64Bit)
1021 dbgDiggerSolarisProcessModCtl64(pUVM, pVMM, pThis, &ModCtl);
1022 else
1023 dbgDiggerSolarisProcessModCtl32(pUVM, pVMM, pThis, &ModCtl);
1024
1025 /* next */
1026 if (pThis->f64Bit)
1027 {
1028 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_next, v9_64.mod_next);
1029 if (!SOL64_VALID_ADDRESS(ModCtl.v9_64.mod_next))
1030 {
1031 LogRel(("sol64: bad modctl_t chain for module %d at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_64.mod_next));
1032 break;
1033 }
1034 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &CurAddr, ModCtl.v9_64.mod_next);
1035 }
1036 else
1037 {
1038 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_next, v9_32.mod_next);
1039 if (!SOL32_VALID_ADDRESS(ModCtl.v9_32.mod_next))
1040 {
1041 LogRel(("sol32: bad modctl_t chain for module %d at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_32.mod_next));
1042 break;
1043 }
1044 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &CurAddr, ModCtl.v9_32.mod_next);
1045 }
1046 if (++iMod >= 1024)
1047 {
1048 LogRel(("sol32: too many modules (%d)\n", iMod));
1049 break;
1050 }
1051 } while (CurAddr.FlatPtr != pThis->AddrUnixModCtl.FlatPtr);
1052 }
1053
1054 pThis->fValid = true;
1055 return VINF_SUCCESS;
1056}
1057
1058
1059/**
1060 * @copydoc DBGFOSREG::pfnProbe
1061 */
1062static DECLCALLBACK(bool) dbgDiggerSolarisProbe(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
1063{
1064 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
1065
1066 /*
1067 * Look for "SunOS Release" in the text segment.
1068 */
1069 DBGFADDRESS Addr;
1070 bool f64Bit = false;
1071
1072 /* 32-bit search range. */
1073 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, 0xfe800000);
1074 RTGCUINTPTR cbRange = 0xfec00000 - 0xfe800000;
1075
1076 DBGFADDRESS HitAddr;
1077 static const uint8_t s_abSunRelease[] = "SunOS Release ";
1078 int rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
1079 if (RT_FAILURE(rc))
1080 {
1081 /* 64-bit.... */
1082 pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, UINT64_C(0xfffffffffb800000));
1083 cbRange = UINT64_C(0xfffffffffbd00000) - UINT64_C(0xfffffffffb800000);
1084 rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
1085 if (RT_FAILURE(rc))
1086 return false;
1087 f64Bit = true;
1088 }
1089
1090 /*
1091 * Look for the copyright string too, just to be sure.
1092 */
1093 static const uint8_t s_abSMI[] = "Sun Microsystems, Inc.";
1094 static const uint8_t s_abORCL[] = "Oracle and/or its affiliates.";
1095 rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abSMI, sizeof(s_abSMI) - 1, &HitAddr);
1096 if (RT_FAILURE(rc))
1097 {
1098 /* Try the alternate copyright string. */
1099 rc = pVMM->pfnDBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abORCL, sizeof(s_abORCL) - 1, &HitAddr);
1100 if (RT_FAILURE(rc))
1101 return false;
1102 }
1103
1104 /*
1105 * Remember the unix text and data addresses and bitness.
1106 */
1107 pThis->AddrUnixText = Addr;
1108 pVMM->pfnDBGFR3AddrAdd(&Addr, SOL_UNIX_MAX_CODE_SEG_SIZE);
1109 pThis->AddrUnixData = Addr;
1110 pThis->f64Bit = f64Bit;
1111
1112 return true;
1113}
1114
1115
1116/**
1117 * @copydoc DBGFOSREG::pfnDestruct
1118 */
1119static DECLCALLBACK(void) dbgDiggerSolarisDestruct(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
1120{
1121 RT_NOREF(pUVM, pVMM, pvData);
1122}
1123
1124
1125/**
1126 * @copydoc DBGFOSREG::pfnConstruct
1127 */
1128static DECLCALLBACK(int) dbgDiggerSolarisConstruct(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData)
1129{
1130 RT_NOREF(pUVM, pVMM, pvData);
1131 return VINF_SUCCESS;
1132}
1133
1134
1135const DBGFOSREG g_DBGDiggerSolaris =
1136{
1137 /* .u32Magic = */ DBGFOSREG_MAGIC,
1138 /* .fFlags = */ 0,
1139 /* .cbData = */ sizeof(DBGDIGGERSOLARIS),
1140 /* .szName = */ "Solaris",
1141 /* .pfnConstruct = */ dbgDiggerSolarisConstruct,
1142 /* .pfnDestruct = */ dbgDiggerSolarisDestruct,
1143 /* .pfnProbe = */ dbgDiggerSolarisProbe,
1144 /* .pfnInit = */ dbgDiggerSolarisInit,
1145 /* .pfnRefresh = */ dbgDiggerSolarisRefresh,
1146 /* .pfnTerm = */ dbgDiggerSolarisTerm,
1147 /* .pfnQueryVersion = */ dbgDiggerSolarisQueryVersion,
1148 /* .pfnQueryInterface = */ dbgDiggerSolarisQueryInterface,
1149 /* .pfnStackUnwindAssist = */ dbgDiggerSolarisStackUnwindAssist,
1150 /* .u32EndMagic = */ DBGFOSREG_MAGIC
1151};
1152
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use