coredumper-solaris.cpp revision fc7eb0ac76e88066738ca527b2bb4fef7faf20ea
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * IPRT Testcase - Core Dumper.
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * Copyright (C) 2010 Oracle Corporation
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * available from http://www.virtualbox.org. This file is free software;
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * you can redistribute it and/or modify it under the terms of the GNU
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * General Public License (GPL) as published by the Free Software
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * The contents of this file may alternatively be used under the terms
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * of the Common Development and Distribution License Version 1.0
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * VirtualBox OSE distribution, in which case the provisions of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * CDDL are applicable instead of those of the GPL.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * You may elect to license modified versions of this file under the
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * terms and conditions of either the GPL or the CDDL or both.
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Header Files *
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync*******************************************************************************/
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync#endif /* RT_OS_SOLARIS */
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync/*******************************************************************************
07557d07616212d7ba6e7ab3059e85cb14633775vboxsync*******************************************************************************/
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncvolatile static uint64_t g_CoreDumpThread = NIL_RTTHREAD;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncvolatile static bool g_fCoreDumpSignalSetup = false;
07557d07616212d7ba6e7ab3059e85cb14633775vboxsyncvolatile static bool g_fCoreDumpDeliberate = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncvolatile static bool g_fCoreDumpInProgress = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Defined Constants And Macros *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync } while (0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * ELFNOTEHDR: ELF NOTE header.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct ELFNOTEHDR
711fe7f5a2aa54e908a51475cf92b2642857bbdavboxsync * Wrapper function to write IPRT format style string to the syslog.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszFormat Format string
static bool IsBigEndian()
return rc;
return rc;
return rc;
struct VBOXSOLPREALLOCTABLE
} aPreAllocTable[] = {
RTStrPrintf(szPath, sizeof(szPath), aPreAllocTable[i].pszFilePath, (int)pVBoxCore->VBoxProc.Process);
if ( cbFile > 0
cb += ((cbFile - aPreAllocTable[i].cbHeader) / aPreAllocTable[i].cbEntry) * (aPreAllocTable[i].cbAccounting > 0 ?
void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1 /* fd */, 0 /* offset */);
if (pv)
return VINF_SUCCESS;
return VERR_NO_MEMORY;
return pb;
return NULL;
static int ProcReadFileInto(PVBOXCORE pVBoxCore, const char *pszProcFileName, void **ppv, size_t *pcb)
RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/%s", (int)pVBoxCore->VBoxProc.Process, pszProcFileName);
if (*pcb > 0)
if (*ppv)
*pcb = 0;
return rc;
return rc;
return rc;
return rc;
return VERR_INVALID_STATE;
return rc;
return rc;
CORELOG((CORELOG_NAME "ProcReadAuxVecs: cbAuxFile=%u auxv_t size %d cAuxVecs=%u\n", cbAuxFile, sizeof(auxv_t), pVBoxProc->cAuxVecs));
return VINF_SUCCESS;
CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile));
CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t)));
CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: aux file too small %u, expecting %u or more\n", cbAuxFile, sizeof(auxv_t)));
return rc;
return rc;
if (pMap)
pVBoxProc->pMapInfoHead = (PVBOXSOLMAPINFO)GetMemoryChunk(pVBoxCore, pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO));
if (pPrev)
uint64_t k = 0;
CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: skipping mapping. vaddr=%#x rc=%Rrc\n", pCur->pMap.pr_vaddr, rc2));
k += cb;
if (pPrev)
CORELOG((CORELOG_NAME "ProcReadMappings: successfully read in %u mappings\n", pVBoxProc->cMappings));
return VINF_SUCCESS;
CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed %u\n", pVBoxProc->cMappings * sizeof(VBOXSOLMAPINFO)));
CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile));
return rc;
CORELOG((CORELOG_NAME "ProcReadThreads: read info(%u) status(%u), threads:cInfo=%u cStatus=%u\n", cbInfoHdrAndData,
if ( cStatus == 0
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: cStatus = %u pStatuslwpid=%d infolwpid=%d\n", cStatus,
cStatus--;
memcpy(&pStatus->pr_fpreg, &pVBoxProc->pCurThreadCtx->uc_mcontext.fpregs, sizeof(pStatus->pr_fpreg));
CORELOG((CORELOG_NAME "ProcReadThreads: patched dumper thread context with pre-dump time context.\n"));
if (pPrev)
if (pPrev)
return VINF_SUCCESS;
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: GetMemoryChunk failed for %u bytes\n", cbThreadInfo));
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: huh!? cbStatusHdrAndData=%u prheader_t=%u entsize=%u\n", cbStatusHdrAndData,
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: huh!? cbInfoHdrAndData=%u entsize=%u\n", cbInfoHdrAndData, pStatusHdr->pr_entsize));
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: ReadFileNoIntr failed for \"lpsinfo\" rc=%Rrc\n", rc));
CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: ReadFileNoIntr failed for \"lstatus\" rc=%Rrc\n", rc));
return rc;
#ifdef RT_OS_SOLARIS
return VERR_GENERAL_FAILURE;
return VERR_GENERAL_FAILURE;
rc = getzonenamebyid(pVBoxProc->ProcInfo.pr_zoneid, pVBoxProc->szZoneName, sizeof(pVBoxProc->szZoneName));
if (rc < 0)
CORELOGRELSYS((CORELOG_NAME "ProcReadMiscInfo: getzonenamebyid failed. rc=%d errno=%d zoneid=%d\n", rc, errno, pVBoxProc->ProcInfo.pr_zoneid));
return VERR_GENERAL_FAILURE;
return rc;
static void GetOldProcessStatus(PVBOXCORE pVBoxCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)
return VINF_SUCCESS;
return VINF_SUCCESS;
static int rtCoreDumperForEachThread(PVBOXCORE pVBoxCore, uint64_t *pcThreads, PFNCORETHREADWORKER pfnWorker)
void *pvInfoHdr = mmap(NULL, cbInfoHdrAndData, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1 /* fd */, 0 /* offset */);
if (pvInfoHdr)
if (pcThreads)
return rc;
return rc;
return rc;
CORELOG((CORELOG_NAME "SuspendThreads: Stopped %u threads successfully with %u tries\n", cThreads, cTries));
return rc;
#ifdef RT_OS_SOLARIS
return rc;
switch (enmType)
case enmOldEra:
while (pThreadInfo)
case enmNewEra:
while (pThreadInfo)
return cb;
#ifdef RT_OS_SOLARIS
typedef struct ELFWRITENOTE
const char *pszType;
const void *pcv;
} ELFWRITENOTE;
switch (enmType)
case enmOldEra:
CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));
rc = ElfWriteNoteHeader(pVBoxCore, NT_PRFPREG, &pThreadInfo->pStatus->pr_fpreg, sizeof(prfpregset_t));
CORELOGRELSYS((CORELOG_NAME "ElfWriteSegment: ElfWriteNote failed for NT_PRSTATUS. rc=%Rrc\n", rc));
case enmNewEra:
{ "NT_PRPRIVINFO", NT_PRPRIVINFO, pVBoxProc->pcPrivImpl, PRIV_IMPL_INFO_SIZE(pVBoxProc->pcPrivImpl) },
CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader failed for %s. rc=%Rrc\n", aElfNotes[i].pszType, rc));
CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSINFO failed. rc=%Rrc\n", rc));
CORELOGRELSYS((CORELOG_NAME "ElfWriteNoteSection: ElfWriteNoteHeader for NT_LWPSTATUS failed. rc=%Rrc\n", rc));
return rc;
while (pMapInfo)
uint64_t k = 0;
CORELOGRELSYS((CORELOG_NAME "ElfWriteMappings: Failed to read mapping, can't recover. Bye. rc=%Rrc\n", rc));
return VERR_INVALID_STATE;
return rc;
k += cb;
return rc;
return VINF_SUCCESS;
while (pMapInfo)
ProgHdr.p_vaddr = pMapInfo->pMap.pr_vaddr; /* Virtual address of this mapping in the process address space */
return rc;
return rc;
return VERR_INVALID_STATE;
if (pfnWriter)
goto WriteCoreDone;
rc = RTFileOpen(&pVBoxCore->hCoreFile, pVBoxCore->szCorePath, RTFILE_O_OPEN_CREATE | RTFILE_O_TRUNCATE | RTFILE_O_READWRITE | RTFILE_O_DENY_ALL);
goto WriteCoreDone;
#ifdef RT_ARCH_AMD64
goto WriteCoreDone;
CORELOGRELSYS((CORELOG_NAME "WriteCore: pfnWriter failed writing old-style ELF program Header. rc=%Rrc\n", rc));
goto WriteCoreDone;
CORELOGRELSYS((CORELOG_NAME "WriteCore: pfnWriter failed writing new-style ELF program header. rc=%Rrc\n", rc));
goto WriteCoreDone;
goto WriteCoreDone;
goto WriteCoreDone;
goto WriteCoreDone;
goto WriteCoreDone;
return rc;
RTProcGetExecutableName(pVBoxProc->szExecPath, sizeof(pVBoxProc->szExecPath)); /* this gets full path not just name */
RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s", g_szCoreDumpDir, g_szCoreDumpFile);
CORELOG((CORELOG_NAME "CreateCore: Taking Core %s from Thread %d\n", pVBoxCore->szCorePath, (int)pVBoxProc->hCurThread));
* Read process status, information such as number of active LWPs will be invalid since we just quiesced the process.
struct COREACCUMULATOR
const char *pszName;
bool fOptional;
} aAccumulators[] =
return VINF_SUCCESS;
return rc;
return VERR_INVALID_STATE;
return VINF_SUCCESS;
if (!pContext)
return VERR_INVALID_POINTER;
CORELOGRELSYS((CORELOG_NAME "TakeDump: WriteCore failed. szCorePath=%s rc=%Rrc\n", VBoxCore.szCorePath, rc));
return rc;
bool fCallSystemDump = false;
fCallSystemDump = true;
fCallSystemDump = true;
CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dump already in progress! Waiting before signalling Sig=%d.\n", Sig));
if (iTimeout <= 0)
if (iTimeout <= 0)
fCallSystemDump = true;
CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dump seems to be stuck. Signalling new signal %d\n", Sig));
if (fCallSystemDump)
return VERR_WRONG_ORDER;
if (pszOutputFile)
return VINF_SUCCESS;
if (pszOutputDir)
return VINF_SUCCESS;
return VINF_SUCCESS;