vbox的更動 54218 路徑 trunk/src/VBox/Debugger
- 時間撮記:
- 2015-2-16 下午03:17:05 (10 年 以前)
- 位置:
- trunk/src/VBox/Debugger
- 檔案:
-
- 修改 3 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Debugger/DBGCCommands.cpp
r51957 r54218 52 52 static FNDBGCCMD dbgcCmdStop; 53 53 static FNDBGCCMD dbgcCmdDetect; 54 static FNDBGCCMD dbgcCmdDmesg; 54 55 static FNDBGCCMD dbgcCmdCpu; 55 56 static FNDBGCCMD dbgcCmdInfo; … … 109 110 110 111 112 /** 'dmesg' arguments. */ 113 static const DBGCVARDESC g_aArgDmesg[] = 114 { 115 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */ 116 { 0, 1, DBGCVAR_CAT_NUMBER_NO_RANGE, 0, "messages", "Limit the output to the last N messages. (optional)" }, 117 }; 118 119 111 120 /** 'help' arguments. */ 112 121 static const DBGCVARDESC g_aArgHelp[] = … … 232 241 { "format", 1, 1, &g_aArgAny[0], RT_ELEMENTS(g_aArgAny), 0, dbgcCmdFormat, "", "Evaluates an expression and formats it." }, 233 242 { "detect", 0, 0, NULL, 0, 0, dbgcCmdDetect, "", "Detects or re-detects the guest os and starts the OS specific digger." }, 243 { "dmesg", 0, 1, &g_aArgDmesg[0], RT_ELEMENTS(g_aArgDmesg), 0, dbgcCmdDmesg, "[N last messages]", "Displays the guest os kernel messages, if available." }, 234 244 { "harakiri", 0, 0, NULL, 0, 0, dbgcCmdHarakiri, "", "Kills debugger process." }, 235 245 { "help", 0, ~0U, &g_aArgHelp[0], RT_ELEMENTS(g_aArgHelp), 0, dbgcCmdHelp, "[cmd/op [..]]", "Display help. For help about info items try 'info help'." }, … … 998 1008 rc = DBGCCmdHlpPrintf(pCmdHlp, "Unable to figure out which guest OS it is, sorry.\n"); 999 1009 NOREF(pCmd); NOREF(paArgs); 1010 return rc; 1011 } 1012 1013 1014 /** 1015 * @interface_method_impl{FNDBCCMD, The 'dmesg' command.} 1016 */ 1017 static DECLCALLBACK(int) dbgcCmdDmesg(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs) 1018 { 1019 /* check that the parser did what it's supposed to do. */ 1020 if (cArgs > 1) 1021 return DBGCCmdHlpPrintf(pCmdHlp, "parser error\n"); 1022 uint32_t cMessages = UINT32_MAX; 1023 if (cArgs == 1) 1024 { 1025 if (paArgs[0].enmType != DBGCVAR_TYPE_NUMBER) 1026 return DBGCCmdHlpPrintf(pCmdHlp, "parser error\n"); 1027 cMessages = paArgs[0].u.u64Number <= UINT32_MAX ? (uint32_t)paArgs[0].u.u64Number : UINT32_MAX; 1028 } 1029 1030 /* 1031 * Query the interface. 1032 */ 1033 int rc; 1034 PDBGFOSIDMESG pDmesg = (PDBGFOSIDMESG)DBGFR3OSQueryInterface(pUVM, DBGFOSINTERFACE_DMESG); 1035 if (pDmesg) 1036 { 1037 size_t cbActual; 1038 size_t cbBuf = _512K; 1039 char *pszBuf = (char *)RTMemAlloc(cbBuf); 1040 if (pszBuf) 1041 { 1042 rc = pDmesg->pfnQueryKernelLog(pDmesg, pUVM, 0 /*fFlags*/, cMessages, pszBuf, cbBuf, &cbActual); 1043 1044 uint32_t cTries = 10; 1045 while (rc == VERR_BUFFER_OVERFLOW && cbBuf < 16*_1M && cTries-- > 0) 1046 { 1047 RTMemFree(pszBuf); 1048 cbBuf = RT_ALIGN_Z(cbActual + _4K, _4K); 1049 pszBuf = (char *)RTMemAlloc(cbBuf); 1050 if (RT_UNLIKELY(!pszBuf)) 1051 { 1052 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Error allocating %#zu bytes.\n", cbBuf); 1053 break; 1054 } 1055 rc = pDmesg->pfnQueryKernelLog(pDmesg, pUVM, 0 /*fFlags*/, cMessages, pszBuf, cbBuf, &cbActual); 1056 } 1057 if (RT_SUCCESS(rc)) 1058 rc = DBGCCmdHlpPrintf(pCmdHlp, "%s\n", pszBuf); 1059 else if (rc == VERR_BUFFER_OVERFLOW && pszBuf) 1060 rc = DBGCCmdHlpPrintf(pCmdHlp, "%s\nWarning: incomplete\n", pszBuf); 1061 else 1062 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Error allocating %#zu bytes.\n", cbBuf); 1063 } 1064 else 1065 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "Error allocating %#zu bytes.\n", cbBuf); 1066 } 1067 else 1068 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "The dmesg interface isn't implemented by guest OS.\n"); 1000 1069 return rc; 1001 1070 } -
trunk/src/VBox/Debugger/DBGPlugInLinux.cpp
r54213 r54218 81 81 DBGFADDRESS AddrKernelTokenIndex; 82 82 83 /** The kernel message log interface. */ 84 DBGFOSIDMESG IDmesg; 83 85 } DBGDIGGERLINUX; 84 86 /** Pointer to the linux guest OS digger instance data. */ 85 87 typedef DBGDIGGERLINUX *PDBGDIGGERLINUX; 88 89 90 /** 91 * The current printk_log structure. 92 */ 93 typedef struct LNXPRINTKHDR 94 { 95 /** Monotonic timestamp. */ 96 uint64_t nsTimestamp; 97 /** The total size of this message record. */ 98 uint16_t cbTotal; 99 /** The size of the text part (immediately follows the header). */ 100 uint16_t cbText; 101 /** The size of the optional dictionary part (follows the text). */ 102 uint16_t cbDict; 103 /** The syslog facility number. */ 104 uint8_t bFacility; 105 /** First 5 bits are internal flags, next 3 bits are log level. */ 106 uint8_t fFlagsAndLevel; 107 } LNXPRINTKHDR; 108 AssertCompileSize(LNXPRINTKHDR, 2*sizeof(uint64_t)); 109 /** Pointer to linux printk_log header. */ 110 typedef LNXPRINTKHDR *PLNXPRINTKHDR; 111 /** Pointer to linux const printk_log header. */ 112 typedef LNXPRINTKHDR const *PCLNXPRINTKHDR; 86 113 87 114 … … 113 140 #define LNX_MAX_KALLSYMS_TOKEN_LEN UINT16_C(32) 114 141 115 116 142 /** Module tag for linux ('linuxmod' on little endian ASCII systems). */ 117 143 #define DIG_LNX_MOD_TAG UINT64_C(0x545f5d78758e898c) … … 137 163 138 164 /** 165 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} 166 */ 167 static DECLCALLBACK(int) dbgDiggerLinuxIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages, 168 char *pszBuf, size_t cbBuf, size_t *pcbActual) 169 { 170 PDBGDIGGERLINUX pData = RT_FROM_MEMBER(pThis, DBGDIGGERLINUX, IDmesg); 171 172 if (cMessages < 1) 173 return VERR_INVALID_PARAMETER; 174 175 /* 176 * Resolve the symbols we need and read their values. 177 */ 178 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 179 RTDBGMOD hMod; 180 int rc = RTDbgAsModuleByName(hAs, "vmlinux", 0, &hMod); 181 if (RT_FAILURE(rc)) 182 return VERR_NOT_FOUND; 183 RTDbgAsRelease(hAs); 184 185 RTGCPTR GCPtrLogBuf; 186 uint32_t cbLogBuf; 187 uint32_t idxFirst; 188 uint32_t idxNext; 189 190 struct { void *pvVar; uint32_t cbHost, cbGuest; const char *pszSymbol; } aSymbols[] = 191 { 192 { &GCPtrLogBuf, sizeof(GCPtrLogBuf), pData->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf" }, 193 { &cbLogBuf, sizeof(cbLogBuf), sizeof(cbLogBuf), "log_buf_len" }, 194 { &idxFirst, sizeof(idxFirst), sizeof(idxFirst), "log_first_idx" }, 195 { &idxNext, sizeof(idxNext), sizeof(idxNext), "log_next_idx" }, 196 }; 197 for (uint32_t i = 0; i < RT_ELEMENTS(aSymbols); i++) 198 { 199 RTDBGSYMBOL SymInfo; 200 rc = RTDbgModSymbolByName(hMod, aSymbols[i].pszSymbol, &SymInfo); 201 if (RT_SUCCESS(rc)) 202 { 203 RT_BZERO(aSymbols[i].pvVar, aSymbols[i].cbHost); 204 Assert(aSymbols[i].cbHost >= aSymbols[i].cbGuest); 205 DBGFADDRESS Addr; 206 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, 207 DBGFR3AddrFromFlat(pUVM, &Addr, (RTGCPTR)SymInfo.Value + pData->AddrKernelBase.FlatPtr), 208 aSymbols[i].pvVar, aSymbols[i].cbGuest); 209 if (RT_SUCCESS(rc)) 210 continue; 211 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Reading '%s' at %RGv: %Rrc\n", aSymbols[i].pszSymbol, Addr.FlatPtr, rc)); 212 } 213 else 214 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error looking up '%s': %Rrc\n", aSymbols[i].pszSymbol, rc)); 215 RTDbgModRelease(hMod); 216 return VERR_NOT_FOUND; 217 } 218 219 /* 220 * Check if the values make sense. 221 */ 222 if (pData->f64Bit ? !LNX64_VALID_ADDRESS(GCPtrLogBuf) : !LNX32_VALID_ADDRESS(GCPtrLogBuf)) 223 { 224 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf' value %RGv is not valid.\n", GCPtrLogBuf)); 225 return VERR_NOT_FOUND; 226 } 227 if ( cbLogBuf < 4096 228 || !RT_IS_POWER_OF_TWO(cbLogBuf) 229 || cbLogBuf > 16*_1M) 230 { 231 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf_len' value %#x is not valid.\n", cbLogBuf)); 232 return VERR_NOT_FOUND; 233 } 234 uint32_t const cbLogAlign = 4; 235 if ( idxFirst > cbLogBuf - sizeof(LNXPRINTKHDR) 236 || (idxFirst & (cbLogAlign - 1)) != 0) 237 { 238 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_first_idx' value %#x is not valid.\n", idxFirst)); 239 return VERR_NOT_FOUND; 240 } 241 if ( idxNext > cbLogBuf - sizeof(LNXPRINTKHDR) 242 || (idxNext & (cbLogAlign - 1)) != 0) 243 { 244 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_next_idx' value %#x is not valid.\n", idxNext)); 245 return VERR_NOT_FOUND; 246 } 247 248 /* 249 * Read the whole log buffer. 250 */ 251 uint8_t *pbLogBuf = (uint8_t *)RTMemAlloc(cbLogBuf); 252 if (!pbLogBuf) 253 { 254 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Failed to allocate %#x bytes for log buffer\n", cbLogBuf)); 255 return VERR_NO_MEMORY; 256 } 257 DBGFADDRESS Addr; 258 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, GCPtrLogBuf), pbLogBuf, cbLogBuf); 259 if (RT_FAILURE(rc)) 260 { 261 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error reading %#x bytes of log buffer at %RGv: %Rrc\n", 262 cbLogBuf, Addr.FlatPtr, rc)); 263 RTMemFree(pbLogBuf); 264 return VERR_NOT_FOUND; 265 } 266 267 /* 268 * Count the messages in the buffer while doing some basic validation. 269 */ 270 uint32_t const cbUsed = idxFirst == idxNext ? cbLogBuf /* could be empty... */ 271 : idxFirst < idxNext ? idxNext - idxFirst : cbLogBuf - idxFirst + idxNext; 272 uint32_t cbLeft = cbUsed; 273 uint32_t offCur = idxFirst; 274 uint32_t cLogMsgs = 0; 275 276 while (cbLeft > 0) 277 { 278 PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 279 if (!pHdr->cbTotal) 280 { 281 /* Wrap around packet, most likely... */ 282 if (cbLogBuf - offCur >= cbLeft) 283 break; 284 offCur = 0; 285 pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 286 } 287 if (RT_UNLIKELY( pHdr->cbTotal > cbLogBuf - sizeof(*pHdr) - offCur 288 || pHdr->cbTotal > cbLeft 289 || (pHdr->cbTotal & (cbLogAlign - 1)) != 0 290 || pHdr->cbTotal < (uint32_t)pHdr->cbText + (uint32_t)pHdr->cbDict + sizeof(*pHdr) )) 291 { 292 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Invalid printk_log record at %#x: cbTotal=%#x cbText=%#x cbDict=%#x cbLogBuf=%#x cbLeft=%#x\n", 293 offCur, pHdr->cbTotal, pHdr->cbText, pHdr->cbDict, cbLogBuf, cbLeft)); 294 rc = VERR_INVALID_STATE; 295 break; 296 } 297 298 if (pHdr->cbText > 0) 299 cLogMsgs++; 300 301 /* next */ 302 offCur += pHdr->cbTotal; 303 cbLeft -= pHdr->cbTotal; 304 } 305 if (RT_FAILURE(rc)) 306 { 307 RTMemFree(pbLogBuf); 308 return rc; 309 } 310 311 /* 312 * Copy the messages into the output buffer. 313 */ 314 offCur = idxFirst; 315 cbLeft = cbUsed; 316 317 /* Skip messages that the caller doesn't want. */ 318 if (cMessages < cLogMsgs) 319 { 320 uint32_t cToSkip = cLogMsgs - cMessages; 321 while (cToSkip > 0) 322 { 323 PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 324 if (!pHdr->cbTotal) 325 { 326 offCur = 0; 327 pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 328 } 329 if (pHdr->cbText > 0) 330 cToSkip--; 331 332 /* next */ 333 offCur += pHdr->cbTotal; 334 cbLeft -= pHdr->cbTotal; 335 } 336 } 337 338 /* Now copy the messages. */ 339 size_t offDst = 0; 340 while (cbLeft > 0) 341 { 342 PCLNXPRINTKHDR pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 343 if (!pHdr->cbTotal) 344 { 345 if (cbLogBuf - offCur >= cbLeft) 346 break; 347 offCur = 0; 348 pHdr = (PCLNXPRINTKHDR)&pbLogBuf[offCur]; 349 } 350 351 if (pHdr->cbText > 0) 352 { 353 char *pchText = (char *)(pHdr + 1); 354 size_t cchText = RTStrNLen(pchText, pHdr->cbText); 355 if (offDst + cchText < cbBuf) 356 { 357 memcpy(&pszBuf[offDst], pHdr + 1, cchText); 358 pszBuf[offDst + cchText] = '\n'; 359 } 360 else if (offDst < cbBuf) 361 memcpy(&pszBuf[offDst], pHdr + 1, cbBuf - offDst); 362 offDst += cchText + 1; 363 } 364 365 /* next */ 366 offCur += pHdr->cbTotal; 367 cbLeft -= pHdr->cbTotal; 368 } 369 370 /* Done with the buffer. */ 371 RTMemFree(pbLogBuf); 372 373 /* Make sure we've reserved a char for the terminator. */ 374 if (!offDst) 375 offDst = 1; 376 377 /* Set return size value. */ 378 if (pcbActual) 379 *pcbActual = offDst; 380 381 /* 382 * All VBox strings are UTF-8 and bad things may in theory happen if we 383 * pass bad UTF-8 to code which assumes it's all valid. So, we enforce 384 * UTF-8 upon the guest kernel messages here even if they (probably) have 385 * no defined code set in reality. 386 */ 387 if (offDst <= cbBuf) 388 { 389 pszBuf[offDst - 1] = '\0'; 390 RTStrPurgeEncoding(pszBuf); 391 return VINF_SUCCESS; 392 } 393 394 if (cbBuf) 395 { 396 pszBuf[cbBuf - 1] = '\0'; 397 RTStrPurgeEncoding(pszBuf); 398 } 399 return VERR_BUFFER_OVERFLOW; 400 } 401 402 403 /** 139 404 * @copydoc DBGFOSREG::pfnQueryInterface 140 405 */ 141 406 static DECLCALLBACK(void *) dbgDiggerLinuxQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf) 142 407 { 143 return NULL; 408 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData; 409 switch (enmIf) 410 { 411 case DBGFOSINTERFACE_DMESG: 412 return &pThis->IDmesg; 413 414 default: 415 return NULL; 416 } 144 417 } 145 418 … … 948 1221 static DECLCALLBACK(int) dbgDiggerLinuxConstruct(PUVM pUVM, void *pvData) 949 1222 { 1223 PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData; 1224 pThis->IDmesg.u32Magic = DBGFOSIDMESG_MAGIC; 1225 pThis->IDmesg.pfnQueryKernelLog = dbgDiggerLinuxIDmsg_QueryKernelLog; 1226 pThis->IDmesg.u32EndMagic = DBGFOSIDMESG_MAGIC; 1227 950 1228 return VINF_SUCCESS; 951 1229 } -
trunk/src/VBox/Debugger/testcase/tstDBGCStubs.cpp
r48946 r54218 294 294 return VERR_INTERNAL_ERROR; 295 295 } 296 VMMR3DECL(void *) DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf) 297 { 298 return NULL; 299 } 296 300 297 301 VMMR3DECL(int) DBGFR3SelQueryInfo(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo)
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器