VirtualBox

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

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

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

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

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