coredumper-solaris.cpp revision 0e3021c718d32b7803f6481d16cb5c847138cb5e
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * IPRT - Custom Core Dumper, Solaris.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Copyright (C) 2010-2011 Oracle Corporation
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This file is part of VirtualBox Open Source Edition (OSE), as
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * available from http://www.virtualbox.org. This file is free software;
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China * you can redistribute it and/or modify it under the terms of the GNU
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * General Public License (GPL) as published by the Free Software
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Foundation, in version 2 as it comes in the "COPYING" file of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file may alternatively be used under the terms
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * of the Common Development and Distribution License Version 1.0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China * VirtualBox OSE distribution, in which case the provisions of the
a79493184c9332129c9c91500069322f6f3fafddReed * CDDL are applicable instead of those of the GPL.
bff3dadc2c9a6711b6e359fc39d0170de218be50duo liu - Sun Microsystems - Beijing China * You may elect to license modified versions of this file under the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * terms and conditions of either the GPL or the CDDL or both.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Header Files *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte#endif /* RT_OS_SOLARIS */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic RTNATIVETHREAD volatile g_CoreDumpThread = NIL_RTNATIVETHREAD;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic bool volatile g_fCoreDumpSignalSetup = false;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte/*******************************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte* Defined Constants And Macros *
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte*******************************************************************************/
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ELFNOTEHDR: ELF NOTE header.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortetypedef struct ELFNOTEHDR
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Wrapper function to write IPRT format style string to the syslog.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pszFormat Format string
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void rtCoreDumperSysLogWrapper(const char *pszFormat, ...)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determines endianness of the system. Just for completeness.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return Will return false if system is little endian, true otherwise.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte const int i = 1;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte char *p = (char *)&i;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (p[0] == 1)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return false;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return true;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reads from a file making sure an interruption doesn't cause a failure.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param fd Handle to the file to read.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pv Where to store the read data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param cbToRead Size of data to read.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int ReadFileNoIntr(int fd, void *pv, size_t cbToRead)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Writes to a file making sure an interruption doesn't cause a failure.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param fd Handle to the file to write to.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pv Pointer to what to write.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param cbToWrite Size of data to write.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int WriteFileNoIntr(int fd, const void *pv, size_t cbToWrite)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read from a given offset in the process' address space.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolProc Pointer to the solaris process.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pv Where to read the data into.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param cb Size of the read buffer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param off Offset to read from.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic ssize_t ProcReadAddrSpace(PRTSOLCOREPROCESS pSolProc, RTFOFF off, void *pvBuf, size_t cbToRead)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ssize_t cbRead = pread(pSolProc->fdAs, pvBuf, cbToRead, off);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Determines if the current process' architecture is suitable for dumping core.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolProc Pointer to the solaris process.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return true if the architecture matches the current one.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic inline bool IsProcessArchNative(PRTSOLCOREPROCESS pSolProc)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return pSolProc->ProcInfo.pr_dmodel == PR_MODEL_NATIVE;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Helper function to get the size_t compatible file size from a file
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * descriptor.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return The file size (in bytes).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param fd The file descriptor.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return st.st_size < ~(size_t)0 ? (size_t)st.st_size : ~(size_t)0;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "GetFileSizeByFd: fstat failed rc=%Rrc\n", RTErrConvertFromErrno(errno)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Helper function to get the size_t compatible size of a file given its path.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return The file size (in bytes).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pszPath Pointer to the full path of the file.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic size_t GetFileSizeByName(const char *pszPath)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "GetFileSizeByName: failed to open %s rc=%Rrc\n", pszPath, RTErrConvertFromErrno(errno)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Pre-compute and pre-allocate sufficient memory for dumping core.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * This is meant to be called once, as a single-large anonymously
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * mapped memory area which will be used during the core dumping routines.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte AssertReturn(pSolCore->pvCore == NULL, VERR_ALREADY_EXISTS);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte static struct
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t cbAccounting; /* Size of each accounting entry per entry */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/map", 0, sizeof(prmap_t), sizeof(RTSOLCOREMAPINFO) },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/auxv", 0, 0, 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/lpsinfo", sizeof(prheader_t), sizeof(lwpsinfo_t), sizeof(RTSOLCORETHREADINFO) },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/lstatus", 0, 0, 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/ldt", 0, 0, 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/cred", sizeof(prcred_t), sizeof(gid_t), 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte { "/proc/%d/priv", sizeof(prpriv_t), sizeof(priv_chunk_t), 0 },
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (unsigned i = 0; i < RT_ELEMENTS(s_aPreAllocTable); i++)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), s_aPreAllocTable[i].pszFilePath, (int)pSolCore->SolProc.Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cb += ((cbFile - s_aPreAllocTable[i].cbHeader) / s_aPreAllocTable[i].cbEntry)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * (s_aPreAllocTable[i].cbAccounting > 0 ? s_aPreAllocTable[i].cbAccounting : 1);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Make room for our own mapping accountant entry which will also be included in the core.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Allocate the required space, plus some extra room.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte void *pv = mmap(NULL, cb, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1 /* fd */, 0 /* offset */);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOG((CORELOG_NAME "AllocMemoryArea: memory area of %u bytes allocated.\n", cb));
a79493184c9332129c9c91500069322f6f3fafddReed CORELOGRELSYS((CORELOG_NAME "AllocMemoryArea: failed cb=%u\n", cb));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Free memory area used by the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOG((CORELOG_NAME "FreeMemoryArea: memory area of %u bytes freed.\n", pSolCore->cbCore));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Get a chunk from the area of allocated memory.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param cb Size of requested chunk.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return Pointer to allocated memory, or NULL on failure.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic void *GetMemoryChunk(PRTSOLCORE pSolCore, size_t cb)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t cbAllocated = (char *)pSolCore->pvFree - (char *)pSolCore->pvCore;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reads the proc file's content into a newly allocated buffer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pszFileFmt Only the name of the file to read from (/proc/<pid> will be prepended)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param ppv Where to store the allocated buffer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pcb Where to store size of the buffer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code. If the proc file is 0 bytes, VINF_SUCCESS is
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * returned with pointed to values of @c ppv, @c pcb set to NULL and 0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * respectively.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int ProcReadFileInto(PRTSOLCORE pSolCore, const char *pszProcFileName, void **ppv, size_t *pcb)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/%s", (int)pSolCore->SolProc.Process, pszProcFileName);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadFileInto: failed to open %s. rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process information (format psinfo_t) from /proc.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/psinfo", (int)pSolProc->Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = ReadFileNoIntr(fd, &pSolProc->ProcInfo, cbProcInfo);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadInfo: failed to open %s. rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process status (format pstatus_t) from /proc.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/status", (int)pSolProc->Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte AssertCompile(sizeof(pstatus_t) == sizeof(pSolProc->ProcStatus));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = ReadFileNoIntr(fd, &pSolProc->ProcStatus, cbProcStatus);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadStatus: failed to open %s. rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process credential information (format prcred_t + array of guid_t)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ProcReadFileInto(pSolCore, "cred", &pSolProc->pvCred, &pSolProc->cbCred);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process privilege information (format prpriv_t + array of priv_chunk_t)
a79493184c9332129c9c91500069322f6f3fafddReed * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = ProcReadFileInto(pSolCore, "priv", (void **)&pSolProc->pPriv, &pSolProc->cbPriv);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadPriv: getprivimplinfo returned NULL.\n"));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process LDT information (format array of struct ssd) from /proc.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolProc Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte return ProcReadFileInto(pSolCore, "ldt", &pSolProc->pvLdt, &pSolProc->cbLdt);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read process auxiliary vectors (format auxv_t) for the process.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/auxv", (int)pSolProc->Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: failed to open %s rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->pAuxVecs = (auxv_t*)GetMemoryChunk(pSolCore, cbAuxFile + sizeof(auxv_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = ReadFileNoIntr(fd, pSolProc->pAuxVecs, cbAuxFile);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Terminate list of vectors */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOG((CORELOG_NAME "ProcReadAuxVecs: cbAuxFile=%u auxv_t size %d cAuxVecs=%u\n", cbAuxFile, sizeof(auxv_t),
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->pAuxVecs[pSolProc->cAuxVecs].a_type = AT_NULL;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->pAuxVecs[pSolProc->cAuxVecs].a_un.a_val = 0L;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: Invalid vector count %u\n", pSolProc->cAuxVecs));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: ReadFileNoIntr failed. rc=%Rrc cbAuxFile=%u\n", rc, cbAuxFile));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: no memory for %u bytes\n", cbAuxFile + sizeof(auxv_t)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadAuxVecs: aux file too small %u, expecting %u or more\n", cbAuxFile, sizeof(auxv_t)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Find an element in the process' auxiliary vector.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic long GetAuxVal(PRTSOLCOREPROCESS pSolProc, int Type)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read the process mappings (format prmap_t array).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/map", (int)pSolProc->Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: failed to open %s. rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/as", (int)pSolProc->Process);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Allocate and read all the prmap_t objects from proc.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte prmap_t *pMap = (prmap_t*)GetMemoryChunk(pSolCore, cbMapFile);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->cMappings = cbMapFile / sizeof(prmap_t);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Allocate for each prmap_t object, a corresponding RTSOLCOREMAPINFO object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->pMapInfoHead = (PRTSOLCOREMAPINFO)GetMemoryChunk(pSolCore, pSolProc->cMappings * sizeof(RTSOLCOREMAPINFO));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Associate the prmap_t with the mapping info object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /*Assert(pSolProc->pMapInfoHead == NULL); - does not make sense */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (uint64_t i = 0; i < pSolProc->cMappings; i++, pMap++, pCur++)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Make sure we can read the mapping, otherwise mark them to be skipped.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte size_t cb = RT_MIN(sizeof(achBuf), pCur->pMap.pr_size - k);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc2 = ProcReadAddrSpace(pSolProc, pCur->pMap.pr_vaddr + k, &achBuf, cb);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: skipping mapping. vaddr=%#x rc=%Rrc\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Instead of storing the actual mapping data which we failed to read, the core
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * will contain an errno in place. So we adjust the prmap_t's size field too
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * so the program header offsets match.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (pCur->fError == 0) /* huh!? somehow errno got reset? fake one! EFAULT is nice. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOG((CORELOG_NAME "ProcReadMappings: successfully read in %u mappings\n", pSolProc->cMappings));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed %u\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte pSolProc->cMappings * sizeof(RTSOLCOREMAPINFO)));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: Invalid mapping count %u\n", pSolProc->cMappings));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: FileReadNoIntr failed. rc=%Rrc cbMapFile=%u\n", rc, cbMapFile));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: GetMemoryChunk failed. cbMapFile=%u\n", cbMapFile));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOGRELSYS((CORELOG_NAME "ProcReadMappings: failed to open %s. rc=%Rrc\n", szPath, rc));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Reads the thread information for all threads in the process.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @param pSolCore Pointer to the core object.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @remarks Should not be called before successful call to @see AllocMemoryArea()
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * @return IPRT status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte AssertReturn(pSolProc->pCurThreadCtx, VERR_NO_DATA);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read the information for threads.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Format: prheader_t + array of lwpsinfo_t's.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte int rc = ProcReadFileInto(pSolCore, "lpsinfo", &pvInfoHdr, &cbInfoHdrAndData);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Read the status of threads.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Format: prheader_t + array of lwpstatus_t's.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte rc = ProcReadFileInto(pSolCore, "lstatus", &pvStatusHdr, &cbStatusHdrAndData);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte prheader_t *pStatusHdr = (prheader_t *)pvStatusHdr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lwpstatus_t *pStatus = (lwpstatus_t *)((uintptr_t)pStatusHdr + sizeof(prheader_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte lwpsinfo_t *pInfo = (lwpsinfo_t *)((uintptr_t)pInfoHdr + sizeof(prheader_t));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte CORELOG((CORELOG_NAME "ProcReadThreads: read info(%u) status(%u), threads:cInfo=%u cStatus=%u\n", cbInfoHdrAndData,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Minor sanity size check (remember sizeof lwpstatus_t & lwpsinfo_t is <= size in file per entry).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ( (cbStatusHdrAndData - sizeof(prheader_t)) % pStatusHdr->pr_entsize == 0
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte && (cbInfoHdrAndData - sizeof(prheader_t)) % pInfoHdr->pr_entsize == 0)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Make sure we have a matching lstatus entry for an lpsinfo entry unless
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * it is a zombie thread, in which case we will not have a matching lstatus entry.
a79493184c9332129c9c91500069322f6f3fafddReed CORELOGRELSYS((CORELOG_NAME "ProcReadThreads: cStatus = %u pStatuslwpid=%d infolwpid=%d\n", cStatus,
a79493184c9332129c9c91500069322f6f3fafddReed pStatus = (lwpstatus_t *)((uintptr_t)pStatus + pStatusHdr->pr_entsize);
a79493184c9332129c9c91500069322f6f3fafddReed pInfo = (lwpsinfo_t *)((uintptr_t)pInfo + pInfoHdr->pr_entsize);
a79493184c9332129c9c91500069322f6f3fafddReed * There can still be more lwpsinfo_t's than lwpstatus_t's, build the
a79493184c9332129c9c91500069322f6f3fafddReed * lists accordingly.
memcpy(&pStatus->pr_fpreg, &pSolProc->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: Invalid state information for threads. rc=%Rrc\n", rc));
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,
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(pSolProc->ProcInfo.pr_zoneid, pSolProc->szZoneName, sizeof(pSolProc->szZoneName));
if (rc < 0)
CORELOGRELSYS((CORELOG_NAME "ProcReadMiscInfo: getzonenamebyid failed. rc=%d errno=%d zoneid=%d\n", rc, errno,
return VERR_GENERAL_FAILURE;
return rc;
static void GetOldProcessStatus(PRTSOLCORE pSolCore, lwpsinfo_t *pInfo, lwpstatus_t *pStatus, prstatus_t *pDst)
return VINF_SUCCESS;
return VINF_SUCCESS;
static int rtCoreDumperForEachThread(PRTSOLCORE pSolCore, uint64_t *pcThreads, PFNRTSOLCORETHREADWORKER pfnWorker)
if (fd >= 0)
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(pSolCore, 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, pSolProc->pcPrivImpl, PRIV_IMPL_INFO_SIZE(pSolProc->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)
if (fd < 0)
goto WriteCoreDone;
if (fd < 0)
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;
static int rtCoreDumperCreateCore(PRTSOLCORE pSolCore, ucontext_t *pContext, const char *pszCoreFilePath)
RTProcGetExecutablePath(pSolProc->szExecPath, sizeof(pSolProc->szExecPath)); /* this gets full path not just name */
if (!pszCoreFilePath)
RTStrPrintf(pSolCore->szCorePath, sizeof(pSolCore->szCorePath), "%s/core.vb.%s", g_szCoreDumpDir, g_szCoreDumpFile);
CORELOG((CORELOG_NAME "CreateCore: Taking Core %s from Thread %d\n", pSolCore->szCorePath, (int)pSolProc->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", SolCore.szCorePath, rc));
return rc;
bool fCallSystemDump = false;
bool fRc;
if (fRc)
CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dumper (thread %u) crashed Sig=%d. Triggering system dump\n",
fCallSystemDump = true;
CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dump already in progress! Waiting a while for completion Sig=%d.\n", Sig));
if (iTimeout <= 0)
if (iTimeout <= 0)
fCallSystemDump = true;
CORELOGRELSYS((CORELOG_NAME "SignalHandler: Core dumper seems to be stuck. Signalling new signal %d\n", Sig));
if (fCallSystemDump)
abort();
if (!rc)
if (!fLiveCore)
abort();
return rc;
if (pszOutputDir)
return VERR_NOT_A_DIRECTORY;
return VINF_SUCCESS;
return VINF_SUCCESS;