Changeset 77146 in vbox
- Timestamp:
- Feb 3, 2019 8:59:09 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 128616
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGPlugInFreeBsd.cpp
r76553 r77146 42 42 * Structures and Typedefs * 43 43 *********************************************************************************************************************************/ 44 45 /** 46 * FreeBSD .dynstr and .dynsym location probing state. 47 */ 48 typedef enum FBSDPROBESTATE 49 { 50 /** Invalid state. */ 51 FBSDPROBESTATE_INVALID = 0, 52 /** Searching for the end of the .dynstr section (terminator). */ 53 FBSDPROBESTATE_DYNSTR_END, 54 /** Last symbol was a symbol terminator character. */ 55 FBSDPROBESTATE_DYNSTR_SYM_TERMINATOR, 56 /** Last symbol was a symbol character. */ 57 FBSDPROBESTATE_DYNSTR_SYM_CHAR, 58 } FBSDPROBESTATE; 44 59 45 60 /** … … 218 233 pThis, pszName, uKernelStart, cbKernel, pAddrDynsym, pAddrDynsym->FlatPtr, cSymbols, pAddrDynstr, pAddrDynstr->FlatPtr, cbDynstr)); 219 234 220 char *pbDynstr = (char *)RTMemAllocZ(cbDynstr );235 char *pbDynstr = (char *)RTMemAllocZ(cbDynstr + 1); /* Extra terminator. */ 221 236 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pAddrDynstr, pbDynstr, cbDynstr); 222 237 if (RT_SUCCESS(rc)) … … 251 266 /* Add it without the type char. */ 252 267 RT_NOREF(uType); 253 if (AddrVal <= uKernelStart + cbKernel) 268 if ( AddrVal <= uKernelStart + cbKernel 269 && idxSymStr < cbDynstr) 254 270 { 255 271 rc = RTDbgModSymbolAdd(hMod, &pbDynstr[idxSymStr], RTDBGSEGIDX_RVA, AddrVal - uKernelStart, … … 322 338 * 323 339 * All checked FreeBSD kernels so far have the following layout in the kernel: 324 * [.interp] - contiains the /red/herring string we used for probing earlier 325 * [.hash] - contains the hashes of the symbol names, 8 byte alignment on 64bit, 4 byte on 32bit 326 * [.dynsym] - contains the ELF symbol descriptors, 8 byte alignment, 4 byte on 32bit 327 * [.dynstr] - contains the symbol names as a string table, 1 byte alignmnt 328 * [.text] - contains the executable code, 16 byte alignment. 329 * The sections are always adjacent (sans alignment) so we just parse the .hash section right after 330 * .interp, ELF states that it can contain 32bit or 64bit words but all observed kernels 331 * always use 32bit words. It contains two counters at the beginning which we can use to 332 * deduct the .hash section size and the beginning of .dynsym. 333 * .dynsym contains an array of symbol descriptors which have a fixed size depending on the 334 * guest bitness. 335 * Finding the end of .dynsym is not easily doable as there is no counter available (it lives 336 * in the section headers) at this point so we just have to check whether the record is valid 337 * and if not check if it contains an ASCII string which marks the start of the .dynstr section. 340 * [.interp] - contains the /red/herring string we used for probing earlier 341 * [.hash] - contains the hashes of the symbol names, 8 byte alignment on 64bit, 4 byte on 32bit 342 * [.gnu.hash] - GNU hash section. (introduced somewhere between 10.0 and 12.0 @todo Find out when exactly) 343 * [.dynsym] - contains the ELF symbol descriptors, 8 byte alignment, 4 byte on 32bit 344 * [.dynstr] - contains the symbol names as a string table, 1 byte alignmnt 345 * [.text] - contains the executable code, 16 byte alignment. 346 * 347 * To find the start of the .dynsym and .dynstr sections we scan backwards from the start of the .text section 348 * and check for all characters allowed for symbol names and count the amount of symbols found. When the start of the 349 * .dynstr section is reached the number of entries in .dynsym is known and we can deduce the start address. 350 * 351 * This applied to the old code before the FreeBSD kernel introduced the .gnu.hash section 352 * (keeping it here for informational pruposes): 353 * The sections are always adjacent (sans alignment) so we just parse the .hash section right after 354 * .interp, ELF states that it can contain 32bit or 64bit words but all observed kernels 355 * always use 32bit words. It contains two counters at the beginning which we can use to 356 * deduct the .hash section size and the beginning of .dynsym. 357 * .dynsym contains an array of symbol descriptors which have a fixed size depending on the 358 * guest bitness. 359 * Finding the end of .dynsym is not easily doable as there is no counter available (it lives 360 * in the section headers) at this point so we just have to check whether the record is valid 361 * and if not check if it contains an ASCII string which marks the start of the .dynstr section. 338 362 */ 339 363 364 #if 0 365 DBGFADDRESS AddrInterpEnd = pThis->AddrKernelInterp; 366 DBGFR3AddrAdd(&AddrInterpEnd, sizeof(g_abNeedleInterp)); 367 368 DBGFADDRESS AddrCur = pThis->AddrKernelText; 369 int rc = VINF_SUCCESS; 370 uint32_t cSymbols = 0; 371 size_t cbKernel = 512 * _1M; 372 RTGCUINTPTR uKernelStart = pThis->AddrKernelElfStart.FlatPtr; 373 FBSDPROBESTATE enmState = FBSDPROBESTATE_DYNSTR_END; /* Start searching for the end of the .dynstr section. */ 374 375 while (AddrCur.FlatPtr > AddrInterpEnd.FlatPtr) 376 { 377 char achBuf[_16K]; 378 size_t cbToRead = RT_MIN(sizeof(achBuf), AddrCur.FlatPtr - AddrInterpEnd.FlatPtr); 379 380 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrSub(&AddrCur, cbToRead), &achBuf[0], cbToRead); 381 if (RT_FAILURE(rc)) 382 break; 383 384 for (unsigned i = cbToRead; i > 0; i--) 385 { 386 char ch = achBuf[i - 1]; 387 388 switch (enmState) 389 { 390 case FBSDPROBESTATE_DYNSTR_END: 391 { 392 if (ch != '\0') 393 enmState = FBSDPROBESTATE_DYNSTR_SYM_CHAR; 394 break; 395 } 396 case FBSDPROBESTATE_DYNSTR_SYM_TERMINATOR: 397 { 398 if ( RT_C_IS_ALNUM(ch) 399 || ch == '_' 400 || ch == '.') 401 enmState = FBSDPROBESTATE_DYNSTR_SYM_CHAR; 402 else 403 { 404 /* Two consecutive terminator symbols mean end of .dynstr section. */ 405 DBGFR3AddrAdd(&AddrCur, i); 406 DBGFADDRESS AddrDynstrStart = AddrCur; 407 DBGFADDRESS AddrDynsymStart = AddrCur; 408 DBGFR3AddrSub(&AddrDynsymStart, cSymbols * (pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf64_Sym))); 409 LogFlowFunc(("Found all required section start addresses (.dynsym=%RGv cSymbols=%u, .dynstr=%RGv cb=%u)\n", 410 AddrDynsymStart.FlatPtr, cSymbols, AddrDynstrStart.FlatPtr, 411 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr)); 412 dbgDiggerFreeBsdLoadSymbols(pThis, pUVM, pszName, uKernelStart, cbKernel, &AddrDynsymStart, cSymbols, &AddrDynstrStart, 413 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr); 414 return; 415 } 416 break; 417 } 418 case FBSDPROBESTATE_DYNSTR_SYM_CHAR: 419 { 420 if ( !RT_C_IS_ALNUM(ch) 421 && ch != '_' 422 && ch != '.') 423 { 424 /* Non symbol character. */ 425 if (ch == '\0') 426 { 427 enmState = FBSDPROBESTATE_DYNSTR_SYM_TERMINATOR; 428 cSymbols++; 429 } 430 else 431 { 432 /* Indicates the end of the .dynstr section. */ 433 DBGFR3AddrAdd(&AddrCur, i); 434 DBGFADDRESS AddrDynstrStart = AddrCur; 435 DBGFADDRESS AddrDynsymStart = AddrCur; 436 DBGFR3AddrSub(&AddrDynsymStart, cSymbols * (pThis->f64Bit ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym))); 437 LogFlowFunc(("Found all required section start addresses (.dynsym=%RGv cSymbols=%u, .dynstr=%RGv cb=%u)\n", 438 AddrDynsymStart.FlatPtr, cSymbols, AddrDynstrStart.FlatPtr, 439 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr)); 440 dbgDiggerFreeBsdLoadSymbols(pThis, pUVM, pszName, uKernelStart, cbKernel, &AddrDynsymStart, cSymbols, &AddrDynstrStart, 441 pThis->AddrKernelText.FlatPtr - AddrDynstrStart.FlatPtr); 442 return; 443 } 444 } 445 break; 446 } 447 default: 448 AssertFailedBreak(); 449 } 450 } 451 } 452 453 LogFlow(("Failed to find valid .dynsym and .dynstr sections (%Rrc), can't load kernel symbols\n", rc)); 454 #else 340 455 /* Calculate the start of the .hash section. */ 341 456 DBGFADDRESS AddrHashStart = pThis->AddrKernelInterp; … … 438 553 pThis->AddrKernelText.FlatPtr - AddrHashStart.FlatPtr)); 439 554 } 555 #endif 440 556 } 441 557 … … 759 875 pThis->AddrKernelElfStart = HitAddr; 760 876 pThis->AddrKernelInterp = HitAddrInterp; 761 pThis->AddrKernelText.FlatPtr = FBSD_UNION(pThis, &ElfHdr, e_entry);877 DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelText, FBSD_UNION(pThis, &ElfHdr, e_entry)); 762 878 LogFunc(("Found %s FreeBSD kernel at %RGv (.interp section at %RGv, .text section at %RGv)\n", 763 879 pThis->f64Bit ? "amd64" : "i386", pThis->AddrKernelElfStart.FlatPtr,
Note:
See TracChangeset
for help on using the changeset viewer.