vbox的更動 64380 路徑 trunk/src/VBox/Debugger
- 時間撮記:
- 2016-10-24 下午12:39:30 (8 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Debugger/DBGPlugInFreeBsd.cpp
r64372 r64380 25 25 #include <VBox/vmm/dbgf.h> 26 26 #include <iprt/asm.h> 27 #include <iprt/ctype.h> 27 28 #include <iprt/mem.h> 28 29 #include <iprt/stream.h> … … 42 43 43 44 /** 45 * ELF headers union. 46 */ 47 typedef union ELFEHDRS 48 { 49 /** 32bit version of the ELF header. */ 50 Elf32_Ehdr Hdr32; 51 /** 64bit version of the ELF header. */ 52 Elf64_Ehdr Hdr64; 53 } ELFEHDRS; 54 /** Pointer to a ELF header union. */ 55 typedef ELFEHDRS *PELFEHDRS; 56 /** Pointer to const ELF header union. */ 57 typedef ELFEHDRS const *PCELFEHDRS; 58 59 /** 60 * ELF symbol entry union. 61 */ 62 typedef union ELFSYMS 63 { 64 /** 32bit version of the ELF section header. */ 65 Elf32_Sym Hdr32; 66 /** 64bit version of the ELF section header. */ 67 Elf64_Sym Hdr64; 68 } ELFSYMS; 69 /** Pointer to a ELF symbol entry union. */ 70 typedef ELFSYMS *PELFSYMS; 71 /** Pointer to const ELF symbol entry union. */ 72 typedef ELFSYMS const *PCELFSYMS; 73 74 /** 75 * Message buffer structure. 76 */ 77 typedef union FBSDMSGBUF 78 { 79 /** 32bit version. */ 80 struct 81 { 82 /** Message buffer pointer. */ 83 uint32_t msg_ptr; 84 /** Magic value to identify the structure. */ 85 uint32_t msg_magic; 86 /** Size of the buffer area. */ 87 uint32_t msg_size; 88 /** Write sequence number. */ 89 uint32_t msg_wseq; 90 /** Read sequence number. */ 91 uint32_t msg_rseq; 92 /** @todo: More fields which are not required atm. */ 93 } Hdr32; 94 /** 64bit version. */ 95 struct 96 { 97 /** Message buffer pointer. */ 98 uint64_t msg_ptr; 99 /** Magic value to identify the structure. */ 100 uint32_t msg_magic; 101 /** Size of the buffer area. */ 102 uint32_t msg_size; 103 /** Write sequence number. */ 104 uint32_t msg_wseq; 105 /** Read sequence number. */ 106 uint32_t msg_rseq; 107 /** @todo: More fields which are not required atm. */ 108 } Hdr64; 109 } FBSDMSGBUF; 110 /** Pointer to a message buffer structure. */ 111 typedef FBSDMSGBUF *PFBSDMSGBUF; 112 /** Pointer to a const message buffer structure. */ 113 typedef FBSDMSGBUF const *PCFBSDMSGBUF; 114 115 /** Magic value to identify the message buffer structure. */ 116 #define FBSD_MSGBUF_MAGIC UINT32_C(0x063062) 117 118 /** 44 119 * FreeBSD guest OS digger instance data. 45 120 */ … … 48 123 /** Whether the information is valid or not. 49 124 * (For fending off illegal interface method calls.) */ 50 bool fValid;125 bool fValid; 51 126 /** 64-bit/32-bit indicator. */ 52 bool f64Bit;127 bool f64Bit; 53 128 54 129 /** Address of the start of the kernel ELF image, 55 130 * set during probing. */ 56 DBGFADDRESS AddrKernelElfStart; 131 DBGFADDRESS AddrKernelElfStart; 132 /** Address of the the interpreter content aka "/red/herring". */ 133 DBGFADDRESS AddrKernelInterp; 134 /** Address of the start of the text section. */ 135 DBGFADDRESS AddrKernelText; 136 137 /** The kernel message log interface. */ 138 DBGFOSIDMESG IDmesg; 57 139 58 140 } DBGDIGGERFBSD; … … 70 152 71 153 /** Min kernel address (64bit). */ 72 #define FBSD64_MIN_KRNL_ADDR UINT64_C(0xFFFFF E0000000000)154 #define FBSD64_MIN_KRNL_ADDR UINT64_C(0xFFFFF80000000000) 73 155 /** Max kernel address (64bit). */ 74 156 #define FBSD64_MAX_KRNL_ADDR UINT64_C(0xFFFFFFFFFFF00000) … … 82 164 && (Addr) < FBSD64_MAX_KRNL_ADDR) 83 165 166 /** Validates a FreeBSD kernel address. */ 167 #define FBSD_VALID_ADDRESS(a_pThis, a_Addr) ((a_pThis)->f64Bit ? FBSD64_VALID_ADDRESS(a_Addr) : FBSD32_VALID_ADDRESS(a_Addr)) 168 84 169 /** Maximum offset from the start of the ELF image we look for the /red/herring .interp section content. */ 85 170 #define FBSD_MAX_INTERP_OFFSET _16K … … 87 172 #define FBSD_MAX_KERNEL_SIZE UINT32_C(0x0f000000) 88 173 174 /** Versioned and bitness wrapper. */ 175 #define FBSD_UNION(a_pThis, a_pUnion, a_Member) ((a_pThis)->f64Bit ? (a_pUnion)->Hdr64. a_Member : (a_pUnion)->Hdr32. a_Member ) 89 176 90 177 /********************************************************************************************************************************* … … 102 189 UINT64_C(0xffffffff80100000) 103 190 }; 191 /** Magic string which resides in the .interp section of the image. */ 192 static const uint8_t g_abNeedleInterp[] = "/red/herring"; 193 194 195 /** 196 * Load the symbols from the .dynsym and .dynstr sections given 197 * by their address in guest memory. 198 * 199 * @returns VBox status code. 200 * @param pThis The instance data. 201 * @param pUVM The user mode VM handle. 202 * @param pszName The image name. 203 * @param uKernelStart The kernel start address. 204 * @param cbKernel Size of the kernel image. 205 * @param pAddrDynsym Start address of the .dynsym section. 206 * @param cSymbols Number of symbols in the .dynsym section. 207 * @param pAddrDynstr Start address of the .dynstr section containing the symbol names. 208 * @param cbDynstr Size of the .dynstr section. 209 */ 210 static int dbgDiggerFreeBsdLoadSymbols(PDBGDIGGERFBSD pThis, PUVM pUVM, const char *pszName, RTGCUINTPTR uKernelStart, 211 size_t cbKernel, PDBGFADDRESS pAddrDynsym, uint32_t cSymbols, PDBGFADDRESS pAddrDynstr, 212 size_t cbDynstr) 213 { 214 LogFlowFunc(("pThis=%#p pszName=%s uKernelStart=%RGv cbKernel=%zu pAddrDynsym=%#p{%RGv} cSymbols=%u pAddrDynstr=%#p{%RGv} cbDynstr=%zu\n", 215 pThis, pszName, uKernelStart, cbKernel, pAddrDynsym, pAddrDynsym->FlatPtr, cSymbols, pAddrDynstr, pAddrDynstr->FlatPtr, cbDynstr)); 216 217 char *pbDynstr = (char *)RTMemAllocZ(cbDynstr); 218 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddrDynstr, pbDynstr, cbDynstr); 219 if (RT_SUCCESS(rc)) 220 { 221 uint32_t cbDynsymEnt = pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym); 222 uint8_t *pbDynsym = (uint8_t *)RTMemAllocZ(cSymbols * cbDynsymEnt); 223 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddrDynsym, pbDynsym, cSymbols * cbDynsymEnt); 224 if (RT_SUCCESS(rc)) 225 { 226 /* 227 * Create a module for the kernel. 228 */ 229 RTDBGMOD hMod; 230 rc = RTDbgModCreate(&hMod, pszName, cbKernel, 0 /*fFlags*/); 231 if (RT_SUCCESS(rc)) 232 { 233 rc = RTDbgModSetTag(hMod, DIG_FBSD_MOD_TAG); AssertRC(rc); 234 rc = VINF_SUCCESS; 235 236 /* 237 * Enumerate the symbols. 238 */ 239 uint32_t cLeft = cSymbols; 240 while (cLeft-- > 0 && RT_SUCCESS(rc)) 241 { 242 PCELFSYMS pSym = (PCELFSYMS)&pbDynsym[cLeft * cbDynsymEnt]; 243 uint32_t idxSymStr = FBSD_UNION(pThis, pSym, st_name); 244 uint8_t uType = FBSD_UNION(pThis, pSym, st_info); 245 RTGCUINTPTR AddrVal = FBSD_UNION(pThis, pSym, st_value); 246 size_t cbSymVal = FBSD_UNION(pThis, pSym, st_size); 247 248 /* Add it without the type char. */ 249 RT_NOREF(uType); 250 if (AddrVal <= uKernelStart + cbKernel) 251 { 252 rc = RTDbgModSymbolAdd(hMod, &pbDynstr[idxSymStr], RTDBGSEGIDX_RVA, AddrVal - uKernelStart, 253 cbSymVal, 0 /*fFlags*/, NULL); 254 if (RT_FAILURE(rc)) 255 { 256 if ( rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE 257 || rc == VERR_DBG_INVALID_RVA 258 || rc == VERR_DBG_ADDRESS_CONFLICT 259 || rc == VERR_DBG_DUPLICATE_SYMBOL) 260 { 261 Log2(("dbgDiggerFreeBsdLoadSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", 262 &pbDynstr[idxSymStr], rc)); 263 rc = VINF_SUCCESS; 264 } 265 else 266 Log(("dbgDiggerFreeBsdLoadSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", 267 &pbDynstr[idxSymStr], rc)); 268 } 269 } 270 } 271 272 /* 273 * Link the module into the address space. 274 */ 275 if (RT_SUCCESS(rc)) 276 { 277 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 278 if (hAs != NIL_RTDBGAS) 279 rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE); 280 else 281 rc = VERR_INTERNAL_ERROR; 282 RTDbgAsRelease(hAs); 283 } 284 else 285 Log(("dbgDiggerFreeBsdLoadSymbols: Failed: %Rrc\n", rc)); 286 RTDbgModRelease(hMod); 287 } 288 else 289 Log(("dbgDiggerFreeBsdLoadSymbols: RTDbgModCreate failed: %Rrc\n", rc)); 290 } 291 else 292 Log(("dbgDiggerFreeBsdLoadSymbols: Reading symbol table at %RGv failed: %Rrc\n", 293 pAddrDynsym->FlatPtr, rc)); 294 RTMemFree(pbDynsym); 295 } 296 else 297 Log(("dbgDiggerFreeBsdLoadSymbols: Reading symbol string table at %RGv failed: %Rrc\n", 298 pAddrDynstr->FlatPtr, rc)); 299 RTMemFree(pbDynstr); 300 301 LogFlowFunc(("returns %Rrc\n", rc)); 302 return rc; 303 } 304 305 /** 306 * Process the kernel image. 307 * 308 * @param pThis The instance data. 309 * @param pUVM The user mode VM handle. 310 * @param pszName The image name. 311 */ 312 static void dbgDiggerFreeBsdProcessKernelImage(PDBGDIGGERFBSD pThis, PUVM pUVM, const char *pszName) 313 { 314 /* 315 * FreeBSD has parts of the kernel ELF image in guest memory, starting with the 316 * ELF header and the content of the sections which are indicated to be loaded 317 * into memory (text, rodata, etc.) of course. Whats missing are the section headers 318 * which is understandable but unfortunate because it would make our life easier. 319 * 320 * All checked FreeBSD kernels so far have the following layout in the kernel: 321 * [.interp] - contiains the /red/herring string we used for probing earlier 322 * [.hash] - contains the hashes of the symbol names, 8 byte alignent 323 * [.dynsym] - contains the ELF symbol descriptors, 8 byte alignment 324 * [.dynstr] - contains the symbol names as a string table, 1 byte alignmnt 325 * [.text] - contains the executable code, 16 byte alignment. 326 * The sections are always adjacent (sans alignment) so we just parse the .hash section right after 327 * .interp, ELF states that it can contain 32bit or 64bit words but all observed kernels 328 * always use 32bit words. It contains two counters at the beginning which we can use to 329 * deduct the .hash section size and the beginning of .dynsym. 330 * .dynsym contains an array of symbol descriptors which have a fixed size depending on the 331 * guest bitness. 332 * Finding the end of .dynsym is not easily doable as there is no counter available (it lives 333 * in the section headers) at this point so we just have to check whether the record is valid 334 * and if not check if it contains an ASCII string which marks the start of the .dynstr section. 335 */ 336 337 /* Calculate the start of the .hash section. */ 338 DBGFADDRESS AddrHashStart = pThis->AddrKernelInterp; 339 DBGFR3AddrAdd(&AddrHashStart, sizeof(g_abNeedleInterp)); 340 AddrHashStart.FlatPtr = RT_ALIGN_GCPT(AddrHashStart.FlatPtr, 8, RTGCUINTPTR); 341 uint32_t au32Counters[2]; 342 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrHashStart, &au32Counters[0], sizeof(au32Counters)); 343 if (RT_SUCCESS(rc)) 344 { 345 size_t cbHash = (au32Counters[0] + au32Counters[1] + 2) * sizeof(uint32_t); 346 if (AddrHashStart.FlatPtr + cbHash < pThis->AddrKernelText.FlatPtr) /* Should be much smaller */ 347 { 348 DBGFADDRESS AddrDynsymStart = AddrHashStart; 349 uint32_t cSymbols = 0; 350 size_t cbKernel = 0; 351 RTGCUINTPTR uKernelStart = pThis->AddrKernelElfStart.FlatPtr; 352 353 DBGFR3AddrAdd(&AddrDynsymStart, cbHash); 354 AddrDynsymStart.FlatPtr = RT_ALIGN_GCPT(AddrDynsymStart.FlatPtr, 8, RTGCUINTPTR); 355 356 DBGFADDRESS AddrDynstrStart = AddrDynsymStart; 357 while (AddrDynstrStart.FlatPtr < pThis->AddrKernelText.FlatPtr) 358 { 359 size_t cbDynSymEnt = pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym); 360 uint8_t abBuf[_16K]; 361 size_t cbToRead = RT_MIN(sizeof(abBuf), pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr); 362 363 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrDynstrStart, &abBuf[0], cbToRead); 364 if (RT_FAILURE(rc)) 365 break; 366 367 for (unsigned i = 0; i < cbToRead / cbDynSymEnt; i++) 368 { 369 PCELFSYMS pSym = (PCELFSYMS)&abBuf[i * cbDynSymEnt]; 370 uint32_t idxSymStr = FBSD_UNION(pThis, pSym, st_name); 371 uint8_t uType = FBSD_UNION(pThis, pSym, st_info); 372 RTGCUINTPTR AddrVal = FBSD_UNION(pThis, pSym, st_value); 373 size_t cbSymVal = FBSD_UNION(pThis, pSym, st_size); 374 375 /* 376 * If the entry doesn't look valid check whether it contains an ASCII string, 377 * we then found the start of the .dynstr section. 378 */ 379 RT_NOREF(uType); 380 if ( ELF32_ST_TYPE(uType) != STT_NOTYPE 381 && ( !FBSD_VALID_ADDRESS(pThis, AddrVal) 382 || cbSymVal > FBSD_MAX_KERNEL_SIZE 383 || idxSymStr > pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr)) 384 { 385 LogFlowFunc(("Invalid symbol table entry found at %RGv\n", 386 AddrDynstrStart.FlatPtr + i * cbDynSymEnt)); 387 388 uint8_t *pbBuf = &abBuf[i * cbDynSymEnt]; 389 size_t cbLeft = cbToRead - i * cbDynSymEnt; 390 /* 391 * Check to the end of the buffer whether it contains only a certain set of 392 * ASCII characters and 0 terminators. 393 */ 394 while ( cbLeft > 0 395 && ( RT_C_IS_ALNUM(*pbBuf) 396 || *pbBuf == '_' 397 || *pbBuf == '\0' 398 || *pbBuf == '.')) 399 { 400 cbLeft--; 401 pbBuf++; 402 } 403 404 if (!cbLeft) 405 { 406 DBGFR3AddrAdd(&AddrDynstrStart, i * cbDynSymEnt); 407 LogFlowFunc(("Found all required section start addresses (.dynsym=%RGv cSymbols=%u, .dynstr=%RGv cb=%u)\n", 408 AddrDynsymStart.FlatPtr, cSymbols, AddrDynstrStart.FlatPtr, 409 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr)); 410 dbgDiggerFreeBsdLoadSymbols(pThis, pUVM, pszName, uKernelStart, cbKernel, &AddrDynsymStart, cSymbols, &AddrDynstrStart, 411 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr); 412 return; 413 } 414 else 415 LogFlowFunc(("Found invalid ASCII character in .dynstr section candidate: %#x\n", *pbBuf)); 416 } 417 else 418 { 419 cSymbols++; 420 if ( ELF32_ST_TYPE(uType) != STT_NOTYPE 421 && FBSD_VALID_ADDRESS(pThis, AddrVal)) 422 { 423 uKernelStart = RT_MIN(uKernelStart, AddrVal); 424 cbKernel = RT_MAX(cbKernel, AddrVal + cbSymVal - uKernelStart); 425 } 426 } 427 } 428 429 /* Don't account incomplete entries. */ 430 DBGFR3AddrAdd(&AddrDynstrStart, (cbToRead / cbDynSymEnt) * cbDynSymEnt); 431 } 432 } 433 else 434 LogFlowFunc((".hash section overlaps with .text section: %zu (expected much less than %u)\n", cbHash, 435 pThis->AddrKernelText.FlatPtr - AddrHashStart.FlatPtr)); 436 } 437 } 438 439 440 /** 441 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} 442 */ 443 static DECLCALLBACK(int) dbgDiggerFreeBsdIDmsg_QueryKernelLog(PDBGFOSIDMESG pThis, PUVM pUVM, uint32_t fFlags, uint32_t cMessages, 444 char *pszBuf, size_t cbBuf, size_t *pcbActual) 445 { 446 RT_NOREF1(fFlags); 447 PDBGDIGGERFBSD pData = RT_FROM_MEMBER(pThis, DBGDIGGERFBSD, IDmesg); 448 449 if (cMessages < 1) 450 return VERR_INVALID_PARAMETER; 451 452 /* Resolve the message buffer address from the msgbufp symbol. */ 453 RTDBGSYMBOL SymInfo; 454 int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "kernel!msgbufp", &SymInfo, NULL); 455 if (RT_SUCCESS(rc)) 456 { 457 DBGFADDRESS AddrMsgBuf; 458 459 /* Read the message buffer pointer. */ 460 RTGCPTR GCPtrMsgBufP = 0; 461 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, SymInfo.Value), 462 &GCPtrMsgBufP, pData->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t)); 463 if (RT_FAILURE(rc)) 464 { 465 Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: failed to read msgbufp at %RGv: %Rrc\n", AddrMsgBuf.FlatPtr, rc)); 466 return VERR_NOT_FOUND; 467 } 468 if (!FBSD_VALID_ADDRESS(pData, GCPtrMsgBufP)) 469 { 470 Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Invalid address for msgbufp: %RGv\n", GCPtrMsgBufP)); 471 return VERR_NOT_FOUND; 472 } 473 474 /* Read the structure. */ 475 FBSDMSGBUF MsgBuf; 476 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, GCPtrMsgBufP), 477 &MsgBuf, sizeof(MsgBuf)); 478 if (RT_SUCCESS(rc)) 479 { 480 RTGCUINTPTR AddrBuf = FBSD_UNION(pData, &MsgBuf, msg_ptr); 481 uint32_t cbMsgBuf = FBSD_UNION(pData, &MsgBuf, msg_size); 482 uint32_t uMsgBufSeqR = FBSD_UNION(pData, &MsgBuf, msg_rseq); 483 uint32_t uMsgBufSeqW = FBSD_UNION(pData, &MsgBuf, msg_wseq); 484 485 /* 486 * Validate the structure. 487 */ 488 if ( FBSD_UNION(pData, &MsgBuf, msg_magic) != FBSD_MSGBUF_MAGIC 489 || cbMsgBuf < UINT32_C(4096) 490 || cbMsgBuf > 16*_1M 491 || FBSD_UNION(pData, &MsgBuf, msg_rseq) > cbMsgBuf 492 || FBSD_UNION(pData, &MsgBuf, msg_wseq) > cbMsgBuf 493 || !FBSD_VALID_ADDRESS(pData, AddrBuf) ) 494 { 495 Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Invalid MsgBuf data: msg_magic=%#x msg_size=%#x msg_rseq=%#x msg_wseq=%#x msg_ptr=%RGv\n", 496 FBSD_UNION(pData, &MsgBuf, msg_magic), cbMsgBuf, uMsgBufSeqR, uMsgBufSeqW, AddrBuf)); 497 return VERR_INVALID_STATE; 498 } 499 500 /* 501 * Read the buffer. 502 */ 503 char *pchMsgBuf = (char *)RTMemAlloc(cbMsgBuf); 504 if (!pchMsgBuf) 505 { 506 Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Failed to allocate %#x bytes of memory for the log buffer\n", 507 cbMsgBuf)); 508 return VERR_INVALID_STATE; 509 } 510 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &AddrMsgBuf, AddrBuf), pchMsgBuf, cbMsgBuf); 511 if (RT_SUCCESS(rc)) 512 { 513 /* 514 * Copy it out raw. 515 */ 516 uint32_t offDst = 0; 517 if (uMsgBufSeqR < uMsgBufSeqW) 518 { 519 /* Single chunk between the read and write offsets. */ 520 uint32_t cbToCopy = uMsgBufSeqW - uMsgBufSeqR; 521 if (cbToCopy < cbBuf) 522 { 523 memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbToCopy); 524 pszBuf[cbToCopy] = '\0'; 525 rc = VINF_SUCCESS; 526 } 527 else 528 { 529 if (cbBuf) 530 { 531 memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbBuf - 1); 532 pszBuf[cbBuf - 1] = '\0'; 533 } 534 rc = VERR_BUFFER_OVERFLOW; 535 } 536 offDst = cbToCopy + 1; 537 } 538 else 539 { 540 /* Two chunks, read offset to end, start to write offset. */ 541 uint32_t cbFirst = cbMsgBuf - uMsgBufSeqR; 542 uint32_t cbSecond = uMsgBufSeqW; 543 if (cbFirst + cbSecond < cbBuf) 544 { 545 memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbFirst); 546 memcpy(&pszBuf[cbFirst], pchMsgBuf, cbSecond); 547 offDst = cbFirst + cbSecond; 548 pszBuf[offDst++] = '\0'; 549 rc = VINF_SUCCESS; 550 } 551 else 552 { 553 offDst = cbFirst + cbSecond + 1; 554 if (cbFirst < cbBuf) 555 { 556 memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbFirst); 557 memcpy(&pszBuf[cbFirst], pchMsgBuf, cbBuf - cbFirst); 558 pszBuf[cbBuf - 1] = '\0'; 559 } 560 else if (cbBuf) 561 { 562 memcpy(pszBuf, &pchMsgBuf[uMsgBufSeqR], cbBuf - 1); 563 pszBuf[cbBuf - 1] = '\0'; 564 } 565 rc = VERR_BUFFER_OVERFLOW; 566 } 567 } 568 569 if (pcbActual) 570 *pcbActual = offDst; 571 } 572 else 573 Log(("dbgDiggerFreeBsdIDmsg_QueryKernelLog: Error reading %#x bytes at %RGv: %Rrc\n", cbBuf, AddrBuf, rc)); 574 RTMemFree(pchMsgBuf); 575 } 576 else 577 LogFlowFunc(("Failed to read message buffer header: %Rrc\n", rc)); 578 } 579 580 return rc; 581 } 582 104 583 105 584 /** … … 108 587 static DECLCALLBACK(void *) dbgDiggerFreeBsdQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf) 109 588 { 110 RT_NOREF3(pUVM, pvData, enmIf); 111 return NULL; 589 RT_NOREF1(pUVM); 590 PDBGDIGGERFBSD pThis = (PDBGDIGGERFBSD)pvData; 591 switch (enmIf) 592 { 593 case DBGFOSINTERFACE_DMESG: 594 return &pThis->IDmesg; 595 596 default: 597 return NULL; 598 } 112 599 } 113 600 … … 121 608 Assert(pThis->fValid); 122 609 123 RT_NOREF4(pUVM, pThis, pszVersion, cchVersion); 124 125 return VERR_NOT_IMPLEMENTED; 610 RTDBGSYMBOL SymInfo; 611 int rc = DBGFR3AsSymbolByName(pUVM, DBGF_AS_KERNEL, "kernel!version", &SymInfo, NULL); 612 if (RT_SUCCESS(rc)) 613 { 614 DBGFADDRESS AddrVersion; 615 DBGFR3AddrFromFlat(pUVM, &AddrVersion, SymInfo.Value); 616 617 rc = DBGFR3MemReadString(pUVM, 0, &AddrVersion, pszVersion, cchVersion); 618 if (RT_SUCCESS(rc)) 619 { 620 char *pszEnd = RTStrEnd(pszVersion, cchVersion); 621 AssertReturn(pszEnd, VERR_BUFFER_OVERFLOW); 622 while ( pszEnd > pszVersion 623 && RT_C_IS_SPACE(pszEnd[-1])) 624 pszEnd--; 625 *pszEnd = '\0'; 626 } 627 else 628 RTStrPrintf(pszVersion, cchVersion, "DBGFR3MemReadString -> %Rrc", rc); 629 } 630 631 return rc; 126 632 } 127 633 … … 167 673 RT_NOREF1(pUVM); 168 674 675 dbgDiggerFreeBsdProcessKernelImage(pThis, pUVM, "kernel"); 169 676 pThis->fValid = true; 170 677 return VINF_SUCCESS; … … 204 711 * ELF header. 205 712 */ 206 static const uint8_t s_abNeedleInterp[] = "/red/herring";207 713 DBGFADDRESS HitAddrInterp; 208 714 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &HitAddr, FBSD_MAX_INTERP_OFFSET, 1, 209 s_abNeedleInterp, sizeof(s_abNeedleInterp), &HitAddrInterp);715 g_abNeedleInterp, sizeof(g_abNeedleInterp), &HitAddrInterp); 210 716 if (RT_SUCCESS(rc)) 211 717 { … … 237 743 pThis->f64Bit = ElfHdr.Hdr32.e_ident[EI_CLASS] == ELFCLASS64; 238 744 pThis->AddrKernelElfStart = HitAddr; 745 pThis->AddrKernelInterp = HitAddrInterp; 746 pThis->AddrKernelText.FlatPtr = FBSD_UNION(pThis, &ElfHdr, e_entry); 747 LogFunc(("Found %s FreeBSD kernel at %RGv (.interp section at %RGv, .text section at %RGv)\n", 748 pThis->f64Bit ? "amd64" : "i386", pThis->AddrKernelElfStart.FlatPtr, 749 pThis->AddrKernelInterp.FlatPtr, pThis->AddrKernelText.FlatPtr)); 239 750 return true; 240 751 } … … 271 782 static DECLCALLBACK(int) dbgDiggerFreeBsdConstruct(PUVM pUVM, void *pvData) 272 783 { 273 RT_NOREF2(pUVM, pvData); 784 RT_NOREF1(pUVM); 785 PDBGDIGGERFBSD pThis = (PDBGDIGGERFBSD)pvData; 786 787 pThis->fValid = false; 788 pThis->f64Bit = false; 789 pThis->IDmesg.u32Magic = DBGFOSIDMESG_MAGIC; 790 pThis->IDmesg.pfnQueryKernelLog = dbgDiggerFreeBsdIDmsg_QueryKernelLog; 791 pThis->IDmesg.u32EndMagic = DBGFOSIDMESG_MAGIC; 792 274 793 return VINF_SUCCESS; 275 794 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器