- Timestamp:
- Mar 22, 2012 2:17:39 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/VBoxTpG.cpp
r40570 r40572 104 104 RTLISTNODE ListEntry; 105 105 const char *pszName; 106 107 uint16_t iFirstProbe; 108 uint16_t cProbes; 106 109 107 110 VTGATTRS AttrSelf; … … 232 235 233 236 237 /** 238 * Invokes the assembler. 239 * 240 * @returns Exit code. 241 * @param pszOutput The output file. 242 * @param pszTempAsm The source file. 243 */ 234 244 static RTEXITCODE generateInvokeAssembler(const char *pszOutput, const char *pszTempAsm) 235 245 { … … 297 307 if (Status.enmReason == RTPROCEXITREASON_SIGNAL) 298 308 return RTMsgErrorExit(RTEXITCODE_FAILURE, "The assembler failed: signal %d", Status.iStatus); 299 if (Status.enmReason == RTPROCEXITREASON_ABEND)309 if (Status.enmReason != RTPROCEXITREASON_NORMAL) 300 310 return RTMsgErrorExit(RTEXITCODE_FAILURE, "The assembler failed: abend"); 301 if ( Status.enmReason != RTPROCEXITREASON_NORMAL 302 || Status.iStatus != 0) 303 return RTMsgErrorExit(RTEXITCODE_FAILURE, "The assembler failed: exit code %d", Status.iStatus); 311 if (Status.iStatus != 0) 312 return RTMsgErrorExit((RTEXITCODE)Status.iStatus, "The assembler failed: exit code %d", Status.iStatus); 304 313 305 314 return RTEXITCODE_SUCCESS; … … 307 316 308 317 318 /** 319 * Worker that does the boring bits when generating a file. 320 * 321 * @returns Exit code. 322 * @param pszOutput The name of the output file. 323 * @param pszWhat What kind of file it is. 324 * @param pfnGenerator The callback function that provides the contents 325 * of the file. 326 */ 309 327 static RTEXITCODE generateFile(const char *pszOutput, const char *pszWhat, 310 328 RTEXITCODE (*pfnGenerator)(PSCMSTREAM)) … … 347 365 } 348 366 367 368 /** 369 * Formats a string and writes it to the SCM stream. 370 * 371 * @returns The number of bytes written (>= 0). Negative value are IPRT error 372 * status codes. 373 * @param pStream The stream to write to. 374 * @param pszFormat The format string. 375 * @param va The arguments to format. 376 */ 349 377 static ssize_t ScmStreamPrintfV(PSCMSTREAM pStream, const char *pszFormat, va_list va) 350 378 { … … 361 389 } 362 390 391 392 /** 393 * Formats a string and writes it to the SCM stream. 394 * 395 * @returns The number of bytes written (>= 0). Negative value are IPRT error 396 * status codes. 397 * @param pStream The stream to write to. 398 * @param pszFormat The format string. 399 * @param ... The arguments to format. 400 */ 363 401 static ssize_t ScmStreamPrintf(PSCMSTREAM pStream, const char *pszFormat, ...) 364 402 { … … 389 427 390 428 429 /** 430 * Generate assembly source that can be turned into an object file. 431 * 432 * (This is a generateFile callback.) 433 * 434 * @returns Exit code. 435 * @param pStrm The output stream. 436 */ 391 437 static RTEXITCODE generateAssembly(PSCMSTREAM pStrm) 392 438 { 439 PVTGPROVIDER pProvider; 440 PVTGPROBE pProbe; 441 PVTGARG pArg; 442 443 393 444 if (g_cVerbosity > 0) 394 445 RTMsgInfo("Generating assembly code..."); … … 452 503 "GLOBALNAME g_afVTGProbeEnabled\n" 453 504 ); 454 PVTGPROVIDER pProv; 455 RTListForEach(&g_ProviderHead, pProv, VTGPROVIDER, ListEntry) 456 { 457 PVTGPROBE pProbe; 458 RTListForEach(&pProv->ProbeHead, pProbe, VTGPROBE, ListEntry) 505 uint32_t cProbes = 0; 506 RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry) 507 { 508 RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry) 459 509 { 460 510 ScmStreamPrintf(pStrm, 461 511 "GLOBALNAME g_fVTGProbeEnabled_%s_%s\n" 462 512 " db 0\n", 463 pProv->pszName, pProbe->pszName); 513 pProvider->pszName, pProbe->pszName); 514 cProbes++; 464 515 } 465 516 } 466 517 ScmStreamPrintf(pStrm, "GLOBALNAME g_afVTGProbeEnabled_End\n"); 518 if (cProbes >= _32K) 519 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Too many probes: %u (max %u)", cProbes, _32K - 1); 467 520 468 521 /* … … 470 523 */ 471 524 ScmStreamPrintf(pStrm, 525 "\n" 472 526 ";\n" 473 527 "; The string table.\n" … … 483 537 */ 484 538 ScmStreamPrintf(pStrm, 539 "\n" 485 540 ";\n" 486 541 "; The argument lists.\n" … … 488 543 "GLOBALNAME g_aVTGArgLists\n"); 489 544 uint32_t off = 0; 490 RTListForEach(&g_ProviderHead, pProv, VTGPROVIDER, ListEntry) 491 { 492 PVTGPROBE pProbe; 493 RTListForEach(&pProv->ProbeHead, pProbe, VTGPROBE, ListEntry) 545 RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry) 546 { 547 RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry) 494 548 { 495 549 if (pProbe->offArgList != UINT32_MAX) … … 504 558 , off, pProbe->cArgs); 505 559 off += 4; 506 PVTGARG pArg;507 560 RTListForEach(&pProbe->ArgHead, pArg, VTGARG, ListEntry) 508 561 { … … 520 573 { 521 574 PVTGPROBE pProbe2; 522 RTListForEach(&pProv ->ProbeHead, pProbe2, VTGPROBE, ListEntry)575 RTListForEach(&pProvider->ProbeHead, pProbe2, VTGPROBE, ListEntry) 523 576 { 524 577 if (pProbe2->offArgList != UINT32_MAX) … … 550 603 551 604 /* 552 * Probe definitions. .605 * Probe definitions. 553 606 */ 554 607 ScmStreamPrintf(pStrm, … … 559 612 "GLOBALNAME g_aVTGProbes\n" 560 613 "\n"); 614 uint32_t iProvider = 0; 561 615 uint32_t iProbe = 0; 562 RTListForEach(&g_ProviderHead, pProv , VTGPROVIDER, ListEntry)563 { 564 PVTGPROBE pProbe;565 RTListForEach(&pProv ->ProbeHead, pProbe, VTGPROBE, ListEntry)616 RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry) 617 { 618 pProvider->iFirstProbe = iProbe; 619 RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry) 566 620 { 567 621 ScmStreamPrintf(pStrm, 568 " ; idx=#%4u - %s::%s\n"622 "GLOBALNAME g_VTGProbeData_%s_%s ; idx=#%4u\n" 569 623 " dd %6u ; name\n" 570 " dd %6u ; provider index\n"571 624 " dd %6u ; Argument list offset\n" 572 " dd g_fVTGProbeEnabled_%s_%s - g_afVTGProbeEnabled\n" 625 " dw g_fVTGProbeEnabled_%s_%s - g_afVTGProbeEnabled\n" 626 " dw %6u ; provider index\n" 573 627 , 574 iProbe, pProv->pszName, pProbe->pszName,628 pProvider->pszName, pProbe->pszName, iProbe, 575 629 strtabGetOff(pProbe->pszName), 576 0 /** @todo provider index */,577 630 pProbe->offArgList, 578 pProv->pszName, pProbe->pszName); 631 pProvider->pszName, pProbe->pszName, 632 iProvider); 579 633 pProbe->iProbe = iProbe; 580 634 iProbe++; 581 635 } 636 pProvider->cProbes = iProbe - pProvider->iFirstProbe; 637 iProvider++; 582 638 } 583 639 ScmStreamPrintf(pStrm, "GLOBALNAME g_aVTGProbes_End\n"); … … 591 647 "; Provider data.\n" 592 648 ";\n" 593 "GLOBALNAME g_aVTGProviders\n" 594 "\n"); 595 uint32_t iProvider = 0; 596 RTListForEach(&g_ProviderHead, pProv, VTGPROVIDER, ListEntry) 649 "GLOBALNAME g_aVTGProviders\n"); 650 iProvider = 0; 651 RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry) 597 652 { 598 653 ScmStreamPrintf(pStrm, 599 " ; idx=#%4u - %s\n 654 " ; idx=#%4u - %s\n" 600 655 " dd %6u ; name\n" 601 " dd %6u ; index of first probe\n" 602 " dd %6u ; index of last probe\n" 603 " db 0, 0, 0 ; AttrSelf\n" 604 " db 0, 0, 0 ; AttrModules\n" 605 " db 0, 0, 0 ; AttrFunctions\n" 606 " db 0, 0, 0 ; AttrName\n" 607 " db 0, 0, 0 ; AttrArguments\n" 656 " dw %6u ; index of first probe\n" 657 " dw %6u ; count of probes\n" 658 " db %d, %d, %d ; AttrSelf\n" 659 " db %d, %d, %d ; AttrModules\n" 660 " db %d, %d, %d ; AttrFunctions\n" 661 " db %d, %d, %d ; AttrName\n" 662 " db %d, %d, %d ; AttrArguments\n" 663 " db 0 ; reserved\n" 608 664 , 609 iProvider, pProv->pszName, 610 strtabGetOff(pProv->pszName), 611 0 /** @todo probe index */, 612 0 /** @todo probe index */ 613 /** @todo attributes */); 665 iProvider, pProvider->pszName, 666 strtabGetOff(pProvider->pszName), 667 pProvider->iFirstProbe, 668 pProvider->cProbes, 669 pProvider->AttrSelf.enmCode, pProvider->AttrSelf.enmData, pProvider->AttrSelf.enmDataDep, 670 pProvider->AttrModules.enmCode, pProvider->AttrModules.enmData, pProvider->AttrModules.enmDataDep, 671 pProvider->AttrFunctions.enmCode, pProvider->AttrFunctions.enmData, pProvider->AttrFunctions.enmDataDep, 672 pProvider->AttrName.enmCode, pProvider->AttrName.enmData, pProvider->AttrName.enmDataDep, 673 pProvider->AttrArguments.enmCode, pProvider->AttrArguments.enmData, pProvider->AttrArguments.enmDataDep); 614 674 iProvider++; 615 675 } … … 619 679 * Emit code for the stub functions. 620 680 */ 681 ScmStreamPrintf(pStrm, 682 "\n" 683 ";\n" 684 "; Prob stubs.\n" 685 ";\n" 686 "BEGINCODE\n" 687 "extern IMPNAME(SUPR0FireProbe)\n" /** @todo VBoxDrv may eventually need special handling wrt importing. */ 688 ); 689 RTListForEach(&g_ProviderHead, pProvider, VTGPROVIDER, ListEntry) 690 { 691 RTListForEach(&pProvider->ProbeHead, pProbe, VTGPROBE, ListEntry) 692 { 693 ScmStreamPrintf(pStrm, 694 "\n" 695 "GLOBALNAME VTGProbeStub_%s_%s ; (VBOXTPGPROBELOC pVTGProbeLoc", 696 pProvider->pszName, pProbe->pszName); 697 RTListForEach(&pProbe->ArgHead, pArg, VTGARG, ListEntry) 698 { 699 ScmStreamPrintf(pStrm, ", %s %s", pArg->pszType, pArg->pszName); 700 } 701 ScmStreamPrintf(pStrm, 702 ");\n"); 703 704 bool const fWin64 = g_cBits == 64 && (!strcmp(g_pszAssemblerFmtVal, "win64") || !strcmp(g_pszAssemblerFmtVal, "pe64")); 705 bool const fMachO32 = g_cBits == 32 && !strcmp(g_pszAssemblerFmtVal, "macho32"); 706 707 /* 708 * Check if the probe in question is enabled. 709 */ 710 if (g_cBits == 32) 711 ScmStreamPrintf(pStrm, 712 " mov eax, [esp + 4]\n" 713 " test byte [eax+3], 0x80 ; fEnabled == true?\n" 714 " jz .return ; jump on false\n"); 715 else if (fWin64) 716 ScmStreamPrintf(pStrm, 717 " test byte [rcx+3], 0x80 ; fEnabled == true?\n" 718 " jz .return ; jump on false\n"); 719 else 720 ScmStreamPrintf(pStrm, 721 " test byte [rdi+3], 0x80 ; fEnabled == true?\n" 722 " jz .return ; jump on false\n"); 723 724 /* 725 * Shuffle the arguments around, replacing the location pointer with the probe ID. 726 */ 727 if (fMachO32) 728 { 729 /* Need to recreate the stack frame entirely here as the probe 730 function differs by taking all uint64_t arguments instead 731 of uintptr_t. Understandable, but real PITA. */ 732 ScmStreamPrintf(pStrm, "int3\n"); 733 } 734 else if (g_cBits == 32) 735 { 736 /** @todo Check that none of the first 5 arguments are larger than pointer or 737 * 32-bit!! */ 738 ScmStreamPrintf(pStrm, 739 " mov edx, [eax + 4] ; idProbe\n" 740 " mov ecx, IMP(SUPR0FireProbe)\n" 741 " mov [esp + 4], edx ; Replace pVTGProbeLoc with idProbe.\n" 742 " jmp ecx\n"); 743 } 744 else if (fWin64) 745 ScmStreamPrintf(pStrm, 746 " mov rax, IMP(SUPR0FireProbe) wrt RIP\n" 747 " mov ecx, [rcx + 4] ; idProbe replaces pVTGProbeLoc.\n" 748 " jmp rax\n"); 749 else 750 ScmStreamPrintf(pStrm, 751 " lea rax, [IMP(SUPR0FireProbe) wrt RIP]\n" //??? macho64? 752 " mov edi, [rdi + 4] ; idProbe replaces pVTGProbeLoc.\n" 753 " jmp rax\n"); 754 755 ScmStreamPrintf(pStrm, 756 ".return:\n" 757 " ret ; The probe was disabled, return\n" 758 "\n"); 759 } 760 } 621 761 622 762 return RTEXITCODE_SUCCESS; … … 773 913 " { \\\n" 774 914 " DECL_DATA_SECT(static, VBOXTPGPROBELOC, s_VTGProbeLoc, VTGPrLc) = \\\n" 775 " { __LINE__, 0, UINT32_MAX, __PRETTY_FUNCTION__, __FILE__, /*&g_VTGProbeData_%s_%s*/ NULL}; \\\n"776 " /*VTGProbeStub_%s_%s(&s_VTGProbeLoc",915 " { __LINE__, 0, UINT32_MAX, __PRETTY_FUNCTION__, __FILE__, &g_VTGProbeData_%s_%s }; \\\n" 916 " VTGProbeStub_%s_%s(&s_VTGProbeLoc", 777 917 pProv->pszName, pProbe->pszName, 778 918 pProv->pszName, pProbe->pszName, … … 783 923 } 784 924 ScmStreamPrintf(pStrm, 785 ");*/ RTAssertMsg2(\"%p\", &s_VTGProbeLoc); \\\n" 786 " } \\\n" 925 "); \\\n" 926 " } \\\n"); 927 RTListForEach(&pProbe->ArgHead, pArg, VTGARG, ListEntry) 928 { 929 ScmStreamPrintf(pStrm, 930 " AssertCompile(sizeof(%s) <= sizeof(uintptr_t));\n" 931 " AssertCompile(sizeof(%s) <= sizeof(uintptr_t));\n", 932 pArg->pszName, 933 pArg->pszType); 934 } 935 ScmStreamPrintf(pStrm, 787 936 " } while (0)\n" 788 937 "\n");
Note:
See TracChangeset
for help on using the changeset viewer.