~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Debugger/DBGPlugInSolaris.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

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