VirtualBox

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

Last change on this file since 61627 was 59747, checked in by vboxsync, 9 years ago

iprt/asm.h: Cleaned up the ASMMemIsAll8/U32 mess and implmeneted the former in assembly. (Found inverted usage due to bad naming in copyUtf8Block, but it is fortunately an unused method.) Replaces the complicated ASMBitFirstSet based scanning in RTSgBufIsZero with a simple call to the new ASMMemIsZero function.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 44.3 KB
Line 
1/* $Id: DBGPlugInSolaris.cpp 59747 2016-02-19 23:18:18Z vboxsync $ */
2/** @file
3 * DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
4 */
5
6/*
7 * Copyright (C) 2008-2015 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::pfnQueryInterface
358 */
359static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
360{
361 return NULL;
362}
363
364
365/**
366 * @copydoc DBGFOSREG::pfnQueryVersion
367 */
368static DECLCALLBACK(int) dbgDiggerSolarisQueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
369{
370 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
371 Assert(pThis->fValid);
372
373 /*
374 * It's all in the utsname symbol...
375 */
376 DBGFADDRESS Addr;
377 SOL_utsname_t UtsName;
378 RTDBGSYMBOL SymUtsName;
379 int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "utsname", &SymUtsName, NULL);
380 if (RT_SUCCESS(rc))
381 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, SymUtsName.Value), &UtsName, sizeof(UtsName));
382 if (RT_FAILURE(rc))
383 {
384 /*
385 * Try searching by the name...
386 */
387 memset(&UtsName, '\0', sizeof(UtsName));
388 strcpy(&UtsName.sysname[0], "SunOS");
389 rc = DBGFR3MemScan(pUVM, 0, &pThis->AddrUnixData, SOL_UNIX_MAX_DATA_SEG_SIZE, 1,
390 &UtsName.sysname[0], sizeof(UtsName.sysname), &Addr);
391 if (RT_SUCCESS(rc))
392 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, Addr.FlatPtr - RT_OFFSETOF(SOL_utsname_t, sysname)),
393 &UtsName, sizeof(UtsName));
394 }
395
396 /*
397 * Copy out the result (if any).
398 */
399 if (RT_SUCCESS(rc))
400 {
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')
406 {
407 //rc = VERR_DBGF_UNEXPECTED_OS_DATA;
408 rc = VERR_GENERAL_FAILURE;
409 RTStrPrintf(pszVersion, cchVersion, "failed - bogus utsname");
410 }
411 else
412 RTStrPrintf(pszVersion, cchVersion, "%s %s", UtsName.version, UtsName.release);
413 }
414 else
415 RTStrPrintf(pszVersion, cchVersion, "failed - %Rrc", rc);
416
417 return rc;
418}
419
420
421
422/**
423 * Processes a modctl_t.
424 *
425 * @param pUVM The user mode VM handle.
426 * @param pThis Our instance data.
427 * @param pModCtl Pointer to the modctl structure.
428 */
429static void dbgDiggerSolarisProcessModCtl32(PUVM pUVM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
430{
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)
438 return;
439
440 /*
441 * Read the module and file names first
442 */
443 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_modname, v9_32.mod_modname);
444 char szModName[64];
445 DBGFADDRESS Addr;
446 int rc = DBGFR3MemReadString(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_modname), szModName, sizeof(szModName));
447 if (RT_FAILURE(rc))
448 return;
449 if (!RTStrEnd(szModName, sizeof(szModName)))
450 szModName[sizeof(szModName) - 1] = '\0';
451
452 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_filename, v9_32.mod_filename);
453 char szFilename[256];
454 rc = DBGFR3MemReadString(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_filename), szFilename, sizeof(szFilename));
455 if (RT_FAILURE(rc))
456 strcpy(szFilename, szModName);
457 else if (!RTStrEnd(szFilename, sizeof(szFilename)))
458 szFilename[sizeof(szFilename) - 1] = '\0';
459
460 /*
461 * Then read the module struct and validate it.
462 */
463 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_mp, v9_32.mod_mp);
464 struct SOL32_module Module;
465 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_32.mod_mp), &Module, sizeof(Module));
466 if (RT_FAILURE(rc))
467 return;
468
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 || !ASMMemIsZero(&Module.hdr.e_ident[EI_PAD], EI_NIDENT - EI_PAD)
478 )
479 return;
480 if (Module.hdr.e_version != EV_CURRENT)
481 return;
482 if (Module.hdr.e_ehsize != sizeof(Module.hdr))
483 return;
484 if ( Module.hdr.e_type != ET_DYN
485 && Module.hdr.e_type != ET_REL
486 && Module.hdr.e_type != ET_EXEC) //??
487 return;
488 if ( Module.hdr.e_machine != EM_386
489 && Module.hdr.e_machine != EM_486)
490 return;
491 if ( Module.hdr.e_phentsize != sizeof(Elf32_Phdr)
492 && Module.hdr.e_phentsize) //??
493 return;
494 if (Module.hdr.e_shentsize != sizeof(Elf32_Shdr))
495 return;
496
497 if (Module.hdr.e_shentsize != sizeof(Elf32_Shdr))
498 return;
499
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))
512 return;
513 if ( Module.symsize > _4M
514 || Module.hdr.e_shnum > 4096
515 || Module.nsyms > _256K)
516 return;
517
518 /* Ignore modules without symbols. */
519 if (!Module.symtbl || !Module.strings || !Module.symspace || !Module.symsize)
520 return;
521
522 /* Check that the symtbl and strings points inside the symspace. */
523 if (Module.strings - Module.symspace >= Module.symsize)
524 return;
525 if (Module.symtbl - Module.symspace >= Module.symsize)
526 return;
527
528 /*
529 * Read the section headers, symbol table and string tables.
530 */
531 size_t cb = Module.hdr.e_shnum * sizeof(Elf32_Shdr);
532 Elf32_Shdr *paShdrs = (Elf32_Shdr *)RTMemTmpAlloc(cb);
533 if (!paShdrs)
534 return;
535 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, Module.shdrs), paShdrs, cb);
536 if (RT_SUCCESS(rc))
537 {
538 void *pvSymSpace = RTMemTmpAlloc(Module.symsize + 1);
539 if (pvSymSpace)
540 {
541 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, Module.symspace), pvSymSpace, Module.symsize);
542 if (RT_SUCCESS(rc))
543 {
544 ((uint8_t *)pvSymSpace)[Module.symsize] = 0;
545
546 /*
547 * Hand it over to the common ELF32 module parser.
548 */
549 char const *pbStrings = (char const *)pvSymSpace + (Module.strings - Module.symspace);
550 size_t cbMaxStrings = Module.symsize - (Module.strings - Module.symspace);
551
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);
555
556 DBGDiggerCommonParseElf32Mod(pUVM, 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);
559 }
560 RTMemTmpFree(pvSymSpace);
561 }
562 }
563
564 RTMemTmpFree(paShdrs);
565 return;
566}
567
568
569/**
570 * Processes a modctl_t.
571 *
572 * @param pUVM The user mode VM handle.
573 * @param pThis Our instance data.
574 * @param pModCtl Pointer to the modctl structure.
575 */
576static void dbgDiggerSolarisProcessModCtl64(PUVM pUVM, PDBGDIGGERSOLARIS pThis, SOL_modctl_t const *pModCtl)
577{
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)
585 return;
586
587 /*
588 * Read the module and file names first
589 */
590 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_modname, v9_64.mod_modname);
591 char szModName[64];
592 DBGFADDRESS Addr;
593 int rc = DBGFR3MemReadString(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_modname), szModName, sizeof(szModName));
594 if (RT_FAILURE(rc))
595 return;
596 if (!RTStrEnd(szModName, sizeof(szModName)))
597 szModName[sizeof(szModName) - 1] = '\0';
598
599 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_filename, v9_64.mod_filename);
600 char szFilename[256];
601 rc = DBGFR3MemReadString(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_filename), szFilename, sizeof(szFilename));
602 if (RT_FAILURE(rc))
603 strcpy(szFilename, szModName);
604 else if (!RTStrEnd(szFilename, sizeof(szFilename)))
605 szFilename[sizeof(szFilename) - 1] = '\0';
606
607 /*
608 * Then read the module struct and validate it.
609 */
610 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_mp, v9_64.mod_mp);
611 struct SOL64_module Module;
612 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, pModCtl->v9_64.mod_mp), &Module, sizeof(Module));
613 if (RT_FAILURE(rc))
614 return;
615
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 || !ASMMemIsZero(&Module.hdr.e_ident[EI_PAD], EI_NIDENT - EI_PAD)
625 )
626 return;
627 if (Module.hdr.e_version != EV_CURRENT)
628 return;
629 if (Module.hdr.e_ehsize != sizeof(Module.hdr))
630 return;
631 if ( Module.hdr.e_type != ET_DYN
632 && Module.hdr.e_type != ET_REL
633 && Module.hdr.e_type != ET_EXEC) //??
634 return;
635 if (Module.hdr.e_machine != EM_X86_64)
636 return;
637 if ( Module.hdr.e_phentsize != sizeof(Elf64_Phdr)
638 && Module.hdr.e_phentsize) //??
639 return;
640 if (Module.hdr.e_shentsize != sizeof(Elf64_Shdr))
641 return;
642
643 if (Module.hdr.e_shentsize != sizeof(Elf64_Shdr))
644 return;
645
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))
658 return;
659 if ( Module.symsize > _4M
660 || Module.hdr.e_shnum > 4096
661 || Module.nsyms > _256K)
662 return;
663
664 /* Ignore modules without symbols. */
665 if (!Module.symtbl || !Module.strings || !Module.symspace || !Module.symsize)
666 return;
667
668 /* Check that the symtbl and strings points inside the symspace. */
669 if (Module.strings - Module.symspace >= Module.symsize)
670 return;
671 if (Module.symtbl - Module.symspace >= Module.symsize)
672 return;
673
674 /*
675 * Read the section headers, symbol table and string tables.
676 */
677 size_t cb = Module.hdr.e_shnum * sizeof(Elf64_Shdr);
678 Elf64_Shdr *paShdrs = (Elf64_Shdr *)RTMemTmpAlloc(cb);
679 if (!paShdrs)
680 return;
681 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, Module.shdrs), paShdrs, cb);
682 if (RT_SUCCESS(rc))
683 {
684 void *pvSymSpace = RTMemTmpAlloc(Module.symsize + 1);
685 if (pvSymSpace)
686 {
687 rc = DBGFR3MemRead(pUVM, 0, DBGFR3AddrFromFlat(pUVM, &Addr, Module.symspace), pvSymSpace, Module.symsize);
688 if (RT_SUCCESS(rc))
689 {
690 ((uint8_t *)pvSymSpace)[Module.symsize] = 0;
691
692 /*
693 * Hand it over to the common ELF64 module parser.
694 */
695 char const *pbStrings = (char const *)pvSymSpace + (Module.strings - Module.symspace);
696 size_t cbMaxStrings = Module.symsize - (Module.strings - Module.symspace);
697
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);
701
702 DBGDiggerCommonParseElf64Mod(pUVM, 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);
705 }
706 RTMemTmpFree(pvSymSpace);
707 }
708 }
709
710 RTMemTmpFree(paShdrs);
711 return;
712}
713
714
715/**
716 * @copydoc DBGFOSREG::pfnTerm
717 */
718static DECLCALLBACK(void) dbgDiggerSolarisTerm(PUVM pUVM, void *pvData)
719{
720 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
721 Assert(pThis->fValid);
722
723 pThis->fValid = false;
724}
725
726
727/**
728 * @copydoc DBGFOSREG::pfnRefresh
729 */
730static DECLCALLBACK(int) dbgDiggerSolarisRefresh(PUVM pUVM, void *pvData)
731{
732 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
733 NOREF(pThis);
734 Assert(pThis->fValid);
735
736 /*
737 * For now we'll flush and reload everything.
738 */
739 RTDBGAS hDbgAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
740 if (hDbgAs != NIL_RTDBGAS)
741 {
742 uint32_t iMod = RTDbgAsModuleCount(hDbgAs);
743 while (iMod-- > 0)
744 {
745 RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);
746 if (hMod != NIL_RTDBGMOD)
747 {
748 if (RTDbgModGetTag(hMod) == DIG_SOL_MOD_TAG)
749 {
750 int rc = RTDbgAsModuleUnlink(hDbgAs, hMod);
751 AssertRC(rc);
752 }
753 RTDbgModRelease(hMod);
754 }
755 }
756 RTDbgAsRelease(hDbgAs);
757 }
758
759 dbgDiggerSolarisTerm(pUVM, pvData);
760 return dbgDiggerSolarisInit(pUVM, pvData);
761}
762
763
764/**
765 * @copydoc DBGFOSREG::pfnInit
766 */
767static DECLCALLBACK(int) dbgDiggerSolarisInit(PUVM pUVM, void *pvData)
768{
769 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
770 Assert(!pThis->fValid);
771 int rc;
772 size_t cbModCtl = 0;
773
774 /*
775 * On Solaris the kernel and is the global address space.
776 */
777 DBGFR3AsSetAlias(pUVM, DBGF_AS_KERNEL, DBGF_AS_GLOBAL);
778
779/** @todo Use debug_info, build 7x / S10U6. */
780
781 /*
782 * Find the 'unix' modctl_t structure (aka modules).
783 * We know it resides in the unix data segment.
784 */
785 DBGFR3AddrFromFlat(pUVM, &pThis->AddrUnixModCtl, 0);
786
787 DBGFADDRESS CurAddr = pThis->AddrUnixData;
788 DBGFADDRESS MaxAddr;
789 DBGFR3AddrFromFlat(pUVM, &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)
794 {
795 DBGFADDRESS HitAddr;
796 rc = DBGFR3MemScan(pUVM, 0, &CurAddr, MaxAddr.FlatPtr - CurAddr.FlatPtr, 1, pbExpr, cbExpr, &HitAddr);
797 if (RT_FAILURE(rc))
798 break;
799
800 /*
801 * Read out the modctl_t structure.
802 */
803 DBGFADDRESS ModCtlAddr;
804
805 /* v11 */
806 if (pThis->f64Bit)
807 {
808 DBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v11_modctl_t, mod_text));
809 SOL64v11_modctl_t ModCtlv11;
810 rc = DBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv11, sizeof(ModCtlv11));
811 if (RT_SUCCESS(rc))
812 {
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)
827 {
828 char szUnix[5];
829 DBGFADDRESS NameAddr;
830 DBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv11.mod_modname);
831 rc = DBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
832 if (RT_SUCCESS(rc))
833 {
834 if (!strcmp(szUnix, "unix"))
835 {
836 pThis->AddrUnixModCtl = ModCtlAddr;
837 pThis->iModCtlVer = 11;
838 cbModCtl = sizeof(ModCtlv11);
839 break;
840 }
841 Log(("sol64 mod_name=%.*s v11\n", sizeof(szUnix), szUnix));
842 }
843 }
844 }
845 }
846 else
847 {
848 DBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v11_modctl_t, mod_text));
849 SOL32v11_modctl_t ModCtlv11;
850 rc = DBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv11, sizeof(ModCtlv11));
851 if (RT_SUCCESS(rc))
852 {
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)
867 {
868 char szUnix[5];
869 DBGFADDRESS NameAddr;
870 DBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv11.mod_modname);
871 rc = DBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
872 if (RT_SUCCESS(rc))
873 {
874 if (!strcmp(szUnix, "unix"))
875 {
876 pThis->AddrUnixModCtl = ModCtlAddr;
877 pThis->iModCtlVer = 11;
878 cbModCtl = sizeof(ModCtlv11);
879 break;
880 }
881 Log(("sol32 mod_name=%.*s v11\n", sizeof(szUnix), szUnix));
882 }
883 }
884 }
885 }
886
887 /* v9 */
888 if (pThis->f64Bit)
889 {
890 DBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL64v9_modctl_t, mod_text));
891 SOL64v9_modctl_t ModCtlv9;
892 rc = DBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv9, sizeof(ModCtlv9));
893 if (RT_SUCCESS(rc))
894 {
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)
907 {
908 char szUnix[5];
909 DBGFADDRESS NameAddr;
910 DBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv9.mod_modname);
911 rc = DBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
912 if (RT_SUCCESS(rc))
913 {
914 if (!strcmp(szUnix, "unix"))
915 {
916 pThis->AddrUnixModCtl = ModCtlAddr;
917 pThis->iModCtlVer = 9;
918 cbModCtl = sizeof(ModCtlv9);
919 break;
920 }
921 Log(("sol64 mod_name=%.*s v9\n", sizeof(szUnix), szUnix));
922 }
923 }
924 }
925 }
926 else
927 {
928 DBGFR3AddrFromFlat(pUVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32v9_modctl_t, mod_text));
929 SOL32v9_modctl_t ModCtlv9;
930 rc = DBGFR3MemRead(pUVM, 0, &ModCtlAddr, &ModCtlv9, sizeof(ModCtlv9));
931 if (RT_SUCCESS(rc))
932 {
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 )
945 {
946 char szUnix[5];
947 DBGFADDRESS NameAddr;
948 DBGFR3AddrFromFlat(pUVM, &NameAddr, ModCtlv9.mod_modname);
949 rc = DBGFR3MemRead(pUVM, 0, &NameAddr, &szUnix, sizeof(szUnix));
950 if (RT_SUCCESS(rc))
951 {
952 if (!strcmp(szUnix, "unix"))
953 {
954 pThis->AddrUnixModCtl = ModCtlAddr;
955 pThis->iModCtlVer = 9;
956 cbModCtl = sizeof(ModCtlv9);
957 break;
958 }
959 Log(("sol32 mod_name=%.*s v9\n", sizeof(szUnix), szUnix));
960 }
961 }
962 }
963 }
964
965 /* next */
966 DBGFR3AddrFromFlat(pUVM, &CurAddr, HitAddr.FlatPtr + cbExpr);
967 }
968
969 /*
970 * Walk the module chain and add the modules and their symbols.
971 */
972 if (pThis->AddrUnixModCtl.FlatPtr)
973 {
974 int iMod = 0;
975 CurAddr = pThis->AddrUnixModCtl;
976 do
977 {
978 /* read it */
979 SOL_modctl_t ModCtl;
980 rc = DBGFR3MemRead(pUVM, 0, &CurAddr, &ModCtl, cbModCtl);
981 if (RT_FAILURE(rc))
982 {
983 LogRel(("sol: bad modctl_t chain for module %d: %RGv - %Rrc\n", iMod, CurAddr.FlatPtr, rc));
984 break;
985 }
986
987 /* process it. */
988 if (pThis->f64Bit)
989 dbgDiggerSolarisProcessModCtl64(pUVM, pThis, &ModCtl);
990 else
991 dbgDiggerSolarisProcessModCtl32(pUVM, pThis, &ModCtl);
992
993 /* next */
994 if (pThis->f64Bit)
995 {
996 AssertCompile2MemberOffsets(SOL_modctl_t, v11_64.mod_next, v9_64.mod_next);
997 if (!SOL64_VALID_ADDRESS(ModCtl.v9_64.mod_next))
998 {
999 LogRel(("sol64: bad modctl_t chain for module %d at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_64.mod_next));
1000 break;
1001 }
1002 DBGFR3AddrFromFlat(pUVM, &CurAddr, ModCtl.v9_64.mod_next);
1003 }
1004 else
1005 {
1006 AssertCompile2MemberOffsets(SOL_modctl_t, v11_32.mod_next, v9_32.mod_next);
1007 if (!SOL32_VALID_ADDRESS(ModCtl.v9_32.mod_next))
1008 {
1009 LogRel(("sol32: bad modctl_t chain for module %d at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.v9_32.mod_next));
1010 break;
1011 }
1012 DBGFR3AddrFromFlat(pUVM, &CurAddr, ModCtl.v9_32.mod_next);
1013 }
1014 if (++iMod >= 1024)
1015 {
1016 LogRel(("sol32: too many modules (%d)\n", iMod));
1017 break;
1018 }
1019 } while (CurAddr.FlatPtr != pThis->AddrUnixModCtl.FlatPtr);
1020 }
1021
1022 pThis->fValid = true;
1023 return VINF_SUCCESS;
1024}
1025
1026
1027/**
1028 * @copydoc DBGFOSREG::pfnProbe
1029 */
1030static DECLCALLBACK(bool) dbgDiggerSolarisProbe(PUVM pUVM, void *pvData)
1031{
1032 PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
1033
1034 /*
1035 * Look for "SunOS Release" in the text segment.
1036 */
1037 DBGFADDRESS Addr;
1038 bool f64Bit = false;
1039
1040 /* 32-bit search range. */
1041 DBGFR3AddrFromFlat(pUVM, &Addr, 0xfe800000);
1042 RTGCUINTPTR cbRange = 0xfec00000 - 0xfe800000;
1043
1044 DBGFADDRESS HitAddr;
1045 static const uint8_t s_abSunRelease[] = "SunOS Release ";
1046 int rc = DBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
1047 if (RT_FAILURE(rc))
1048 {
1049 /* 64-bit.... */
1050 DBGFR3AddrFromFlat(pUVM, &Addr, UINT64_C(0xfffffffffb800000));
1051 cbRange = UINT64_C(0xfffffffffbd00000) - UINT64_C(0xfffffffffb800000);
1052 rc = DBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
1053 if (RT_FAILURE(rc))
1054 return false;
1055 f64Bit = true;
1056 }
1057
1058 /*
1059 * Look for the copyright string too, just to be sure.
1060 */
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(pUVM, 0, &Addr, cbRange, 1, s_abSMI, sizeof(s_abSMI) - 1, &HitAddr);
1064 if (RT_FAILURE(rc))
1065 {
1066 /* Try the alternate copyright string. */
1067 rc = DBGFR3MemScan(pUVM, 0, &Addr, cbRange, 1, s_abORCL, sizeof(s_abORCL) - 1, &HitAddr);
1068 if (RT_FAILURE(rc))
1069 return false;
1070 }
1071
1072 /*
1073 * Remember the unix text and data addresses and bitness.
1074 */
1075 pThis->AddrUnixText = Addr;
1076 DBGFR3AddrAdd(&Addr, SOL_UNIX_MAX_CODE_SEG_SIZE);
1077 pThis->AddrUnixData = Addr;
1078 pThis->f64Bit = f64Bit;
1079
1080 return true;
1081}
1082
1083
1084/**
1085 * @copydoc DBGFOSREG::pfnDestruct
1086 */
1087static DECLCALLBACK(void) dbgDiggerSolarisDestruct(PUVM pUVM, void *pvData)
1088{
1089
1090}
1091
1092
1093/**
1094 * @copydoc DBGFOSREG::pfnConstruct
1095 */
1096static DECLCALLBACK(int) dbgDiggerSolarisConstruct(PUVM pUVM, void *pvData)
1097{
1098 return VINF_SUCCESS;
1099}
1100
1101
1102const DBGFOSREG g_DBGDiggerSolaris =
1103{
1104 /* .u32Magic = */ DBGFOSREG_MAGIC,
1105 /* .fFlags = */ 0,
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
1117};
1118
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