VirtualBox

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

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

The debugger is back in the OSE.

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