- Timestamp:
- Aug 23, 2010 1:56:17 PM (14 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r31829 r31860 759 759 r3/solaris/alloc-solaris.cpp \ 760 760 r3/solaris/mp-solaris.cpp \ 761 r3/solaris/coredumper-solaris.cpp \ 761 762 r3/solaris/rtProcInitExePath-solaris.cpp 762 763 RuntimeR3_SOURCES.solaris.amd64 = \ -
trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
r31822 r31860 28 28 * Header Files * 29 29 *******************************************************************************/ 30 #define LOG_GROUP LOG_GROUP_CORE_DUMPER 31 #include <VBox/log.h> 32 #include <iprt/coredumper.h> 30 33 #include <iprt/types.h> 31 34 #include <iprt/file.h> … … 34 37 #include <iprt/path.h> 35 38 #include <iprt/string.h> 36 #include <iprt/stream.h>37 #include <iprt/initterm.h>38 39 #include <iprt/thread.h> 39 40 #include <iprt/param.h> 40 41 #include <iprt/asm.h> 41 #include " tstRTCoreDump.h"42 #include "coredumper-solaris.h" 42 43 43 44 #ifdef RT_OS_SOLARIS 45 # include <syslog.h> 44 46 # include <signal.h> 45 47 # include <unistd.h> … … 53 55 54 56 /******************************************************************************* 57 * Globals * 58 *******************************************************************************/ 59 volatile static uint64_t g_CoreDumpThread = NIL_RTTHREAD; 60 volatile static bool g_fCoreDumpSignalSetup = false; 61 volatile static bool g_fCoreDumpDeliberate = false; 62 volatile static bool g_fCoreDumpInProgress = false; 63 volatile static uint32_t g_fCoreDumpFlags = 0; 64 static char g_szCoreDumpDir[PATH_MAX] = { 0 }; 65 static char g_szCoreDumpFile[PATH_MAX] = { 0 }; 66 67 68 /******************************************************************************* 55 69 * Defined Constants And Macros * 56 70 *******************************************************************************/ 57 #define CORELOG(a) RTPrintf a 58 #define CORELOGREL(a) RTPrintf a 59 60 /** 61 * VBOXSOLCORETYPE: Whether this is an old or new style core. 62 */ 63 typedef enum VBOXSOLCORETYPE 64 { 65 enmOldEra = 0x01d, /* old */ 66 enmNewEra = 0x5c151 /* sci-fi */ 67 } VBOXSOLCORETYPE; 68 69 static unsigned volatile g_cErrors = 0; 70 71 volatile bool g_fCoreDumpInProgress = false; 71 #define CORELOG_NAME "CoreDumper: " 72 #define CORELOG(a) Log(a) 73 #define CORELOGRELSYS(a) \ 74 do { \ 75 LogRel(a); \ 76 rtCoreDumperSysLogWrapper a; \ 77 } while (0) 78 79 80 /** 81 * Wrapper function to write IPRT format style string to the syslog. 82 * 83 * @param pszFormat Format string 84 */ 85 static void rtCoreDumperSysLogWrapper(const char *pszFormat, ...) 86 { 87 va_list va; 88 va_start(va, pszFormat); 89 char szBuf[1024]; 90 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va); 91 va_end(va); 92 syslog(LOG_ERR, "%s", szBuf); 93 } 72 94 73 95 … … 143 165 * @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR. 144 166 */ 145 static ssize_t ReadProcAddrSpace(PVBOXPROCESS pVBoxProc, RTFOFF off, void *pvBuf, size_t cbToRead)167 static ssize_t ProcReadAddrSpace(PVBOXPROCESS pVBoxProc, RTFOFF off, void *pvBuf, size_t cbToRead) 146 168 { 147 169 while (1) … … 162 184 * @return true if the architecture matches the current one. 163 185 */ 164 inline bool IsProcArchNative(PVBOXPROCESS pVBoxProc)186 static inline bool IsProcessArchNative(PVBOXPROCESS pVBoxProc) 165 187 { 166 188 return pVBoxProc->ProcInfo.pr_dmodel == PR_MODEL_NATIVE; … … 175 197 * @return The size of the file in bytes. 176 198 */ 177 s ize_t GetFileSize(const char *pszPath)199 static size_t GetFileSize(const char *pszPath) 178 200 { 179 201 size_t cb = 0; … … 186 208 } 187 209 else 188 CORELOGREL (("GetFileSize failed to open %s rc=%Rrc\n", pszPath, rc));210 CORELOGRELSYS((CORELOG_NAME "GetFileSize failed to open %s rc=%Rrc\n", pszPath, rc)); 189 211 return cb; 190 212 } … … 200 222 * @return VBox status code. 201 223 */ 202 int AllocMemoryArea(PVBOXCORE pVBoxCore)224 static int AllocMemoryArea(PVBOXCORE pVBoxCore) 203 225 { 204 226 AssertReturn(pVBoxCore->pvCore == NULL, VERR_ALREADY_EXISTS); … … 249 271 if (pv) 250 272 { 251 CORELOG(( "AllocMemoryArea: memory area of %u bytes allocated.\n", cb));273 CORELOG((CORELOG_NAME "AllocMemoryArea: memory area of %u bytes allocated.\n", cb)); 252 274 pVBoxCore->pvCore = pv; 253 275 pVBoxCore->pvFree = pv; … … 257 279 else 258 280 { 259 CORELOGREL (("AllocMemoryArea: failed cb=%u\n", cb));281 CORELOGRELSYS((CORELOG_NAME "AllocMemoryArea: failed cb=%u\n", cb)); 260 282 return VERR_NO_MEMORY; 261 283 } … … 268 290 * @param pVBoxCore Pointer to the core object. 269 291 */ 270 void FreeMemoryArea(PVBOXCORE pVBoxCore)292 static void FreeMemoryArea(PVBOXCORE pVBoxCore) 271 293 { 272 294 AssertReturnVoid(pVBoxCore); … … 275 297 276 298 munmap(pVBoxCore->pvCore, pVBoxCore->cbCore); 277 CORELOG(( "FreeMemoryArea: memory area of %u bytes freed.\n", pVBoxCore->cbCore));299 CORELOG((CORELOG_NAME "FreeMemoryArea: memory area of %u bytes freed.\n", pVBoxCore->cbCore)); 278 300 279 301 pVBoxCore->pvCore = NULL; … … 291 313 * @return Pointer to allocated memory, or NULL on failure. 292 314 */ 293 void *GetMemoryChunk(PVBOXCORE pVBoxCore, size_t cb)315 static void *GetMemoryChunk(PVBOXCORE pVBoxCore, size_t cb) 294 316 { 295 317 AssertReturn(pVBoxCore, NULL); … … 319 341 * @return VBox status code. 320 342 */ 321 int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)343 static int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb) 322 344 { 323 345 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 346 368 } 347 369 else 348 CORELOGREL (("ProcReadFileInto: failed to open %s. rc=%Rrc\n", szPath, rc));370 CORELOGRELSYS((CORELOG_NAME "ProcReadFileInto: failed to open %s. rc=%Rrc\n", szPath, rc)); 349 371 return rc; 350 372 } … … 358 380 * @return VBox status code. 359 381 */ 360 int ReadProcInfo(PVBOXCORE pVBoxCore)382 static int ProcReadInfo(PVBOXCORE pVBoxCore) 361 383 { 362 384 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 386 408 * @return VBox status code. 387 409 */ 388 int ReadProcStatus(PVBOXCORE pVBoxCore)410 static int ProcReadStatus(PVBOXCORE pVBoxCore) 389 411 { 390 412 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 417 439 * @return VBox status code. 418 440 */ 419 int ReadProcCred(PVBOXCORE pVBoxCore)441 static int ProcReadCred(PVBOXCORE pVBoxCore) 420 442 { 421 443 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 434 456 * @return VBox status code. 435 457 */ 436 int ReadProcPriv(PVBOXCORE pVBoxCore)458 static int ProcReadPriv(PVBOXCORE pVBoxCore) 437 459 { 438 460 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 445 467 if (!pVBoxProc->pcPrivImpl) 446 468 { 447 CORELOGREL (("ReadProcPriv: getprivimplinfo returned NULL.\n"));469 CORELOGRELSYS((CORELOG_NAME "ProcReadPriv: getprivimplinfo returned NULL.\n")); 448 470 return VERR_INVALID_STATE; 449 471 } … … 460 482 * @return VBox status code. 461 483 */ 462 int ReadProcLdt(PVBOXCORE pVBoxCore)484 static int ProcReadLdt(PVBOXCORE pVBoxCore) 463 485 { 464 486 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 477 499 * @return VBox status code. 478 500 */ 479 int ReadProcAuxVecs(PVBOXCORE pVBoxCore)501 static int ProcReadAuxVecs(PVBOXCORE pVBoxCore) 480 502 { 481 503 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 488 510 if (RT_FAILURE(rc)) 489 511 { 490 CORELOGREL (("ReadProcAuxVecs: RTFileOpen %s failed rc=%Rrc\n", szPath, rc));512 CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: RTFileOpen %s failed rc=%Rrc\n", szPath, rc)); 491 513 return rc; 492 514 } … … 504 526 /* Terminate list of vectors */ 505 527 pVBoxProc->cAuxVecs = cbAuxFile / sizeof(auxv_t); 506 CORELOG(( "ReadProcAuxVecs: cbAuxFile=%u auxv_t size %d cAuxVecs=%u\n", cbAuxFile, sizeof(auxv_t), pVBoxProc->cAuxVecs));528 CORELOG((CORELOG_NAME "ProcReadAuxVecs: cbAuxFile=%u auxv_t size %d cAuxVecs=%u\n", cbAuxFile, sizeof(auxv_t), pVBoxProc->cAuxVecs)); 507 529 if (pVBoxProc->cAuxVecs > 0) 508 530 { … … 514 536 else 515 537 { 516 CORELOGREL (("ReadProcAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs));538 CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs)); 517 539 rc = VERR_READ_ERROR; 518 540 } 519 541 } 520 542 else 521 CORELOGREL (("ReadProcAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile));543 CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile)); 522 544 523 545 pVBoxProc->pAuxVecs = NULL; … … 526 548 else 527 549 { 528 CORELOGREL (("ReadProcAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t)));550 CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t))); 529 551 rc = VERR_NO_MEMORY; 530 552 } 531 553 } 532 554 else 533 CORELOGREL (("ReadProcAuxVecs: aux file too small %u, expecting %u or more\n", cbAuxFile, sizeof(auxv_t)));555 CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: aux file too small %u, expecting %u or more\n", cbAuxFile, sizeof(auxv_t))); 534 556 535 557 RTFileClose(hFile); … … 541 563 * Find an element in the process' auxiliary vector. 542 564 */ 543 long GetAuxVal(PVBOXPROCESS pVBoxProc, int Type)565 static long GetAuxVal(PVBOXPROCESS pVBoxProc, int Type) 544 566 { 545 567 AssertReturn(pVBoxProc, -1); … … 565 587 * @return VBox status code. 566 588 */ 567 int ReadProcMappings(PVBOXCORE pVBoxCore)589 static int ProcReadMappings(PVBOXCORE pVBoxCore) 568 590 { 569 591 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 625 647 { 626 648 size_t cb = RT_MIN(sizeof(achBuf), pCur->pMap.pr_size - k); 627 int rc2 = ReadProcAddrSpace(pVBoxProc, pCur->pMap.pr_vaddr + k, &achBuf, cb);649 int rc2 = ProcReadAddrSpace(pVBoxProc, pCur->pMap.pr_vaddr + k, &achBuf, cb); 628 650 if (RT_FAILURE(rc2)) 629 651 { 630 CORELOGREL (("ReadProcMappings: skipping mapping. vaddr=%#x rc=%Rrc\n", pCur->pMap.pr_vaddr, rc2));652 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: skipping mapping. vaddr=%#x rc=%Rrc\n", pCur->pMap.pr_vaddr, rc2)); 631 653 632 654 /* … … 652 674 RTFileClose(pVBoxProc->hAs); 653 675 pVBoxProc->hAs = NIL_RTFILE; 654 CORELOG(( "ReadProcMappings: successfully read in %u mappings\n", pVBoxProc->cMappings));676 CORELOG((CORELOG_NAME "ProcReadMappings: successfully read in %u mappings\n", pVBoxProc->cMappings)); 655 677 return VINF_SUCCESS; 656 678 } 657 679 else 658 680 { 659 CORELOGREL (("ReadProcMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));681 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO))); 660 682 rc = VERR_NO_MEMORY; 661 683 } … … 663 685 else 664 686 { 665 CORELOGREL (("ReadProcMappings: Invalid mapping count %u\n", pVBoxProc->cMappings));687 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: Invalid mapping count %u\n", pVBoxProc->cMappings)); 666 688 rc = VERR_READ_ERROR; 667 689 } 668 690 } 669 691 else 670 CORELOGREL (("ReadProcMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile));692 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile)); 671 693 } 672 694 else 673 695 { 674 CORELOGREL (("ReadProcMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile));696 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile)); 675 697 rc = VERR_NO_MEMORY; 676 698 } … … 681 703 } 682 704 else 683 CORELOGREL (("ReadProcMappings: failed to open %s. rc=%Rrc\n", szPath, rc));705 CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: failed to open %s. rc=%Rrc\n", szPath, rc)); 684 706 685 707 RTFileClose(hFile); … … 696 718 * @return VBox status code. 697 719 */ 698 int ReadProcThreads(PVBOXCORE pVBoxCore)720 static int ProcReadThreads(PVBOXCORE pVBoxCore) 699 721 { 700 722 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 728 750 uint64_t cInfo = pInfoHdr->pr_nent; 729 751 730 CORELOG(("ReadProcThreads: read info(%u) status(%u), threads:cInfo=%u cStatus=%u\n", cbInfoHdrAndData, cbStatusHdrAndData, cInfo, cStatus)); 752 CORELOG((CORELOG_NAME "ProcReadThreads: read info(%u) status(%u), threads:cInfo=%u cStatus=%u\n", cbInfoHdrAndData, 753 cbStatusHdrAndData, cInfo, cStatus)); 731 754 732 755 /* … … 747 770 || pStatus->pr_lwpid != pInfo->pr_lwpid) 748 771 { 749 CORELOGREL(("ReadProcThreads: cStatus = %u pStatuslwpid=%d infolwpid=%d\n", cStatus, pStatus->pr_lwpid, pInfo->pr_lwpid)); 772 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: cStatus = %u pStatuslwpid=%d infolwpid=%d\n", cStatus, 773 pStatus->pr_lwpid, pInfo->pr_lwpid)); 750 774 rc = VERR_INVALID_STATE; 751 775 break; … … 796 820 pStatus->pr_ustack = (uintptr_t)&pVBoxProc->pCurThreadCtx->uc_stack; 797 821 798 CORELOG(( "ReadProcThreads: patched dumper thread context with pre-dump time context.\n"));822 CORELOG((CORELOG_NAME "ProcReadThreads: patched dumper thread context with pre-dump time context.\n")); 799 823 } 800 824 … … 804 828 else 805 829 { 806 CORELOGREL (("ReadProcThreads: missing status for lwp %d\n", pInfo->pr_lwpid));830 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: missing status for lwp %d\n", pInfo->pr_lwpid)); 807 831 pCur->pStatus = NULL; 808 832 } … … 816 840 pPrev->pNext = NULL; 817 841 818 CORELOG(( "ReadProcThreads: successfully read %u threads.\n", cInfo));842 CORELOG((CORELOG_NAME "ProcReadThreads: successfully read %u threads.\n", cInfo)); 819 843 pVBoxProc->cThreads = cInfo; 820 844 return VINF_SUCCESS; … … 822 846 else 823 847 { 824 CORELOGREL (("ReadProcThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));848 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo)); 825 849 rc = VERR_NO_MEMORY; 826 850 } 827 851 } 828 852 else 829 CORELOGREL (("ReadProcThreads: Invalid state information for threads.\n", rc));853 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: Invalid state information for threads.\n", rc)); 830 854 } 831 855 else 832 856 { 833 CORELOGREL (("ReadProcThreads: huh!? cbStatusHdrAndData=%u prheader_t=%u entsize=%u\n", cbStatusHdrAndData,857 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: huh!? cbStatusHdrAndData=%u prheader_t=%u entsize=%u\n", cbStatusHdrAndData, 834 858 sizeof(prheader_t), pStatusHdr->pr_entsize)); 835 CORELOGREL (("ReadProcThreads: huh!? cbInfoHdrAndData=%u entsize=%u\n", cbInfoHdrAndData, pStatusHdr->pr_entsize));859 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: huh!? cbInfoHdrAndData=%u entsize=%u\n", cbInfoHdrAndData, pStatusHdr->pr_entsize)); 836 860 rc = VERR_INVALID_STATE; 837 861 } 838 862 } 839 863 else 840 CORELOGREL (("ReadProcThreads: ReadFileNoIntr failed for \"lpsinfo\" rc=%Rrc\n", rc));864 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: ReadFileNoIntr failed for \"lpsinfo\" rc=%Rrc\n", rc)); 841 865 } 842 866 else 843 CORELOGREL (("ReadProcThreads: ReadFileNoIntr failed for \"lstatus\" rc=%Rrc\n", rc));867 CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: ReadFileNoIntr failed for \"lstatus\" rc=%Rrc\n", rc)); 844 868 return rc; 845 869 } … … 854 878 * @return VBox status code. 855 879 */ 856 int ReadProcMiscInfo(PVBOXCORE pVBoxCore)880 static int ProcReadMiscInfo(PVBOXCORE pVBoxCore) 857 881 { 858 882 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 867 891 if (rc == -1) 868 892 { 869 CORELOGREL (("ReadProcMiscInfo: sysinfo failed. rc=%d errno=%d\n", rc, errno));893 CORELOGRELSYS((CORELOG_NAME "ProcReadMiscInfo: sysinfo failed. rc=%d errno=%d\n", rc, errno)); 870 894 return VERR_GENERAL_FAILURE; 871 895 } … … 875 899 if (rc == -1) 876 900 { 877 CORELOGREL (("ReadProcMiscInfo: uname failed. rc=%d errno=%d\n", rc, errno));901 CORELOGRELSYS((CORELOG_NAME "ProcReadMiscInfo: uname failed. rc=%d errno=%d\n", rc, errno)); 878 902 return VERR_GENERAL_FAILURE; 879 903 } … … 882 906 if (rc < 0) 883 907 { 884 CORELOGREL (("ReadProcMiscInfo: getzonenamebyid failed. rc=%d errno=%d zoneid=%d\n", rc, errno, pVBoxProc->ProcInfo.pr_zoneid));908 CORELOGRELSYS((CORELOG_NAME "ProcReadMiscInfo: getzonenamebyid failed. rc=%d errno=%d zoneid=%d\n", rc, errno, pVBoxProc->ProcInfo.pr_zoneid)); 885 909 return VERR_GENERAL_FAILURE; 886 910 } … … 902 926 * @param pInfo Pointer to the old prpsinfo_t structure to update. 903 927 */ 904 void GetOldProcessInfo(PVBOXCORE pVBoxCore, prpsinfo_t *pInfo)928 static void GetOldProcessInfo(PVBOXCORE pVBoxCore, prpsinfo_t *pInfo) 905 929 { 906 930 AssertReturnVoid(pVBoxCore); … … 961 985 * 962 986 */ 963 void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)987 static void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst) 964 988 { 965 989 AssertReturnVoid(pVBoxCore); … … 1040 1064 1041 1065 /** 1042 * Count the number of sections which will be dumped into the core file.1043 *1044 * @param pVBoxCore Pointer to the core object.1045 *1046 * @return Number of sections for the core file.1047 */1048 uint32_t CountSections(PVBOXCORE pVBoxCore)1049 {1050 /* @todo sections */1051 NOREF(pVBoxCore);1052 return 0;1053 }1054 1055 1056 /**1057 1066 * Resume all threads of this process. 1058 1067 * … … 1061 1070 * @return VBox error code. 1062 1071 */ 1063 int ResumeAllThreads(PVBOXPROCESS pVBoxProc)1072 static int ResumeAllThreads(PVBOXPROCESS pVBoxProc) 1064 1073 { 1065 1074 AssertReturn(pVBoxProc, VERR_INVALID_POINTER); … … 1094 1103 } 1095 1104 1096 CORELOG(( "ResumeAllThreads: resumed %d threads\n", cRunningThreads));1105 CORELOG((CORELOG_NAME "ResumeAllThreads: resumed %d threads\n", cRunningThreads)); 1097 1106 RTDirClose(pDir); 1098 1107 } 1099 1108 else 1100 1109 { 1101 CORELOGREL (("ResumeAllThreads: Failed to open %s\n", szPath));1110 CORELOGRELSYS((CORELOG_NAME "ResumeAllThreads: Failed to open %s\n", szPath)); 1102 1111 rc = VERR_READ_ERROR; 1103 1112 } … … 1115 1124 * @return VBox error code. 1116 1125 */ 1117 int SuspendAllThreads(PVBOXPROCESS pVBoxProc)1126 static int SuspendAllThreads(PVBOXPROCESS pVBoxProc) 1118 1127 { 1119 1128 char szCurThread[128]; … … 1161 1170 else 1162 1171 { 1163 CORELOGREL (("SuspendAllThreads: Failed to open %s cTries=%d\n", szPath, cTries));1172 CORELOGRELSYS((CORELOG_NAME "SuspendAllThreads: Failed to open %s cTries=%d\n", szPath, cTries)); 1164 1173 rc = VERR_READ_ERROR; 1165 1174 break; … … 1168 1177 1169 1178 if (RT_SUCCESS(rc)) 1170 CORELOG(( "Stopped %u threads successfully with %u tries\n", cThreads, cTries));1179 CORELOG((CORELOG_NAME "Stopped %u threads successfully with %u tries\n", cThreads, cTries)); 1171 1180 1172 1181 return rc; … … 1181 1190 * @return Size of data actually used for NOTE header and section. 1182 1191 */ 1183 inline size_t ElfNoteHeaderSize(size_t cb)1192 static inline size_t ElfNoteHeaderSize(size_t cb) 1184 1193 { 1185 1194 return sizeof(ELFNOTEHDR) + RT_ALIGN_Z(cb, 4); … … 1197 1206 * @return VBox status code. 1198 1207 */ 1199 int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb)1208 static int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb) 1200 1209 { 1201 1210 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1225 1234 1226 1235 if (RT_FAILURE(rc)) 1227 CORELOGREL (("ElfWriteNote: pfnWriter failed. Type=%d rc=%Rrc\n", Type, rc));1236 CORELOGRELSYS((CORELOG_NAME "ElfWriteNote: pfnWriter failed. Type=%d rc=%Rrc\n", Type, rc)); 1228 1237 #else 1229 1238 #error Port Me! … … 1242 1251 * @return Size of NOTE section. 1243 1252 */ 1244 s ize_t ElfNoteSectionSize(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)1253 static size_t ElfNoteSectionSize(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType) 1245 1254 { 1246 1255 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc; … … 1303 1312 default: 1304 1313 { 1305 CORELOGREL (("ElfNoteSectionSize: Unknown segment era %d\n", enmType));1314 CORELOGRELSYS((CORELOG_NAME "ElfNoteSectionSize: Unknown segment era %d\n", enmType)); 1306 1315 break; 1307 1316 } … … 1321 1330 * @return VBox status code. 1322 1331 */ 1323 int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)1332 static int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType) 1324 1333 { 1325 1334 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1329 1338 1330 1339 #ifdef RT_OS_SOLARIS 1331 1332 1340 typedef int (*PFNELFWRITENOTEHDR)(PVBOXCORE pVBoxCore, uint_t, const void *pcv, size_t cb); 1333 1341 typedef struct ELFWRITENOTE … … 1355 1363 if (RT_FAILURE(rc)) 1356 1364 { 1357 CORELOGREL (("ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));1365 CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc)); 1358 1366 break; 1359 1367 } … … 1378 1386 if (RT_FAILURE(rc)) 1379 1387 { 1380 CORELOGREL (("ElfWriteSegment: ElfWriteNote failed for NT_PRFPREF. rc=%Rrc\n", rc));1388 CORELOGRELSYS((CORELOG_NAME "ElfWriteSegment: ElfWriteNote failed for NT_PRFPREF. rc=%Rrc\n", rc)); 1381 1389 break; 1382 1390 } … … 1384 1392 else 1385 1393 { 1386 CORELOGREL (("ElfWriteSegment: ElfWriteNote failed for NT_PRSTATUS. rc=%Rrc\n", rc));1394 CORELOGRELSYS((CORELOG_NAME "ElfWriteSegment: ElfWriteNote failed for NT_PRSTATUS. rc=%Rrc\n", rc)); 1387 1395 break; 1388 1396 } … … 1412 1420 if (RT_FAILURE(rc)) 1413 1421 { 1414 CORELOGREL (("ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));1422 CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc)); 1415 1423 break; 1416 1424 } … … 1427 1435 if (RT_FAILURE(rc)) 1428 1436 { 1429 CORELOGREL (("ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSINFO failed. rc=%Rrc\n", rc));1437 CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSINFO failed. rc=%Rrc\n", rc)); 1430 1438 break; 1431 1439 } … … 1436 1444 if (RT_FAILURE(rc)) 1437 1445 { 1438 CORELOGREL (("ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSTATUS failed. rc=%Rrc\n", rc));1446 CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSTATUS failed. rc=%Rrc\n", rc)); 1439 1447 break; 1440 1448 } … … 1446 1454 default: 1447 1455 { 1448 CORELOGREL (("ElfWriteNoteSection: Invalid type %d\n", enmType));1456 CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: Invalid type %d\n", enmType)); 1449 1457 rc = VERR_GENERAL_FAILURE; 1450 1458 break; … … 1465 1473 * @return VBox status code. 1466 1474 */ 1467 int ElfWriteMappings(PVBOXCORE pVBoxCore)1475 static int ElfWriteMappings(PVBOXCORE pVBoxCore) 1468 1476 { 1469 1477 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc; … … 1480 1488 { 1481 1489 size_t cb = RT_MIN(sizeof(achBuf), pMapInfo->pMap.pr_size - k); 1482 int rc2 = ReadProcAddrSpace(pVBoxProc, pMapInfo->pMap.pr_vaddr + k, &achBuf, cb);1490 int rc2 = ProcReadAddrSpace(pVBoxProc, pMapInfo->pMap.pr_vaddr + k, &achBuf, cb); 1483 1491 if (RT_FAILURE(rc2)) 1484 1492 { 1485 CORELOGREL (("ElfWriteMappings: Failed to read mapping, can't recover. Bye. rc=%Rrc\n", rc));1493 CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: Failed to read mapping, can't recover. Bye. rc=%Rrc\n", rc)); 1486 1494 return VERR_INVALID_STATE; 1487 1495 } … … 1490 1498 if (RT_FAILURE(rc)) 1491 1499 { 1492 CORELOGREL (("ElfWriteMappings: pfnWriter failed. rc=%Rrc\n", rc));1500 CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: pfnWriter failed. rc=%Rrc\n", rc)); 1493 1501 return rc; 1494 1502 } … … 1502 1510 memcpy(achBuf, &pMapInfo->fError, sizeof(pMapInfo->fError)); 1503 1511 if (sizeof(achBuf) != pMapInfo->pMap.pr_size) 1504 CORELOGREL (("ElfWriteMappings: Huh!? something is wrong!\n"));1512 CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: Huh!? something is wrong!\n")); 1505 1513 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &achBuf, sizeof(achBuf)); 1506 1514 if (RT_FAILURE(rc)) 1507 1515 { 1508 CORELOGREL (("ElfWriteMappings: pfnWriter(2) failed. rc=%Rrc\n", rc));1516 CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: pfnWriter(2) failed. rc=%Rrc\n", rc)); 1509 1517 return rc; 1510 1518 } … … 1517 1525 } 1518 1526 1527 1519 1528 /** 1520 1529 * Write program headers for all mappings into the core file. … … 1524 1533 * @return VBox status code. 1525 1534 */ 1526 int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore)1535 static int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore) 1527 1536 { 1528 1537 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1556 1565 if (RT_FAILURE(rc)) 1557 1566 { 1558 CORELOGREL (("ElfWriteMappingHeaders: pfnWriter failed. rc=%Rrc\n", rc));1567 CORELOGRELSYS((CORELOG_NAME "ElfWriteMappingHeaders: pfnWriter failed. rc=%Rrc\n", rc)); 1559 1568 return rc; 1560 1569 } … … 1577 1586 * @return VBox status. 1578 1587 */ 1579 intWriteCore(PVBOXCORE pVBoxCore, PFNCOREWRITER pfnWriter)1588 static int rtCoreDumperWriteCore(PVBOXCORE pVBoxCore, PFNCOREWRITER pfnWriter) 1580 1589 { 1581 1590 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1597 1606 if (RT_FAILURE(rc)) 1598 1607 { 1599 CORELOGREL (("WriteCore: Failed to open address space, %s. rc=%Rrc\n", szPath, rc));1608 CORELOGRELSYS((CORELOG_NAME "WriteCore: Failed to open address space, %s. rc=%Rrc\n", szPath, rc)); 1600 1609 goto WriteCoreDone; 1601 1610 } … … 1608 1617 if (RT_FAILURE(rc)) 1609 1618 { 1610 CORELOGREL (("WriteCore: failed to open %s. rc=%Rrc\n", szPath, rc));1619 CORELOGRELSYS((CORELOG_NAME "WriteCore: failed to open %s. rc=%Rrc\n", szPath, rc)); 1611 1620 goto WriteCoreDone; 1612 1621 } … … 1614 1623 pVBoxCore->offWrite = 0; 1615 1624 uint32_t cProgHdrs = pVBoxProc->cMappings + 2; /* two PT_NOTE program headers (old, new style) */ 1616 uint32_t cSecHdrs = CountSections(pVBoxCore);1617 1625 1618 1626 /* … … 1646 1654 if (RT_FAILURE(rc)) 1647 1655 { 1648 CORELOGREL (("WriteCore: pfnWriter failed writing ELF header. rc=%Rrc\n", rc));1656 CORELOGRELSYS((CORELOG_NAME "WriteCore: pfnWriter failed writing ELF header. rc=%Rrc\n", rc)); 1649 1657 goto WriteCoreDone; 1650 1658 } … … 1667 1675 if (RT_FAILURE(rc)) 1668 1676 { 1669 CORELOGREL (("WriteCore: pfnWriter failed writing old-style ELF program Header. rc=%Rrc\n", rc));1677 CORELOGRELSYS((CORELOG_NAME "WriteCore: pfnWriter failed writing old-style ELF program Header. rc=%Rrc\n", rc)); 1670 1678 goto WriteCoreDone; 1671 1679 } … … 1680 1688 if (RT_FAILURE(rc)) 1681 1689 { 1682 CORELOGREL (("WriteCore: pfnWriter failed writing new-style ELF program header. rc=%Rrc\n", rc));1690 CORELOGRELSYS((CORELOG_NAME "WriteCore: pfnWriter failed writing new-style ELF program header. rc=%Rrc\n", rc)); 1683 1691 goto WriteCoreDone; 1684 1692 } … … 1691 1699 if (RT_FAILURE(rc)) 1692 1700 { 1693 CORELOGREL (("Write: ElfWriteMappings failed. rc=%Rrc\n", rc));1701 CORELOGRELSYS((CORELOG_NAME "Write: ElfWriteMappings failed. rc=%Rrc\n", rc)); 1694 1702 goto WriteCoreDone; 1695 1703 } … … 1701 1709 if (RT_FAILURE(rc)) 1702 1710 { 1703 CORELOGREL (("WriteCore: ElfWriteNoteSection old-style failed. rc=%Rrc\n", rc));1711 CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteNoteSection old-style failed. rc=%Rrc\n", rc)); 1704 1712 goto WriteCoreDone; 1705 1713 } … … 1711 1719 if (RT_FAILURE(rc)) 1712 1720 { 1713 CORELOGREL (("WriteCore: ElfWriteNoteSection new-style failed. rc=%Rrc\n", rc));1721 CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteNoteSection new-style failed. rc=%Rrc\n", rc)); 1714 1722 goto WriteCoreDone; 1715 1723 } … … 1721 1729 if (RT_FAILURE(rc)) 1722 1730 { 1723 CORELOGREL (("WriteCore: ElfWriteMappings failed. rc=%Rrc\n", rc));1731 CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteMappings failed. rc=%Rrc\n", rc)); 1724 1732 goto WriteCoreDone; 1725 1733 } … … 1755 1763 * @return VBox status code. 1756 1764 */ 1757 intCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext)1765 static int rtCoreDumperCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext) 1758 1766 { 1759 1767 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1778 1786 RTProcGetExecutableName(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath)); /* this gets full path not just name */ 1779 1787 pVBoxProc->pszExecName = RTPathFilename(pVBoxProc->szExecPath); 1780 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "core.vb.%s.%d", pVBoxProc->pszExecName, (int)pVBoxProc->Process); 1781 1782 CORELOG(("tstRTCoreDump: Taking Core %s from Thread %d\n", pVBoxCore->szCorePath, (int)pVBoxProc->hCurThread)); 1788 1789 /* 1790 * If no output directory is specified, use current directory. 1791 */ 1792 if (g_szCoreDumpDir[0] == '\0') 1793 g_szCoreDumpDir[0] = '.'; 1794 1795 if (g_szCoreDumpFile[0] == '\0') 1796 { 1797 /* We cannot call RTPathAbs*() as they call getcwd() which calls malloc. */ 1798 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s.%d", 1799 g_szCoreDumpDir, pVBoxProc->pszExecName, (int)pVBoxProc->Process); 1800 } 1801 else 1802 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s", g_szCoreDumpDir, g_szCoreDumpFile); 1803 1804 CORELOG((CORELOG_NAME "CreateCore: Taking Core %s from Thread %d\n", pVBoxCore->szCorePath, (int)pVBoxProc->hCurThread)); 1783 1805 1784 1806 /* … … 1788 1810 if (RT_SUCCESS(rc)) 1789 1811 { 1790 rc = ReadProcInfo(pVBoxCore);1812 rc = ProcReadInfo(pVBoxCore); 1791 1813 if (RT_SUCCESS(rc)) 1792 1814 { 1793 1815 GetOldProcessInfo(pVBoxCore, &pVBoxProc->ProcInfoOld); 1794 if (IsProc ArchNative(pVBoxProc))1816 if (IsProcessArchNative(pVBoxProc)) 1795 1817 { 1796 1818 /* 1797 1819 * Read process status, information such as number of active LWPs will be invalid since we just quiesced the process. 1798 1820 */ 1799 rc = ReadProcStatus(pVBoxCore);1821 rc = ProcReadStatus(pVBoxCore); 1800 1822 if (RT_SUCCESS(rc)) 1801 1823 { … … 1810 1832 } aAccumulators[] = 1811 1833 { 1812 { " ReadProcLdt", &ReadProcLdt, false },1813 { " ReadProcCred", &ReadProcCred, false },1814 { " ReadProcPriv", &ReadProcPriv, false },1815 { " ReadProcAuxVecs", &ReadProcAuxVecs, false },1816 { " ReadProcMappings", &ReadProcMappings, false },1817 { " ReadProcThreads", &ReadProcThreads, false },1818 { " ReadProcMiscInfo", &ReadProcMiscInfo, false }1834 { "ProcReadLdt", &ProcReadLdt, false }, 1835 { "ProcReadCred", &ProcReadCred, false }, 1836 { "ProcReadPriv", &ProcReadPriv, false }, 1837 { "ProcReadAuxVecs", &ProcReadAuxVecs, false }, 1838 { "ProcReadMappings", &ProcReadMappings, false }, 1839 { "ProcReadThreads", &ProcReadThreads, false }, 1840 { "ProcReadMiscInfo", &ProcReadMiscInfo, false } 1819 1841 }; 1820 1842 … … 1824 1846 if (RT_FAILURE(rc)) 1825 1847 { 1826 CORELOGREL (("DumpCore: %s failed. rc=%Rrc\n", aAccumulators[i].pszName, rc));1848 CORELOGRELSYS((CORELOG_NAME "CreateCore: %s failed. rc=%Rrc\n", aAccumulators[i].pszName, rc)); 1827 1849 if (!aAccumulators[i].fOptional) 1828 1850 break; … … 1839 1861 } 1840 1862 else 1841 CORELOGREL (("DumpCore: AllocMemoryArea failed. rc=%Rrc\n", rc));1863 CORELOGRELSYS((CORELOG_NAME "CreateCore: AllocMemoryArea failed. rc=%Rrc\n", rc)); 1842 1864 } 1843 1865 else 1844 CORELOGREL (("DumpCore: ReadProcStatus failed. rc=%Rrc\n", rc));1866 CORELOGRELSYS((CORELOG_NAME "CreateCore: ProcReadStatus failed. rc=%Rrc\n", rc)); 1845 1867 } 1846 1868 else 1847 1869 { 1848 CORELOGREL (("DumpCore: IsProcArchNative failed.\n"));1870 CORELOGRELSYS((CORELOG_NAME "CreateCore: IsProcessArchNative failed.\n")); 1849 1871 rc = VERR_BAD_EXE_FORMAT; 1850 1872 } 1851 1873 } 1852 1874 else 1853 CORELOGREL (("DumpCore: ReadProcInfo failed. rc=%Rrc\n", rc));1875 CORELOGRELSYS((CORELOG_NAME "CreateCore: ProcReadInfo failed. rc=%Rrc\n", rc)); 1854 1876 1855 1877 /* … … 1859 1881 } 1860 1882 else 1861 CORELOG(( "DumpCore: SuspendAllThreads failed. Thread bomb!?! rc=%Rrc\n", rc));1883 CORELOG((CORELOG_NAME "CreateCore: SuspendAllThreads failed. Thread bomb!?! rc=%Rrc\n", rc)); 1862 1884 1863 1885 return rc; … … 1872 1894 * @return VBox status code. 1873 1895 */ 1874 intDestroyCore(PVBOXCORE pVBoxCore)1896 static int rtCoreDumperDestroyCore(PVBOXCORE pVBoxCore) 1875 1897 { 1876 1898 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1884 1906 1885 1907 1886 void CoreSigHandler(int Sig, siginfo_t *pSigInfo, void *pvArg) 1887 { 1888 CORELOG(("CoreSigHandler Sig=%d pvArg=%p\n", Sig, pvArg)); 1889 1890 ucontext_t *pContext = (ucontext_t *)pvArg; 1908 /** 1909 * Takes a core dump. This function has no other parameters than the context 1910 * because it can be called from signal handlers. 1911 * 1912 * @param pContext The context of the caller. 1913 * @returns VBox status code. 1914 */ 1915 static int rtCoreDumperTakeDump(ucontext_t *pContext) 1916 { 1891 1917 if (!pContext) 1892 CORELOGREL(("CoreSigHandler: Missing context.\n")); 1918 { 1919 CORELOGRELSYS((CORELOG_NAME "TakeDump: Missing context.\n")); 1920 return VERR_INVALID_POINTER; 1921 } 1922 1923 /* 1924 * Take a snapshot, then dump core to disk, all threads except this one are halted 1925 * from before taking the snapshot until writing the core is completely finished. 1926 * Any errors would resume all threads if they were halted. 1927 */ 1928 VBOXCORE VBoxCore; 1929 RT_ZERO(VBoxCore); 1930 int rc = rtCoreDumperCreateCore(&VBoxCore, pContext); 1931 if (RT_SUCCESS(rc)) 1932 { 1933 rc = rtCoreDumperWriteCore(&VBoxCore, &WriteFileNoIntr); 1934 if (RT_SUCCESS(rc)) 1935 CORELOGRELSYS((CORELOG_NAME "Success! Core written to %s\n", VBoxCore.szCorePath)); 1936 else 1937 CORELOGRELSYS((CORELOG_NAME "TakeDump: WriteCore failed. szCorePath=%s rc=%Rrc\n", VBoxCore.szCorePath, rc)); 1938 1939 rtCoreDumperDestroyCore(&VBoxCore); 1940 } 1893 1941 else 1894 { 1895 if (!ASMAtomicUoReadBool(&g_fCoreDumpInProgress)) 1896 { 1897 ASMAtomicWriteBool(&g_fCoreDumpInProgress, true); 1898 1942 CORELOGRELSYS((CORELOG_NAME "TakeDump: CreateCore failed. rc=%Rrc\n", rc)); 1943 1944 return rc; 1945 } 1946 1947 1948 /** 1949 * The signal handler that will be invoked to take core dumps. 1950 * 1951 * @param Sig The signal that invoked us. 1952 * @param pSigInfo The signal information. 1953 * @param pvArg Opaque pointer to the caller context structure, 1954 * this cannot be NULL. 1955 */ 1956 static void rtCoreDumperSignalHandler(int Sig, siginfo_t *pSigInfo, void *pvArg) 1957 { 1958 CORELOG((CORELOG_NAME "SignalHandler Sig=%d pvArg=%p\n", Sig, pvArg)); 1959 1960 int rc = VERR_GENERAL_FAILURE; 1961 bool fCallSystemDump = false; 1962 if (ASMAtomicUoReadBool(&g_fCoreDumpInProgress) == false) 1963 { 1964 ASMAtomicWriteBool(&g_fCoreDumpInProgress, true); 1965 ASMAtomicWriteU64(&g_CoreDumpThread, (uint64_t)RTThreadSelf()); 1966 1967 rc = rtCoreDumperTakeDump((ucontext_t *)pvArg); 1968 1969 ASMAtomicWriteU64(&g_CoreDumpThread, NIL_RTTHREAD); 1970 ASMAtomicWriteBool(&g_fCoreDumpInProgress, false); 1971 1972 if (RT_FAILURE(rc)) 1973 { 1899 1974 /* 1900 * Take a snapshot, then dump core to disk, all threads except this one are halted 1901 * from before taking the snapshot until writing the core is completely finished. 1902 * Any errors would resume all threads if they were halted. 1975 * If it is NOT a deliberate dump taken by us & our handler fails we assume the 1976 * worst, try to use the system signal handler and abort the process. 1903 1977 */ 1904 VBOXCORE VBoxCore; 1905 RT_ZERO(VBoxCore); 1906 int rc = CreateCore(&VBoxCore, pContext); 1907 if (RT_SUCCESS(rc)) 1908 { 1909 rc = WriteCore(&VBoxCore, &WriteFileNoIntr); 1910 if (RT_SUCCESS(rc)) 1911 CORELOG(("CoreSigHandler: Successfully wrote core file to disk.\n")); 1912 else 1913 CORELOGREL(("CoreSigHandler: WriteCore failed. rc=%Rrc\n", rc)); 1914 1915 DestroyCore(&VBoxCore); 1916 } 1917 else 1918 CORELOGREL(("CoreSigHandler: CreateCore failed. rc=%Rrc\n", rc)); 1919 1920 ASMAtomicWriteBool(&g_fCoreDumpInProgress, false); 1921 } 1978 CORELOGRELSYS((CORELOG_NAME "TakeDump failed! rc=%Rrc\n", rc)); 1979 if (ASMAtomicReadBool(&g_fCoreDumpDeliberate) == false) 1980 fCallSystemDump = true; 1981 } 1982 } 1983 else 1984 { 1985 /* 1986 * Core dumping is already in progress and we've somehow ended up being 1987 * signalled again. 1988 */ 1989 rc = VERR_INTERNAL_ERROR; 1990 1991 /* 1992 * If our dumper has crashed. No point in waiting, trigger the system one. 1993 * Wait only when the dumping thread is not the one generating this signal. 1994 */ 1995 if (ASMAtomicReadU64(&g_CoreDumpThread) != (uint64_t)RTThreadSelf()) 1996 fCallSystemDump = true; 1922 1997 else 1923 1998 { 1924 /* @todo detect if we are awaiting for ourselves, if so don't. */ 1925 CORELOGREL(("CoreSigHandler: Core dump already in progress! Waiting before signalling Sig=%d.\n", Sig)); 1999 CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dump already in progress! Waiting before signalling Sig=%d.\n", Sig)); 1926 2000 int64_t iTimeout = 10000; /* timeout (ms) */ 1927 while ( !ASMAtomicUoReadBool(&g_fCoreDumpInProgress))2001 while (ASMAtomicUoReadBool(&g_fCoreDumpInProgress) == true) 1928 2002 { 1929 2003 RTThreadSleep(200); … … 1933 2007 } 1934 2008 if (iTimeout <= 0) 1935 CORELOGREL(("CoreSigHandler: Core dump seems to be stuck. Signalling new signal %d\n", Sig)); 1936 } 1937 } 1938 1939 signal(Sig, SIG_DFL); 1940 kill((int)getpid(), Sig); 1941 } 1942 1943 1944 static DECLCALLBACK(int) SleepyThread(RTTHREAD Thread, void *pvUser) 1945 { 1946 NOREF(pvUser); 1947 sleep(10000); 2009 { 2010 fCallSystemDump = true; 2011 CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dump seems to be stuck. Signalling new signal %d\n", Sig)); 2012 } 2013 } 2014 } 2015 2016 if (fCallSystemDump) 2017 { 2018 signal(Sig, SIG_DFL); 2019 raise(Sig); 2020 } 2021 } 2022 2023 2024 /** 2025 * Take a core dump of the current process without terminating it. 2026 * 2027 * @returns IPRT status code. 2028 * @param pszOutputFile Name of the core file. If NULL use the 2029 * default naming scheme. 2030 */ 2031 RTDECL(int) RTCoreDumperTakeDump(const char *pszOutputFile) 2032 { 2033 if (ASMAtomicReadBool(&g_fCoreDumpSignalSetup) == false) 2034 return VERR_WRONG_ORDER; 2035 2036 RT_ZERO(g_szCoreDumpFile); 2037 if (pszOutputFile) 2038 RTStrCopy(g_szCoreDumpFile, sizeof(g_szCoreDumpFile), pszOutputFile); 2039 2040 ASMAtomicWriteBool(&g_fCoreDumpDeliberate, true); 2041 raise(SIGSEGV); 2042 ASMAtomicWriteBool(&g_fCoreDumpDeliberate, false); 1948 2043 return VINF_SUCCESS; 1949 2044 } 1950 2045 1951 2046 1952 int main() 1953 { 1954 RTR3Init(); 1955 CORELOG(("tstRTCoreDump: TESTING pid=%d\n", getpid())); 2047 /** 2048 * Sets up and enables the core dumper. 2049 * 2050 * Installs signal / unhandled exception handlers for catching fatal errors 2051 * that should result in a core dump. If you wish to install your own handlers 2052 * you should do that after calling this function and make sure you pass on 2053 * events you don't handle. 2054 * 2055 * This can be called multiple times to change the settings without needing to 2056 * call RTCoreDumperDisable in between. 2057 * 2058 * @param pszOutputDir The directory to store the cores in. If NULL 2059 * the current directory will be used. 2060 * @param pszBaseName Base file name, no directory. If NULL the 2061 * dumper will generate an appropriate name. 2062 * @param fFlags Reserved for later, MBZ. 2063 */ 2064 RTDECL(int) RTCoreDumperSetup(const char *pszOutputDir, uint32_t fFlags) 2065 { 2066 /* 2067 * Validate flags. 2068 */ 2069 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); 1956 2070 1957 2071 /* 1958 2072 * Install core dump signal handler. 1959 2073 */ 1960 struct sigaction sigAction; 1961 sigAction.sa_sigaction = CoreSigHandler; 1962 sigemptyset(&sigAction.sa_mask); 1963 sigAction.sa_flags = SA_RESTART | SA_SIGINFO; 1964 sigaction(SIGSEGV, &sigAction, NULL); 1965 sigaction(SIGBUS, &sigAction, NULL); 1966 sigaction(SIGUSR1, &sigAction, NULL); 1967 2074 struct sigaction sigAct; 2075 sigAct.sa_sigaction = &rtCoreDumperSignalHandler; 2076 sigemptyset(&sigAct.sa_mask); 2077 sigAct.sa_flags = SA_RESTART | SA_SIGINFO; 2078 sigaction(SIGSEGV, &sigAct, NULL); 2079 sigaction(SIGBUS, &sigAct, NULL); 2080 2081 ASMAtomicWriteBool(&g_fCoreDumpSignalSetup, true); 2082 2083 RT_ZERO(g_szCoreDumpDir); 2084 if (pszOutputDir) 2085 RTStrCopy(g_szCoreDumpDir, sizeof(g_szCoreDumpDir), pszOutputDir); 2086 2087 ASMAtomicWriteU32(&g_fCoreDumpFlags, fFlags); 2088 2089 return VINF_SUCCESS; 2090 } 2091 2092 2093 /** 2094 * Disables the core dumper, i.e. undoes what RTCoreDumperSetup did. 2095 * 2096 * @returns IPRT status code. 2097 */ 2098 RTDECL(int) RTCoreDumperDisable(void) 2099 { 1968 2100 /* 1969 * Spawn a few threads.2101 * Remove core dump signal handler & reset variables. 1970 2102 */ 1971 RTTHREAD ahThreads[5]; 1972 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) 1973 { 1974 int rc = RTThreadCreate(&ahThreads[i], SleepyThread, &ahThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "TEST1"); 1975 if (RT_FAILURE(rc)) 1976 { 1977 CORELOG(("tstRTCoreDump: FAILURE(%d) - %d RTThreadCreate failed, rc=%Rrc\n", __LINE__, i, rc)); 1978 g_cErrors++; 1979 ahThreads[i] = NIL_RTTHREAD; 1980 break; 1981 } 1982 } 1983 1984 CORELOG(("Spawned %d threads\n", RT_ELEMENTS(ahThreads))); 1985 1986 /* 1987 * Send signal to dump core. 1988 */ 1989 kill(getpid(), SIGSEGV); 1990 g_cErrors++; 1991 1992 sleep(10); 1993 1994 /* 1995 * Summary. 1996 */ 1997 if (!g_cErrors) 1998 CORELOG(("tstRTCoreDump: SUCCESS\n")); 1999 else 2000 CORELOG(("tstRTCoreDump: FAILURE - %d errors\n", g_cErrors)); 2001 2002 return !!g_cErrors; 2003 } 2004 2103 signal(SIGSEGV, SIG_DFL); 2104 signal(SIGBUS, SIG_DFL); 2105 ASMAtomicWriteBool(&g_fCoreDumpSignalSetup, false); 2106 2107 RT_ZERO(g_szCoreDumpDir); 2108 RT_ZERO(g_szCoreDumpFile); 2109 return VINF_SUCCESS; 2110 } 2111 -
trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
r31822 r31860 61 61 62 62 /** 63 * ELF NOTE header.63 * ELFNOTEHDR: ELF NOTE header. 64 64 */ 65 65 typedef struct ELFNOTEHDR … … 70 70 typedef ELFNOTEHDR *PELFNOTEHDR; 71 71 72 72 73 #ifdef RT_OS_SOLARIS 74 /** 75 * VBOXSOLMAPINFO: Memory mapping description. 76 */ 73 77 typedef struct VBOXSOLMAPINFO 74 78 { … … 79 83 typedef VBOXSOLMAPINFO *PVBOXSOLMAPINFO; 80 84 85 /** 86 * VBOXSOLCORETYPE: Whether this is an old or new style core. 87 */ 88 typedef enum VBOXSOLCORETYPE 89 { 90 enmOldEra = 0x01d, /* old */ 91 enmNewEra = 0x5c151 /* sci-fi */ 92 } VBOXSOLCORETYPE; 93 94 /** 95 * VBOXSOLTHREADINFO: Per-Thread information. 96 */ 81 97 typedef struct VBOXSOLTHREADINFO 82 98 { … … 88 104 #endif 89 105 90 typedef int (*PFNCOREREADER)(RTFILE hFile, void *pv, size_t cb);91 typedef int (*PFNCOREWRITER)(RTFILE hFile, const void *pcv, size_t cb);92 106 107 /** 108 * VBOXPROCESS: Current (also the core target) process information. 109 */ 93 110 typedef struct VBOXPROCESS 94 111 { … … 127 144 typedef VBOXPROCESS *PVBOXPROCESS; 128 145 146 typedef int (*PFNCOREREADER)(RTFILE hFile, void *pv, size_t cb); 147 typedef int (*PFNCOREWRITER)(RTFILE hFile, const void *pcv, size_t cb); 148 149 /** 150 * VBOXCORE: Core file object. 151 */ 129 152 typedef struct VBOXCORE 130 153 { … … 142 165 typedef VBOXCORE *PVBOXCORE; 143 166 144 typedef int (*PFNCOREACCUMULATOR)(PVBOXCORE pVBoxCOre); 167 typedef int (*PFNCOREACCUMULATOR)(PVBOXCORE pVBoxCore); 168 -
trunk/src/VBox/Runtime/testcase/tstRTCoreDump.cpp
r31820 r31860 29 29 *******************************************************************************/ 30 30 #include <iprt/types.h> 31 #include <iprt/file.h>32 31 #include <iprt/err.h> 33 #include <iprt/dir.h>34 #include <iprt/path.h>35 #include <iprt/string.h>36 #include <iprt/stream.h>37 32 #include <iprt/initterm.h> 38 33 #include <iprt/thread.h> 39 #include <iprt/param.h> 40 #include <iprt/asm.h> 41 #include "tstRTCoreDump.h" 34 #include <iprt/stream.h> 35 #include <iprt/coredumper.h> 42 36 43 #ifdef RT_OS_SOLARIS44 # include <signal.h>45 # include <unistd.h>46 # include <errno.h>47 # include <zone.h>48 # include <sys/proc.h>49 # include <sys/sysmacros.h>50 # include <sys/systeminfo.h>51 # include <sys/mman.h>52 #endif /* RT_OS_SOLARIS */53 37 54 38 /******************************************************************************* 55 * Defined Constants And Macros*39 * Globals * 56 40 *******************************************************************************/ 57 #define CORELOG(a) RTPrintf a58 #define CORELOGREL(a) RTPrintf a59 60 /**61 * VBOXSOLCORETYPE: Whether this is an old or new style core.62 */63 typedef enum VBOXSOLCORETYPE64 {65 enmOldEra = 0x01d, /* old */66 enmNewEra = 0x5c151 /* sci-fi */67 } VBOXSOLCORETYPE;68 69 41 static unsigned volatile g_cErrors = 0; 70 71 volatile bool g_fCoreDumpInProgress = false;72 73 74 /**75 * Determines endianness of the system. Just for completeness.76 *77 * @return Will return false if system is little endian, true otherwise.78 */79 static bool IsBigEndian()80 {81 const int i = 1;82 char *p = (char *)&i;83 if (p[0] == 1)84 return false;85 return true;86 }87 88 89 /**90 * Reads from a file making sure an interruption doesn't cause a failure.91 *92 * @param hFile Handle to the file to read.93 * @param pv Where to store the read data.94 * @param cbToRead Size of data to read.95 *96 * @return VBox status code.97 */98 static int ReadFileNoIntr(RTFILE hFile, void *pv, size_t cbToRead)99 {100 int rc = VERR_READ_ERROR;101 while (1)102 {103 rc = RTFileRead(hFile, pv, cbToRead, NULL /* Read all */);104 if (rc == VERR_INTERRUPTED)105 continue;106 break;107 }108 return rc;109 }110 111 112 /**113 * Writes to a file making sure an interruption doesn't cause a failure.114 *115 * @param hFile Handle to the file to write.116 * @param pv Pointer to what to write.117 * @param cbToRead Size of data to write.118 *119 * @return VBox status code.120 */121 static int WriteFileNoIntr(RTFILE hFile, const void *pcv, size_t cbToRead)122 {123 int rc = VERR_READ_ERROR;124 while (1)125 {126 rc = RTFileWrite(hFile, pcv, cbToRead, NULL /* Write all */);127 if (rc == VERR_INTERRUPTED)128 continue;129 break;130 }131 return rc;132 }133 134 135 /**136 * Read from a given offet in the process' address space.137 *138 * @param pVBoxProc Pointer to the VBox process.139 * @param pv Where to read the data into.140 * @param cb Size of the read buffer.141 * @param off Offset to read from.142 *143 * @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR.144 */145 static ssize_t ReadProcAddrSpace(PVBOXPROCESS pVBoxProc, RTFOFF off, void *pvBuf, size_t cbToRead)146 {147 while (1)148 {149 int rc = RTFileReadAt(pVBoxProc->hAs, off, pvBuf, cbToRead, NULL);150 if (rc == VERR_INTERRUPTED)151 continue;152 return rc;153 }154 }155 156 157 /**158 * Determines if the current process' architecture is suitable for dumping core.159 *160 * @param pVBoxProc Pointer to the VBox process.161 *162 * @return true if the architecture matches the current one.163 */164 inline bool IsProcArchNative(PVBOXPROCESS pVBoxProc)165 {166 return pVBoxProc->ProcInfo.pr_dmodel == PR_MODEL_NATIVE;167 }168 169 170 /**171 * Helper function to get the size of a file given it's path.172 *173 * @param pszPath Pointer to the full path of the file.174 *175 * @return The size of the file in bytes.176 */177 size_t GetFileSize(const char *pszPath)178 {179 size_t cb = 0;180 RTFILE hFile;181 int rc = RTFileOpen(&hFile, pszPath, RTFILE_O_OPEN | RTFILE_O_READ);182 if (RT_SUCCESS(rc))183 {184 RTFileGetSize(hFile, (uint64_t *)&cb);185 RTFileClose(hFile);186 }187 else188 CORELOGREL(("GetFileSize failed to open %s rc=%Rrc\n", pszPath, rc));189 return cb;190 }191 192 193 /**194 * Pre-compute and pre-allocate sufficient memory for dumping core.195 * This is meant to be called once, as a single-large anonymously196 * mapped memory area which will be used during the core dumping routines.197 *198 * @param pVBoxCore Pointer to the core object.199 *200 * @return VBox status code.201 */202 int AllocMemoryArea(PVBOXCORE pVBoxCore)203 {204 AssertReturn(pVBoxCore->pvCore == NULL, VERR_ALREADY_EXISTS);205 AssertReturn(pVBoxCore->VBoxProc.Process != NIL_RTPROCESS, VERR_PROCESS_NOT_FOUND);206 207 struct VBOXSOLPREALLOCTABLE208 {209 const char *pszFilePath; /* Proc based path */210 size_t cbHeader; /* Size of header */211 size_t cbEntry; /* Size of each entry in file */212 size_t cbAccounting; /* Size of each accounting entry per entry */213 } aPreAllocTable[] = {214 { "/proc/%d/map", 0, sizeof(prmap_t), sizeof(VBOXSOLMAPINFO) },215 { "/proc/%d/auxv", 0, 0, 0 },216 { "/proc/%d/lpsinfo", sizeof(prheader_t), sizeof(lwpsinfo_t), sizeof(VBOXSOLTHREADINFO) },217 { "/proc/%d/lstatus", 0, 0, 0 },218 { "/proc/%d/ldt", 0, 0, 0 },219 { "/proc/%d/cred", sizeof(prcred_t), sizeof(gid_t), 1 },220 { "/proc/%d/priv", sizeof(prpriv_t), sizeof(priv_chunk_t), 1 },221 };222 223 size_t cb = 0;224 for (int i = 0; i < (int)RT_ELEMENTS(aPreAllocTable); i++)225 {226 char szPath[PATH_MAX];227 RTStrPrintf(szPath, sizeof(szPath), aPreAllocTable[i].pszFilePath, (int)pVBoxCore->VBoxProc.Process);228 size_t cbFile = GetFileSize(szPath);229 cb += cbFile;230 if ( cbFile > 0231 && aPreAllocTable[i].cbEntry > 0232 && aPreAllocTable[i].cbAccounting > 0)233 {234 cb += ((cbFile - aPreAllocTable[i].cbHeader) / aPreAllocTable[i].cbEntry) * aPreAllocTable[i].cbAccounting;235 cb += aPreAllocTable[i].cbHeader;236 }237 }238 239 /*240 * Make Room for our own mapping accountant entry which will also be included in the core.241 */242 cb += sizeof(VBOXSOLMAPINFO);243 244 /*245 * Allocate the required space, plus some extra room.246 */247 cb += _128K;248 void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1 /* fd */, 0 /* offset */);249 if (pv)250 {251 CORELOG(("AllocMemoryArea: memory area of %u bytes allocated.\n", cb));252 pVBoxCore->pvCore = pv;253 pVBoxCore->pvFree = pv;254 pVBoxCore->cbCore = cb;255 return VINF_SUCCESS;256 }257 else258 {259 CORELOGREL(("AllocMemoryArea: failed cb=%u\n", cb));260 return VERR_NO_MEMORY;261 }262 }263 264 265 /**266 * Free memory area used by the core object.267 *268 * @param pVBoxCore Pointer to the core object.269 */270 void FreeMemoryArea(PVBOXCORE pVBoxCore)271 {272 AssertReturnVoid(pVBoxCore);273 AssertReturnVoid(pVBoxCore->pvCore);274 AssertReturnVoid(pVBoxCore->cbCore > 0);275 276 munmap(pVBoxCore->pvCore, pVBoxCore->cbCore);277 CORELOG(("FreeMemoryArea: memory area of %u bytes freed.\n", pVBoxCore->cbCore));278 279 pVBoxCore->pvCore = NULL;280 pVBoxCore->pvFree= NULL;281 pVBoxCore->cbCore = 0;282 }283 284 285 /**286 * Get a chunk from the area of allocated memory.287 *288 * @param pVBoxCore Pointer to the core object.289 * @param cb Size of requested chunk.290 *291 * @return Pointer to allocated memory, or NULL on failure.292 */293 void *GetMemoryChunk(PVBOXCORE pVBoxCore, size_t cb)294 {295 AssertReturn(pVBoxCore, NULL);296 AssertReturn(pVBoxCore->pvCore, NULL);297 AssertReturn(pVBoxCore->pvFree, NULL);298 299 size_t cbAllocated = (char *)pVBoxCore->pvFree - (char *)pVBoxCore->pvCore;300 if (cbAllocated < pVBoxCore->cbCore)301 {302 char *pb = (char *)pVBoxCore->pvFree;303 pVBoxCore->pvFree = pb + cb;304 return pb;305 }306 307 return NULL;308 }309 310 311 /**312 * Reads the proc file's content into a newly allocated buffer.313 *314 * @param pVBoxCore Pointer to the core object.315 * @param pszFileFmt Only the name of the file to read from (/proc/<pid> will be prepended)316 * @param ppv Where to store the allocated buffer.317 * @param pcb Where to store size of the buffer.318 *319 * @return VBox status code.320 */321 int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)322 {323 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);324 325 char szPath[PATH_MAX];326 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/%s", (int)pVBoxCore->VBoxProc.Process, pszProcFileName);327 RTFILE hFile;328 int rc = RTFileOpen(&hFile, szPath, RTFILE_O_OPEN | RTFILE_O_READ);329 if (RT_SUCCESS(rc))330 {331 RTFileGetSize(hFile, (uint64_t *)pcb);332 if (*pcb > 0)333 {334 *ppv = GetMemoryChunk(pVBoxCore, *pcb);335 if (*ppv)336 rc = ReadFileNoIntr(hFile, *ppv, *pcb);337 else338 rc = VERR_NO_MEMORY;339 }340 else341 {342 *pcb = 0;343 *ppv = NULL;344 }345 RTFileClose(hFile);346 }347 else348 CORELOGREL(("ProcReadFileInto: failed to open %s. rc=%Rrc\n", szPath, rc));349 return rc;350 }351 352 353 /**354 * Read process information (format psinfo_t) from /proc.355 *356 * @param pVBoxCore Pointer to the core object.357 *358 * @return VBox status code.359 */360 int ReadProcInfo(PVBOXCORE pVBoxCore)361 {362 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);363 364 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;365 char szPath[PATH_MAX];366 RTFILE hFile;367 368 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/psinfo", (int)pVBoxProc->Process);369 int rc = RTFileOpen(&hFile, szPath, RTFILE_O_OPEN | RTFILE_O_READ);370 if (RT_SUCCESS(rc))371 {372 size_t cbProcInfo = sizeof(psinfo_t);373 rc = ReadFileNoIntr(hFile, &pVBoxProc->ProcInfo, cbProcInfo);374 }375 376 RTFileClose(hFile);377 return rc;378 }379 380 381 /**382 * Read process status (format pstatus_t) from /proc.383 *384 * @param pVBoxCore Pointer to the core object.385 *386 * @return VBox status code.387 */388 int ReadProcStatus(PVBOXCORE pVBoxCore)389 {390 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);391 392 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;393 394 char szPath[PATH_MAX];395 RTFILE hFile;396 397 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/status", (int)pVBoxProc->Process);398 int rc = RTFileOpen(&hFile, szPath, RTFILE_O_OPEN | RTFILE_O_READ);399 if (RT_SUCCESS(rc))400 {401 size_t cbRead;402 size_t cbProcStatus = sizeof(pstatus_t);403 AssertCompile(sizeof(pstatus_t) == sizeof(pVBoxProc->ProcStatus));404 rc = ReadFileNoIntr(hFile, &pVBoxProc->ProcStatus, cbProcStatus);405 }406 RTFileClose(hFile);407 return rc;408 }409 410 411 /**412 * Read process credential information (format prcred_t + array of guid_t)413 *414 * @param pVBoxCore Pointer to the core object.415 *416 * @remarks Should not be called before successful call to @see AllocMemoryArea()417 * @return VBox status code.418 */419 int ReadProcCred(PVBOXCORE pVBoxCore)420 {421 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);422 423 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;424 return ProcReadFileInto(pVBoxCore, "cred", &pVBoxProc->pvCred, &pVBoxProc->cbCred);425 }426 427 428 /**429 * Read process privilege information (format prpriv_t + array of priv_chunk_t)430 *431 * @param pVBoxCore Pointer to the core object.432 *433 * @remarks Should not be called before successful call to @see AllocMemoryArea()434 * @return VBox status code.435 */436 int ReadProcPriv(PVBOXCORE pVBoxCore)437 {438 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);439 440 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;441 int rc = ProcReadFileInto(pVBoxCore, "priv", (void **)&pVBoxProc->pPriv, &pVBoxProc->cbPriv);442 if (RT_FAILURE(rc))443 return rc;444 pVBoxProc->pcPrivImpl = getprivimplinfo();445 if (!pVBoxProc->pcPrivImpl)446 {447 CORELOGREL(("ReadProcPriv: getprivimplinfo returned NULL.\n"));448 return VERR_INVALID_STATE;449 }450 return rc;451 }452 453 454 /**455 * Read process LDT information (format array of struct ssd) from /proc.456 *457 * @param pVBoxProc Pointer to the core object.458 *459 * @remarks Should not be called before successful call to @see AllocMemoryArea()460 * @return VBox status code.461 */462 int ReadProcLdt(PVBOXCORE pVBoxCore)463 {464 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);465 466 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;467 return ProcReadFileInto(pVBoxCore, "ldt", &pVBoxProc->pvLdt, &pVBoxProc->cbLdt);468 }469 470 471 /**472 * Read process auxiliary vectors (format auxv_t) for the process.473 *474 * @param pVBoxCore Pointer to the core object.475 *476 * @remarks Should not be called before successful call to @see AllocMemoryArea()477 * @return VBox status code.478 */479 int ReadProcAuxVecs(PVBOXCORE pVBoxCore)480 {481 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);482 483 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;484 char szPath[PATH_MAX];485 RTFILE hFile = NIL_RTFILE;486 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/auxv", (int)pVBoxProc->Process);487 int rc = RTFileOpen(&hFile, szPath, RTFILE_O_OPEN | RTFILE_O_READ);488 if (RT_FAILURE(rc))489 {490 CORELOGREL(("ReadProcAuxVecs: RTFileOpen %s failed rc=%Rrc\n", szPath, rc));491 return rc;492 }493 494 size_t cbAuxFile = 0;495 RTFileGetSize(hFile, (uint64_t *)&cbAuxFile);496 if (cbAuxFile >= sizeof(auxv_t))497 {498 pVBoxProc->pAuxVecs = (auxv_t*)GetMemoryChunk(pVBoxCore, cbAuxFile + sizeof(auxv_t));499 if (pVBoxProc->pAuxVecs)500 {501 rc = ReadFileNoIntr(hFile, pVBoxProc->pAuxVecs, cbAuxFile);502 if (RT_SUCCESS(rc))503 {504 /* Terminate list of vectors */505 pVBoxProc->cAuxVecs = cbAuxFile / sizeof(auxv_t);506 CORELOG(("ReadProcAuxVecs: cbAuxFile=%u auxv_t size %d cAuxVecs=%u\n", cbAuxFile, sizeof(auxv_t), pVBoxProc->cAuxVecs));507 if (pVBoxProc->cAuxVecs > 0)508 {509 pVBoxProc->pAuxVecs[pVBoxProc->cAuxVecs].a_type = AT_NULL;510 pVBoxProc->pAuxVecs[pVBoxProc->cAuxVecs].a_un.a_val = 0L;511 RTFileClose(hFile);512 return VINF_SUCCESS;513 }514 else515 {516 CORELOGREL(("ReadProcAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs));517 rc = VERR_READ_ERROR;518 }519 }520 else521 CORELOGREL(("ReadProcAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile));522 523 pVBoxProc->pAuxVecs = NULL;524 pVBoxProc->cAuxVecs = 0;525 }526 else527 {528 CORELOGREL(("ReadProcAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t)));529 rc = VERR_NO_MEMORY;530 }531 }532 else533 CORELOGREL(("ReadProcAuxVecs: aux file too small %u, expecting %u or more\n", cbAuxFile, sizeof(auxv_t)));534 535 RTFileClose(hFile);536 return rc;537 }538 539 540 /*541 * Find an element in the process' auxiliary vector.542 */543 long GetAuxVal(PVBOXPROCESS pVBoxProc, int Type)544 {545 AssertReturn(pVBoxProc, -1);546 if (pVBoxProc->pAuxVecs)547 {548 auxv_t *pAuxVec = pVBoxProc->pAuxVecs;549 for (; pAuxVec->a_type != AT_NULL; pAuxVec++)550 {551 if (pAuxVec->a_type == Type)552 return pAuxVec->a_un.a_val;553 }554 }555 return -1;556 }557 558 559 /**560 * Read the process mappings (format prmap_t array).561 *562 * @param pVBoxCore Pointer to the core object.563 *564 * @remarks Should not be called before successful call to @see AllocMemoryArea()565 * @return VBox status code.566 */567 int ReadProcMappings(PVBOXCORE pVBoxCore)568 {569 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);570 571 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;572 char szPath[PATH_MAX];573 RTFILE hFile = NIL_RTFILE;574 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/map", (int)pVBoxProc->Process);575 int rc = RTFileOpen(&hFile, szPath, RTFILE_O_OPEN | RTFILE_O_READ);576 if (RT_FAILURE(rc))577 return rc;578 579 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/as", (int)pVBoxProc->Process);580 rc = RTFileOpen(&pVBoxProc->hAs, szPath, RTFILE_O_OPEN | RTFILE_O_READ);581 if (RT_SUCCESS(rc))582 {583 /*584 * Allocate and read all the prmap_t objects from proc.585 */586 size_t cbMapFile = 0;587 RTFileGetSize(hFile, (uint64_t *)&cbMapFile);588 if (cbMapFile >= sizeof(prmap_t))589 {590 prmap_t *pMap = (prmap_t*)GetMemoryChunk(pVBoxCore, cbMapFile);591 if (pMap)592 {593 rc = ReadFileNoIntr(hFile, pMap, cbMapFile);594 if (RT_SUCCESS(rc))595 {596 pVBoxProc->cMappings = cbMapFile / sizeof(prmap_t);597 if (pVBoxProc->cMappings > 0)598 {599 /*600 * Allocate for each prmap_t object, a corresponding VBOXSOLMAPINFO object.601 */602 pVBoxProc->pMapInfoHead = (PVBOXSOLMAPINFO)GetMemoryChunk(pVBoxCore, pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO));603 if (pVBoxProc->pMapInfoHead)604 {605 /*606 * Associate the prmap_t with the mapping info object.607 */608 Assert(pVBoxProc->pMapInfoHead == NULL);609 PVBOXSOLMAPINFO pCur = pVBoxProc->pMapInfoHead;610 PVBOXSOLMAPINFO pPrev = NULL;611 for (uint64_t i = 0; i < pVBoxProc->cMappings; i++, pMap++, pCur++)612 {613 memcpy(&pCur->pMap, pMap, sizeof(pCur->pMap));614 if (pPrev)615 pPrev->pNext = pCur;616 617 pCur->fError = 0;618 619 /*620 * Make sure we can read the mapping, otherwise mark them to be skipped.621 */622 char achBuf[PAGE_SIZE];623 uint64_t k = 0;624 while (k < pCur->pMap.pr_size)625 {626 size_t cb = RT_MIN(sizeof(achBuf), pCur->pMap.pr_size - k);627 int rc2 = ReadProcAddrSpace(pVBoxProc, pCur->pMap.pr_vaddr + k, &achBuf, cb);628 if (RT_FAILURE(rc2))629 {630 CORELOGREL(("ReadProcMappings: skipping mapping. vaddr=%#x rc=%Rrc\n", pCur->pMap.pr_vaddr, rc2));631 632 /*633 * Instead of storing the actual mapping data which we failed to read, the core634 * will contain an errno in place. So we adjust the prmap_t's size field too635 * so the program header offsets match.636 */637 pCur->pMap.pr_size = RT_ALIGN_Z(sizeof(int), 8);638 pCur->fError = errno;639 if (pCur->fError == 0) /* huh!? somehow errno got reset? fake one! EFAULT is nice. */640 pCur->fError = EFAULT;641 break;642 }643 k += cb;644 }645 646 pPrev = pCur;647 }648 if (pPrev)649 pPrev->pNext = NULL;650 651 RTFileClose(hFile);652 RTFileClose(pVBoxProc->hAs);653 pVBoxProc->hAs = NIL_RTFILE;654 CORELOG(("ReadProcMappings: successfully read in %u mappings\n", pVBoxProc->cMappings));655 return VINF_SUCCESS;656 }657 else658 {659 CORELOGREL(("ReadProcMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));660 rc = VERR_NO_MEMORY;661 }662 }663 else664 {665 CORELOGREL(("ReadProcMappings: Invalid mapping count %u\n", pVBoxProc->cMappings));666 rc = VERR_READ_ERROR;667 }668 }669 else670 CORELOGREL(("ReadProcMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile));671 }672 else673 {674 CORELOGREL(("ReadProcMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile));675 rc = VERR_NO_MEMORY;676 }677 }678 679 RTFileClose(pVBoxProc->hAs);680 pVBoxProc->hAs = NIL_RTFILE;681 }682 else683 CORELOGREL(("ReadProcMappings: failed to open %s. rc=%Rrc\n", szPath, rc));684 685 RTFileClose(hFile);686 return rc;687 }688 689 690 /**691 * Reads the thread information for all threads in the process.692 *693 * @param pVBoxCore Pointer to the core object.694 *695 * @remarks Should not be called before successful call to @see AllocMemoryArea()696 * @return VBox status code.697 */698 int ReadProcThreads(PVBOXCORE pVBoxCore)699 {700 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);701 702 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;703 AssertReturn(pVBoxProc->pCurThreadCtx, VERR_NO_DATA);704 705 /*706 * Read the information for threads.707 * Format: prheader_t + array of lwpsinfo_t's.708 */709 size_t cbInfoHdrAndData;710 void *pvInfoHdr = NULL;711 int rc = ProcReadFileInto(pVBoxCore, "lpsinfo", &pvInfoHdr, &cbInfoHdrAndData);712 if (RT_SUCCESS(rc))713 {714 /*715 * Read the status of threads.716 * Format: prheader_t + array of lwpstatus_t's.717 */718 void *pvStatusHdr = NULL;719 size_t cbStatusHdrAndData;720 rc = ProcReadFileInto(pVBoxCore, "lstatus", &pvStatusHdr, &cbStatusHdrAndData);721 if (RT_SUCCESS(rc))722 {723 prheader_t *pInfoHdr = (prheader_t *)pvInfoHdr;724 prheader_t *pStatusHdr = (prheader_t *)pvStatusHdr;725 lwpstatus_t *pStatus = (lwpstatus_t *)((uintptr_t)pStatusHdr + sizeof(prheader_t));726 lwpsinfo_t *pInfo = (lwpsinfo_t *)((uintptr_t)pInfoHdr + sizeof(prheader_t));727 uint64_t cStatus = pStatusHdr->pr_nent;728 uint64_t cInfo = pInfoHdr->pr_nent;729 730 CORELOG(("ReadProcThreads: read info(%u) status(%u), threads:cInfo=%u cStatus=%u\n", cbInfoHdrAndData, cbStatusHdrAndData, cInfo, cStatus));731 732 /*733 * Minor sanity size check (remember sizeof lwpstatus_t & lwpsinfo_t is <= size in file per entry).734 */735 if ( (cbStatusHdrAndData - sizeof(prheader_t)) % pStatusHdr->pr_entsize == 0736 && (cbInfoHdrAndData - sizeof(prheader_t)) % pInfoHdr->pr_entsize == 0)737 {738 /*739 * Make sure we have a matching lstatus entry for an lpsinfo entry unless740 * it is a zombie thread, in which case we will not have a matching lstatus entry.741 */742 for (; cInfo != 0; cInfo--)743 {744 if (pInfo->pr_sname != 'Z') /* zombie */745 {746 if ( cStatus == 0747 || pStatus->pr_lwpid != pInfo->pr_lwpid)748 {749 CORELOGREL(("ReadProcThreads: cStatus = %u pStatuslwpid=%d infolwpid=%d\n", cStatus, pStatus->pr_lwpid, pInfo->pr_lwpid));750 rc = VERR_INVALID_STATE;751 break;752 }753 pStatus = (lwpstatus_t *)((uintptr_t)pStatus + pStatusHdr->pr_entsize);754 cStatus--;755 }756 pInfo = (lwpsinfo_t *)((uintptr_t)pInfo + pInfoHdr->pr_entsize);757 }758 759 if (RT_SUCCESS(rc))760 {761 /*762 * Threre can still be more lwpsinfo_t's than lwpstatus_t's, build the763 * lists accordingly.764 */765 pStatus = (lwpstatus_t *)((uintptr_t)pStatusHdr + sizeof(prheader_t));766 pInfo = (lwpsinfo_t *)((uintptr_t)pInfoHdr + sizeof(prheader_t));767 cInfo = pInfoHdr->pr_nent;768 cStatus = pInfoHdr->pr_nent;769 770 size_t cbThreadInfo = RT_MAX(cStatus, cInfo) * sizeof(VBOXSOLTHREADINFO);771 pVBoxProc->pThreadInfoHead = (PVBOXSOLTHREADINFO)GetMemoryChunk(pVBoxCore, cbThreadInfo);772 if (pVBoxProc->pThreadInfoHead)773 {774 PVBOXSOLTHREADINFO pCur = pVBoxProc->pThreadInfoHead;775 PVBOXSOLTHREADINFO pPrev = NULL;776 for (uint64_t i = 0; i < cInfo; i++, pCur++)777 {778 pCur->Info = *pInfo;779 if ( pInfo->pr_sname != 'Z'780 && pInfo->pr_lwpid == pStatus->pr_lwpid)781 {782 /*783 * Adjust the context of the dumping thread to reflect the context784 * when the core dump got initiated before whatever signal caused it.785 */786 if ( pStatus /* noid droid */787 && pStatus->pr_lwpid == (id_t)pVBoxProc->hCurThread)788 {789 AssertCompile(sizeof(pStatus->pr_reg) == sizeof(pVBoxProc->pCurThreadCtx->uc_mcontext.gregs));790 AssertCompile(sizeof(pStatus->pr_fpreg) == sizeof(pVBoxProc->pCurThreadCtx->uc_mcontext.fpregs));791 memcpy(&pStatus->pr_reg, &pVBoxProc->pCurThreadCtx->uc_mcontext.gregs, sizeof(pStatus->pr_reg));792 memcpy(&pStatus->pr_fpreg, &pVBoxProc->pCurThreadCtx->uc_mcontext.fpregs, sizeof(pStatus->pr_fpreg));793 794 AssertCompile(sizeof(pStatus->pr_lwphold) == sizeof(pVBoxProc->pCurThreadCtx->uc_sigmask));795 memcpy(&pStatus->pr_lwphold, &pVBoxProc->pCurThreadCtx->uc_sigmask, sizeof(pStatus->pr_lwphold));796 pStatus->pr_ustack = (uintptr_t)&pVBoxProc->pCurThreadCtx->uc_stack;797 798 CORELOG(("ReadProcThreads: patched dumper thread context with pre-dump time context.\n"));799 }800 801 pCur->pStatus = pStatus;802 pStatus = (lwpstatus_t *)((uintptr_t)pStatus + pStatusHdr->pr_entsize);803 }804 else805 {806 CORELOGREL(("ReadProcThreads: missing status for lwp %d\n", pInfo->pr_lwpid));807 pCur->pStatus = NULL;808 }809 810 if (pPrev)811 pPrev->pNext = pCur;812 pPrev = pCur;813 pInfo = (lwpsinfo_t *)((uintptr_t)pInfo + pInfoHdr->pr_entsize);814 }815 if (pPrev)816 pPrev->pNext = NULL;817 818 CORELOG(("ReadProcThreads: successfully read %u threads.\n", cInfo));819 pVBoxProc->cThreads = cInfo;820 return VINF_SUCCESS;821 }822 else823 {824 CORELOGREL(("ReadProcThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));825 rc = VERR_NO_MEMORY;826 }827 }828 else829 CORELOGREL(("ReadProcThreads: Invalid state information for threads.\n", rc));830 }831 else832 {833 CORELOGREL(("ReadProcThreads: huh!? cbStatusHdrAndData=%u prheader_t=%u entsize=%u\n", cbStatusHdrAndData,834 sizeof(prheader_t), pStatusHdr->pr_entsize));835 CORELOGREL(("ReadProcThreads: huh!? cbInfoHdrAndData=%u entsize=%u\n", cbInfoHdrAndData, pStatusHdr->pr_entsize));836 rc = VERR_INVALID_STATE;837 }838 }839 else840 CORELOGREL(("ReadProcThreads: ReadFileNoIntr failed for \"lpsinfo\" rc=%Rrc\n", rc));841 }842 else843 CORELOGREL(("ReadProcThreads: ReadFileNoIntr failed for \"lstatus\" rc=%Rrc\n", rc));844 return rc;845 }846 847 848 /**849 * Reads miscellaneous information that is collected as part of a core file.850 * This may include platform name, zone name and other OS-specific information.851 *852 * @param pVBoxCore Pointer to the core object.853 *854 * @return VBox status code.855 */856 int ReadProcMiscInfo(PVBOXCORE pVBoxCore)857 {858 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);859 860 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;861 862 #ifdef RT_OS_SOLARIS863 /*864 * Read the platform name, uname string and zone name.865 */866 int rc = sysinfo(SI_PLATFORM, pVBoxProc->szPlatform, sizeof(pVBoxProc->szPlatform));867 if (rc == -1)868 {869 CORELOGREL(("ReadProcMiscInfo: sysinfo failed. rc=%d errno=%d\n", rc, errno));870 return VERR_GENERAL_FAILURE;871 }872 pVBoxProc->szPlatform[sizeof(pVBoxProc->szPlatform) - 1] = '\0';873 874 rc = uname(&pVBoxProc->UtsName);875 if (rc == -1)876 {877 CORELOGREL(("ReadProcMiscInfo: uname failed. rc=%d errno=%d\n", rc, errno));878 return VERR_GENERAL_FAILURE;879 }880 881 rc = getzonenamebyid(pVBoxProc->ProcInfo.pr_zoneid, pVBoxProc->szZoneName, sizeof(pVBoxProc->szZoneName));882 if (rc < 0)883 {884 CORELOGREL(("ReadProcMiscInfo: getzonenamebyid failed. rc=%d errno=%d zoneid=%d\n", rc, errno, pVBoxProc->ProcInfo.pr_zoneid));885 return VERR_GENERAL_FAILURE;886 }887 pVBoxProc->szZoneName[sizeof(pVBoxProc->szZoneName) - 1] = '\0';888 rc = VINF_SUCCESS;889 890 #else891 # error Port Me!892 #endif893 return rc;894 }895 896 897 /**898 * On Solaris use the old-style procfs interfaces but the core file still should have this899 * info. for backward and GDB compatibility, hence the need for this ugly function.900 *901 * @param pVBoxCore Pointer to the core object.902 * @param pInfo Pointer to the old prpsinfo_t structure to update.903 */904 void GetOldProcessInfo(PVBOXCORE pVBoxCore, prpsinfo_t *pInfo)905 {906 AssertReturnVoid(pVBoxCore);907 AssertReturnVoid(pInfo);908 909 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;910 psinfo_t *pSrc = &pVBoxProc->ProcInfo;911 memset(pInfo, 0, sizeof(prpsinfo_t));912 pInfo->pr_state = pSrc->pr_lwp.pr_state;913 pInfo->pr_zomb = (pInfo->pr_state == SZOMB);914 RTStrCopy(pInfo->pr_clname, sizeof(pInfo->pr_clname), pSrc->pr_lwp.pr_clname);915 RTStrCopy(pInfo->pr_fname, sizeof(pInfo->pr_fname), pSrc->pr_fname);916 memcpy(&pInfo->pr_psargs, &pSrc->pr_psargs, sizeof(pInfo->pr_psargs));917 pInfo->pr_nice = pSrc->pr_lwp.pr_nice;918 pInfo->pr_flag = pSrc->pr_lwp.pr_flag;919 pInfo->pr_uid = pSrc->pr_uid;920 pInfo->pr_gid = pSrc->pr_gid;921 pInfo->pr_pid = pSrc->pr_pid;922 pInfo->pr_ppid = pSrc->pr_ppid;923 pInfo->pr_pgrp = pSrc->pr_pgid;924 pInfo->pr_sid = pSrc->pr_sid;925 pInfo->pr_addr = (caddr_t)pSrc->pr_addr;926 pInfo->pr_size = pSrc->pr_size;927 pInfo->pr_rssize = pSrc->pr_rssize;928 pInfo->pr_wchan = (caddr_t)pSrc->pr_lwp.pr_wchan;929 pInfo->pr_start = pSrc->pr_start;930 pInfo->pr_time = pSrc->pr_time;931 pInfo->pr_pri = pSrc->pr_lwp.pr_pri;932 pInfo->pr_oldpri = pSrc->pr_lwp.pr_oldpri;933 pInfo->pr_cpu = pSrc->pr_lwp.pr_cpu;934 pInfo->pr_ottydev = cmpdev(pSrc->pr_ttydev);935 pInfo->pr_lttydev = pSrc->pr_ttydev;936 pInfo->pr_syscall = pSrc->pr_lwp.pr_syscall;937 pInfo->pr_ctime = pSrc->pr_ctime;938 pInfo->pr_bysize = pSrc->pr_size * PAGESIZE;939 pInfo->pr_byrssize = pSrc->pr_rssize * PAGESIZE;940 pInfo->pr_argc = pSrc->pr_argc;941 pInfo->pr_argv = (char **)pSrc->pr_argv;942 pInfo->pr_envp = (char **)pSrc->pr_envp;943 pInfo->pr_wstat = pSrc->pr_wstat;944 pInfo->pr_pctcpu = pSrc->pr_pctcpu;945 pInfo->pr_pctmem = pSrc->pr_pctmem;946 pInfo->pr_euid = pSrc->pr_euid;947 pInfo->pr_egid = pSrc->pr_egid;948 pInfo->pr_aslwpid = 0;949 pInfo->pr_dmodel = pSrc->pr_dmodel;950 }951 952 953 /**954 * On Solaris use the old-style procfs interfaces but the core file still should have this955 * info. for backward and GDB compatibility, hence the need for this ugly function.956 *957 * @param pVBoxCore Pointer to the core object.958 * @param pInfo Pointer to the thread info.959 * @param pStatus Pointer to the thread status.960 * @param pDst Pointer to the old-style status structure to update.961 *962 */963 void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)964 {965 AssertReturnVoid(pVBoxCore);966 AssertReturnVoid(pInfo);967 AssertReturnVoid(pStatus);968 AssertReturnVoid(pDst);969 970 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;971 memset(pDst, 0, sizeof(prstatus_t));972 if (pStatus->pr_flags & PR_STOPPED)973 pDst->pr_flags = 0x0001;974 if (pStatus->pr_flags & PR_ISTOP)975 pDst->pr_flags = 0x0002;976 if (pStatus->pr_flags & PR_DSTOP)977 pDst->pr_flags = 0x0004;978 if (pStatus->pr_flags & PR_ASLEEP)979 pDst->pr_flags = 0x0008;980 if (pStatus->pr_flags & PR_FORK)981 pDst->pr_flags = 0x0010;982 if (pStatus->pr_flags & PR_RLC)983 pDst->pr_flags = 0x0020;984 /* PR_PTRACE is never set */985 if (pStatus->pr_flags & PR_PCINVAL)986 pDst->pr_flags = 0x0080;987 if (pStatus->pr_flags & PR_ISSYS)988 pDst->pr_flags = 0x0100;989 if (pStatus->pr_flags & PR_STEP)990 pDst->pr_flags = 0x0200;991 if (pStatus->pr_flags & PR_KLC)992 pDst->pr_flags = 0x0400;993 if (pStatus->pr_flags & PR_ASYNC)994 pDst->pr_flags = 0x0800;995 if (pStatus->pr_flags & PR_PTRACE)996 pDst->pr_flags = 0x1000;997 if (pStatus->pr_flags & PR_MSACCT)998 pDst->pr_flags = 0x2000;999 if (pStatus->pr_flags & PR_BPTADJ)1000 pDst->pr_flags = 0x4000;1001 if (pStatus->pr_flags & PR_ASLWP)1002 pDst->pr_flags = 0x8000;1003 1004 pDst->pr_who = pStatus->pr_lwpid;1005 pDst->pr_why = pStatus->pr_why;1006 pDst->pr_what = pStatus->pr_what;1007 pDst->pr_info = pStatus->pr_info;1008 pDst->pr_cursig = pStatus->pr_cursig;1009 pDst->pr_sighold = pStatus->pr_lwphold;1010 pDst->pr_altstack = pStatus->pr_altstack;1011 pDst->pr_action = pStatus->pr_action;1012 pDst->pr_syscall = pStatus->pr_syscall;1013 pDst->pr_nsysarg = pStatus->pr_nsysarg;1014 pDst->pr_lwppend = pStatus->pr_lwppend;1015 pDst->pr_oldcontext = (ucontext_t *)pStatus->pr_oldcontext;1016 memcpy(pDst->pr_reg, pStatus->pr_reg, sizeof(pDst->pr_reg));1017 memcpy(pDst->pr_sysarg, pStatus->pr_sysarg, sizeof(pDst->pr_sysarg));1018 RTStrCopy(pDst->pr_clname, sizeof(pDst->pr_clname), pStatus->pr_clname);1019 1020 pDst->pr_nlwp = pVBoxProc->ProcStatus.pr_nlwp;1021 pDst->pr_sigpend = pVBoxProc->ProcStatus.pr_sigpend;1022 pDst->pr_pid = pVBoxProc->ProcStatus.pr_pid;1023 pDst->pr_ppid = pVBoxProc->ProcStatus.pr_ppid;1024 pDst->pr_pgrp = pVBoxProc->ProcStatus.pr_pgid;1025 pDst->pr_sid = pVBoxProc->ProcStatus.pr_sid;1026 pDst->pr_utime = pVBoxProc->ProcStatus.pr_utime;1027 pDst->pr_stime = pVBoxProc->ProcStatus.pr_stime;1028 pDst->pr_cutime = pVBoxProc->ProcStatus.pr_cutime;1029 pDst->pr_cstime = pVBoxProc->ProcStatus.pr_cstime;1030 pDst->pr_brkbase = (caddr_t)pVBoxProc->ProcStatus.pr_brkbase;1031 pDst->pr_brksize = pVBoxProc->ProcStatus.pr_brksize;1032 pDst->pr_stkbase = (caddr_t)pVBoxProc->ProcStatus.pr_stkbase;1033 pDst->pr_stksize = pVBoxProc->ProcStatus.pr_stksize;1034 1035 pDst->pr_processor = (short)pInfo->pr_onpro;1036 pDst->pr_bind = (short)pInfo->pr_bindpro;1037 pDst->pr_instr = pStatus->pr_instr;1038 }1039 1040 1041 /**1042 * Count the number of sections which will be dumped into the core file.1043 *1044 * @param pVBoxCore Pointer to the core object.1045 *1046 * @return Number of sections for the core file.1047 */1048 uint32_t CountSections(PVBOXCORE pVBoxCore)1049 {1050 /* @todo sections */1051 NOREF(pVBoxCore);1052 return 0;1053 }1054 1055 1056 /**1057 * Resume all threads of this process.1058 *1059 * @param pVBoxProc Pointer to the VBox process.1060 *1061 * @return VBox error code.1062 */1063 int ResumeAllThreads(PVBOXPROCESS pVBoxProc)1064 {1065 AssertReturn(pVBoxProc, VERR_INVALID_POINTER);1066 1067 char szCurThread[128];1068 char szPath[PATH_MAX];1069 PRTDIR pDir = NULL;1070 1071 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/lwp", (int)pVBoxProc->Process);1072 RTStrPrintf(szCurThread, sizeof(szCurThread), "%d", (int)pVBoxProc->hCurThread);1073 1074 int32_t cRunningThreads = 0;1075 int rc = RTDirOpen(&pDir, szPath);1076 if (RT_SUCCESS(rc))1077 {1078 /*1079 * Loop through all our threads & resume them.1080 */1081 RTDIRENTRY DirEntry;1082 while (RT_SUCCESS(RTDirRead(pDir, &DirEntry, NULL)))1083 {1084 if ( !strcmp(DirEntry.szName, ".")1085 || !strcmp(DirEntry.szName, ".."))1086 continue;1087 1088 if ( !strcmp(DirEntry.szName, szCurThread))1089 continue;1090 1091 int32_t ThreadId = RTStrToInt32(DirEntry.szName);1092 _lwp_continue((lwpid_t)ThreadId);1093 ++cRunningThreads;1094 }1095 1096 CORELOG(("ResumeAllThreads: resumed %d threads\n", cRunningThreads));1097 RTDirClose(pDir);1098 }1099 else1100 {1101 CORELOGREL(("ResumeAllThreads: Failed to open %s\n", szPath));1102 rc = VERR_READ_ERROR;1103 }1104 1105 return rc;1106 }1107 1108 1109 /**1110 * Stop all running threads of this process. Before dumping any1111 * core we need to make sure the process is quiesced.1112 *1113 * @param pVBoxProc Pointer to the VBox process.1114 *1115 * @return VBox error code.1116 */1117 int SuspendAllThreads(PVBOXPROCESS pVBoxProc)1118 {1119 char szCurThread[128];1120 char szPath[PATH_MAX];1121 PRTDIR pDir = NULL;1122 1123 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/lwp", (int)pVBoxProc->Process);1124 RTStrPrintf(szCurThread, sizeof(szCurThread), "%d", (int)pVBoxProc->hCurThread);1125 1126 int rc = -1;1127 uint32_t cThreads = 0;1128 uint16_t cTries = 0;1129 for (cTries = 0; cTries < 10; cTries++)1130 {1131 uint32_t cRunningThreads = 0;1132 rc = RTDirOpen(&pDir, szPath);1133 if (RT_SUCCESS(rc))1134 {1135 /*1136 * Loop through all our threads & suspend them, multiple calls to _lwp_suspend() are okay.1137 */1138 RTDIRENTRY DirEntry;1139 while (RT_SUCCESS(RTDirRead(pDir, &DirEntry, NULL)))1140 {1141 if ( !strcmp(DirEntry.szName, ".")1142 || !strcmp(DirEntry.szName, ".."))1143 continue;1144 1145 if ( !strcmp(DirEntry.szName, szCurThread))1146 continue;1147 1148 int32_t ThreadId = RTStrToInt32(DirEntry.szName);1149 _lwp_suspend((lwpid_t)ThreadId);1150 ++cRunningThreads;1151 }1152 1153 if (cTries > 5 && cThreads == cRunningThreads)1154 {1155 rc = VINF_SUCCESS;1156 break;1157 }1158 cThreads = cRunningThreads;1159 RTDirClose(pDir);1160 }1161 else1162 {1163 CORELOGREL(("SuspendAllThreads: Failed to open %s cTries=%d\n", szPath, cTries));1164 rc = VERR_READ_ERROR;1165 break;1166 }1167 }1168 1169 if (RT_SUCCESS(rc))1170 CORELOG(("Stopped %u threads successfully with %u tries\n", cThreads, cTries));1171 1172 return rc;1173 }1174 1175 1176 /**1177 * Returns size of an ELF NOTE header given the size of data the NOTE section will contain.1178 *1179 * @param cb Size of the data.1180 *1181 * @return Size of data actually used for NOTE header and section.1182 */1183 inline size_t ElfNoteHeaderSize(size_t cb)1184 {1185 return sizeof(ELFNOTEHDR) + RT_ALIGN_Z(cb, 4);1186 }1187 1188 1189 /**1190 * Write an ELF NOTE header into the core file.1191 *1192 * @param pVBoxCore Pointer to the core object.1193 * @param Type Type of this NOTE section.1194 * @param pcv Opaque pointer to the data, if NULL only computes size.1195 * @param cb Size of the data.1196 *1197 * @return VBox status code.1198 */1199 int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb)1200 {1201 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1202 AssertReturn(pcv, VERR_INVALID_POINTER);1203 AssertReturn(cb > 0, VERR_NO_DATA);1204 AssertReturn(pVBoxCore->pfnWriter, VERR_WRITE_ERROR);1205 AssertReturn(pVBoxCore->hCoreFile, VERR_INVALID_HANDLE);1206 1207 int rc = VERR_GENERAL_FAILURE;1208 #ifdef RT_OS_SOLARIS1209 ELFNOTEHDR ElfNoteHdr;1210 RT_ZERO(ElfNoteHdr);1211 ElfNoteHdr.achName[0] = 'C';1212 ElfNoteHdr.achName[1] = 'O';1213 ElfNoteHdr.achName[2] = 'R';1214 ElfNoteHdr.achName[3] = 'E';1215 ElfNoteHdr.Hdr.n_namesz = 5;1216 ElfNoteHdr.Hdr.n_type = Type;1217 ElfNoteHdr.Hdr.n_descsz = RT_ALIGN_Z(cb, 4);1218 1219 /*1220 * Write note header and description.1221 */1222 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &ElfNoteHdr, sizeof(ElfNoteHdr));1223 if (RT_SUCCESS(rc))1224 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, pcv, ElfNoteHdr.Hdr.n_descsz);1225 1226 if (RT_FAILURE(rc))1227 CORELOGREL(("ElfWriteNote: pfnWriter failed. Type=%d rc=%Rrc\n", Type, rc));1228 #else1229 #error Port Me!1230 #endif1231 return rc;1232 }1233 1234 1235 /**1236 * Computes the size of NOTE section for the given core type.1237 * Solaris has two types of program header information (new and old).1238 *1239 * @param pVBoxCore Pointer to the core object.1240 * @param enmType Type of core file information required.1241 *1242 * @return Size of NOTE section.1243 */1244 size_t ElfNoteSectionSize(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)1245 {1246 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1247 size_t cb = 0;1248 switch (enmType)1249 {1250 case enmOldEra:1251 {1252 cb += ElfNoteHeaderSize(sizeof(prpsinfo_t));1253 cb += ElfNoteHeaderSize(pVBoxProc->cAuxVecs * sizeof(auxv_t));1254 cb += ElfNoteHeaderSize(strlen(pVBoxProc->szPlatform));1255 1256 PVBOXSOLTHREADINFO pThreadInfo = pVBoxProc->pThreadInfoHead;1257 while (pThreadInfo)1258 {1259 if (pThreadInfo->pStatus)1260 {1261 cb += ElfNoteHeaderSize(sizeof(prstatus_t));1262 cb += ElfNoteHeaderSize(sizeof(prfpregset_t));1263 }1264 pThreadInfo = pThreadInfo->pNext;1265 }1266 1267 break;1268 }1269 1270 case enmNewEra:1271 {1272 cb += ElfNoteHeaderSize(sizeof(psinfo_t));1273 cb += ElfNoteHeaderSize(sizeof(pstatus_t));1274 cb += ElfNoteHeaderSize(pVBoxProc->cAuxVecs * sizeof(auxv_t));1275 cb += ElfNoteHeaderSize(strlen(pVBoxProc->szPlatform) + 1);1276 cb += ElfNoteHeaderSize(sizeof(struct utsname));1277 cb += ElfNoteHeaderSize(sizeof(core_content_t));1278 cb += ElfNoteHeaderSize(pVBoxProc->cbCred);1279 1280 if (pVBoxProc->pPriv)1281 cb += ElfNoteHeaderSize(PRIV_PRPRIV_SIZE(pVBoxProc->pPriv)); /* Ought to be same as cbPriv!? */1282 1283 if (pVBoxProc->pcPrivImpl)1284 cb += ElfNoteHeaderSize(PRIV_IMPL_INFO_SIZE(pVBoxProc->pcPrivImpl));1285 1286 cb += ElfNoteHeaderSize(strlen(pVBoxProc->szZoneName) + 1);1287 if (pVBoxProc->cbLdt > 0)1288 cb += ElfNoteHeaderSize(pVBoxProc->cbLdt);1289 1290 PVBOXSOLTHREADINFO pThreadInfo = pVBoxProc->pThreadInfoHead;1291 while (pThreadInfo)1292 {1293 cb += ElfNoteHeaderSize(sizeof(lwpsinfo_t));1294 if (pThreadInfo->pStatus)1295 cb += ElfNoteHeaderSize(sizeof(lwpstatus_t));1296 1297 pThreadInfo = pThreadInfo->pNext;1298 }1299 1300 break;1301 }1302 1303 default:1304 {1305 CORELOGREL(("ElfNoteSectionSize: Unknown segment era %d\n", enmType));1306 break;1307 }1308 }1309 1310 return cb;1311 }1312 1313 1314 /**1315 * Write the note section for the given era into the core file.1316 * Solaris has two types of program header information (new and old).1317 *1318 * @param pVBoxCore Pointer to the core object.1319 * @param enmType Type of core file information required.1320 *1321 * @return VBox status code.1322 */1323 int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)1324 {1325 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1326 1327 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1328 int rc = VERR_GENERAL_FAILURE;1329 1330 #ifdef RT_OS_SOLARIS1331 1332 typedef int (*PFNELFWRITENOTEHDR)(PVBOXCORE pVBoxCore, uint_t, const void *pcv, size_t cb);1333 typedef struct ELFWRITENOTE1334 {1335 const char *pszType;1336 uint_t Type;1337 const void *pcv;1338 size_t cb;1339 } ELFWRITENOTE;1340 1341 switch (enmType)1342 {1343 case enmOldEra:1344 {1345 ELFWRITENOTE aElfNotes[] =1346 {1347 { "NT_PRPSINFO", NT_PRPSINFO, &pVBoxProc->ProcInfoOld, sizeof(prpsinfo_t) },1348 { "NT_AUXV", NT_AUXV, pVBoxProc->pAuxVecs, pVBoxProc->cAuxVecs * sizeof(auxv_t) },1349 { "NT_PLATFORM", NT_PLATFORM, pVBoxProc->szPlatform, strlen(pVBoxProc->szPlatform) + 1 }1350 };1351 1352 for (unsigned i = 0; i < RT_ELEMENTS(aElfNotes); i++)1353 {1354 rc = ElfWriteNoteHeader(pVBoxCore, aElfNotes[i].Type, aElfNotes[i].pcv, aElfNotes[i].cb);1355 if (RT_FAILURE(rc))1356 {1357 CORELOGREL(("ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));1358 break;1359 }1360 }1361 1362 /*1363 * Write old-style thread info., they contain nothing about zombies,1364 * so we just skip if there is no status information for them.1365 */1366 PVBOXSOLTHREADINFO pThreadInfo = pVBoxProc->pThreadInfoHead;1367 for (; pThreadInfo; pThreadInfo = pThreadInfo->pNext)1368 {1369 if (!pThreadInfo->pStatus)1370 continue;1371 1372 prstatus_t OldProcessStatus;1373 GetOldProcessStatus(pVBoxCore, &pThreadInfo->Info, pThreadInfo->pStatus, &OldProcessStatus);1374 rc = ElfWriteNoteHeader(pVBoxCore, NT_PRSTATUS, &OldProcessStatus, sizeof(prstatus_t));1375 if (RT_SUCCESS(rc))1376 {1377 rc = ElfWriteNoteHeader(pVBoxCore, NT_PRFPREG, &pThreadInfo->pStatus->pr_fpreg, sizeof(prfpregset_t));1378 if (RT_FAILURE(rc))1379 {1380 CORELOGREL(("ElfWriteSegment: ElfWriteNote failed for NT_PRFPREF. rc=%Rrc\n", rc));1381 break;1382 }1383 }1384 else1385 {1386 CORELOGREL(("ElfWriteSegment: ElfWriteNote failed for NT_PRSTATUS. rc=%Rrc\n", rc));1387 break;1388 }1389 }1390 break;1391 }1392 1393 case enmNewEra:1394 {1395 ELFWRITENOTE aElfNotes[] =1396 {1397 { "NT_PSINFO", NT_PSINFO, &pVBoxProc->ProcInfo, sizeof(psinfo_t) },1398 { "NT_PSTATUS", NT_PSTATUS, &pVBoxProc->ProcStatus, sizeof(pstatus_t) },1399 { "NT_AUXV", NT_AUXV, pVBoxProc->pAuxVecs, pVBoxProc->cAuxVecs * sizeof(auxv_t) },1400 { "NT_PLATFORM", NT_PLATFORM, pVBoxProc->szPlatform, strlen(pVBoxProc->szPlatform) + 1 },1401 { "NT_UTSNAME", NT_UTSNAME, &pVBoxProc->UtsName, sizeof(struct utsname) },1402 { "NT_CONTENT", NT_CONTENT, &pVBoxProc->CoreContent, sizeof(core_content_t) },1403 { "NT_PRCRED", NT_PRCRED, pVBoxProc->pvCred, pVBoxProc->cbCred },1404 { "NT_PRPRIV", NT_PRPRIV, pVBoxProc->pPriv, PRIV_PRPRIV_SIZE(pVBoxProc->pPriv) },1405 { "NT_PRPRIVINFO", NT_PRPRIVINFO, pVBoxProc->pcPrivImpl, PRIV_IMPL_INFO_SIZE(pVBoxProc->pcPrivImpl) },1406 { "NT_ZONENAME", NT_ZONENAME, pVBoxProc->szZoneName, strlen(pVBoxProc->szZoneName) + 1 }1407 };1408 1409 for (unsigned i = 0; i < RT_ELEMENTS(aElfNotes); i++)1410 {1411 rc = ElfWriteNoteHeader(pVBoxCore, aElfNotes[i].Type, aElfNotes[i].pcv, aElfNotes[i].cb);1412 if (RT_FAILURE(rc))1413 {1414 CORELOGREL(("ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));1415 break;1416 }1417 }1418 1419 /*1420 * Write new-style thread info., missing lwpstatus_t indicates it's a zombie thread1421 * we only dump the lwpsinfo_t in that case.1422 */1423 PVBOXSOLTHREADINFO pThreadInfo = pVBoxProc->pThreadInfoHead;1424 for (; pThreadInfo; pThreadInfo = pThreadInfo->pNext)1425 {1426 rc = ElfWriteNoteHeader(pVBoxCore, NT_LWPSINFO, &pThreadInfo->Info, sizeof(lwpsinfo_t));1427 if (RT_FAILURE(rc))1428 {1429 CORELOGREL(("ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSINFO failed. rc=%Rrc\n", rc));1430 break;1431 }1432 1433 if (pThreadInfo->pStatus)1434 {1435 rc = ElfWriteNoteHeader(pVBoxCore, NT_LWPSTATUS, pThreadInfo->pStatus, sizeof(lwpstatus_t));1436 if (RT_FAILURE(rc))1437 {1438 CORELOGREL(("ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSTATUS failed. rc=%Rrc\n", rc));1439 break;1440 }1441 }1442 }1443 break;1444 }1445 1446 default:1447 {1448 CORELOGREL(("ElfWriteNoteSection: Invalid type %d\n", enmType));1449 rc = VERR_GENERAL_FAILURE;1450 break;1451 }1452 }1453 #else1454 # error Port Me!1455 #endif1456 return rc;1457 }1458 1459 1460 /**1461 * Write mappings into the core file.1462 *1463 * @param pVBoxCore Pointer to the core object.1464 *1465 * @return VBox status code.1466 */1467 int ElfWriteMappings(PVBOXCORE pVBoxCore)1468 {1469 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1470 1471 int rc = VERR_GENERAL_FAILURE;1472 PVBOXSOLMAPINFO pMapInfo = pVBoxProc->pMapInfoHead;1473 while (pMapInfo)1474 {1475 if (!pMapInfo->fError)1476 {1477 uint64_t k = 0;1478 char achBuf[PAGE_SIZE];1479 while (k < pMapInfo->pMap.pr_size)1480 {1481 size_t cb = RT_MIN(sizeof(achBuf), pMapInfo->pMap.pr_size - k);1482 int rc2 = ReadProcAddrSpace(pVBoxProc, pMapInfo->pMap.pr_vaddr + k, &achBuf, cb);1483 if (RT_FAILURE(rc2))1484 {1485 CORELOGREL(("ElfWriteMappings: Failed to read mapping, can't recover. Bye. rc=%Rrc\n", rc));1486 return VERR_INVALID_STATE;1487 }1488 1489 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, achBuf, sizeof(achBuf));1490 if (RT_FAILURE(rc))1491 {1492 CORELOGREL(("ElfWriteMappings: pfnWriter failed. rc=%Rrc\n", rc));1493 return rc;1494 }1495 k += cb;1496 }1497 }1498 else1499 {1500 char achBuf[RT_ALIGN_Z(sizeof(int), 8)];1501 RT_ZERO(achBuf);1502 memcpy(achBuf, &pMapInfo->fError, sizeof(pMapInfo->fError));1503 if (sizeof(achBuf) != pMapInfo->pMap.pr_size)1504 CORELOGREL(("ElfWriteMappings: Huh!? something is wrong!\n"));1505 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &achBuf, sizeof(achBuf));1506 if (RT_FAILURE(rc))1507 {1508 CORELOGREL(("ElfWriteMappings: pfnWriter(2) failed. rc=%Rrc\n", rc));1509 return rc;1510 }1511 }1512 1513 pMapInfo = pMapInfo->pNext;1514 }1515 1516 return VINF_SUCCESS;1517 }1518 1519 /**1520 * Write program headers for all mappings into the core file.1521 *1522 * @param pVBoxCore Pointer to the core object.1523 *1524 * @return VBox status code.1525 */1526 int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore)1527 {1528 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1529 1530 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1531 Phdr ProgHdr;1532 RT_ZERO(ProgHdr);1533 ProgHdr.p_type = PT_LOAD;1534 1535 int rc = VERR_GENERAL_FAILURE;1536 PVBOXSOLMAPINFO pMapInfo = pVBoxProc->pMapInfoHead;1537 while (pMapInfo)1538 {1539 ProgHdr.p_vaddr = pMapInfo->pMap.pr_vaddr; /* Virtual address of this mapping in the process address space */1540 ProgHdr.p_offset = pVBoxCore->offWrite; /* Where this mapping is located in the core file */1541 ProgHdr.p_memsz = pMapInfo->pMap.pr_size; /* Size of the memory image of the mapping */1542 ProgHdr.p_filesz = pMapInfo->pMap.pr_size; /* Size of the file image of the mapping */1543 1544 ProgHdr.p_flags = 0; /* Reset fields in a loop when needed! */1545 if (pMapInfo->pMap.pr_mflags & MA_READ)1546 ProgHdr.p_flags |= PF_R;1547 if (pMapInfo->pMap.pr_mflags & MA_WRITE)1548 ProgHdr.p_flags |= PF_W;1549 if (pMapInfo->pMap.pr_mflags & MA_EXEC)1550 ProgHdr.p_flags |= PF_X;1551 1552 if (pMapInfo->fError)1553 ProgHdr.p_flags |= PF_SUNW_FAILURE;1554 1555 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &ProgHdr, sizeof(ProgHdr));1556 if (RT_FAILURE(rc))1557 {1558 CORELOGREL(("ElfWriteMappingHeaders: pfnWriter failed. rc=%Rrc\n", rc));1559 return rc;1560 }1561 1562 pVBoxCore->offWrite += ProgHdr.p_filesz;1563 pMapInfo = pMapInfo->pNext;1564 }1565 return rc;1566 }1567 1568 1569 /**1570 * Write a prepared core file using a user-passed in writer function, requires all threads1571 * to be in suspended state (i.e. called after CreateCore).1572 *1573 * @param pVBoxCore Pointer to the core object.1574 * @param pfnWriter Pointer to the writer function to override default writer (NULL uses default).1575 *1576 * @remarks Resumes all suspended threads, unless it's an invalid core.1577 * @return VBox status.1578 */1579 int WriteCore(PVBOXCORE pVBoxCore, PFNCOREWRITER pfnWriter)1580 {1581 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1582 1583 if (!pVBoxCore->fIsValid)1584 return VERR_INVALID_STATE;1585 1586 if (pfnWriter)1587 pVBoxCore->pfnWriter = pfnWriter;1588 1589 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1590 char szPath[PATH_MAX];1591 1592 /*1593 * Open the process address space file.1594 */1595 RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/as", (int)pVBoxProc->Process);1596 int rc = RTFileOpen(&pVBoxProc->hAs, szPath, RTFILE_O_OPEN | RTFILE_O_READ);1597 if (RT_FAILURE(rc))1598 {1599 CORELOGREL(("WriteCore: Failed to open address space, %s. rc=%Rrc\n", szPath, rc));1600 goto WriteCoreDone;1601 }1602 1603 /*1604 * Create the core file.1605 */1606 RTStrPrintf(szPath, sizeof(szPath), "/export/home/ram/vbox/out/solaris.amd64/release/bin/%s", pVBoxCore->szCorePath, pVBoxCore->VBoxProc.Process); /* @todo fix this */1607 rc = RTFileOpen(&pVBoxCore->hCoreFile, szPath, RTFILE_O_OPEN_CREATE | RTFILE_O_TRUNCATE | RTFILE_O_READWRITE | RTFILE_O_DENY_ALL);1608 if (RT_FAILURE(rc))1609 {1610 CORELOGREL(("WriteCore: failed to open %s. rc=%Rrc\n", szPath, rc));1611 goto WriteCoreDone;1612 }1613 1614 pVBoxCore->offWrite = 0;1615 uint32_t cProgHdrs = pVBoxProc->cMappings + 2; /* two PT_NOTE program headers (old, new style) */1616 uint32_t cSecHdrs = CountSections(pVBoxCore);1617 1618 /*1619 * Write the ELF header.1620 */1621 Ehdr ElfHdr;1622 RT_ZERO(ElfHdr);1623 ElfHdr.e_ident[EI_MAG0] = ELFMAG0;1624 ElfHdr.e_ident[EI_MAG1] = ELFMAG1;1625 ElfHdr.e_ident[EI_MAG2] = ELFMAG2;1626 ElfHdr.e_ident[EI_MAG3] = ELFMAG3;1627 ElfHdr.e_ident[EI_DATA] = IsBigEndian() ? ELFDATA2MSB : ELFDATA2LSB;1628 ElfHdr.e_type = ET_CORE;1629 ElfHdr.e_version = EV_CURRENT;1630 #ifdef RT_ARCH_AMD641631 ElfHdr.e_machine = EM_AMD64;1632 ElfHdr.e_ident[EI_CLASS] = ELFCLASS64;1633 #else1634 ElfHdr.e_machine = EM_386;1635 ElfHdr.e_ident[EI_CLASS] = ELFCLASS32;1636 #endif1637 if (cProgHdrs >= PN_XNUM)1638 ElfHdr.e_phnum = PN_XNUM;1639 else1640 ElfHdr.e_phnum = cProgHdrs;1641 ElfHdr.e_ehsize = sizeof(ElfHdr);1642 ElfHdr.e_phoff = sizeof(ElfHdr);1643 ElfHdr.e_phentsize = sizeof(Phdr);1644 ElfHdr.e_shentsize = sizeof(Shdr);1645 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &ElfHdr, sizeof(ElfHdr));1646 if (RT_FAILURE(rc))1647 {1648 CORELOGREL(("WriteCore: pfnWriter failed writing ELF header. rc=%Rrc\n", rc));1649 goto WriteCoreDone;1650 }1651 1652 /*1653 * Setup program header.1654 */1655 Phdr ProgHdr;1656 RT_ZERO(ProgHdr);1657 ProgHdr.p_type = PT_NOTE;1658 ProgHdr.p_flags = PF_R;1659 1660 /*1661 * Write old-style NOTE program header.1662 */1663 pVBoxCore->offWrite += sizeof(ElfHdr) + cProgHdrs * sizeof(ProgHdr);1664 ProgHdr.p_offset = pVBoxCore->offWrite;1665 ProgHdr.p_filesz = ElfNoteSectionSize(pVBoxCore, enmOldEra);1666 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &ProgHdr, sizeof(ProgHdr));1667 if (RT_FAILURE(rc))1668 {1669 CORELOGREL(("WriteCore: pfnWriter failed writing old-style ELF program Header. rc=%Rrc\n", rc));1670 goto WriteCoreDone;1671 }1672 1673 /*1674 * Write new-style NOTE program header.1675 */1676 pVBoxCore->offWrite += ProgHdr.p_filesz;1677 ProgHdr.p_offset = pVBoxCore->offWrite;1678 ProgHdr.p_filesz = ElfNoteSectionSize(pVBoxCore, enmNewEra);1679 rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &ProgHdr, sizeof(ProgHdr));1680 if (RT_FAILURE(rc))1681 {1682 CORELOGREL(("WriteCore: pfnWriter failed writing new-style ELF program header. rc=%Rrc\n", rc));1683 goto WriteCoreDone;1684 }1685 1686 /*1687 * Write program headers per mapping.1688 */1689 pVBoxCore->offWrite += ProgHdr.p_filesz;1690 rc = ElfWriteMappingHeaders(pVBoxCore);1691 if (RT_FAILURE(rc))1692 {1693 CORELOGREL(("Write: ElfWriteMappings failed. rc=%Rrc\n", rc));1694 goto WriteCoreDone;1695 }1696 1697 /*1698 * Write old-style note section.1699 */1700 rc = ElfWriteNoteSection(pVBoxCore, enmOldEra);1701 if (RT_FAILURE(rc))1702 {1703 CORELOGREL(("WriteCore: ElfWriteNoteSection old-style failed. rc=%Rrc\n", rc));1704 goto WriteCoreDone;1705 }1706 1707 /*1708 * Write new-style section.1709 */1710 rc = ElfWriteNoteSection(pVBoxCore, enmNewEra);1711 if (RT_FAILURE(rc))1712 {1713 CORELOGREL(("WriteCore: ElfWriteNoteSection new-style failed. rc=%Rrc\n", rc));1714 goto WriteCoreDone;1715 }1716 1717 /*1718 * Write all mappings.1719 */1720 rc = ElfWriteMappings(pVBoxCore);1721 if (RT_FAILURE(rc))1722 {1723 CORELOGREL(("WriteCore: ElfWriteMappings failed. rc=%Rrc\n", rc));1724 goto WriteCoreDone;1725 }1726 1727 1728 WriteCoreDone:1729 if (pVBoxCore->hCoreFile != NIL_RTFILE)1730 {1731 RTFileClose(pVBoxCore->hCoreFile);1732 pVBoxCore->hCoreFile = NIL_RTFILE;1733 }1734 1735 if (pVBoxProc->hAs != NIL_RTFILE)1736 {1737 RTFileClose(pVBoxProc->hAs);1738 pVBoxProc->hAs = NIL_RTFILE;1739 }1740 1741 ResumeAllThreads(pVBoxProc);1742 return rc;1743 }1744 1745 1746 /**1747 * Takes a process snapshot into a passed-in core object. It has the side-effect of halting1748 * all threads which can lead to things like spurious wakeups of threads (if and when threads1749 * are ultimately resumed en-masse) already suspended while calling this function.1750 *1751 * @param pVBoxCore Pointer to a core object.1752 * @param pContext Pointer to the caller context thread.1753 *1754 * @remarks Halts all threads.1755 * @return VBox status code.1756 */1757 int CreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext)1758 {1759 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1760 AssertReturn(pContext, VERR_INVALID_POINTER);1761 1762 /*1763 * Initialize core structures.1764 */1765 memset(pVBoxCore, 0, sizeof(VBOXCORE));1766 pVBoxCore->pfnReader = &ReadFileNoIntr;1767 pVBoxCore->pfnWriter = &WriteFileNoIntr;1768 pVBoxCore->fIsValid = false;1769 pVBoxCore->hCoreFile = NIL_RTFILE;1770 1771 PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;1772 pVBoxProc->Process = RTProcSelf();1773 pVBoxProc->hCurThread = _lwp_self(); /* thr_self() */1774 pVBoxProc->hAs = NIL_RTFILE;1775 pVBoxProc->pCurThreadCtx = pContext;1776 pVBoxProc->CoreContent = CC_CONTENT_DEFAULT;1777 1778 RTProcGetExecutableName(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath)); /* this gets full path not just name */1779 pVBoxProc->pszExecName = RTPathFilename(pVBoxProc->szExecPath);1780 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "core.vb.%s.%d", pVBoxProc->pszExecName, (int)pVBoxProc->Process);1781 1782 CORELOG(("tstRTCoreDump: Taking Core %s from Thread %d\n", pVBoxCore->szCorePath, (int)pVBoxProc->hCurThread));1783 1784 /*1785 * Quiesce the process.1786 */1787 int rc = SuspendAllThreads(pVBoxProc);1788 if (RT_SUCCESS(rc))1789 {1790 rc = ReadProcInfo(pVBoxCore);1791 if (RT_SUCCESS(rc))1792 {1793 GetOldProcessInfo(pVBoxCore, &pVBoxProc->ProcInfoOld);1794 if (IsProcArchNative(pVBoxProc))1795 {1796 /*1797 * Read process status, information such as number of active LWPs will be invalid since we just quiesced the process.1798 */1799 rc = ReadProcStatus(pVBoxCore);1800 if (RT_SUCCESS(rc))1801 {1802 rc = AllocMemoryArea(pVBoxCore);1803 if (RT_SUCCESS(rc))1804 {1805 struct COREACCUMULATOR1806 {1807 const char *pszName;1808 PFNCOREACCUMULATOR pfnAcc;1809 bool fOptional;1810 } aAccumulators[] =1811 {1812 { "ReadProcLdt", &ReadProcLdt, false },1813 { "ReadProcCred", &ReadProcCred, false },1814 { "ReadProcPriv", &ReadProcPriv, false },1815 { "ReadProcAuxVecs", &ReadProcAuxVecs, false },1816 { "ReadProcMappings", &ReadProcMappings, false },1817 { "ReadProcThreads", &ReadProcThreads, false },1818 { "ReadProcMiscInfo", &ReadProcMiscInfo, false }1819 };1820 1821 for (unsigned i = 0; i < RT_ELEMENTS(aAccumulators); i++)1822 {1823 rc = aAccumulators[i].pfnAcc(pVBoxCore);1824 if (RT_FAILURE(rc))1825 {1826 CORELOGREL(("DumpCore: %s failed. rc=%Rrc\n", aAccumulators[i].pszName, rc));1827 if (!aAccumulators[i].fOptional)1828 break;1829 }1830 }1831 1832 if (RT_SUCCESS(rc))1833 {1834 pVBoxCore->fIsValid = true;1835 return VINF_SUCCESS;1836 }1837 1838 FreeMemoryArea(pVBoxCore);1839 }1840 else1841 CORELOGREL(("DumpCore: AllocMemoryArea failed. rc=%Rrc\n", rc));1842 }1843 else1844 CORELOGREL(("DumpCore: ReadProcStatus failed. rc=%Rrc\n", rc));1845 }1846 else1847 {1848 CORELOGREL(("DumpCore: IsProcArchNative failed.\n"));1849 rc = VERR_BAD_EXE_FORMAT;1850 }1851 }1852 else1853 CORELOGREL(("DumpCore: ReadProcInfo failed. rc=%Rrc\n", rc));1854 1855 /*1856 * Resume threads on failure.1857 */1858 ResumeAllThreads(pVBoxProc);1859 }1860 else1861 CORELOG(("DumpCore: SuspendAllThreads failed. Thread bomb!?! rc=%Rrc\n", rc));1862 1863 return rc;1864 }1865 1866 1867 /**1868 * Destroy an existing core object.1869 *1870 * @param pVBoxCore Pointer to the core object.1871 *1872 * @return VBox status code.1873 */1874 int DestroyCore(PVBOXCORE pVBoxCore)1875 {1876 AssertReturn(pVBoxCore, VERR_INVALID_POINTER);1877 if (!pVBoxCore->fIsValid)1878 return VERR_INVALID_STATE;1879 1880 FreeMemoryArea(pVBoxCore);1881 pVBoxCore->fIsValid = false;1882 return VINF_SUCCESS;1883 }1884 1885 1886 void CoreSigHandler(int Sig, siginfo_t *pSigInfo, void *pvArg)1887 {1888 CORELOG(("CoreSigHandler Sig=%d pvArg=%p\n", Sig, pvArg));1889 1890 ucontext_t *pContext = (ucontext_t *)pvArg;1891 if (!pContext)1892 CORELOGREL(("CoreSigHandler: Missing context.\n"));1893 else1894 {1895 if (!ASMAtomicUoReadBool(&g_fCoreDumpInProgress))1896 {1897 ASMAtomicWriteBool(&g_fCoreDumpInProgress, true);1898 1899 /*1900 * Take a snapshot, then dump core to disk, all threads except this one are halted1901 * from before taking the snapshot until writing the core is completely finished.1902 * Any errors would resume all threads if they were halted.1903 */1904 VBOXCORE VBoxCore;1905 RT_ZERO(VBoxCore);1906 int rc = CreateCore(&VBoxCore, pContext);1907 if (RT_SUCCESS(rc))1908 {1909 rc = WriteCore(&VBoxCore, &WriteFileNoIntr);1910 if (RT_SUCCESS(rc))1911 CORELOG(("CoreSigHandler: Successfully wrote core file to disk.\n"));1912 else1913 CORELOGREL(("CoreSigHandler: WriteCore failed. rc=%Rrc\n", rc));1914 1915 DestroyCore(&VBoxCore);1916 }1917 else1918 CORELOGREL(("CoreSigHandler: CreateCore failed. rc=%Rrc\n", rc));1919 1920 ASMAtomicWriteBool(&g_fCoreDumpInProgress, false);1921 }1922 else1923 {1924 /* @todo detect if we are awaiting for ourselves, if so don't. */1925 CORELOGREL(("CoreSigHandler: Core dump already in progress! Waiting before signalling Sig=%d.\n", Sig));1926 int64_t iTimeout = 10000; /* timeout (ms) */1927 while (!ASMAtomicUoReadBool(&g_fCoreDumpInProgress))1928 {1929 RTThreadSleep(200);1930 iTimeout -= 200;1931 if (iTimeout <= 0)1932 break;1933 }1934 if (iTimeout <= 0)1935 CORELOGREL(("CoreSigHandler: Core dump seems to be stuck. Signalling new signal %d\n", Sig));1936 }1937 }1938 1939 signal(Sig, SIG_DFL);1940 kill((int)getpid(), Sig);1941 }1942 1943 42 1944 43 static DECLCALLBACK(int) SleepyThread(RTTHREAD Thread, void *pvUser) 1945 44 { 1946 45 NOREF(pvUser); 1947 sleep(10000);46 RTThreadSleep(90000000); 1948 47 return VINF_SUCCESS; 1949 48 } 1950 1951 49 1952 50 int main() 1953 51 { 1954 52 RTR3Init(); 1955 CORELOG(("tstRTCoreDump: TESTING pid=%d\n", getpid()));53 RTPrintf("tstRTCoreDump: TESTING...\n"); 1956 54 1957 55 /* 1958 * Install core dump signal handler.56 * Setup core dumping. 1959 57 */ 1960 struct sigaction sigAction; 1961 sigAction.sa_sigaction = CoreSigHandler; 1962 sigemptyset(&sigAction.sa_mask); 1963 sigAction.sa_flags = SA_RESTART | SA_SIGINFO; 1964 sigaction(SIGSEGV, &sigAction, NULL); 1965 sigaction(SIGBUS, &sigAction, NULL); 1966 sigaction(SIGUSR1, &sigAction, NULL); 1967 1968 /* 1969 * Spawn a few threads. 1970 */ 1971 RTTHREAD ahThreads[5]; 1972 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++) 58 int rc = RTCoreDumperSetup(NULL, 0); 59 if (RT_SUCCESS(rc)) 1973 60 { 1974 int rc = RTThreadCreate(&ahThreads[i], SleepyThread, &ahThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "TEST1"); 61 /* 62 * Spawn a few threads. 63 */ 64 RTTHREAD ahThreads[5]; 65 unsigned i = 0; 66 for (; i < RT_ELEMENTS(ahThreads); i++) 67 { 68 rc = RTThreadCreate(&ahThreads[i], SleepyThread, &ahThreads[i], 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "TEST1"); 69 if (RT_FAILURE(rc)) 70 { 71 RTPrintf("tstRTCoreDump: FAILURE(%d) - %d RTThreadCreate failed, rc=%Rrc\n", __LINE__, i, rc); 72 g_cErrors++; 73 ahThreads[i] = NIL_RTTHREAD; 74 break; 75 } 76 } 77 RTPrintf("Spawned %d threads.\n", i); 78 79 /* 80 * Write the core to disk. 81 */ 82 rc = RTCoreDumperTakeDump(NULL); 1975 83 if (RT_FAILURE(rc)) 1976 84 { 1977 CORELOG(("tstRTCoreDump: FAILURE(%d) - %d RTThreadCreate failed, rc=%Rrc\n", __LINE__, i, rc));1978 85 g_cErrors++; 1979 ahThreads[i] = NIL_RTTHREAD; 1980 break; 86 RTPrintf("RTCoreDumperTakeDump failed. rc=%Rrc\n", rc); 1981 87 } 1982 88 } 1983 1984 CORELOG(("Spawned %d threads\n", RT_ELEMENTS(ahThreads))); 1985 1986 /* 1987 * Send signal to dump core. 1988 */ 1989 kill(getpid(), SIGSEGV); 1990 g_cErrors++; 1991 1992 sleep(10); 89 else 90 { 91 g_cErrors++; 92 RTPrintf("RTCoreDumperSetup failed. rc=%Rrc\n", rc); 93 } 1993 94 1994 95 /* … … 1996 97 */ 1997 98 if (!g_cErrors) 1998 CORELOG(("tstRTCoreDump: SUCCESS\n"));99 RTPrintf("tstRTCoreDump: SUCCESS\n"); 1999 100 else 2000 CORELOG(("tstRTCoreDump: FAILURE - %d errors\n", g_cErrors));101 RTPrintf("tstRTCoreDump: FAILURE - %d errors\n", g_cErrors); 2001 102 2002 103 return !!g_cErrors;
Note:
See TracChangeset
for help on using the changeset viewer.