VirtualBox

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

Last change on this file since 82968 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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