3 * DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
7 * Copyright (C) 2008-2010 Oracle Corporation
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.
19 /*******************************************************************************
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>
28 #include <iprt/stream.h>
29 #include <iprt/string.h>
32 /*******************************************************************************
33 * Defined Constants And Macros *
34 *******************************************************************************/
35 /** Solaris on little endian ASCII systems. */
36 #define DIG_SOL_MOD_TAG UINT64_C(0x00736972616c6f53)
39 /*******************************************************************************
40 * Structures and Typedefs *
41 *******************************************************************************/
43 /** @name InternalSolaris structures
47 typedef struct SOL32v11_modctl
49 uint32_t mod_next
; /**< 0 */
50 uint32_t mod_prev
; /**< 4 */
51 int32_t mod_id
; /**< 8 */
52 uint32_t mod_mp
; /**< c Pointer to the kernel runtime loader bits. */
53 uint32_t mod_inprogress_thread
; /**< 10 */
54 uint32_t mod_modinfo
; /**< 14 */
55 uint32_t mod_linkage
; /**< 18 */
56 uint32_t mod_filename
; /**< 1c */
57 uint32_t mod_modname
; /**< 20 */
58 int8_t mod_busy
; /**< 24 */
59 int8_t mod_want
; /**< 25 */
60 int8_t mod_prim
; /**< 26 this is 1 for 'unix' and a few others. */
61 int8_t mod_unused_padding
; /**< 27 */
62 int32_t mod_ref
; /**< 28 */
63 int8_t mod_loaded
; /**< 2c */
64 int8_t mod_installed
; /**< 2d */
65 int8_t mod_loadflags
; /**< 2e */
66 int8_t mod_delay_unload
; /**< 2f */
67 uint32_t mod_requisites
; /**< 30 */
68 uint32_t mod___unused
; /**< 34 */
69 int32_t mod_loadcnt
; /**< 38 */
70 int32_t mod_nenabled
; /**< 3c */
71 uint32_t mod_text
; /**< 40 */
72 uint32_t mod_text_size
; /**< 44 */
73 int32_t mod_gencount
; /**< 48 */
74 uint32_t mod_requisite_loading
; /**< 4c */
76 AssertCompileSize(SOL32v11_modctl_t
, 0x50);
78 typedef struct SOL64v11_modctl
80 uint64_t mod_next
; /**< 0 */
81 uint64_t mod_prev
; /**< 8 */
82 int32_t mod_id
; /**< 10 */
84 uint64_t mod_mp
; /**< 18 Pointer to the kernel runtime loader bits. */
85 uint64_t mod_inprogress_thread
; /**< 20 */
86 uint64_t mod_modinfo
; /**< 28 */
87 uint64_t mod_linkage
; /**< 30 */
88 uint64_t mod_filename
; /**< 38 */
89 uint64_t mod_modname
; /**< 40 */
90 int8_t mod_busy
; /**< 48 */
91 int8_t mod_want
; /**< 49 */
92 int8_t mod_prim
; /**< 4a this is 1 for 'unix' and a few others. */
93 int8_t mod_unused_padding
; /**< 4b */
94 int32_t mod_ref
; /**< 4c */
95 int8_t mod_loaded
; /**< 50 */
96 int8_t mod_installed
; /**< 51 */
97 int8_t mod_loadflags
; /**< 52 */
98 int8_t mod_delay_unload
; /**< 53 */
100 uint64_t mod_requisites
; /**< 58 */
101 uint64_t mod___unused
; /**< 60 */
102 int32_t mod_loadcnt
; /**< 68 */
103 int32_t mod_nenabled
; /**< 6c */
104 uint64_t mod_text
; /**< 70 */
105 uint64_t mod_text_size
; /**< 78 */
106 int32_t mod_gencount
; /**< 80 */
107 int32_t mod_padding2
;
108 uint64_t mod_requisite_loading
; /**< 88 */
110 AssertCompileSize(SOL64v11_modctl_t
, 0x90);
112 typedef struct SOL32v9_modctl
114 uint32_t mod_next
; /**< 0 */
115 uint32_t mod_prev
; /**< 4 */
116 int32_t mod_id
; /**< 8 */
117 uint32_t mod_mp
; /**< c Pointer to the kernel runtime loader bits. */
118 uint32_t mod_inprogress_thread
; /**< 10 */
119 uint32_t mod_modinfo
; /**< 14 */
120 uint32_t mod_linkage
; /**< 18 */
121 uint32_t mod_filename
; /**< 1c */
122 uint32_t mod_modname
; /**< 20 */
123 int32_t mod_busy
; /**< 24 */
124 int32_t mod_stub
; /**< 28 DIFF 1 */
125 int8_t mod_loaded
; /**< 2c */
126 int8_t mod_installed
; /**< 2d */
127 int8_t mod_loadflags
; /**< 2e */
128 int8_t mod_want
; /**< 2f DIFF 2 */
129 uint32_t mod_requisites
; /**< 30 */
130 uint32_t mod_dependents
; /**< 34 DIFF 3 */
131 int32_t mod_loadcnt
; /**< 38 */
132 /* DIFF 4: 4 bytes added in v11 */
133 uint32_t mod_text
; /**< 3c */
134 uint32_t mod_text_size
; /**< 40 */
135 /* DIFF 5: 8 bytes added in v11 */
137 AssertCompileSize(SOL32v9_modctl_t
, 0x44);
139 typedef struct SOL64v9_modctl
141 uint64_t mod_next
; /**< 0 */
142 uint64_t mod_prev
; /**< 8 */
143 int32_t mod_id
; /**< 10 */
144 int32_t mod_padding0
;
145 uint64_t mod_mp
; /**< 18 Pointer to the kernel runtime loader bits. */
146 uint64_t mod_inprogress_thread
; /**< 20 */
147 uint64_t mod_modinfo
; /**< 28 */
148 uint64_t mod_linkage
; /**< 30 */
149 uint64_t mod_filename
; /**< 38 */
150 uint64_t mod_modname
; /**< 40 */
151 int32_t mod_busy
; /**< 48 */
152 int32_t mod_stub
; /**< 4c DIFF 1 - is this a pointer? */
153 int8_t mod_loaded
; /**< 50 */
154 int8_t mod_installed
; /**< 51 */
155 int8_t mod_loadflags
; /**< 52 */
156 int8_t mod_want
; /**< 53 DIFF 2 */
157 int32_t mod_padding1
;
158 uint64_t mod_requisites
; /**< 58 */
159 uint64_t mod_dependencies
; /**< 60 DIFF 3 */
160 int32_t mod_loadcnt
; /**< 68 */
161 int32_t mod_padding3
; /**< 6c DIFF 4 */
162 uint64_t mod_text
; /**< 70 */
163 uint64_t mod_text_size
; /**< 78 */
164 /* DIFF 5: 8 bytes added in v11 */
166 AssertCompileSize(SOL64v9_modctl_t
, 0x80);
168 typedef union SOL_modctl
170 SOL32v9_modctl_t v9_32
;
171 SOL32v11_modctl_t v11_32
;
172 SOL64v9_modctl_t v9_64
;
173 SOL64v11_modctl_t v11_64
;
177 typedef struct SOL32_module
179 int32_t total_allocated
; /**< 0 */
180 Elf32_Ehdr hdr
; /**< 4 Easy to validate */
181 uint32_t shdrs
; /**< 38 */
182 uint32_t symhdr
; /**< 3c */
183 uint32_t strhdr
; /**< 40 */
184 uint32_t depends_on
; /**< 44 */
185 uint32_t symsize
; /**< 48 */
186 uint32_t symspace
; /**< 4c */
187 int32_t flags
; /**< 50 */
188 uint32_t text_size
; /**< 54 */
189 uint32_t data_size
; /**< 58 */
190 uint32_t text
; /**< 5c */
191 uint32_t data
; /**< 60 */
192 uint32_t symtbl_section
; /**< 64 */
193 uint32_t symtbl
; /**< 68 */
194 uint32_t strings
; /**< 6c */
195 uint32_t hashsize
; /**< 70 */
196 uint32_t buckets
; /**< 74 */
197 uint32_t chains
; /**< 78 */
198 uint32_t nsyms
; /**< 7c */
199 uint32_t bss_align
; /**< 80 */
200 uint32_t bss_size
; /**< 84 */
201 uint32_t bss
; /**< 88 */
202 uint32_t filename
; /**< 8c */
203 uint32_t head
; /**< 90 */
204 uint32_t tail
; /**< 94 */
205 uint32_t destination
; /**< 98 */
206 uint32_t machdata
; /**< 9c */
207 uint32_t ctfdata
; /**< a0 */
208 uint32_t ctfsize
; /**< a4 */
209 uint32_t fbt_tab
; /**< a8 */
210 uint32_t fbt_size
; /**< ac */
211 uint32_t fbt_nentries
; /**< b0 */
212 uint32_t textwin
; /**< b4 */
213 uint32_t textwin_base
; /**< b8 */
214 uint32_t sdt_probes
; /**< bc */
215 uint32_t sdt_nprobes
; /**< c0 */
216 uint32_t sdt_tab
; /**< c4 */
217 uint32_t sdt_size
; /**< c8 */
218 uint32_t sigdata
; /**< cc */
219 uint32_t sigsize
; /**< d0 */
221 AssertCompileSize(Elf32_Ehdr
, 0x34);
222 AssertCompileSize(SOL32_module_t
, 0xd4);
224 typedef struct SOL64_module
226 int32_t total_allocated
; /**< 0 */
228 Elf64_Ehdr hdr
; /**< 8 Easy to validate */
229 uint64_t shdrs
; /**< 48 */
230 uint64_t symhdr
; /**< 50 */
231 uint64_t strhdr
; /**< 58 */
232 uint64_t depends_on
; /**< 60 */
233 uint64_t symsize
; /**< 68 */
234 uint64_t symspace
; /**< 70 */
235 int32_t flags
; /**< 78 */
237 uint64_t text_size
; /**< 80 */
238 uint64_t data_size
; /**< 88 */
239 uint64_t text
; /**< 90 */
240 uint64_t data
; /**< 98 */
241 uint32_t symtbl_section
; /**< a0 */
243 uint64_t symtbl
; /**< a8 */
244 uint64_t strings
; /**< b0 */
245 uint32_t hashsize
; /**< b8 */
247 uint64_t buckets
; /**< c0 */
248 uint64_t chains
; /**< c8 */
249 uint32_t nsyms
; /**< d0 */
250 uint32_t bss_align
; /**< d4 */
251 uint64_t bss_size
; /**< d8 */
252 uint64_t bss
; /**< e0 */
253 uint64_t filename
; /**< e8 */
254 uint64_t head
; /**< f0 */
255 uint64_t tail
; /**< f8 */
256 uint64_t destination
; /**< 100 */
257 uint64_t machdata
; /**< 108 */
258 uint64_t ctfdata
; /**< 110 */
259 uint64_t ctfsize
; /**< 118 */
260 uint64_t fbt_tab
; /**< 120 */
261 uint64_t fbt_size
; /**< 128 */
262 uint64_t fbt_nentries
; /**< 130 */
263 uint64_t textwin
; /**< 138 */
264 uint64_t textwin_base
; /**< 140 */
265 uint64_t sdt_probes
; /**< 148 */
266 uint64_t sdt_nprobes
; /**< 150 */
267 uint64_t sdt_tab
; /**< 158 */
268 uint64_t sdt_size
; /**< 160 */
269 uint64_t sigdata
; /**< 168 */
270 uint64_t sigsize
; /**< 170 */
272 AssertCompileSize(Elf64_Ehdr
, 0x40);
273 AssertCompileSize(SOL64_module_t
, 0x178);
275 typedef struct SOL_utsname
283 AssertCompileSize(SOL_utsname_t
, 5 * 257);
289 * Solaris guest OS digger instance data.
291 typedef struct DBGDIGGERSOLARIS
293 /** Whether the information is valid or not.
294 * (For fending off illegal interface method calls.) */
297 /** Address of the 'unix' text segment.
298 * This is set during probing. */
299 DBGFADDRESS AddrUnixText
;
300 /** Address of the 'unix' text segment.
301 * This is set during probing. */
302 DBGFADDRESS AddrUnixData
;
303 /** Address of the 'unix' modctl_t (aka modules). */
304 DBGFADDRESS AddrUnixModCtl
;
305 /** modctl_t version number. */
307 /** 64-bit/32-bit indicator. */
311 /** Pointer to the solaris guest OS digger instance data. */
312 typedef DBGDIGGERSOLARIS
*PDBGDIGGERSOLARIS
;
315 /*******************************************************************************
316 * Defined Constants And Macros *
317 *******************************************************************************/
318 /** Min kernel address. */
319 #define SOL32_MIN_KRNL_ADDR UINT32_C(0x80000000)
320 /** Max kernel address. */
321 #define SOL32_MAX_KRNL_ADDR UINT32_C(0xfffff000)
323 /** Min kernel address. */
324 #define SOL64_MIN_KRNL_ADDR UINT64_C(0xFFFFFD8000000000)
325 /** Max kernel address. */
326 #define SOL64_MAX_KRNL_ADDR UINT64_C(0xFFFFFFFFFFF00000)
329 /** Validates a 32-bit solaris kernel address */
330 #if 0 /* OpenSolaris, early boot have symspace at 0x27a2000 */
331 # define SOL32_VALID_ADDRESS(Addr) ((Addr) > SOL32_MIN_KRNL_ADDR && (Addr) < SOL32_MAX_KRNL_ADDR)
333 # define SOL32_VALID_ADDRESS(Addr) ( ((Addr) > SOL32_MIN_KRNL_ADDR && (Addr) < SOL32_MAX_KRNL_ADDR) \
334 || ((Addr) > UINT32_C(0x02000000) && (Addr) < UINT32_C(0x04000000)) /* boot */ )
337 /** Validates a 64-bit solaris kernel address */
338 #define SOL64_VALID_ADDRESS(Addr) ( (Addr) > SOL64_MIN_KRNL_ADDR \
339 && (Addr) < SOL64_MAX_KRNL_ADDR)
341 /** The max data segment size of the 'unix' module. */
342 #define SOL_UNIX_MAX_DATA_SEG_SIZE 0x01000000
344 /** The max code segment size of the 'unix' module.
345 * This is the same for both 64-bit and 32-bit. */
346 #define SOL_UNIX_MAX_CODE_SEG_SIZE 0x00400000
349 /*******************************************************************************
350 * Internal Functions *
351 *******************************************************************************/
352 static DECLCALLBACK(int) dbgDiggerSolarisInit(PVM pVM
, void *pvData
);
357 * @copydoc DBGFOSREG::pfnQueryInterface
359 static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PVM pVM
, void *pvData
, DBGFOSINTERFACE enmIf
)
366 * @copydoc DBGFOSREG::pfnQueryVersion
368 static DECLCALLBACK(int) dbgDiggerSolarisQueryVersion(PVM pVM
, void *pvData
, char *pszVersion
, size_t cchVersion
)
370 PDBGDIGGERSOLARIS pThis
= (PDBGDIGGERSOLARIS
)pvData
;
371 Assert(pThis
->fValid
);
374 * It's all in the utsname symbol...
377 SOL_utsname_t UtsName
;
378 RTDBGSYMBOL SymUtsName
;
379 int rc
= DBGFR3AsSymbolByName(pVM
, DBGF_AS_KERNEL
, "utsname", &SymUtsName
, NULL
);
381 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, SymUtsName
.Value
), &UtsName
, sizeof(UtsName
));
385 * Try searching by the name...
387 memset(&UtsName
, '\0', sizeof(UtsName
));
388 strcpy(&UtsName
.sysname
[0], "SunOS");
389 rc
= DBGFR3MemScan(pVM
, 0, &pThis
->AddrUnixData
, SOL_UNIX_MAX_DATA_SEG_SIZE
, 1,
390 &UtsName
.sysname
[0], sizeof(UtsName
.sysname
), &Addr
);
392 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, Addr
.FlatPtr
- RT_OFFSETOF(SOL_utsname_t
, sysname
)),
393 &UtsName
, sizeof(UtsName
));
397 * Copy out the result (if any).
401 if ( UtsName
.sysname
[sizeof(UtsName
.sysname
) - 1] != '\0'
402 || UtsName
.nodename
[sizeof(UtsName
.nodename
) - 1] != '\0'
403 || UtsName
.release
[sizeof(UtsName
.release
) - 1] != '\0'
404 || UtsName
.version
[sizeof(UtsName
.version
) - 1] != '\0'
405 || UtsName
.machine
[sizeof(UtsName
.machine
) - 1] != '\0')
407 //rc = VERR_DBGF_UNEXPECTED_OS_DATA;
408 rc
= VERR_GENERAL_FAILURE
;
409 RTStrPrintf(pszVersion
, cchVersion
, "failed - bogus utsname");
412 RTStrPrintf(pszVersion
, cchVersion
, "%s %s", UtsName
.version
, UtsName
.release
);
415 RTStrPrintf(pszVersion
, cchVersion
, "failed - %Rrc", rc
);
423 * Processes a modctl_t.
425 * @param pVM The VM handle.
426 * @param pThis Our instance data.
427 * @param pModCtl Pointer to the modctl structure.
429 static void dbgDiggerSolarisProcessModCtl32(PVM pVM
, PDBGDIGGERSOLARIS pThis
, SOL_modctl_t
const *pModCtl
)
431 /* skip it if it's not loaded and installed */
432 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_loaded
, v9_32
.mod_loaded
);
433 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_installed
, v9_32
.mod_installed
);
434 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_id
, v9_32
.mod_id
);
435 if ( ( !pModCtl
->v9_32
.mod_loaded
436 || !pModCtl
->v9_32
.mod_installed
)
437 && pModCtl
->v9_32
.mod_id
> 3)
441 * Read the module and file names first
443 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_modname
, v9_32
.mod_modname
);
446 int rc
= DBGFR3MemReadString(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_32
.mod_modname
), szModName
, sizeof(szModName
));
449 if (!RTStrEnd(szModName
, sizeof(szModName
)))
450 szModName
[sizeof(szModName
) - 1] = '\0';
452 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_filename
, v9_32
.mod_filename
);
453 char szFilename
[256];
454 rc
= DBGFR3MemReadString(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_32
.mod_filename
), szFilename
, sizeof(szFilename
));
456 strcpy(szFilename
, szModName
);
457 else if (!RTStrEnd(szFilename
, sizeof(szFilename
)))
458 szFilename
[sizeof(szFilename
) - 1] = '\0';
461 * Then read the module struct and validate it.
463 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_mp
, v9_32
.mod_mp
);
464 struct SOL32_module Module
;
465 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_32
.mod_mp
), &Module
, sizeof(Module
));
469 /* Basic validations of the elf header. */
470 if ( Module
.hdr
.e_ident
[EI_MAG0
] != ELFMAG0
471 || Module
.hdr
.e_ident
[EI_MAG1
] != ELFMAG1
472 || Module
.hdr
.e_ident
[EI_MAG2
] != ELFMAG2
473 || Module
.hdr
.e_ident
[EI_MAG3
] != ELFMAG3
474 || Module
.hdr
.e_ident
[EI_CLASS
] != ELFCLASS32
475 || Module
.hdr
.e_ident
[EI_DATA
] != ELFDATA2LSB
476 || Module
.hdr
.e_ident
[EI_VERSION
] != EV_CURRENT
477 || ASMMemIsAll8(&Module
.hdr
.e_ident
[EI_PAD
], EI_NIDENT
- EI_PAD
, 0) != NULL
480 if (Module
.hdr
.e_version
!= EV_CURRENT
)
482 if (Module
.hdr
.e_ehsize
!= sizeof(Module
.hdr
))
484 if ( Module
.hdr
.e_type
!= ET_DYN
485 && Module
.hdr
.e_type
!= ET_REL
486 && Module
.hdr
.e_type
!= ET_EXEC
) //??
488 if ( Module
.hdr
.e_machine
!= EM_386
489 && Module
.hdr
.e_machine
!= EM_486
)
491 if ( Module
.hdr
.e_phentsize
!= sizeof(Elf32_Phdr
)
492 && Module
.hdr
.e_phentsize
) //??
494 if (Module
.hdr
.e_shentsize
!= sizeof(Elf32_Shdr
))
497 if (Module
.hdr
.e_shentsize
!= sizeof(Elf32_Shdr
))
500 /* Basic validations of the rest of the stuff. */
501 if ( !SOL32_VALID_ADDRESS(Module
.shdrs
)
502 || !SOL32_VALID_ADDRESS(Module
.symhdr
)
503 || !SOL32_VALID_ADDRESS(Module
.strhdr
)
504 || (!SOL32_VALID_ADDRESS(Module
.symspace
) && Module
.symspace
)
505 || !SOL32_VALID_ADDRESS(Module
.text
)
506 || !SOL32_VALID_ADDRESS(Module
.data
)
507 || (!SOL32_VALID_ADDRESS(Module
.symtbl
) && Module
.symtbl
)
508 || (!SOL32_VALID_ADDRESS(Module
.strings
) && Module
.strings
)
509 || (!SOL32_VALID_ADDRESS(Module
.head
) && Module
.head
)
510 || (!SOL32_VALID_ADDRESS(Module
.tail
) && Module
.tail
)
511 || !SOL32_VALID_ADDRESS(Module
.filename
))
513 if ( Module
.symsize
> _4M
514 || Module
.hdr
.e_shnum
> 4096
515 || Module
.nsyms
> _256K
)
518 /* Ignore modules without symbols. */
519 if (!Module
.symtbl
|| !Module
.strings
|| !Module
.symspace
|| !Module
.symspace
)
522 /* Check that the symtbl and strings points inside the symspace. */
523 if (Module
.strings
- Module
.symspace
>= Module
.symsize
)
525 if (Module
.symtbl
- Module
.symspace
>= Module
.symsize
)
529 * Read the section headers, symbol table and string tables.
531 size_t cb
= Module
.hdr
.e_shnum
* sizeof(Elf32_Shdr
);
532 Elf32_Shdr
*paShdrs
= (Elf32_Shdr
*)RTMemTmpAlloc(cb
);
535 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, Module
.shdrs
), paShdrs
, cb
);
538 void *pvSymSpace
= RTMemTmpAlloc(Module
.symsize
+ 1);
541 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, Module
.symspace
), pvSymSpace
, Module
.symsize
);
544 ((uint8_t *)pvSymSpace
)[Module
.symsize
] = 0;
547 * Hand it over to the common ELF32 module parser.
549 char const *pbStrings
= (char const *)pvSymSpace
+ (Module
.strings
- Module
.symspace
);
550 size_t cbMaxStrings
= Module
.symsize
- (Module
.strings
- Module
.symspace
);
552 Elf32_Sym
const *paSyms
= (Elf32_Sym
const *)((uintptr_t)pvSymSpace
+ (Module
.symtbl
- Module
.symspace
));
553 size_t cMaxSyms
= (Module
.symsize
- (Module
.symtbl
- Module
.symspace
)) / sizeof(Elf32_Sym
);
554 cMaxSyms
= RT_MIN(cMaxSyms
, Module
.nsyms
);
556 DBGDiggerCommonParseElf32Mod(pVM
, szModName
, szFilename
, DBG_DIGGER_ELF_FUNNY_SHDRS
,
557 &Module
.hdr
, paShdrs
, paSyms
, cMaxSyms
, pbStrings
, cbMaxStrings
,
558 SOL32_MIN_KRNL_ADDR
, SOL32_MAX_KRNL_ADDR
- 1, DIG_SOL_MOD_TAG
);
560 RTMemTmpFree(pvSymSpace
);
564 RTMemTmpFree(paShdrs
);
570 * Processes a modctl_t.
572 * @param pVM The VM handle.
573 * @param pThis Our instance data.
574 * @param pModCtl Pointer to the modctl structure.
576 static void dbgDiggerSolarisProcessModCtl64(PVM pVM
, PDBGDIGGERSOLARIS pThis
, SOL_modctl_t
const *pModCtl
)
578 /* skip it if it's not loaded and installed */
579 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_loaded
, v9_64
.mod_loaded
);
580 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_installed
, v9_64
.mod_installed
);
581 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_id
, v9_64
.mod_id
);
582 if ( ( !pModCtl
->v9_64
.mod_loaded
583 || !pModCtl
->v9_64
.mod_installed
)
584 && pModCtl
->v9_64
.mod_id
> 3)
588 * Read the module and file names first
590 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_modname
, v9_64
.mod_modname
);
593 int rc
= DBGFR3MemReadString(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_64
.mod_modname
), szModName
, sizeof(szModName
));
596 if (!RTStrEnd(szModName
, sizeof(szModName
)))
597 szModName
[sizeof(szModName
) - 1] = '\0';
599 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_filename
, v9_64
.mod_filename
);
600 char szFilename
[256];
601 rc
= DBGFR3MemReadString(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_64
.mod_filename
), szFilename
, sizeof(szFilename
));
603 strcpy(szFilename
, szModName
);
604 else if (!RTStrEnd(szFilename
, sizeof(szFilename
)))
605 szFilename
[sizeof(szFilename
) - 1] = '\0';
608 * Then read the module struct and validate it.
610 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_mp
, v9_64
.mod_mp
);
611 struct SOL64_module Module
;
612 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, pModCtl
->v9_64
.mod_mp
), &Module
, sizeof(Module
));
616 /* Basic validations of the elf header. */
617 if ( Module
.hdr
.e_ident
[EI_MAG0
] != ELFMAG0
618 || Module
.hdr
.e_ident
[EI_MAG1
] != ELFMAG1
619 || Module
.hdr
.e_ident
[EI_MAG2
] != ELFMAG2
620 || Module
.hdr
.e_ident
[EI_MAG3
] != ELFMAG3
621 || Module
.hdr
.e_ident
[EI_CLASS
] != ELFCLASS64
622 || Module
.hdr
.e_ident
[EI_DATA
] != ELFDATA2LSB
623 || Module
.hdr
.e_ident
[EI_VERSION
] != EV_CURRENT
624 || ASMMemIsAll8(&Module
.hdr
.e_ident
[EI_PAD
], EI_NIDENT
- EI_PAD
, 0) != NULL
627 if (Module
.hdr
.e_version
!= EV_CURRENT
)
629 if (Module
.hdr
.e_ehsize
!= sizeof(Module
.hdr
))
631 if ( Module
.hdr
.e_type
!= ET_DYN
632 && Module
.hdr
.e_type
!= ET_REL
633 && Module
.hdr
.e_type
!= ET_EXEC
) //??
635 if (Module
.hdr
.e_machine
!= EM_X86_64
)
637 if ( Module
.hdr
.e_phentsize
!= sizeof(Elf64_Phdr
)
638 && Module
.hdr
.e_phentsize
) //??
640 if (Module
.hdr
.e_shentsize
!= sizeof(Elf64_Shdr
))
643 if (Module
.hdr
.e_shentsize
!= sizeof(Elf64_Shdr
))
646 /* Basic validations of the rest of the stuff. */
647 if ( !SOL64_VALID_ADDRESS(Module
.shdrs
)
648 || !SOL64_VALID_ADDRESS(Module
.symhdr
)
649 || !SOL64_VALID_ADDRESS(Module
.strhdr
)
650 || (!SOL64_VALID_ADDRESS(Module
.symspace
) && Module
.symspace
)
651 || !SOL64_VALID_ADDRESS(Module
.text
)
652 || !SOL64_VALID_ADDRESS(Module
.data
)
653 || (!SOL64_VALID_ADDRESS(Module
.symtbl
) && Module
.symtbl
)
654 || (!SOL64_VALID_ADDRESS(Module
.strings
) && Module
.strings
)
655 || (!SOL64_VALID_ADDRESS(Module
.head
) && Module
.head
)
656 || (!SOL64_VALID_ADDRESS(Module
.tail
) && Module
.tail
)
657 || !SOL64_VALID_ADDRESS(Module
.filename
))
659 if ( Module
.symsize
> _4M
660 || Module
.hdr
.e_shnum
> 4096
661 || Module
.nsyms
> _256K
)
664 /* Ignore modules without symbols. */
665 if (!Module
.symtbl
|| !Module
.strings
|| !Module
.symspace
|| !Module
.symspace
)
668 /* Check that the symtbl and strings points inside the symspace. */
669 if (Module
.strings
- Module
.symspace
>= Module
.symsize
)
671 if (Module
.symtbl
- Module
.symspace
>= Module
.symsize
)
675 * Read the section headers, symbol table and string tables.
677 size_t cb
= Module
.hdr
.e_shnum
* sizeof(Elf64_Shdr
);
678 Elf64_Shdr
*paShdrs
= (Elf64_Shdr
*)RTMemTmpAlloc(cb
);
681 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, Module
.shdrs
), paShdrs
, cb
);
684 void *pvSymSpace
= RTMemTmpAlloc(Module
.symsize
+ 1);
687 rc
= DBGFR3MemRead(pVM
, 0, DBGFR3AddrFromFlat(pVM
, &Addr
, Module
.symspace
), pvSymSpace
, Module
.symsize
);
690 ((uint8_t *)pvSymSpace
)[Module
.symsize
] = 0;
693 * Hand it over to the common ELF64 module parser.
695 char const *pbStrings
= (char const *)pvSymSpace
+ (Module
.strings
- Module
.symspace
);
696 size_t cbMaxStrings
= Module
.symsize
- (Module
.strings
- Module
.symspace
);
698 Elf64_Sym
const *paSyms
= (Elf64_Sym
const *)((uintptr_t)pvSymSpace
+ (uintptr_t)(Module
.symtbl
- Module
.symspace
));
699 size_t cMaxSyms
= (Module
.symsize
- (Module
.symtbl
- Module
.symspace
)) / sizeof(Elf32_Sym
);
700 cMaxSyms
= RT_MIN(cMaxSyms
, Module
.nsyms
);
702 DBGDiggerCommonParseElf64Mod(pVM
, szModName
, szFilename
, DBG_DIGGER_ELF_FUNNY_SHDRS
,
703 &Module
.hdr
, paShdrs
, paSyms
, cMaxSyms
, pbStrings
, cbMaxStrings
,
704 SOL64_MIN_KRNL_ADDR
, SOL64_MAX_KRNL_ADDR
- 1, DIG_SOL_MOD_TAG
);
706 RTMemTmpFree(pvSymSpace
);
710 RTMemTmpFree(paShdrs
);
716 * @copydoc DBGFOSREG::pfnTerm
718 static DECLCALLBACK(void) dbgDiggerSolarisTerm(PVM pVM
, void *pvData
)
720 PDBGDIGGERSOLARIS pThis
= (PDBGDIGGERSOLARIS
)pvData
;
721 Assert(pThis
->fValid
);
723 pThis
->fValid
= false;
728 * @copydoc DBGFOSREG::pfnRefresh
730 static DECLCALLBACK(int) dbgDiggerSolarisRefresh(PVM pVM
, void *pvData
)
732 PDBGDIGGERSOLARIS pThis
= (PDBGDIGGERSOLARIS
)pvData
;
734 Assert(pThis
->fValid
);
737 * For now we'll flush and reload everything.
739 RTDBGAS hDbgAs
= DBGFR3AsResolveAndRetain(pVM
, DBGF_AS_KERNEL
);
740 if (hDbgAs
!= NIL_RTDBGAS
)
742 uint32_t iMod
= RTDbgAsModuleCount(hDbgAs
);
745 RTDBGMOD hMod
= RTDbgAsModuleByIndex(hDbgAs
, iMod
);
746 if (hMod
!= NIL_RTDBGMOD
)
748 if (RTDbgModGetTag(hMod
) == DIG_SOL_MOD_TAG
)
750 int rc
= RTDbgAsModuleUnlink(hDbgAs
, hMod
);
753 RTDbgModRelease(hMod
);
756 RTDbgAsRelease(hDbgAs
);
759 dbgDiggerSolarisTerm(pVM
, pvData
);
760 return dbgDiggerSolarisInit(pVM
, pvData
);
765 * @copydoc DBGFOSREG::pfnInit
767 static DECLCALLBACK(int) dbgDiggerSolarisInit(PVM pVM
, void *pvData
)
769 PDBGDIGGERSOLARIS pThis
= (PDBGDIGGERSOLARIS
)pvData
;
770 Assert(!pThis
->fValid
);
775 * On Solaris the kernel and is the global address space.
777 DBGFR3AsSetAlias(pVM
, DBGF_AS_KERNEL
, DBGF_AS_GLOBAL
);
779 /** @todo Use debug_info, build 7x / S10U6. */
782 * Find the 'unix' modctl_t structure (aka modules).
783 * We know it resides in the unix data segment.
785 DBGFR3AddrFromFlat(pVM
, &pThis
->AddrUnixModCtl
, 0);
787 DBGFADDRESS CurAddr
= pThis
->AddrUnixData
;
789 DBGFR3AddrFromFlat(pVM
, &MaxAddr
, CurAddr
.FlatPtr
+ SOL_UNIX_MAX_DATA_SEG_SIZE
);
790 const uint8_t *pbExpr
= (const uint8_t *)&pThis
->AddrUnixText
.FlatPtr
;
791 const uint32_t cbExpr
= pThis
->f64Bit
? sizeof(uint64_t) : sizeof(uint32_t);
792 while ( CurAddr
.FlatPtr
< MaxAddr
.FlatPtr
793 && CurAddr
.FlatPtr
>= pThis
->AddrUnixData
.FlatPtr
)
796 rc
= DBGFR3MemScan(pVM
, 0, &CurAddr
, MaxAddr
.FlatPtr
- CurAddr
.FlatPtr
, 1, pbExpr
, cbExpr
, &HitAddr
);
801 * Read out the modctl_t structure.
803 DBGFADDRESS ModCtlAddr
;
808 DBGFR3AddrFromFlat(pVM
, &ModCtlAddr
, HitAddr
.FlatPtr
- RT_OFFSETOF(SOL32v11_modctl_t
, mod_text
));
809 SOL64v11_modctl_t ModCtlv11
;
810 rc
= DBGFR3MemRead(pVM
, 0, &ModCtlAddr
, &ModCtlv11
, sizeof(ModCtlv11
));
813 if ( SOL64_VALID_ADDRESS(ModCtlv11
.mod_next
)
814 && SOL64_VALID_ADDRESS(ModCtlv11
.mod_prev
)
815 && ModCtlv11
.mod_id
== 0
816 && SOL64_VALID_ADDRESS(ModCtlv11
.mod_mp
)
817 && SOL64_VALID_ADDRESS(ModCtlv11
.mod_filename
)
818 && SOL64_VALID_ADDRESS(ModCtlv11
.mod_modname
)
819 && ModCtlv11
.mod_prim
== 1
820 && ModCtlv11
.mod_loaded
== 1
821 && ModCtlv11
.mod_installed
== 1
822 && ModCtlv11
.mod_requisites
== 0
823 && ModCtlv11
.mod_loadcnt
== 1
824 /*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
825 && ModCtlv11
.mod_text_size
< SOL_UNIX_MAX_CODE_SEG_SIZE
826 && ModCtlv11
.mod_text_size
>= _128K
)
829 DBGFADDRESS NameAddr
;
830 DBGFR3AddrFromFlat(pVM
, &NameAddr
, ModCtlv11
.mod_modname
);
831 rc
= DBGFR3MemRead(pVM
, 0, &NameAddr
, &szUnix
, sizeof(szUnix
));
834 if (!strcmp(szUnix
, "unix"))
836 pThis
->AddrUnixModCtl
= ModCtlAddr
;
837 pThis
->iModCtlVer
= 11;
838 cbModCtl
= sizeof(ModCtlv11
);
841 Log(("sol64 mod_name=%.*s v11\n", sizeof(szUnix
), szUnix
));
848 DBGFR3AddrFromFlat(pVM
, &ModCtlAddr
, HitAddr
.FlatPtr
- RT_OFFSETOF(SOL32v11_modctl_t
, mod_text
));
849 SOL32v11_modctl_t ModCtlv11
;
850 rc
= DBGFR3MemRead(pVM
, 0, &ModCtlAddr
, &ModCtlv11
, sizeof(ModCtlv11
));
853 if ( SOL32_VALID_ADDRESS(ModCtlv11
.mod_next
)
854 && SOL32_VALID_ADDRESS(ModCtlv11
.mod_prev
)
855 && ModCtlv11
.mod_id
== 0
856 && SOL32_VALID_ADDRESS(ModCtlv11
.mod_mp
)
857 && SOL32_VALID_ADDRESS(ModCtlv11
.mod_filename
)
858 && SOL32_VALID_ADDRESS(ModCtlv11
.mod_modname
)
859 && ModCtlv11
.mod_prim
== 1
860 && ModCtlv11
.mod_loaded
== 1
861 && ModCtlv11
.mod_installed
== 1
862 && ModCtlv11
.mod_requisites
== 0
863 && ModCtlv11
.mod_loadcnt
== 1
864 /*&& ModCtlv11.mod_text == pThis->AddrUnixText.FlatPtr*/
865 && ModCtlv11
.mod_text_size
< SOL_UNIX_MAX_CODE_SEG_SIZE
866 && ModCtlv11
.mod_text_size
>= _128K
)
869 DBGFADDRESS NameAddr
;
870 DBGFR3AddrFromFlat(pVM
, &NameAddr
, ModCtlv11
.mod_modname
);
871 rc
= DBGFR3MemRead(pVM
, 0, &NameAddr
, &szUnix
, sizeof(szUnix
));
874 if (!strcmp(szUnix
, "unix"))
876 pThis
->AddrUnixModCtl
= ModCtlAddr
;
877 pThis
->iModCtlVer
= 11;
878 cbModCtl
= sizeof(ModCtlv11
);
881 Log(("sol32 mod_name=%.*s v11\n", sizeof(szUnix
), szUnix
));
890 DBGFR3AddrFromFlat(pVM
, &ModCtlAddr
, HitAddr
.FlatPtr
- RT_OFFSETOF(SOL64v9_modctl_t
, mod_text
));
891 SOL64v9_modctl_t ModCtlv9
;
892 rc
= DBGFR3MemRead(pVM
, 0, &ModCtlAddr
, &ModCtlv9
, sizeof(ModCtlv9
));
895 if ( SOL64_VALID_ADDRESS(ModCtlv9
.mod_next
)
896 && SOL64_VALID_ADDRESS(ModCtlv9
.mod_prev
)
897 && ModCtlv9
.mod_id
== 0
898 && SOL64_VALID_ADDRESS(ModCtlv9
.mod_mp
)
899 && SOL64_VALID_ADDRESS(ModCtlv9
.mod_filename
)
900 && SOL64_VALID_ADDRESS(ModCtlv9
.mod_modname
)
901 && (ModCtlv9
.mod_loaded
== 1 || ModCtlv9
.mod_loaded
== 0)
902 && (ModCtlv9
.mod_installed
== 1 || ModCtlv9
.mod_installed
== 0)
903 && ModCtlv9
.mod_requisites
== 0
904 && (ModCtlv9
.mod_loadcnt
== 1 || ModCtlv9
.mod_loadcnt
== 0)
905 /*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
906 && ModCtlv9
.mod_text_size
< SOL_UNIX_MAX_CODE_SEG_SIZE
)
909 DBGFADDRESS NameAddr
;
910 DBGFR3AddrFromFlat(pVM
, &NameAddr
, ModCtlv9
.mod_modname
);
911 rc
= DBGFR3MemRead(pVM
, 0, &NameAddr
, &szUnix
, sizeof(szUnix
));
914 if (!strcmp(szUnix
, "unix"))
916 pThis
->AddrUnixModCtl
= ModCtlAddr
;
917 pThis
->iModCtlVer
= 9;
918 cbModCtl
= sizeof(ModCtlv9
);
921 Log(("sol64 mod_name=%.*s v9\n", sizeof(szUnix
), szUnix
));
928 DBGFR3AddrFromFlat(pVM
, &ModCtlAddr
, HitAddr
.FlatPtr
- RT_OFFSETOF(SOL32v9_modctl_t
, mod_text
));
929 SOL32v9_modctl_t ModCtlv9
;
930 rc
= DBGFR3MemRead(pVM
, 0, &ModCtlAddr
, &ModCtlv9
, sizeof(ModCtlv9
));
933 if ( SOL32_VALID_ADDRESS(ModCtlv9
.mod_next
)
934 && SOL32_VALID_ADDRESS(ModCtlv9
.mod_prev
)
935 && ModCtlv9
.mod_id
== 0
936 && SOL32_VALID_ADDRESS(ModCtlv9
.mod_mp
)
937 && SOL32_VALID_ADDRESS(ModCtlv9
.mod_filename
)
938 && SOL32_VALID_ADDRESS(ModCtlv9
.mod_modname
)
939 && (ModCtlv9
.mod_loaded
== 1 || ModCtlv9
.mod_loaded
== 0)
940 && (ModCtlv9
.mod_installed
== 1 || ModCtlv9
.mod_installed
== 0)
941 && ModCtlv9
.mod_requisites
== 0
942 && (ModCtlv9
.mod_loadcnt
== 1 || ModCtlv9
.mod_loadcnt
== 0)
943 /*&& ModCtlv9.mod_text == pThis->AddrUnixText.FlatPtr*/
944 && ModCtlv9
.mod_text_size
< SOL_UNIX_MAX_CODE_SEG_SIZE
)
947 DBGFADDRESS NameAddr
;
948 DBGFR3AddrFromFlat(pVM
, &NameAddr
, ModCtlv9
.mod_modname
);
949 rc
= DBGFR3MemRead(pVM
, 0, &NameAddr
, &szUnix
, sizeof(szUnix
));
952 if (!strcmp(szUnix
, "unix"))
954 pThis
->AddrUnixModCtl
= ModCtlAddr
;
955 pThis
->iModCtlVer
= 9;
956 cbModCtl
= sizeof(ModCtlv9
);
959 Log(("sol32 mod_name=%.*s v9\n", sizeof(szUnix
), szUnix
));
966 DBGFR3AddrFromFlat(pVM
, &CurAddr
, HitAddr
.FlatPtr
+ cbExpr
);
970 * Walk the module chain and add the modules and their symbols.
972 if (pThis
->AddrUnixModCtl
.FlatPtr
)
975 CurAddr
= pThis
->AddrUnixModCtl
;
980 rc
= DBGFR3MemRead(pVM
, 0, &CurAddr
, &ModCtl
, cbModCtl
);
983 LogRel(("sol: bad modctl_t chain: %RGv - %Rrc\n", iMod
, CurAddr
.FlatPtr
, rc
));
989 dbgDiggerSolarisProcessModCtl64(pVM
, pThis
, &ModCtl
);
991 dbgDiggerSolarisProcessModCtl32(pVM
, pThis
, &ModCtl
);
996 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_64
.mod_next
, v9_64
.mod_next
);
997 if (!SOL64_VALID_ADDRESS(ModCtl
.v9_64
.mod_next
))
999 LogRel(("sol64: bad modctl_t chain at %RGv: %RGv\n", iMod
, CurAddr
.FlatPtr
, (RTGCUINTPTR
)ModCtl
.v9_64
.mod_next
));
1002 DBGFR3AddrFromFlat(pVM
, &CurAddr
, ModCtl
.v9_64
.mod_next
);
1006 AssertCompile2MemberOffsets(SOL_modctl_t
, v11_32
.mod_next
, v9_32
.mod_next
);
1007 if (!SOL32_VALID_ADDRESS(ModCtl
.v9_32
.mod_next
))
1009 LogRel(("sol32: bad modctl_t chain at %RGv: %RGv\n", iMod
, CurAddr
.FlatPtr
, (RTGCUINTPTR
)ModCtl
.v9_32
.mod_next
));
1012 DBGFR3AddrFromFlat(pVM
, &CurAddr
, ModCtl
.v9_32
.mod_next
);
1016 LogRel(("sol32: too many modules (%d)\n", iMod
));
1019 } while (CurAddr
.FlatPtr
!= pThis
->AddrUnixModCtl
.FlatPtr
);
1022 pThis
->fValid
= true;
1023 return VINF_SUCCESS
;
1028 * @copydoc DBGFOSREG::pfnProbe
1030 static DECLCALLBACK(bool) dbgDiggerSolarisProbe(PVM pVM
, void *pvData
)
1032 PDBGDIGGERSOLARIS pThis
= (PDBGDIGGERSOLARIS
)pvData
;
1035 * Look for "SunOS Release" in the text segment.
1038 bool f64Bit
= false;
1040 /* 32-bit search range. */
1041 DBGFR3AddrFromFlat(pVM
, &Addr
, 0xfe800000);
1042 RTGCUINTPTR cbRange
= 0xfec00000 - 0xfe800000;
1044 DBGFADDRESS HitAddr
;
1045 static const uint8_t s_abSunRelease
[] = "SunOS Release ";
1046 int rc
= DBGFR3MemScan(pVM
, 0, &Addr
, cbRange
, 1, s_abSunRelease
, sizeof(s_abSunRelease
) - 1, &HitAddr
);
1050 DBGFR3AddrFromFlat(pVM
, &Addr
, UINT64_C(0xfffffffffb800000));
1051 cbRange
= UINT64_C(0xfffffffffbc00000) - UINT64_C(0xfffffffffb800000);
1052 rc
= DBGFR3MemScan(pVM
, 0, &Addr
, cbRange
, 1, s_abSunRelease
, sizeof(s_abSunRelease
) - 1, &HitAddr
);
1059 * Look for the copyright string too, just to be sure.
1061 static const uint8_t s_abSMI
[] = "Sun Microsystems, Inc.";
1062 static const uint8_t s_abORCL
[] = "Oracle and/or its affiliates.";
1063 rc
= DBGFR3MemScan(pVM
, 0, &Addr
, cbRange
, 1, s_abSMI
, sizeof(s_abSMI
) - 1, &HitAddr
);
1066 /* Try the alternate copyright string. */
1067 rc
= DBGFR3MemScan(pVM
, 0, &Addr
, cbRange
, 1, s_abORCL
, sizeof(s_abORCL
) - 1, &HitAddr
);
1073 * Remember the unix text and data addresses and bitness.
1075 pThis
->AddrUnixText
= Addr
;
1076 DBGFR3AddrAdd(&Addr
, SOL_UNIX_MAX_CODE_SEG_SIZE
);
1077 pThis
->AddrUnixData
= Addr
;
1078 pThis
->f64Bit
= f64Bit
;
1085 * @copydoc DBGFOSREG::pfnDestruct
1087 static DECLCALLBACK(void) dbgDiggerSolarisDestruct(PVM pVM
, void *pvData
)
1094 * @copydoc DBGFOSREG::pfnConstruct
1096 static DECLCALLBACK(int) dbgDiggerSolarisConstruct(PVM pVM
, void *pvData
)
1098 return VINF_SUCCESS
;
1102 const DBGFOSREG g_DBGDiggerSolaris
=
1104 /* .u32Magic = */ DBGFOSREG_MAGIC
,
1106 /* .cbData = */ sizeof(DBGDIGGERSOLARIS
),
1107 /* .szName = */ "Solaris",
1108 /* .pfnConstruct = */ dbgDiggerSolarisConstruct
,
1109 /* .pfnDestruct = */ dbgDiggerSolarisDestruct
,
1110 /* .pfnProbe = */ dbgDiggerSolarisProbe
,
1111 /* .pfnInit = */ dbgDiggerSolarisInit
,
1112 /* .pfnRefresh = */ dbgDiggerSolarisRefresh
,
1113 /* .pfnTerm = */ dbgDiggerSolarisTerm
,
1114 /* .pfnQueryVersion = */ dbgDiggerSolarisQueryVersion
,
1115 /* .pfnQueryInterface = */ dbgDiggerSolarisQueryInterface
,
1116 /* .u32EndMagic = */ DBGFOSREG_MAGIC