vbox的更動 61558 路徑 trunk/src/VBox/Debugger
- 時間撮記:
- 2016-6-8 上午08:13:51 (8 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Debugger/DBGPlugInLinux.cpp
r61369 r61558 162 162 }; 163 163 164 static const uint8_t g_abLinuxVersion[] = "Linux version "; 164 165 165 166 /** … … 308 309 309 310 /** 310 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} 311 */ 312 static DECLCALLBACK(int) dbgDiggerLinuxIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages, 313 char *pszBuf, size_t cbBuf, size_t *pcbActual) 314 { 315 PDBGDIGGERLINUX pData = RT_FROM_MEMBER(pThis, DBGDIGGERLINUX, IDmesg); 316 317 if (cMessages < 1) 318 return VERR_INVALID_PARAMETER; 319 320 /* 321 * Resolve the symbols we need and read their values. 322 */ 323 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 324 RTDBGMOD hMod; 325 int rc = RTDbgAsModuleByName(hAs, "vmlinux", 0, &hMod); 311 * Returns whether the log buffer is a simple ascii buffer or a record based implementation 312 * based on the kernel version found. 313 * 314 * @returns Flag whether the log buffer is the simple ascii buffer. 315 * @param pThis The Linux digger data. 316 * @param pUVM The user mode VM handle. 317 */ 318 static bool dbgDiggerLinuxLogBufferIsAsciiBuffer(PDBGDIGGERLINUX pThis, PUVM pUVM) 319 { 320 char szTmp[128]; 321 char const *pszVer = &szTmp[sizeof(g_abLinuxVersion) - 1]; 322 323 RT_ZERO(szTmp); 324 int rc = DBGFR3MemReadString(pUVM, 0, &pThis->AddrLinuxBanner, szTmp, sizeof(szTmp) - 1); 325 if ( RT_SUCCESS(rc) 326 && RTStrVersionCompare(pszVer, "3.4") == -1) 327 return true; 328 329 return false; 330 } 331 332 /** 333 * Worker to get at the kernel log for pre 3.4 kernels where the log buffer was just a char buffer. 334 * 335 * @returns VBox status code. 336 * @param pThis The Linux digger data. 337 * @param pUVM The VM user mdoe handle. 338 * @param hMod The debug module handle. 339 * @param fFlags Flags reserved for future use, MBZ. 340 * @param cMessages The number of messages to retrieve, counting from the 341 * end of the log (i.e. like tail), use UINT32_MAX for all. 342 * @param pszBuf The output buffer. 343 * @param cbBuf The buffer size. 344 * @param pcbActual Where to store the number of bytes actually returned, 345 * including zero terminator. On VERR_BUFFER_OVERFLOW this 346 * holds the necessary buffer size. Optional. 347 */ 348 static int dbgDiggerLinuxLogBufferQueryAscii(PDBGDIGGERLINUX pThis, PUVM pUVM, RTDBGMOD hMod, 349 uint32_t fFlags, uint32_t cMessages, 350 char *pszBuf, size_t cbBuf, size_t *pcbActual) 351 { 352 int rc = VINF_SUCCESS; 353 RTGCPTR GCPtrLogBuf; 354 uint32_t cbLogBuf; 355 356 struct { void *pvVar; size_t cbHost, cbGuest; const char *pszSymbol; } aSymbols[] = 357 { 358 { &GCPtrLogBuf, sizeof(GCPtrLogBuf), pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf" }, 359 { &cbLogBuf, sizeof(cbLogBuf), sizeof(cbLogBuf), "log_buf_len" }, 360 }; 361 for (uint32_t i = 0; i < RT_ELEMENTS(aSymbols); i++) 362 { 363 RTDBGSYMBOL SymInfo; 364 rc = RTDbgModSymbolByName(hMod, aSymbols[i].pszSymbol, &SymInfo); 365 if (RT_SUCCESS(rc)) 366 { 367 RT_BZERO(aSymbols[i].pvVar, aSymbols[i].cbHost); 368 Assert(aSymbols[i].cbHost >= aSymbols[i].cbGuest); 369 DBGFADDRESS Addr; 370 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, 371 DBGFR3AddrFromFlat(pUVM, &Addr, (RTGCPTR)SymInfo.Value + pThis->AddrKernelBase.FlatPtr), 372 aSymbols[i].pvVar, aSymbols[i].cbGuest); 373 if (RT_SUCCESS(rc)) 374 continue; 375 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Reading '%s' at %RGv: %Rrc\n", aSymbols[i].pszSymbol, Addr.FlatPtr, rc)); 376 } 377 else 378 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error looking up '%s': %Rrc\n", aSymbols[i].pszSymbol, rc)); 379 rc = VERR_NOT_FOUND; 380 break; 381 } 382 326 383 if (RT_FAILURE(rc)) 384 return rc; 385 386 /* 387 * Check if the values make sense. 388 */ 389 if (pThis->f64Bit ? !LNX64_VALID_ADDRESS(GCPtrLogBuf) : !LNX32_VALID_ADDRESS(GCPtrLogBuf)) 390 { 391 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf' value %RGv is not valid.\n", GCPtrLogBuf)); 327 392 return VERR_NOT_FOUND; 328 RTDbgAsRelease(hAs); 329 393 } 394 if ( cbLogBuf < 4096 395 || !RT_IS_POWER_OF_TWO(cbLogBuf) 396 || cbLogBuf > 16*_1M) 397 { 398 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf_len' value %#x is not valid.\n", cbLogBuf)); 399 return VERR_NOT_FOUND; 400 } 401 402 /* 403 * Read the whole log buffer. 404 */ 405 uint8_t *pbLogBuf = (uint8_t *)RTMemAlloc(cbLogBuf); 406 if (!pbLogBuf) 407 { 408 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Failed to allocate %#x bytes for log buffer\n", cbLogBuf)); 409 return VERR_NO_MEMORY; 410 } 411 DBGFADDRESS Addr; 412 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, GCPtrLogBuf), pbLogBuf, cbLogBuf); 413 if (RT_FAILURE(rc)) 414 { 415 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error reading %#x bytes of log buffer at %RGv: %Rrc\n", 416 cbLogBuf, Addr.FlatPtr, rc)); 417 RTMemFree(pbLogBuf); 418 return VERR_NOT_FOUND; 419 } 420 421 /** @todo: Try to parse where the single messages start to make use of cMessages. */ 422 memcpy(&pszBuf[0], pbLogBuf, RT_MIN(cbBuf, cbLogBuf)); 423 424 /* Done with the buffer. */ 425 RTMemFree(pbLogBuf); 426 427 /* Set return size value. */ 428 if (pcbActual) 429 *pcbActual = RT_MIN(cbBuf, cbLogBuf); 430 431 return cbBuf <= cbLogBuf ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW; 432 } 433 434 /** 435 * Worker to get at the kernel log for post 3.4 kernels where the log buffer contains records. 436 * 437 * @returns VBox status code. 438 * @param pThis The Linux digger data. 439 * @param pUVM The VM user mdoe handle. 440 * @param hMod The debug module handle. 441 * @param fFlags Flags reserved for future use, MBZ. 442 * @param cMessages The number of messages to retrieve, counting from the 443 * end of the log (i.e. like tail), use UINT32_MAX for all. 444 * @param pszBuf The output buffer. 445 * @param cbBuf The buffer size. 446 * @param pcbActual Where to store the number of bytes actually returned, 447 * including zero terminator. On VERR_BUFFER_OVERFLOW this 448 * holds the necessary buffer size. Optional. 449 */ 450 static int dbgDiggerLinuxLogBufferQueryRecords(PDBGDIGGERLINUX pThis, PUVM pUVM, RTDBGMOD hMod, 451 uint32_t fFlags, uint32_t cMessages, 452 char *pszBuf, size_t cbBuf, size_t *pcbActual) 453 { 454 int rc = VINF_SUCCESS; 330 455 RTGCPTR GCPtrLogBuf; 331 456 uint32_t cbLogBuf; … … 335 460 struct { void *pvVar; size_t cbHost, cbGuest; const char *pszSymbol; } aSymbols[] = 336 461 { 337 { &GCPtrLogBuf, sizeof(GCPtrLogBuf), p Data->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf" },462 { &GCPtrLogBuf, sizeof(GCPtrLogBuf), pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf" }, 338 463 { &cbLogBuf, sizeof(cbLogBuf), sizeof(cbLogBuf), "log_buf_len" }, 339 464 { &idxFirst, sizeof(idxFirst), sizeof(idxFirst), "log_first_idx" }, … … 350 475 DBGFADDRESS Addr; 351 476 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, 352 DBGFR3AddrFromFlat(pUVM, &Addr, (RTGCPTR)SymInfo.Value + p Data->AddrKernelBase.FlatPtr),477 DBGFR3AddrFromFlat(pUVM, &Addr, (RTGCPTR)SymInfo.Value + pThis->AddrKernelBase.FlatPtr), 353 478 aSymbols[i].pvVar, aSymbols[i].cbGuest); 354 479 if (RT_SUCCESS(rc)) … … 372 497 idxFirst = 0; 373 498 idxNext = 0; 374 rc = dbgDiggerLinuxQueryLogBufferPtrs(pData, pUVM, hMod, &GCPtrLogBuf, &cbLogBuf); 375 376 /* Release the module in any case. */ 377 RTDbgModRelease(hMod); 378 499 rc = dbgDiggerLinuxQueryLogBufferPtrs(pThis, pUVM, hMod, &GCPtrLogBuf, &cbLogBuf); 379 500 if (RT_FAILURE(rc)) 380 501 return rc; … … 384 505 * Check if the values make sense. 385 506 */ 386 if (p Data->f64Bit ? !LNX64_VALID_ADDRESS(GCPtrLogBuf) : !LNX32_VALID_ADDRESS(GCPtrLogBuf))507 if (pThis->f64Bit ? !LNX64_VALID_ADDRESS(GCPtrLogBuf) : !LNX32_VALID_ADDRESS(GCPtrLogBuf)) 387 508 { 388 509 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: 'log_buf' value %RGv is not valid.\n", GCPtrLogBuf)); … … 543 664 *pcbActual = offDst; 544 665 666 if (offDst <= cbBuf) 667 return VINF_SUCCESS; 668 else 669 return VERR_BUFFER_OVERFLOW; 670 } 671 672 /** 673 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} 674 */ 675 static DECLCALLBACK(int) dbgDiggerLinuxIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages, 676 char *pszBuf, size_t cbBuf, size_t *pcbActual) 677 { 678 PDBGDIGGERLINUX pData = RT_FROM_MEMBER(pThis, DBGDIGGERLINUX, IDmesg); 679 680 if (cMessages < 1) 681 return VERR_INVALID_PARAMETER; 682 683 /* 684 * Resolve the symbols we need and read their values. 685 */ 686 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 687 RTDBGMOD hMod; 688 int rc = RTDbgAsModuleByName(hAs, "vmlinux", 0, &hMod); 689 if (RT_FAILURE(rc)) 690 return VERR_NOT_FOUND; 691 RTDbgAsRelease(hAs); 692 693 size_t cbActual; 694 /* 695 * Check whether the kernel log buffer is a simple char buffer or the newer 696 * record based implementation. 697 * The record based implementation was presumably introduced with kernel 3.4, 698 * see: http://thread.gmane.org/gmane.linux.kernel/1284184 699 */ 700 if (dbgDiggerLinuxLogBufferIsAsciiBuffer(pData, pUVM)) 701 rc = dbgDiggerLinuxLogBufferQueryAscii(pData, pUVM, hMod, fFlags, cMessages, pszBuf, cbBuf, &cbActual); 702 else 703 rc = dbgDiggerLinuxLogBufferQueryRecords(pData, pUVM, hMod, fFlags, cMessages, pszBuf, cbBuf, &cbActual); 704 705 /* Release the module in any case. */ 706 RTDbgModRelease(hMod); 707 708 if (RT_FAILURE(rc) && rc != VERR_BUFFER_OVERFLOW) 709 return rc; 710 711 if (pcbActual) 712 *pcbActual = cbActual; 713 545 714 /* 546 715 * All VBox strings are UTF-8 and bad things may in theory happen if we … … 549 718 * no defined code set in reality. 550 719 */ 551 if (offDst <= cbBuf) 552 { 553 pszBuf[offDst - 1] = '\0'; 720 if ( RT_SUCCESS(rc) 721 && cbActual <= cbBuf) 722 { 723 pszBuf[cbActual - 1] = '\0'; 554 724 RTStrPurgeEncoding(pszBuf); 555 725 return VINF_SUCCESS; … … 1330 1500 DBGFR3AddrFromFlat(pUVM, &KernelAddr, g_au64LnxKernelAddresses[i]); 1331 1501 DBGFADDRESS HitAddr; 1332 static const uint8_t s_abLinuxVersion[] = "Linux version ";1333 1502 int rc = DBGFR3MemScan(pUVM, 0, &KernelAddr, LNX_MAX_KERNEL_SIZE, 1, 1334 s_abLinuxVersion, sizeof(s_abLinuxVersion) - 1, &HitAddr);1503 g_abLinuxVersion, sizeof(g_abLinuxVersion) - 1, &HitAddr); 1335 1504 if (RT_SUCCESS(rc)) 1336 1505 { 1337 1506 char szTmp[128]; 1338 char const *pszX = &szTmp[sizeof( s_abLinuxVersion) - 1];1507 char const *pszX = &szTmp[sizeof(g_abLinuxVersion) - 1]; 1339 1508 rc = DBGFR3MemReadString(pUVM, 0, &HitAddr, szTmp, sizeof(szTmp)); 1340 1509 if ( RT_SUCCESS(rc)
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器