VirtualBox

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

Last change on this file since 65522 was 63567, checked in by vboxsync, 8 years ago

scm: cleaning up todos

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