VirtualBox

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

Last change on this file since 52442 was 50665, checked in by vboxsync, 11 years ago

DBGC: add detection of Linux 3.x

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