1 | /* $Id: DBGPlugInSolaris.cpp 8800 2008-05-14 03:03:54Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * DBGPlugInSolaris - Debugger and Guest OS Digger Plugin For Solaris.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2008 Sun Microsystems, Inc.
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.215389.xyz. 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 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
|
---|
18 | * Clara, CA 95054 USA or visit http://www.sun.com if you need
|
---|
19 | * additional information or have any questions.
|
---|
20 | */
|
---|
21 |
|
---|
22 |
|
---|
23 | /*******************************************************************************
|
---|
24 | * Header Files *
|
---|
25 | *******************************************************************************/
|
---|
26 | #include "DBGPlugIns.h"
|
---|
27 | #include <VBox/dbgf.h>
|
---|
28 | #include <iprt/string.h>
|
---|
29 |
|
---|
30 |
|
---|
31 | /*******************************************************************************
|
---|
32 | * Structures and Typedefs *
|
---|
33 | *******************************************************************************/
|
---|
34 |
|
---|
35 | /** @name InternalSolaris structures
|
---|
36 | * @{ */
|
---|
37 |
|
---|
38 | typedef struct SOL32_modctl
|
---|
39 | {
|
---|
40 | uint32_t mod_next; /**< 0 */
|
---|
41 | uint32_t mod_prev; /**< 4 */
|
---|
42 | int32_t mod_id; /**< 8 */
|
---|
43 | uint32_t mod_mp; /**< c Pointer to the kernel runtime loader bits. */
|
---|
44 | uint32_t mod_inprogress_thread; /**< 10 */
|
---|
45 | uint32_t mod_modinfo; /**< 14 */
|
---|
46 | uint32_t mod_linkage; /**< 18 */
|
---|
47 | uint32_t mod_filename; /**< 1c */
|
---|
48 | uint32_t mod_modname; /**< 20 */
|
---|
49 | int8_t mod_busy; /**< 24 */
|
---|
50 | int8_t mod_want; /**< 25 */
|
---|
51 | int8_t mod_prim; /**< 26 this is 1 for 'unix' and a few others. */
|
---|
52 | int8_t mod_unused_padding; /**< 27 */
|
---|
53 | int32_t mod_ref; /**< 28 */
|
---|
54 | int8_t mod_loaded; /**< 2c */
|
---|
55 | int8_t mod_installed; /**< 2d */
|
---|
56 | int8_t mod_loadflags; /**< 2e */
|
---|
57 | int8_t mod_delay_unload; /**< 2f */
|
---|
58 | uint32_t mod_requisites; /**< 30 */
|
---|
59 | uint32_t mod___unused; /**< 34 */
|
---|
60 | int32_t mod_loadcnt; /**< 38 */
|
---|
61 | int32_t mod_nenabled; /**< 3c */
|
---|
62 | uint32_t mod_text; /**< 40 */
|
---|
63 | uint32_t mod_text_size; /**< 44 */
|
---|
64 | int32_t mod_gencount; /**< 48 */
|
---|
65 | uint32_t mod_requisite_loading; /**< 4c */
|
---|
66 | } SOL32_modctl_t;
|
---|
67 | AssertCompileSize(SOL32_modctl_t, 0x50);
|
---|
68 |
|
---|
69 | /** @} */
|
---|
70 |
|
---|
71 |
|
---|
72 | /**
|
---|
73 | * Solaris guest OS digger instance data.
|
---|
74 | */
|
---|
75 | typedef struct DBGDIGGERSOLARIS
|
---|
76 | {
|
---|
77 | /** Whether the information is valid or not.
|
---|
78 | * (For fending off illegal interface method calls.) */
|
---|
79 | bool fValid;
|
---|
80 |
|
---|
81 | /** Address of the 'unix' text segment.
|
---|
82 | * This is set during probing. */
|
---|
83 | DBGFADDRESS AddrUnixText;
|
---|
84 | /** Address of the 'unix' text segment.
|
---|
85 | * This is set during probing. */
|
---|
86 | DBGFADDRESS AddrUnixData;
|
---|
87 | /** Address of the 'unix' modctl_t (aka modules). */
|
---|
88 | DBGFADDRESS AddrUnixModCtl;
|
---|
89 |
|
---|
90 | } DBGDIGGERSOLARIS;
|
---|
91 | /** Pointer to the solaris guest OS digger instance data. */
|
---|
92 | typedef DBGDIGGERSOLARIS *PDBGDIGGERSOLARIS;
|
---|
93 |
|
---|
94 |
|
---|
95 | /*******************************************************************************
|
---|
96 | * Defined Constants And Macros *
|
---|
97 | *******************************************************************************/
|
---|
98 | /** Validates a 32-bit solaris kernel address */
|
---|
99 | #define SOL32_VALID_ADDRESS(Addr) ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
|
---|
100 |
|
---|
101 |
|
---|
102 |
|
---|
103 | /*******************************************************************************
|
---|
104 | * Internal Functions *
|
---|
105 | *******************************************************************************/
|
---|
106 | static DECLCALLBACK(int) dbgDiggerSolarisInit(PVM pVM, void *pvData);
|
---|
107 |
|
---|
108 |
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * @copydoc DBGFOSREG::pfnQueryInterface
|
---|
112 | */
|
---|
113 | static DECLCALLBACK(void *) dbgDiggerSolarisQueryInterface(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf)
|
---|
114 | {
|
---|
115 | return NULL;
|
---|
116 | }
|
---|
117 |
|
---|
118 |
|
---|
119 | /**
|
---|
120 | * @copydoc DBGFOSREG::pfnQueryVersion
|
---|
121 | */
|
---|
122 | static DECLCALLBACK(int) dbgDiggerSolarisQueryVersion(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion)
|
---|
123 | {
|
---|
124 | PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
|
---|
125 | Assert(pThis->fValid);
|
---|
126 |
|
---|
127 | return VERR_NOT_IMPLEMENTED;
|
---|
128 | }
|
---|
129 |
|
---|
130 |
|
---|
131 | /**
|
---|
132 | * @copydoc DBGFOSREG::pfnTerm
|
---|
133 | */
|
---|
134 | static DECLCALLBACK(void) dbgDiggerSolarisTerm(PVM pVM, void *pvData)
|
---|
135 | {
|
---|
136 | PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
|
---|
137 | Assert(pThis->fValid);
|
---|
138 |
|
---|
139 | pThis->fValid = false;
|
---|
140 | }
|
---|
141 |
|
---|
142 |
|
---|
143 | /**
|
---|
144 | * @copydoc DBGFOSREG::pfnRefresh
|
---|
145 | */
|
---|
146 | static DECLCALLBACK(int) dbgDiggerSolarisRefresh(PVM pVM, void *pvData)
|
---|
147 | {
|
---|
148 | PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
|
---|
149 | Assert(pThis->fValid);
|
---|
150 |
|
---|
151 | /*
|
---|
152 | * For now we'll flush and reload everything.
|
---|
153 | */
|
---|
154 | dbgDiggerSolarisTerm(pVM, pvData);
|
---|
155 | return dbgDiggerSolarisInit(pVM, pvData);
|
---|
156 | }
|
---|
157 |
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * @copydoc DBGFOSREG::pfnInit
|
---|
161 | */
|
---|
162 | static DECLCALLBACK(int) dbgDiggerSolarisInit(PVM pVM, void *pvData)
|
---|
163 | {
|
---|
164 | PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
|
---|
165 | Assert(!pThis->fValid);
|
---|
166 | int rc;
|
---|
167 |
|
---|
168 | /*
|
---|
169 | * Find the 'unix' modctl_t structure (aka modules).
|
---|
170 | * We know it resides in the unix data segment.
|
---|
171 | */
|
---|
172 | DBGFR3AddrFromFlat(pVM, &pThis->AddrUnixModCtl, 0);
|
---|
173 |
|
---|
174 | DBGFADDRESS CurAddr = pThis->AddrUnixData;
|
---|
175 | DBGFADDRESS MaxAddr;
|
---|
176 | DBGFR3AddrFromFlat(pVM, &MaxAddr, CurAddr.FlatPtr + 0x01000000);
|
---|
177 | const uint8_t *pbExpr = (const uint8_t *)&pThis->AddrUnixText.FlatPtr;
|
---|
178 | const uint32_t cbExpr = sizeof(uint32_t);//pThis->AddrUnixText.FlatPtr < _4G ? sizeof(uint32_t) : sizeof(uint64_t)
|
---|
179 | while ( CurAddr.FlatPtr < MaxAddr.FlatPtr
|
---|
180 | && CurAddr.FlatPtr >= pThis->AddrUnixData.FlatPtr)
|
---|
181 | {
|
---|
182 | DBGFADDRESS HitAddr;
|
---|
183 | rc = DBGFR3MemScan(pVM, &CurAddr, MaxAddr.FlatPtr - CurAddr.FlatPtr, pbExpr, cbExpr, &HitAddr);
|
---|
184 | if (RT_FAILURE(rc))
|
---|
185 | break;
|
---|
186 |
|
---|
187 | /*
|
---|
188 | * Read out the modctl_t structure.
|
---|
189 | */
|
---|
190 | DBGFADDRESS ModCtlAddr;
|
---|
191 | DBGFR3AddrFromFlat(pVM, &ModCtlAddr, HitAddr.FlatPtr - RT_OFFSETOF(SOL32_modctl_t, mod_text));
|
---|
192 | SOL32_modctl_t ModCtl;
|
---|
193 | rc = DBGFR3MemRead(pVM, &ModCtlAddr, &ModCtl, sizeof(ModCtl));
|
---|
194 | if (RT_SUCCESS(rc))
|
---|
195 | {
|
---|
196 | if ( SOL32_VALID_ADDRESS(ModCtl.mod_next)
|
---|
197 | && SOL32_VALID_ADDRESS(ModCtl.mod_prev)
|
---|
198 | && ModCtl.mod_id == 0
|
---|
199 | && SOL32_VALID_ADDRESS(ModCtl.mod_mp)
|
---|
200 | && SOL32_VALID_ADDRESS(ModCtl.mod_filename)
|
---|
201 | && SOL32_VALID_ADDRESS(ModCtl.mod_modname)
|
---|
202 | && ModCtl.mod_prim == 1
|
---|
203 | && ModCtl.mod_loaded == 1
|
---|
204 | && ModCtl.mod_installed == 1
|
---|
205 | && ModCtl.mod_requisites == 0
|
---|
206 | && ModCtl.mod_loadcnt == 1
|
---|
207 | /*&& ModCtl.mod_text == pThis->AddrUnixText.FlatPtr*/
|
---|
208 | && ModCtl.mod_text_size < UINT32_C(0xfec00000) - UINT32_C(0xfe800000) )
|
---|
209 | {
|
---|
210 | char szUnix[5];
|
---|
211 | DBGFADDRESS NameAddr;
|
---|
212 | DBGFR3AddrFromFlat(pVM, &NameAddr, ModCtl.mod_modname);
|
---|
213 | rc = DBGFR3MemRead(pVM, &NameAddr, &szUnix, sizeof(szUnix));
|
---|
214 | if (RT_SUCCESS(rc))
|
---|
215 | {
|
---|
216 | if (!strcmp(szUnix, "unix"))
|
---|
217 | {
|
---|
218 | pThis->AddrUnixModCtl = ModCtlAddr;
|
---|
219 | break;
|
---|
220 | }
|
---|
221 | Log(("sol32 mod_name=%.*s\n", sizeof(szUnix), szUnix));
|
---|
222 | }
|
---|
223 | }
|
---|
224 | }
|
---|
225 |
|
---|
226 | /* next */
|
---|
227 | DBGFR3AddrFromFlat(pVM, &CurAddr, HitAddr.FlatPtr + cbExpr);
|
---|
228 | }
|
---|
229 |
|
---|
230 | /*
|
---|
231 | * Walk the module chain and add the modules and their symbols.
|
---|
232 | */
|
---|
233 | if (pThis->AddrUnixModCtl.FlatPtr)
|
---|
234 | {
|
---|
235 | int iMod = 0;
|
---|
236 | CurAddr = pThis->AddrUnixModCtl;
|
---|
237 | do
|
---|
238 | {
|
---|
239 | /* read it */
|
---|
240 | SOL32_modctl_t ModCtl;
|
---|
241 | rc = DBGFR3MemRead(pVM, &CurAddr, &ModCtl, sizeof(ModCtl));
|
---|
242 | if (RT_FAILURE(rc))
|
---|
243 | {
|
---|
244 | LogRel(("sol32: bad modctl_t chain: %RGv - %Rrc\n", iMod, CurAddr.FlatPtr, rc));
|
---|
245 | break;
|
---|
246 | }
|
---|
247 |
|
---|
248 | /* process it. */
|
---|
249 |
|
---|
250 |
|
---|
251 | /* next */
|
---|
252 | if (!SOL32_VALID_ADDRESS(ModCtl.mod_next))
|
---|
253 | {
|
---|
254 | LogRel(("sol32: bad modctl_t chain at %RGv: %RGv\n", iMod, CurAddr.FlatPtr, (RTGCUINTPTR)ModCtl.mod_next));
|
---|
255 | break;
|
---|
256 | }
|
---|
257 | if (++iMod >= 1024)
|
---|
258 | {
|
---|
259 | LogRel(("sol32: too many modules (%d)\n", iMod));
|
---|
260 | break;
|
---|
261 | }
|
---|
262 | DBGFR3AddrFromFlat(pVM, &CurAddr, ModCtl.mod_next);
|
---|
263 | } while (CurAddr.FlatPtr != pThis->AddrUnixModCtl.FlatPtr);
|
---|
264 | }
|
---|
265 |
|
---|
266 | pThis->fValid = true;
|
---|
267 | return VINF_SUCCESS;
|
---|
268 | }
|
---|
269 |
|
---|
270 |
|
---|
271 | /**
|
---|
272 | * @copydoc DBGFOSREG::pfnProbe
|
---|
273 | */
|
---|
274 | static DECLCALLBACK(bool) dbgDiggerSolarisProbe(PVM pVM, void *pvData)
|
---|
275 | {
|
---|
276 | PDBGDIGGERSOLARIS pThis = (PDBGDIGGERSOLARIS)pvData;
|
---|
277 |
|
---|
278 | /*
|
---|
279 | * Look for "SunOS Release" in the text segment.
|
---|
280 | */
|
---|
281 | DBGFADDRESS Addr;
|
---|
282 | DBGFR3AddrFromFlat(pVM, &Addr, 0xfe800000);
|
---|
283 | RTGCUINTPTR cbRange = 0xfec00000 - 0xfe800000;
|
---|
284 |
|
---|
285 | DBGFADDRESS HitAddr;
|
---|
286 | static const uint8_t s_abSunRelease[] = "SunOS Release ";
|
---|
287 | int rc = DBGFR3MemScan(pVM, &Addr, cbRange, s_abSunRelease, sizeof(s_abSunRelease) - 1, &HitAddr);
|
---|
288 | if (RT_FAILURE(rc))
|
---|
289 | return false;
|
---|
290 |
|
---|
291 | /*
|
---|
292 | * Look for the copy right string too, just to be sure.
|
---|
293 | */
|
---|
294 | static const uint8_t s_abSMI[] = "Sun Microsystems, Inc.";
|
---|
295 | rc = DBGFR3MemScan(pVM, &Addr, cbRange, s_abSMI, sizeof(s_abSMI) - 1, &HitAddr);
|
---|
296 | if (RT_FAILURE(rc))
|
---|
297 | return false;
|
---|
298 |
|
---|
299 | /*
|
---|
300 | * Remember the unix text and data addresses (32-bit vs 64-bit).
|
---|
301 | */
|
---|
302 | pThis->AddrUnixText = Addr;
|
---|
303 | // if (pThis->AddrUnixText.FlatPtr == 0xfe800000)
|
---|
304 | {
|
---|
305 | DBGFR3AddrFromFlat(pVM, &Addr, 0xfec00000);
|
---|
306 | pThis->AddrUnixData = Addr;
|
---|
307 | }
|
---|
308 | // else
|
---|
309 | // {
|
---|
310 | // DBGFR3AddrFromFlat(pVM, &Addr, UINT64_C(0xwhateveritis));
|
---|
311 | // pThis->AddrUnixData = Addr;
|
---|
312 | // }
|
---|
313 |
|
---|
314 | return true;
|
---|
315 | }
|
---|
316 |
|
---|
317 |
|
---|
318 | /**
|
---|
319 | * @copydoc DBGFOSREG::pfnDestruct
|
---|
320 | */
|
---|
321 | static DECLCALLBACK(void) dbgDiggerSolarisDestruct(PVM pVM, void *pvData)
|
---|
322 | {
|
---|
323 |
|
---|
324 | }
|
---|
325 |
|
---|
326 |
|
---|
327 | /**
|
---|
328 | * @copydoc DBGFOSREG::pfnConstruct
|
---|
329 | */
|
---|
330 | static DECLCALLBACK(int) dbgDiggerSolarisConstruct(PVM pVM, void *pvData)
|
---|
331 | {
|
---|
332 | return VINF_SUCCESS;
|
---|
333 | }
|
---|
334 |
|
---|
335 |
|
---|
336 | const DBGFOSREG g_DBGDiggerSolaris =
|
---|
337 | {
|
---|
338 | /* .u32Magic = */ DBGFOSREG_MAGIC,
|
---|
339 | /* .fFlags = */ 0,
|
---|
340 | /* .cbData = */ sizeof(DBGDIGGERSOLARIS),
|
---|
341 | /* .szName = */ "Solaris",
|
---|
342 | /* .pfnConstruct = */ dbgDiggerSolarisConstruct,
|
---|
343 | /* .pfnDestruct = */ dbgDiggerSolarisDestruct,
|
---|
344 | /* .pfnProbe = */ dbgDiggerSolarisProbe,
|
---|
345 | /* .pfnInit = */ dbgDiggerSolarisInit,
|
---|
346 | /* .pfnRefresh = */ dbgDiggerSolarisRefresh,
|
---|
347 | /* .pfnTerm = */ dbgDiggerSolarisTerm,
|
---|
348 | /* .pfnQueryVersion = */ dbgDiggerSolarisQueryVersion,
|
---|
349 | /* .pfnQueryInterface = */ dbgDiggerSolarisQueryInterface,
|
---|
350 | /* .u32EndMagic = */ DBGFOSREG_MAGIC
|
---|
351 | };
|
---|
352 |
|
---|