VirtualBox

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

Last change on this file since 35253 was 35253, checked in by vboxsync, 14 years ago

Debugger: Fixed memory editing commands.

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