VirtualBox

Changeset 31860 in vbox for trunk/src


Ignore:
Timestamp:
Aug 23, 2010 1:56:17 PM (14 years ago)
Author:
vboxsync
Message:

RTCoreDumper: integration into IPRT, cleanup.

Location:
trunk/src/VBox/Runtime
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r31829 r31860  
    759759        r3/solaris/alloc-solaris.cpp \
    760760        r3/solaris/mp-solaris.cpp \
     761        r3/solaris/coredumper-solaris.cpp \
    761762        r3/solaris/rtProcInitExePath-solaris.cpp
    762763RuntimeR3_SOURCES.solaris.amd64 = \
  • trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp

    r31822 r31860  
    2828*   Header Files                                                               *
    2929*******************************************************************************/
     30#define LOG_GROUP LOG_GROUP_CORE_DUMPER
     31#include <VBox/log.h>
     32#include <iprt/coredumper.h>
    3033#include <iprt/types.h>
    3134#include <iprt/file.h>
     
    3437#include <iprt/path.h>
    3538#include <iprt/string.h>
    36 #include <iprt/stream.h>
    37 #include <iprt/initterm.h>
    3839#include <iprt/thread.h>
    3940#include <iprt/param.h>
    4041#include <iprt/asm.h>
    41 #include "tstRTCoreDump.h"
     42#include "coredumper-solaris.h"
    4243
    4344#ifdef RT_OS_SOLARIS
     45# include <syslog.h>
    4446# include <signal.h>
    4547# include <unistd.h>
     
    5355
    5456/*******************************************************************************
     57*   Globals                                                                    *
     58*******************************************************************************/
     59volatile static uint64_t   g_CoreDumpThread = NIL_RTTHREAD;
     60volatile static bool       g_fCoreDumpSignalSetup = false;
     61volatile static bool       g_fCoreDumpDeliberate = false;
     62volatile static bool       g_fCoreDumpInProgress = false;
     63volatile static uint32_t   g_fCoreDumpFlags = 0;
     64static char                g_szCoreDumpDir[PATH_MAX] = { 0 };
     65static char                g_szCoreDumpFile[PATH_MAX] = { 0 };
     66
     67
     68/*******************************************************************************
    5569*   Defined Constants And Macros                                               *
    5670*******************************************************************************/
    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 */
     85static 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}
    7294
    7395
     
    143165 * @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR.
    144166 */
    145 static ssize_t ReadProcAddrSpace(PVBOXPROCESS pVBoxProc, RTFOFF off, void *pvBuf, size_t cbToRead)
     167static ssize_t ProcReadAddrSpace(PVBOXPROCESS pVBoxProc, RTFOFF off, void *pvBuf, size_t cbToRead)
    146168{
    147169    while (1)
     
    162184 * @return true if the architecture matches the current one.
    163185 */
    164 inline bool IsProcArchNative(PVBOXPROCESS pVBoxProc)
     186static inline bool IsProcessArchNative(PVBOXPROCESS pVBoxProc)
    165187{
    166188    return pVBoxProc->ProcInfo.pr_dmodel == PR_MODEL_NATIVE;
     
    175197 * @return The size of the file in bytes.
    176198 */
    177 size_t GetFileSize(const char *pszPath)
     199static size_t GetFileSize(const char *pszPath)
    178200{
    179201    size_t cb = 0;
     
    186208    }
    187209    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));
    189211    return cb;
    190212}
     
    200222 * @return VBox status code.
    201223 */
    202 int AllocMemoryArea(PVBOXCORE pVBoxCore)
     224static int AllocMemoryArea(PVBOXCORE pVBoxCore)
    203225{
    204226    AssertReturn(pVBoxCore->pvCore == NULL, VERR_ALREADY_EXISTS);
     
    249271    if (pv)
    250272    {
    251         CORELOG(("AllocMemoryArea: memory area of %u bytes allocated.\n", cb));
     273        CORELOG((CORELOG_NAME "AllocMemoryArea: memory area of %u bytes allocated.\n", cb));
    252274        pVBoxCore->pvCore = pv;
    253275        pVBoxCore->pvFree = pv;
     
    257279    else
    258280    {
    259         CORELOGREL(("AllocMemoryArea: failed cb=%u\n", cb));
     281        CORELOGRELSYS((CORELOG_NAME "AllocMemoryArea: failed cb=%u\n", cb));
    260282        return VERR_NO_MEMORY;
    261283    }
     
    268290 * @param pVBoxCore         Pointer to the core object.
    269291 */
    270 void FreeMemoryArea(PVBOXCORE pVBoxCore)
     292static void FreeMemoryArea(PVBOXCORE pVBoxCore)
    271293{
    272294    AssertReturnVoid(pVBoxCore);
     
    275297
    276298    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));
    278300
    279301    pVBoxCore->pvCore = NULL;
     
    291313 * @return Pointer to allocated memory, or NULL on failure.
    292314 */
    293 void *GetMemoryChunk(PVBOXCORE pVBoxCore, size_t cb)
     315static void *GetMemoryChunk(PVBOXCORE pVBoxCore, size_t cb)
    294316{
    295317    AssertReturn(pVBoxCore, NULL);
     
    319341 * @return VBox status code.
    320342 */
    321 int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)
     343static int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)
    322344{
    323345    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    346368    }
    347369    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));
    349371    return rc;
    350372}
     
    358380 * @return VBox status code.
    359381 */
    360 int ReadProcInfo(PVBOXCORE pVBoxCore)
     382static int ProcReadInfo(PVBOXCORE pVBoxCore)
    361383{
    362384    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    386408 * @return VBox status code.
    387409 */
    388 int ReadProcStatus(PVBOXCORE pVBoxCore)
     410static int ProcReadStatus(PVBOXCORE pVBoxCore)
    389411{
    390412    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    417439 * @return VBox status code.
    418440 */
    419 int ReadProcCred(PVBOXCORE pVBoxCore)
     441static int ProcReadCred(PVBOXCORE pVBoxCore)
    420442{
    421443    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    434456 * @return VBox status code.
    435457 */
    436 int ReadProcPriv(PVBOXCORE pVBoxCore)
     458static int ProcReadPriv(PVBOXCORE pVBoxCore)
    437459{
    438460    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    445467    if (!pVBoxProc->pcPrivImpl)
    446468    {
    447         CORELOGREL(("ReadProcPriv: getprivimplinfo returned NULL.\n"));
     469        CORELOGRELSYS((CORELOG_NAME "ProcReadPriv: getprivimplinfo returned NULL.\n"));
    448470        return VERR_INVALID_STATE;
    449471    }
     
    460482 * @return VBox status code.
    461483 */
    462 int ReadProcLdt(PVBOXCORE pVBoxCore)
     484static int ProcReadLdt(PVBOXCORE pVBoxCore)
    463485{
    464486    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    477499 * @return VBox status code.
    478500 */
    479 int ReadProcAuxVecs(PVBOXCORE pVBoxCore)
     501static int ProcReadAuxVecs(PVBOXCORE pVBoxCore)
    480502{
    481503    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    488510    if (RT_FAILURE(rc))
    489511    {
    490         CORELOGREL(("ReadProcAuxVecs: RTFileOpen %s failed rc=%Rrc\n", szPath, rc));
     512        CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: RTFileOpen %s failed rc=%Rrc\n", szPath, rc));
    491513        return rc;
    492514    }
     
    504526                /* Terminate list of vectors */
    505527                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));
    507529                if (pVBoxProc->cAuxVecs > 0)
    508530                {
     
    514536                else
    515537                {
    516                     CORELOGREL(("ReadProcAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs));
     538                    CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs));
    517539                    rc = VERR_READ_ERROR;
    518540                }
    519541            }
    520542            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));
    522544
    523545            pVBoxProc->pAuxVecs = NULL;
     
    526548        else
    527549        {
    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)));
    529551            rc = VERR_NO_MEMORY;
    530552        }
    531553    }
    532554    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)));
    534556
    535557    RTFileClose(hFile);
     
    541563 * Find an element in the process' auxiliary vector.
    542564 */
    543 long GetAuxVal(PVBOXPROCESS pVBoxProc, int Type)
     565static long GetAuxVal(PVBOXPROCESS pVBoxProc, int Type)
    544566{
    545567    AssertReturn(pVBoxProc, -1);
     
    565587 * @return VBox status code.
    566588 */
    567 int ReadProcMappings(PVBOXCORE pVBoxCore)
     589static int ProcReadMappings(PVBOXCORE pVBoxCore)
    568590{
    569591    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    625647                                {
    626648                                    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);
    628650                                    if (RT_FAILURE(rc2))
    629651                                    {
    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));
    631653
    632654                                        /*
     
    652674                            RTFileClose(pVBoxProc->hAs);
    653675                            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));
    655677                            return VINF_SUCCESS;
    656678                        }
    657679                        else
    658680                        {
    659                             CORELOGREL(("ReadProcMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));
     681                            CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));
    660682                            rc = VERR_NO_MEMORY;
    661683                        }
     
    663685                    else
    664686                    {
    665                         CORELOGREL(("ReadProcMappings: Invalid mapping count %u\n", pVBoxProc->cMappings));
     687                        CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: Invalid mapping count %u\n", pVBoxProc->cMappings));
    666688                        rc = VERR_READ_ERROR;
    667689                    }
    668690                }
    669691                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));
    671693            }
    672694            else
    673695            {
    674                 CORELOGREL(("ReadProcMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile));
     696                CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile));
    675697                rc = VERR_NO_MEMORY;
    676698            }
     
    681703    }
    682704    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));
    684706
    685707    RTFileClose(hFile);
     
    696718 * @return VBox status code.
    697719 */
    698 int ReadProcThreads(PVBOXCORE pVBoxCore)
     720static int ProcReadThreads(PVBOXCORE pVBoxCore)
    699721{
    700722    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    728750            uint64_t cInfo         = pInfoHdr->pr_nent;
    729751
    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));
    731754
    732755            /*
     
    747770                            || pStatus->pr_lwpid != pInfo->pr_lwpid)
    748771                        {
    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));
    750774                            rc = VERR_INVALID_STATE;
    751775                            break;
     
    796820                                    pStatus->pr_ustack = (uintptr_t)&pVBoxProc->pCurThreadCtx->uc_stack;
    797821
    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"));
    799823                                }
    800824
     
    804828                            else
    805829                            {
    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));
    807831                                pCur->pStatus = NULL;
    808832                            }
     
    816840                            pPrev->pNext = NULL;
    817841
    818                         CORELOG(("ReadProcThreads: successfully read %u threads.\n", cInfo));
     842                        CORELOG((CORELOG_NAME "ProcReadThreads: successfully read %u threads.\n", cInfo));
    819843                        pVBoxProc->cThreads = cInfo;
    820844                        return VINF_SUCCESS;
     
    822846                    else
    823847                    {
    824                         CORELOGREL(("ReadProcThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));
     848                        CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));
    825849                        rc = VERR_NO_MEMORY;
    826850                    }
    827851                }
    828852                else
    829                     CORELOGREL(("ReadProcThreads: Invalid state information for threads.\n", rc));
     853                    CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: Invalid state information for threads.\n", rc));
    830854            }
    831855            else
    832856            {
    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,
    834858                            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));
    836860                rc = VERR_INVALID_STATE;
    837861            }
    838862        }
    839863        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));
    841865    }
    842866    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));
    844868    return rc;
    845869}
     
    854878 * @return VBox status code.
    855879 */
    856 int ReadProcMiscInfo(PVBOXCORE pVBoxCore)
     880static int ProcReadMiscInfo(PVBOXCORE pVBoxCore)
    857881{
    858882    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    867891    if (rc == -1)
    868892    {
    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));
    870894        return VERR_GENERAL_FAILURE;
    871895    }
     
    875899    if (rc == -1)
    876900    {
    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));
    878902        return VERR_GENERAL_FAILURE;
    879903    }
     
    882906    if (rc < 0)
    883907    {
    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));
    885909        return VERR_GENERAL_FAILURE;
    886910    }
     
    902926 * @param pInfo             Pointer to the old prpsinfo_t structure to update.
    903927 */
    904 void GetOldProcessInfo(PVBOXCORE pVBoxCore, prpsinfo_t *pInfo)
     928static void GetOldProcessInfo(PVBOXCORE pVBoxCore, prpsinfo_t *pInfo)
    905929{
    906930    AssertReturnVoid(pVBoxCore);
     
    961985 *
    962986 */
    963 void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)
     987static void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)
    964988{
    965989    AssertReturnVoid(pVBoxCore);
     
    10401064
    10411065/**
    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 /**
    10571066 * Resume all threads of this process.
    10581067 *
     
    10611070 * @return VBox error code.
    10621071 */
    1063 int ResumeAllThreads(PVBOXPROCESS pVBoxProc)
     1072static int ResumeAllThreads(PVBOXPROCESS pVBoxProc)
    10641073{
    10651074    AssertReturn(pVBoxProc, VERR_INVALID_POINTER);
     
    10941103        }
    10951104
    1096         CORELOG(("ResumeAllThreads: resumed %d threads\n", cRunningThreads));
     1105        CORELOG((CORELOG_NAME "ResumeAllThreads: resumed %d threads\n", cRunningThreads));
    10971106        RTDirClose(pDir);
    10981107    }
    10991108    else
    11001109    {
    1101         CORELOGREL(("ResumeAllThreads: Failed to open %s\n", szPath));
     1110        CORELOGRELSYS((CORELOG_NAME "ResumeAllThreads: Failed to open %s\n", szPath));
    11021111        rc = VERR_READ_ERROR;
    11031112    }
     
    11151124 * @return VBox error code.
    11161125 */
    1117 int SuspendAllThreads(PVBOXPROCESS pVBoxProc)
     1126static int SuspendAllThreads(PVBOXPROCESS pVBoxProc)
    11181127{
    11191128    char szCurThread[128];
     
    11611170        else
    11621171        {
    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));
    11641173            rc = VERR_READ_ERROR;
    11651174            break;
     
    11681177
    11691178    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));
    11711180
    11721181    return rc;
     
    11811190 * @return Size of data actually used for NOTE header and section.
    11821191 */
    1183 inline size_t ElfNoteHeaderSize(size_t cb)
     1192static inline size_t ElfNoteHeaderSize(size_t cb)
    11841193{
    11851194    return sizeof(ELFNOTEHDR) + RT_ALIGN_Z(cb, 4);
     
    11971206 * @return VBox status code.
    11981207 */
    1199 int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb)
     1208static int ElfWriteNoteHeader(PVBOXCORE pVBoxCore, uint_t Type, const void *pcv, size_t cb)
    12001209{
    12011210    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    12251234
    12261235    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));
    12281237#else
    12291238#error Port Me!
     
    12421251 * @return Size of NOTE section.
    12431252 */
    1244 size_t ElfNoteSectionSize(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)
     1253static size_t ElfNoteSectionSize(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)
    12451254{
    12461255    PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;
     
    13031312        default:
    13041313        {
    1305             CORELOGREL(("ElfNoteSectionSize: Unknown segment era %d\n", enmType));
     1314            CORELOGRELSYS((CORELOG_NAME "ElfNoteSectionSize: Unknown segment era %d\n", enmType));
    13061315            break;
    13071316        }
     
    13211330 * @return VBox status code.
    13221331 */
    1323 int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)
     1332static int ElfWriteNoteSection(PVBOXCORE pVBoxCore, VBOXSOLCORETYPE enmType)
    13241333{
    13251334    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    13291338
    13301339#ifdef RT_OS_SOLARIS
    1331 
    13321340    typedef int (*PFNELFWRITENOTEHDR)(PVBOXCORE pVBoxCore, uint_t, const void *pcv, size_t cb);
    13331341    typedef struct ELFWRITENOTE
     
    13551363                if (RT_FAILURE(rc))
    13561364                {
    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));
    13581366                    break;
    13591367                }
     
    13781386                    if (RT_FAILURE(rc))
    13791387                    {
    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));
    13811389                        break;
    13821390                    }
     
    13841392                else
    13851393                {
    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));
    13871395                    break;
    13881396                }
     
    14121420                if (RT_FAILURE(rc))
    14131421                {
    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));
    14151423                    break;
    14161424                }
     
    14271435                if (RT_FAILURE(rc))
    14281436                {
    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));
    14301438                    break;
    14311439                }
     
    14361444                    if (RT_FAILURE(rc))
    14371445                    {
    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));
    14391447                        break;
    14401448                    }
     
    14461454        default:
    14471455        {
    1448             CORELOGREL(("ElfWriteNoteSection: Invalid type %d\n", enmType));
     1456            CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: Invalid type %d\n", enmType));
    14491457            rc = VERR_GENERAL_FAILURE;
    14501458            break;
     
    14651473 * @return VBox status code.
    14661474 */
    1467 int ElfWriteMappings(PVBOXCORE pVBoxCore)
     1475static int ElfWriteMappings(PVBOXCORE pVBoxCore)
    14681476{
    14691477    PVBOXPROCESS pVBoxProc = &pVBoxCore->VBoxProc;
     
    14801488            {
    14811489                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);
    14831491                if (RT_FAILURE(rc2))
    14841492                {
    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));
    14861494                    return VERR_INVALID_STATE;
    14871495                }
     
    14901498                if (RT_FAILURE(rc))
    14911499                {
    1492                     CORELOGREL(("ElfWriteMappings: pfnWriter failed. rc=%Rrc\n", rc));
     1500                    CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: pfnWriter failed. rc=%Rrc\n", rc));
    14931501                    return rc;
    14941502                }
     
    15021510            memcpy(achBuf, &pMapInfo->fError, sizeof(pMapInfo->fError));
    15031511            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"));
    15051513            rc = pVBoxCore->pfnWriter(pVBoxCore->hCoreFile, &achBuf, sizeof(achBuf));
    15061514            if (RT_FAILURE(rc))
    15071515            {
    1508                 CORELOGREL(("ElfWriteMappings: pfnWriter(2) failed. rc=%Rrc\n", rc));
     1516                CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: pfnWriter(2) failed. rc=%Rrc\n", rc));
    15091517                return rc;
    15101518            }
     
    15171525}
    15181526
     1527
    15191528/**
    15201529 * Write program headers for all mappings into the core file.
     
    15241533 * @return VBox status code.
    15251534 */
    1526 int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore)
     1535static int ElfWriteMappingHeaders(PVBOXCORE pVBoxCore)
    15271536{
    15281537    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    15561565        if (RT_FAILURE(rc))
    15571566        {
    1558             CORELOGREL(("ElfWriteMappingHeaders: pfnWriter failed. rc=%Rrc\n", rc));
     1567            CORELOGRELSYS((CORELOG_NAME "ElfWriteMappingHeaders: pfnWriter failed. rc=%Rrc\n", rc));
    15591568            return rc;
    15601569        }
     
    15771586 * @return VBox status.
    15781587 */
    1579 int WriteCore(PVBOXCORE pVBoxCore, PFNCOREWRITER pfnWriter)
     1588static int rtCoreDumperWriteCore(PVBOXCORE pVBoxCore, PFNCOREWRITER pfnWriter)
    15801589{
    15811590    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    15971606    if (RT_FAILURE(rc))
    15981607    {
    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));
    16001609        goto WriteCoreDone;
    16011610    }
     
    16081617    if (RT_FAILURE(rc))
    16091618    {
    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));
    16111620        goto WriteCoreDone;
    16121621    }
     
    16141623    pVBoxCore->offWrite = 0;
    16151624    uint32_t cProgHdrs  = pVBoxProc->cMappings + 2; /* two PT_NOTE program headers (old, new style) */
    1616     uint32_t cSecHdrs   = CountSections(pVBoxCore);
    16171625
    16181626    /*
     
    16461654    if (RT_FAILURE(rc))
    16471655    {
    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));
    16491657        goto WriteCoreDone;
    16501658    }
     
    16671675    if (RT_FAILURE(rc))
    16681676    {
    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));
    16701678        goto WriteCoreDone;
    16711679    }
     
    16801688    if (RT_FAILURE(rc))
    16811689    {
    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));
    16831691        goto WriteCoreDone;
    16841692    }
     
    16911699    if (RT_FAILURE(rc))
    16921700    {
    1693         CORELOGREL(("Write: ElfWriteMappings failed. rc=%Rrc\n", rc));
     1701        CORELOGRELSYS((CORELOG_NAME "Write: ElfWriteMappings failed. rc=%Rrc\n", rc));
    16941702        goto WriteCoreDone;
    16951703    }
     
    17011709    if (RT_FAILURE(rc))
    17021710    {
    1703         CORELOGREL(("WriteCore: ElfWriteNoteSection old-style failed. rc=%Rrc\n", rc));
     1711        CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteNoteSection old-style failed. rc=%Rrc\n", rc));
    17041712        goto WriteCoreDone;
    17051713    }
     
    17111719    if (RT_FAILURE(rc))
    17121720    {
    1713         CORELOGREL(("WriteCore: ElfWriteNoteSection new-style failed. rc=%Rrc\n", rc));
     1721        CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteNoteSection new-style failed. rc=%Rrc\n", rc));
    17141722        goto WriteCoreDone;
    17151723    }
     
    17211729    if (RT_FAILURE(rc))
    17221730    {
    1723         CORELOGREL(("WriteCore: ElfWriteMappings failed. rc=%Rrc\n", rc));
     1731        CORELOGRELSYS((CORELOG_NAME "WriteCore: ElfWriteMappings failed. rc=%Rrc\n", rc));
    17241732        goto WriteCoreDone;
    17251733    }
     
    17551763 * @return VBox status code.
    17561764 */
    1757 int CreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext)
     1765static int rtCoreDumperCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext)
    17581766{
    17591767    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    17781786    RTProcGetExecutableName(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath));  /* this gets full path not just name */
    17791787    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));
    17831805
    17841806    /*
     
    17881810    if (RT_SUCCESS(rc))
    17891811    {
    1790         rc = ReadProcInfo(pVBoxCore);
     1812        rc = ProcReadInfo(pVBoxCore);
    17911813        if (RT_SUCCESS(rc))
    17921814        {
    17931815            GetOldProcessInfo(pVBoxCore, &pVBoxProc->ProcInfoOld);
    1794             if (IsProcArchNative(pVBoxProc))
     1816            if (IsProcessArchNative(pVBoxProc))
    17951817            {
    17961818                /*
    17971819                 * Read process status, information such as number of active LWPs will be invalid since we just quiesced the process.
    17981820                 */
    1799                 rc = ReadProcStatus(pVBoxCore);
     1821                rc = ProcReadStatus(pVBoxCore);
    18001822                if (RT_SUCCESS(rc))
    18011823                {
     
    18101832                        } aAccumulators[] =
    18111833                        {
    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 }
    18191841                        };
    18201842
     
    18241846                            if (RT_FAILURE(rc))
    18251847                            {
    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));
    18271849                                if (!aAccumulators[i].fOptional)
    18281850                                    break;
     
    18391861                    }
    18401862                    else
    1841                         CORELOGREL(("DumpCore: AllocMemoryArea failed. rc=%Rrc\n", rc));
     1863                        CORELOGRELSYS((CORELOG_NAME "CreateCore: AllocMemoryArea failed. rc=%Rrc\n", rc));
    18421864                }
    18431865                else
    1844                     CORELOGREL(("DumpCore: ReadProcStatus failed. rc=%Rrc\n", rc));
     1866                    CORELOGRELSYS((CORELOG_NAME "CreateCore: ProcReadStatus failed. rc=%Rrc\n", rc));
    18451867            }
    18461868            else
    18471869            {
    1848                 CORELOGREL(("DumpCore: IsProcArchNative failed.\n"));
     1870                CORELOGRELSYS((CORELOG_NAME "CreateCore: IsProcessArchNative failed.\n"));
    18491871                rc = VERR_BAD_EXE_FORMAT;
    18501872            }
    18511873        }
    18521874        else
    1853             CORELOGREL(("DumpCore: ReadProcInfo failed. rc=%Rrc\n", rc));
     1875            CORELOGRELSYS((CORELOG_NAME "CreateCore: ProcReadInfo failed. rc=%Rrc\n", rc));
    18541876
    18551877        /*
     
    18591881    }
    18601882    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));
    18621884
    18631885    return rc;
     
    18721894 * @return VBox status code.
    18731895 */
    1874 int DestroyCore(PVBOXCORE pVBoxCore)
     1896static int rtCoreDumperDestroyCore(PVBOXCORE pVBoxCore)
    18751897{
    18761898    AssertReturn(pVBoxCore, VERR_INVALID_POINTER);
     
    18841906
    18851907
    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 */
     1915static int rtCoreDumperTakeDump(ucontext_t *pContext)
     1916{
    18911917    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    }
    18931941    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 */
     1956static 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        {
    18991974            /*
    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.
    19031977             */
    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;
    19221997        else
    19231998        {
    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));
    19262000            int64_t iTimeout = 10000;  /* timeout (ms) */
    1927             while (!ASMAtomicUoReadBool(&g_fCoreDumpInProgress))
     2001            while (ASMAtomicUoReadBool(&g_fCoreDumpInProgress) == true)
    19282002            {
    19292003                RTThreadSleep(200);
     
    19332007            }
    19342008            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 */
     2031RTDECL(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);
    19482043    return VINF_SUCCESS;
    19492044}
    19502045
    19512046
    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 */
     2064RTDECL(int) RTCoreDumperSetup(const char *pszOutputDir, uint32_t fFlags)
     2065{
     2066    /*
     2067     * Validate flags.
     2068     */
     2069    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
    19562070
    19572071    /*
    19582072     * Install core dump signal handler.
    19592073     */
    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 */
     2098RTDECL(int) RTCoreDumperDisable(void)
     2099{
    19682100    /*
    1969      * Spawn a few threads.
     2101     * Remove core dump signal handler & reset variables.
    19702102     */
    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  
    6161
    6262/**
    63  * ELF NOTE header.
     63 * ELFNOTEHDR: ELF NOTE header.
    6464 */
    6565typedef struct ELFNOTEHDR
     
    7070typedef ELFNOTEHDR *PELFNOTEHDR;
    7171
     72
    7273#ifdef RT_OS_SOLARIS
     74/**
     75 * VBOXSOLMAPINFO: Memory mapping description.
     76 */
    7377typedef struct VBOXSOLMAPINFO
    7478{
     
    7983typedef VBOXSOLMAPINFO *PVBOXSOLMAPINFO;
    8084
     85/**
     86 * VBOXSOLCORETYPE: Whether this is an old or new style core.
     87 */
     88typedef enum VBOXSOLCORETYPE
     89{
     90    enmOldEra       = 0x01d,        /* old */
     91    enmNewEra       = 0x5c151       /* sci-fi */
     92} VBOXSOLCORETYPE;
     93
     94/**
     95 * VBOXSOLTHREADINFO: Per-Thread information.
     96 */
    8197typedef struct VBOXSOLTHREADINFO
    8298{
     
    88104#endif
    89105
    90 typedef int (*PFNCOREREADER)(RTFILE hFile, void *pv, size_t cb);
    91 typedef int (*PFNCOREWRITER)(RTFILE hFile, const void *pcv, size_t cb);
    92106
     107/**
     108 * VBOXPROCESS: Current (also the core target) process information.
     109 */
    93110typedef struct VBOXPROCESS
    94111{
     
    127144typedef VBOXPROCESS *PVBOXPROCESS;
    128145
     146typedef int (*PFNCOREREADER)(RTFILE hFile, void *pv, size_t cb);
     147typedef int (*PFNCOREWRITER)(RTFILE hFile, const void *pcv, size_t cb);
     148
     149/**
     150 * VBOXCORE: Core file object.
     151 */
    129152typedef struct VBOXCORE
    130153{
     
    142165typedef VBOXCORE *PVBOXCORE;
    143166
    144 typedef int (*PFNCOREACCUMULATOR)(PVBOXCORE pVBoxCOre);
     167typedef int (*PFNCOREACCUMULATOR)(PVBOXCORE pVBoxCore);
     168
  • trunk/src/VBox/Runtime/testcase/tstRTCoreDump.cpp

    r31820 r31860  
    2929*******************************************************************************/
    3030#include <iprt/types.h>
    31 #include <iprt/file.h>
    3231#include <iprt/err.h>
    33 #include <iprt/dir.h>
    34 #include <iprt/path.h>
    35 #include <iprt/string.h>
    36 #include <iprt/stream.h>
    3732#include <iprt/initterm.h>
    3833#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>
    4236
    43 #ifdef RT_OS_SOLARIS
    44 # 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 */
    5337
    5438/*******************************************************************************
    55 *   Defined Constants And Macros                                               *
     39*   Globals                                                                    *
    5640*******************************************************************************/
    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 
    6941static 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     else
    188         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 anonymously
    196  * 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 VBOXSOLPREALLOCTABLE
    208     {
    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 > 0
    231             && aPreAllocTable[i].cbEntry > 0
    232             && 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     else
    258     {
    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             else
    338                 rc = VERR_NO_MEMORY;
    339         }
    340         else
    341         {
    342             *pcb =  0;
    343             *ppv = NULL;
    344         }
    345         RTFileClose(hFile);
    346     }
    347     else
    348         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                 else
    515                 {
    516                     CORELOGREL(("ReadProcAuxVecs: Invalid vector count %u\n", pVBoxProc->cAuxVecs));
    517                     rc = VERR_READ_ERROR;
    518                 }
    519             }
    520             else
    521                 CORELOGREL(("ReadProcAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile));
    522 
    523             pVBoxProc->pAuxVecs = NULL;
    524             pVBoxProc->cAuxVecs = 0;
    525         }
    526         else
    527         {
    528             CORELOGREL(("ReadProcAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t)));
    529             rc = VERR_NO_MEMORY;
    530         }
    531     }
    532     else
    533         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 core
    634                                          * will contain an errno in place. So we adjust the prmap_t's size field too
    635                                          * 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                         else
    658                         {
    659                             CORELOGREL(("ReadProcMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));
    660                             rc = VERR_NO_MEMORY;
    661                         }
    662                     }
    663                     else
    664                     {
    665                         CORELOGREL(("ReadProcMappings: Invalid mapping count %u\n", pVBoxProc->cMappings));
    666                         rc = VERR_READ_ERROR;
    667                     }
    668                 }
    669                 else
    670                     CORELOGREL(("ReadProcMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile));
    671             }
    672             else
    673             {
    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     else
    683         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 == 0
    736                 && (cbInfoHdrAndData - sizeof(prheader_t)) % pInfoHdr->pr_entsize == 0)
    737             {
    738                 /*
    739                  * Make sure we have a matching lstatus entry for an lpsinfo entry unless
    740                  * 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 == 0
    747                             || 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 the
    763                      * 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 context
    784                                  * 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                             else
    805                             {
    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                     else
    823                     {
    824                         CORELOGREL(("ReadProcThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));
    825                         rc = VERR_NO_MEMORY;
    826                     }
    827                 }
    828                 else
    829                     CORELOGREL(("ReadProcThreads: Invalid state information for threads.\n", rc));
    830             }
    831             else
    832             {
    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         else
    840             CORELOGREL(("ReadProcThreads: ReadFileNoIntr failed for \"lpsinfo\" rc=%Rrc\n", rc));
    841     }
    842     else
    843         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_SOLARIS
    863     /*
    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 #else
    891 # error Port Me!
    892 #endif
    893     return rc;
    894 }
    895 
    896 
    897 /**
    898  * On Solaris use the old-style procfs interfaces but the core file still should have this
    899  * 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 this
    955  * 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     else
    1100     {
    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 any
    1111  * 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         else
    1162         {
    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_SOLARIS
    1209     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 #else
    1229 #error Port Me!
    1230 #endif
    1231     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_SOLARIS
    1331 
    1332     typedef int (*PFNELFWRITENOTEHDR)(PVBOXCORE pVBoxCore, uint_t, const void *pcv, size_t cb);
    1333     typedef struct ELFWRITENOTE
    1334     {
    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                 else
    1385                 {
    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 thread
    1421              * 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 #else
    1454 # error Port Me!
    1455 #endif
    1456     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         else
    1499         {
    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 threads
    1571  * 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_AMD64
    1631     ElfHdr.e_machine         = EM_AMD64;
    1632     ElfHdr.e_ident[EI_CLASS] = ELFCLASS64;
    1633 #else
    1634     ElfHdr.e_machine         = EM_386;
    1635     ElfHdr.e_ident[EI_CLASS] = ELFCLASS32;
    1636 #endif
    1637     if (cProgHdrs >= PN_XNUM)
    1638         ElfHdr.e_phnum       = PN_XNUM;
    1639     else
    1640         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 halting
    1748  * all threads which can lead to things like spurious wakeups of threads (if and when threads
    1749  * 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 COREACCUMULATOR
    1806                         {
    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                     else
    1841                         CORELOGREL(("DumpCore: AllocMemoryArea failed. rc=%Rrc\n", rc));
    1842                 }
    1843                 else
    1844                     CORELOGREL(("DumpCore: ReadProcStatus failed. rc=%Rrc\n", rc));
    1845             }
    1846             else
    1847             {
    1848                 CORELOGREL(("DumpCore: IsProcArchNative failed.\n"));
    1849                 rc = VERR_BAD_EXE_FORMAT;
    1850             }
    1851         }
    1852         else
    1853             CORELOGREL(("DumpCore: ReadProcInfo failed. rc=%Rrc\n", rc));
    1854 
    1855         /*
    1856          * Resume threads on failure.
    1857          */
    1858         ResumeAllThreads(pVBoxProc);
    1859     }
    1860     else
    1861         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     else
    1894     {
    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 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.
    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                 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         }
    1922         else
    1923         {
    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 
    194342
    194443static DECLCALLBACK(int) SleepyThread(RTTHREAD Thread, void *pvUser)
    194544{
    194645    NOREF(pvUser);
    1947     sleep(10000);
     46    RTThreadSleep(90000000);
    194847    return VINF_SUCCESS;
    194948}
    1950 
    195149
    195250int main()
    195351{
    195452    RTR3Init();
    1955     CORELOG(("tstRTCoreDump: TESTING pid=%d\n", getpid()));
     53    RTPrintf("tstRTCoreDump: TESTING...\n");
    195654
    195755    /*
    1958      * Install core dump signal handler.
     56     * Setup core dumping.
    195957     */
    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))
    197360    {
    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);
    197583        if (RT_FAILURE(rc))
    197684        {
    1977             CORELOG(("tstRTCoreDump: FAILURE(%d) - %d RTThreadCreate failed, rc=%Rrc\n", __LINE__, i, rc));
    197885            g_cErrors++;
    1979             ahThreads[i] = NIL_RTTHREAD;
    1980             break;
     86            RTPrintf("RTCoreDumperTakeDump failed. rc=%Rrc\n", rc);
    198187        }
    198288    }
    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    }
    199394
    199495    /*
     
    199697     */
    199798    if (!g_cErrors)
    1998         CORELOG(("tstRTCoreDump: SUCCESS\n"));
     99        RTPrintf("tstRTCoreDump: SUCCESS\n");
    1999100    else
    2000         CORELOG(("tstRTCoreDump: FAILURE - %d errors\n", g_cErrors));
     101        RTPrintf("tstRTCoreDump: FAILURE - %d errors\n", g_cErrors);
    2001102
    2002103    return !!g_cErrors;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette