VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGPlugInLinux.cpp@ 31510

Last change on this file since 31510 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 Author Date Id Revision
File size: 7.2 KB
Line 
1/* $Id: DBGPlugInLinux.cpp 31510 2010-08-10 08:48:11Z vboxsync $ */
2/** @file
3 * DBGPlugInLinux - Debugger and Guest OS Digger Plugin For Linux.
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/string.h>
22#include <iprt/mem.h>
23#include <iprt/stream.h>
24#include <iprt/ctype.h>
25
26
27/*******************************************************************************
28* Structures and Typedefs *
29*******************************************************************************/
30
31/** @name InternalLinux structures
32 * @{ */
33
34
35/** @} */
36
37
38/**
39 * Linux guest OS digger instance data.
40 */
41typedef struct DBGDIGGERLINUX
42{
43 /** Whether the information is valid or not.
44 * (For fending off illegal interface method calls.) */
45 bool fValid;
46
47 /** The address of the linux banner.
48 * This is set during probing. */
49 DBGFADDRESS AddrLinuxBanner;
50 /** Kernel base address.
51 * This is set during probing. */
52 DBGFADDRESS AddrKernelBase;
53} DBGDIGGERLINUX;
54/** Pointer to the linux guest OS digger instance data. */
55typedef DBGDIGGERLINUX *PDBGDIGGERLINUX;
56
57
58/*******************************************************************************
59* Defined Constants And Macros *
60*******************************************************************************/
61/** Validates a 32-bit linux kernel address */
62#define LNX32_VALID_ADDRESS(Addr) ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
63
64/** The max kernel size. */
65#define LNX_MAX_KERNEL_SIZE 0x0f000000
66
67
68/*******************************************************************************
69* Internal Functions *
70*******************************************************************************/
71static DECLCALLBACK(int) dbgDiggerLinuxInit(PVM pVM, void *pvData);
72
73
74/*******************************************************************************
75* Global Variables *
76*******************************************************************************/
77/** Table of common linux kernel addresses. */
78static uint64_t g_au64LnxKernelAddresses[] =
79{
80 UINT64_C(0xc0100000),
81 UINT64_C(0x90100000),
82 UINT64_C(0xffffffff80200000)
83};
84
85
86/**
87 * @copydoc DBGFOSREG::pfnQueryInterface
88 */
89static DECLCALLBACK(void *) dbgDiggerLinuxQueryInterface(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf)
90{
91 return NULL;
92}
93
94
95/**
96 * @copydoc DBGFOSREG::pfnQueryVersion
97 */
98static DECLCALLBACK(int) dbgDiggerLinuxQueryVersion(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion)
99{
100 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
101 Assert(pThis->fValid);
102
103 /*
104 * It's all in the linux banner.
105 */
106 int rc = DBGFR3MemReadString(pVM, 0, &pThis->AddrLinuxBanner, pszVersion, cchVersion);
107 if (RT_SUCCESS(rc))
108 {
109 char *pszEnd = RTStrEnd(pszVersion, cchVersion);
110 AssertReturn(pszEnd, VERR_BUFFER_OVERFLOW);
111 while ( pszEnd > pszVersion
112 && RT_C_IS_SPACE(pszEnd[-1]))
113 pszEnd--;
114 *pszEnd = '\0';
115 }
116 else
117 RTStrPrintf(pszVersion, cchVersion, "DBGFR3MemRead -> %Rrc", rc);
118
119 return rc;
120}
121
122
123/**
124 * @copydoc DBGFOSREG::pfnTerm
125 */
126static DECLCALLBACK(void) dbgDiggerLinuxTerm(PVM pVM, void *pvData)
127{
128 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
129 Assert(pThis->fValid);
130
131 pThis->fValid = false;
132}
133
134
135/**
136 * @copydoc DBGFOSREG::pfnRefresh
137 */
138static DECLCALLBACK(int) dbgDiggerLinuxRefresh(PVM pVM, void *pvData)
139{
140 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
141 NOREF(pThis);
142 Assert(pThis->fValid);
143
144 /*
145 * For now we'll flush and reload everything.
146 */
147 dbgDiggerLinuxTerm(pVM, pvData);
148 return dbgDiggerLinuxInit(pVM, pvData);
149}
150
151
152/**
153 * @copydoc DBGFOSREG::pfnInit
154 */
155static DECLCALLBACK(int) dbgDiggerLinuxInit(PVM pVM, void *pvData)
156{
157 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
158 Assert(!pThis->fValid);
159#if 0 /* later */
160 int rc;
161
162 /*
163 * Algorithm to find the ksymtab:
164 * 1. Find a known export string in kstrtab ("init_task", "enable_hlt" or something).
165 * 2. Search for the address its at, this should give you the corresponding ksymtab entry.
166 * 3. Search backwards assuming that kstrtab is corresponding to ksymtab.
167 */
168 DBGFADDRESS AddrKernelKsymTab;
169
170
171#endif
172 pThis->fValid = true;
173 return VINF_SUCCESS;
174}
175
176
177/**
178 * @copydoc DBGFOSREG::pfnProbe
179 */
180static DECLCALLBACK(bool) dbgDiggerLinuxProbe(PVM pVM, void *pvData)
181{
182 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
183
184 /*
185 * Look for "Linux version " at the start of the rodata segment.
186 * Hope that this comes before any message buffer or other similar string.
187 * .
188 * Note! Only Linux version 2.x.y, where x in {0..6}. .
189 */
190 for (unsigned i = 0; i < RT_ELEMENTS(g_au64LnxKernelAddresses); i++)
191 {
192 DBGFADDRESS KernelAddr;
193 DBGFR3AddrFromFlat(pVM, &KernelAddr, g_au64LnxKernelAddresses[i]);
194 DBGFADDRESS HitAddr;
195 static const uint8_t s_abLinuxVersion[] = "Linux version 2.";
196 int rc = DBGFR3MemScan(pVM, 0, &KernelAddr, LNX_MAX_KERNEL_SIZE, 1,
197 s_abLinuxVersion, sizeof(s_abLinuxVersion) - 1, &HitAddr);
198 if (RT_SUCCESS(rc))
199 {
200 char szTmp[128];
201 char const *pszY = &szTmp[sizeof(s_abLinuxVersion) - 1];
202 rc = DBGFR3MemReadString(pVM, 0, &HitAddr, szTmp, sizeof(szTmp));
203 if ( RT_SUCCESS(rc)
204 && *pszY >= '0'
205 && *pszY <= '6')
206 {
207 pThis->AddrKernelBase = KernelAddr;
208 pThis->AddrLinuxBanner = HitAddr;
209 return true;
210 }
211 }
212 }
213 return false;
214}
215
216
217/**
218 * @copydoc DBGFOSREG::pfnDestruct
219 */
220static DECLCALLBACK(void) dbgDiggerLinuxDestruct(PVM pVM, void *pvData)
221{
222
223}
224
225
226/**
227 * @copydoc DBGFOSREG::pfnConstruct
228 */
229static DECLCALLBACK(int) dbgDiggerLinuxConstruct(PVM pVM, void *pvData)
230{
231 return VINF_SUCCESS;
232}
233
234
235const DBGFOSREG g_DBGDiggerLinux =
236{
237 /* .u32Magic = */ DBGFOSREG_MAGIC,
238 /* .fFlags = */ 0,
239 /* .cbData = */ sizeof(DBGDIGGERLINUX),
240 /* .szName = */ "Linux",
241 /* .pfnConstruct = */ dbgDiggerLinuxConstruct,
242 /* .pfnDestruct = */ dbgDiggerLinuxDestruct,
243 /* .pfnProbe = */ dbgDiggerLinuxProbe,
244 /* .pfnInit = */ dbgDiggerLinuxInit,
245 /* .pfnRefresh = */ dbgDiggerLinuxRefresh,
246 /* .pfnTerm = */ dbgDiggerLinuxTerm,
247 /* .pfnQueryVersion = */ dbgDiggerLinuxQueryVersion,
248 /* .pfnQueryInterface = */ dbgDiggerLinuxQueryInterface,
249 /* .u32EndMagic = */ DBGFOSREG_MAGIC
250};
251
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