* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* bbox_elf_dump.cpp
*
* IDENTIFICATION
* src/gausskernel/cbb/bbox/bbox_elf_dump.cpp
*
* -------------------------------------------------------------------------
*/
#include "bbox_elf_dump.h"
#include "bbox_syscall_support.h"
#include "postgres.h"
#include "gs_bbox.h"
#include "../../src/include/securec.h"
#include "../../src/include/securec_check.h"
#if UINTPTR_MAX == 0xffffffff
#define Elf_Ehdr Elf32_Ehdr
#else
#define Elf_Ehdr Elf64_Ehdr
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
extern long int g_iCoreDumpBeginTime;
struct BBOX_ELF_SECTION g_stElfSectionInfo;
BBOX_SECTION_STRU g_stSectionInfo[BBOX_SECTION_NUM];
char g_acBboxAddonInfo[BBOX_ADDON_INFO_SIZE];
char g_acBboxStrTabInfo[BBOX_SH_STR_TAB_SIZE];
* ignore the field that discribe equipment or node when analyze a line of /proc/self/maps.
* in : struct BBOX_READ_FILE_IO *pstReadIO - file pointer to be read
* return : iGetChar - current character of the file being read
* RET_ERR - failed
*/
static int BBOX_SkipDeviceAndNodeField(struct BBOX_READ_FILE_IO* pstReadIO)
{
int iCount = -1;
int iGetChar = -1;
if (NULL == pstReadIO) {
bbox_print(PRINT_ERR, "BBOX_SkipDeviceAndNodeField parameters is invalid: pstReadIO is NULL.\n");
return RET_ERR;
}
iGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
for (iCount = 0; iCount < DEVICE_AND_NODE_FIELD_NUM; iCount++) {
while (iGetChar == ' ') {
iGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
}
while (iGetChar != ' ' && iGetChar != '\n') {
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
iGetChar = BBOX_GetCharFromFile(pstReadIO);
}
while (iGetChar == ' ') {
iGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
}
}
return iGetChar;
}
* set whether the mapping is labeled as PF_DEVICE, means that, whether or not it's a device mapping.
* in : int *piGetChar - pointer to the character read
* struct BBOX_READ_FILE_IO *pstReadIO - pointer to struct of file read
* struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to discription of mapping segment structure.
* return RET_OK or RET_ERR
*/
static int BBOX_SetMappingDeviceFlag(
int* piGetChar, struct BBOX_READ_FILE_IO* pstReadIO, struct BBOX_VM_MAPS* pstSegmentMapping)
{
int iIsMappingDevicesFlag = BBOX_FALSE;
const char* pszDeviceZero = DEVICE_ZERO_NAME_STRING;
const char* pszDevice = pszDeviceZero;
if (NULL == piGetChar || NULL == pstReadIO || NULL == pstSegmentMapping) {
bbox_print(PRINT_ERR,
"BBOX_FillMappingFlagsAndOffset parameters is invalid: " \
"piGetChar, pstReadIO or pstSegmentMapping is NULL.\n");
return RET_ERR;
}
while (*pszDevice && *piGetChar == *pszDevice) {
*piGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == *piGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, *piGetChar= %d.\n", *piGetChar);
return RET_ERR;
}
pszDevice++;
}
iIsMappingDevicesFlag = (pszDevice >= pszDeviceZero + DEVICE_PREFIX_LEN) &&
((*piGetChar != '\n' && *piGetChar != ' ') || *pszDevice != '\000');
if (BBOX_TRUE == iIsMappingDevicesFlag) {
pstSegmentMapping->iFlags |= PF_DEVICE;
bbox_print(PRINT_DBG,
" Get Device Segment: StartAddr = %zu, EndAddr = %zu.\n",
pstSegmentMapping->uiStartAddress,
pstSegmentMapping->uiEndAddress);
}
return RET_OK;
}
* set whether the mapping is labeled as PF_VDSO, means that, whether or not it's a VDSO mapping.
* in : int *piGetChar - pointer to the character read
* struct BBOX_READ_FILE_IO *pstReadIO - pointer to struct of file read
* struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to discription of mapping segment structure.
* return RET_OK or RET_ERR
*/
static int BBOX_SetMappingVDSOFlag(
int* piGetChar, struct BBOX_READ_FILE_IO* pstReadIO, struct BBOX_VM_MAPS* pstSegmentMapping)
{
int iIsMappingVdsoFlag = BBOX_FALSE;
int iIsMappingVvarFlag = BBOX_TRUE;
const char* pszVdso = VDSO_NAME_STRING;
const char* pszVvar = VVAR_NAME_STRING;
if (NULL == piGetChar || NULL == pstReadIO || NULL == pstSegmentMapping) {
bbox_print(PRINT_ERR,
"BBOX_FillMappingFlagsAndOffset parameters is invalid: piGetChar," \
"pstReadIO or pstSegmentMapping is NULL.\n");
return RET_ERR;
}
while (*pszVdso && *piGetChar == *pszVdso) {
if (iIsMappingVvarFlag == BBOX_TRUE) {
iIsMappingVvarFlag = (*piGetChar == *pszVvar) ? BBOX_TRUE : BBOX_FALSE;
pszVvar++;
}
*piGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == *piGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, *piGetChar= %d.\n", *piGetChar);
return RET_ERR;
}
pszVdso++;
}
iIsMappingVdsoFlag = (*pszVdso == '\0' && (*piGetChar == '\n' || *piGetChar == ' ' || *piGetChar == '\0'));
if (BBOX_TRUE == iIsMappingVdsoFlag) {
pstSegmentMapping->iFlags |= PF_VDSO;
bbox_print(PRINT_DBG,
" Get VDSO StartAddr = %zu, EndAddr = %zu.\n",
pstSegmentMapping->uiStartAddress,
pstSegmentMapping->uiEndAddress);
}
if (iIsMappingVvarFlag == BBOX_TRUE) {
while (*pszVdso && *piGetChar == *pszVvar) {
*piGetChar = BBOX_GetCharFromFile(pstReadIO);
if (RET_ERR == *piGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, *piGetChar= %d.\n", *piGetChar);
return RET_ERR;
}
pszVvar++;
}
if (*pszVvar == '\0' && (*piGetChar == '\n' || *piGetChar == ' ' || *piGetChar == '\0')) {
pstSegmentMapping->iFlags |= PF_VVAR;
bbox_print(PRINT_DBG,
" Get VVAR StartAddr = %zu, EndAddr = %zu.\n",
pstSegmentMapping->uiStartAddress, pstSegmentMapping->uiEndAddress);
}
}
return RET_OK;
}
* check if the file is a dynamic library file.
* in : char* pszFilePath - path
* struct BBOX_VM_MAPS *pstSegmentMapping - pointer to discription of mapping segment structuer.
* return RET_OK or RET_ERR.
*/
static int BBOX_SettingMappedFileFlag(char* pszFilePath, struct BBOX_VM_MAPS* pstSegmentMapping)
{
int fd = -1;
int retval = -1;
Elf_Ehdr ehdr;
fd = sys_open(pszFilePath, O_RDONLY, 0);
if (fd < 0) {
bbox_print(PRINT_ERR, "open file %s failed, errno = %d\n", pszFilePath, errno);
return RET_ERR;
}
retval = sys_read(fd, &ehdr, sizeof(ehdr));
if (retval < 0) {
bbox_print(PRINT_ERR, "read elf failed, errno = %d\n", errno);
goto errout;
}
if (bbox_strncmp(ELFMAG, (char*)ehdr.e_ident, SELFMAG)) {
pstSegmentMapping->iFlags |= PF_MAPPEDFILE;
bbox_print(PRINT_DBG, "not an elf file.\n");
bbox_print(PRINT_DBG, "mapped file : %s\n", pszFilePath);
}
sys_close(fd);
return RET_OK;
errout:
if (fd > 0) {
sys_close(fd);
}
return RET_ERR;
}
* check if the file is equipment file.
* in : char* pszFilePath - path
* struct BBOX_VM_MAPS *pstSegmentMapping - pointer to discription of mapping segment structuer.
* return RET_OK or RET_ERR.
*/
static int BBOX_SettingDeviceFileFlag(char* pszFilePath, struct BBOX_VM_MAPS* pstSegmentMapping)
{
struct kernel_stat stMarkerSB = {0};
if (sys_stat(pszFilePath, &stMarkerSB) < 0) {
bbox_print(PRINT_ERR, "sys_stat error, errno = %d, path = %s\n", errno, pszFilePath);
return RET_ERR;
}
if (S_ISCHR(stMarkerSB.st_mode) || S_ISBLK(stMarkerSB.st_mode) || S_ISFIFO(stMarkerSB.st_mode) ||
S_ISSOCK(stMarkerSB.st_mode)) {
bbox_print(PRINT_DBG, "Device file : %s\n", pszFilePath);
pstSegmentMapping->iFlags |= PF_DEVICE;
return RET_OK;
}
return RET_ERR;
}
* check if corresponding address is a general file mapping by mmap instead of a dynamic library file
* when read /proc/self/maps.
* in : struct BBOX_READ_FILE_IO *pstReadIO - pointer to file to be read.
* struct BBOX_VM_MAPS *pstSegmentMapping - pointer to discription of mapping segment structuer.
* return : int iGetChar - current character of file reading
* RET_ERR - read failed
*/
static int BBOX_SettingFileFlags(
int* iGetChar, struct BBOX_READ_FILE_IO* pstReadIO, struct BBOX_VM_MAPS* pstSegmentMapping)
{
char MapFilePath[PATH_MAX];
int i = 0;
MapFilePath[0] = *iGetChar;
i++;
while ((*iGetChar = BBOX_GetCharFromFile(pstReadIO)) != '\n' && i < PATH_MAX - 1) {
if (RET_ERR == *iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", *iGetChar);
return RET_ERR;
}
MapFilePath[i] = *iGetChar;
i++;
}
MapFilePath[i] = 0;
if (BBOX_SettingDeviceFileFlag(MapFilePath, pstSegmentMapping) == RET_OK) {
return RET_OK;
}
if (BBOX_SettingMappedFileFlag(MapFilePath, pstSegmentMapping) == RET_OK) {
return RET_OK;
}
return RET_ERR;
}
* fill flag and offset of struct BBOX_VM_MAPS when reading /proc/self/maps.
* in : struct BBOX_READ_FILE_IO *pstReadIO - pointer to file to be read.
* struct BBOX_VM_MAPS *pstSegmentMapping - pointer to discription of mapping segment structuer.
* return : int iGetChar - current character of file reading
* RET_ERR - read failed
*/
static int BBOX_FillMappingFlagsAndOffset(struct BBOX_READ_FILE_IO* pstReadIO, struct BBOX_VM_MAPS* pstSegmentMapping)
{
int iRessult = 0;
int iGetChar = -1;
int iIsMappingAnonymousFlag = BBOX_FALSE;
int iIsMappedFile = BBOX_FALSE;
if (NULL == pstReadIO || NULL == pstSegmentMapping) {
bbox_print(PRINT_ERR,
"BBOX_FillMappingFlagsAndOffset parameters is invalid: pstReadIO or " \
"pstSegmentMapping is NULL.\n");
return RET_ERR;
}
while ((iGetChar = BBOX_GetCharFromFile(pstReadIO)) != ' ') {
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_GetCharFromFile is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
pstSegmentMapping->iFlags = (pstSegmentMapping->iFlags << 1) | (unsigned int)(iGetChar != '-');
}
pstSegmentMapping->iFlags = ((pstSegmentMapping->iFlags) >> 1) & PF_MASK;
iGetChar = BBOX_StringSwitchInt(pstReadIO, &(pstSegmentMapping->uiOffset));
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_StringSwitchInt is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
iGetChar = BBOX_SkipDeviceAndNodeField(pstReadIO);
if (RET_ERR == iGetChar) {
bbox_print(PRINT_ERR, "BBOX_SkipDeviceAndNodeField is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
iIsMappingAnonymousFlag = ((iGetChar == '\n') || (iGetChar == '['));
if (BBOX_TRUE == iIsMappingAnonymousFlag) {
pstSegmentMapping->iFlags |= PF_ANONYMOUS;
iRessult = BBOX_SetMappingVDSOFlag(&iGetChar, pstReadIO, pstSegmentMapping);
if (RET_OK != iRessult) {
bbox_print(PRINT_ERR, "BBOX_SetMappingVDSOFlag is failed, iRessult= %d.\n", iRessult);
return RET_ERR;
}
return iGetChar;
}
iRessult = BBOX_SetMappingDeviceFlag(&iGetChar, pstReadIO, pstSegmentMapping);
if (RET_OK != iRessult) {
bbox_print(PRINT_ERR, "BBOX_SetMappingDeviceFlag is failed, iRessult= %d.\n", iRessult);
return RET_ERR;
}
iIsMappedFile = (iGetChar == '/');
if (BBOX_TRUE == iIsMappedFile) {
iRessult = BBOX_SettingFileFlags(&iGetChar, pstReadIO, pstSegmentMapping);
if (RET_OK != iRessult) {
bbox_print(PRINT_ERR, "BBOX_SettingFileFlags is failed, iRessult= %d.\n", iRessult);
return RET_ERR;
}
}
return iGetChar;
}
* read /proc/self/maps and get count of line in which.
* return : iLineNum - line count of /proc/self/maps, it is not a negative.
* RET_ERR
*/
static int BBOX_GetVmMapsNum(void)
{
int iFd = -1;
int iLineNum = 0;
int iCount = 0;
ssize_t iReadSize = -1;
char acBuff[BBOX_BUFF_LITTLE_SIZE];
errno_t rc = EOK;
BBOX_NOINTR(iFd = sys_open(THREAD_SELF_MAPS_FILE, O_RDONLY, 0));
if (iFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed, iFd= %d.\n", iFd);
return RET_ERR;
}
bbox_print(PRINT_DBG, "Read file : /proc/self/Maps:\n");
do {
iReadSize = -1;
rc = memset_s(acBuff, BBOX_BUFF_LITTLE_SIZE, 0, sizeof(acBuff));
securec_check_c(rc, "\0", "\0");
BBOX_NOINTR(iReadSize = sys_read(iFd, acBuff, sizeof(acBuff)));
if (RET_ERR == iReadSize) {
BBOX_NOINTR(sys_close(iFd));
return RET_ERR;
} else if (0 == iReadSize) {
break;
}
bbox_print(PRINT_DBG, "%s", acBuff);
for (iCount = 0; iCount < iReadSize; iCount++) {
if ('\n' == acBuff[iCount]) {
iLineNum++;
}
}
} while (iReadSize);
BBOX_NOINTR(sys_close(iFd));
return iLineNum ? iLineNum : RET_ERR;
}
* fill address feild in struct BBOX_VM_MAPS when reading /proc/self/maps.
* in : struct BBOX_READ_FILE_IO *pstReadIO - pointer to file to be read.
* struct BBOX_VM_MAPS *pstSegmentMapping - pointer to discription of mapping segment structuer.
* return : int iGetChar - current character of file reading
* RET_ERR - read failed
*/
static char BBOX_FillMappingAddress(struct BBOX_READ_FILE_IO* pstReadIO, struct BBOX_VM_MAPS* pstSegmentMapping)
{
int iGetChar = -1;
if (NULL == pstReadIO || NULL == pstSegmentMapping) {
bbox_print(PRINT_ERR,
"BBOX_FillMappingAddress parameters is invalid: pstReadIO or pstSegmentMapping is NULL.\n");
return RET_ERR;
}
This is start address and then ready to read end address. */
iGetChar = BBOX_StringSwitchInt(pstReadIO, &(pstSegmentMapping->uiStartAddress));
if ('-' == iGetChar) {
iGetChar = BBOX_StringSwitchInt(pstReadIO, &(pstSegmentMapping->uiEndAddress));
if (' ' != iGetChar) {
bbox_print(PRINT_ERR, "BBOX_StringSwitchInt is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
} else {
bbox_print(PRINT_ERR, "BBOX_StringSwitchInt is failed, iGetChar= %d.\n", iGetChar);
return RET_ERR;
}
return (char)iGetChar;
}
* use blacklist items to split the segment, thus drop partal slice from core file.
* struct BBOX_WRITE_FDS *pstWriteFds : segment to be written into core file
* return RET_OK if success else RET_ERR.
*/
static int BBOX_VmExecludeBlackList(struct BBOX_VM_MAPS *pstVmMappingSegment)
{
void *pStartAddress = (void *)(uintptr_t)pstVmMappingSegment->uiStartAddress;
void *pEndAddress = (void *)(uintptr_t)pstVmMappingSegment->uiEndAddress;
void *pBlackStartAddress = NULL;
void *pBlackEndAddress = NULL;
size_t uiPageSize = sys_sysconf(_SC_PAGESIZE);
BBOX_BLACKLIST_STRU *pstBlackNode = NULL;
struct BBOX_VM_MAPS *pstNextVmSegment = NULL;
pstBlackNode = _BBOX_FindAddrInBlackList(pStartAddress, pEndAddress);
if (pstBlackNode != NULL) {
pBlackStartAddress = pstBlackNode->pBlackStartAddr;
pBlackEndAddress = pstBlackNode->pBlackEndAddr;
pstNextVmSegment = pstVmMappingSegment + 1;
pstNextVmSegment->iFlags = pstVmMappingSegment->iFlags;
if (pStartAddress < pBlackStartAddress) {
pstVmMappingSegment->uiWriteSize= (size_t)((uintptr_t)pBlackStartAddress - (uintptr_t)pStartAddress);
if ((pstVmMappingSegment->uiWriteSize) < uiPageSize) {
pstVmMappingSegment->uiEndAddress =
(size_t)((uintptr_t)pBlackStartAddress + (pstVmMappingSegment->uiWriteSize % uiPageSize));
} else {
pstVmMappingSegment->uiEndAddress = (size_t)(uintptr_t)pBlackStartAddress;
}
pstVmMappingSegment->uiWriteSize= (size_t)((uintptr_t)pBlackStartAddress - (uintptr_t)pStartAddress);
pstVmMappingSegment->uiStartAddress = (size_t)(uintptr_t)pStartAddress;
pstVmMappingSegment->iIsRemoveFlags = BBOX_FALSE;
} else {
pstVmMappingSegment->iIsRemoveFlags = BBOX_TRUE;
}
if (pBlackEndAddress < pEndAddress) {
pstNextVmSegment->uiWriteSize = (size_t)((uintptr_t)pEndAddress - (uintptr_t)pBlackEndAddress);
if ((pstNextVmSegment->uiWriteSize) < uiPageSize) {
pstNextVmSegment->uiStartAddress =
(size_t)((uintptr_t)pBlackEndAddress - (pstNextVmSegment->uiWriteSize % uiPageSize));
} else {
pstNextVmSegment->uiStartAddress = (size_t)(uintptr_t)pBlackEndAddress;
}
pstNextVmSegment->uiWriteSize = (size_t)((uintptr_t)pEndAddress - (uintptr_t)pBlackEndAddress);
pstNextVmSegment->uiEndAddress = (size_t)(uintptr_t)pEndAddress;
pstNextVmSegment->iIsRemoveFlags = BBOX_FALSE;
} else {
pstNextVmSegment->iIsRemoveFlags = BBOX_TRUE;
}
} else {
}
bbox_print(PRINT_DBG, "execlude black list success.\n");
return RET_OK;
}
* read /proc/self/maps and fill struct BBOX_VM_MAPS
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to discription of mapping segment structure.
* int iSegmentNum - count of mapping segment in address space.
* return RET_OK or RET_ERR.
*/
static int BBOX_GetMappingSegment(struct BBOX_VM_MAPS* pstSegmentMapping, int* piSegmentNum)
{
int iGetChar = -1;
int iResult = RET_ERR;
int iNewVmTotal = 0;
int iVmTotal = 0;
struct BBOX_READ_FILE_IO stReadIO;
struct BBOX_VM_MAPS* pstCurSegment = NULL;
errno_t rc = EOK;
if (NULL == pstSegmentMapping || NULL == piSegmentNum) {
bbox_print(PRINT_ERR,
"BBOX_GetMappingSegment parameters is invalid: " \
"pstSegmentMapping or piSegmentNum is NULL.\n");
return RET_ERR;
}
iVmTotal = *piSegmentNum;
rc = memset_s(&stReadIO, sizeof(struct BBOX_READ_FILE_IO), 0, sizeof(struct BBOX_READ_FILE_IO));
securec_check_c(rc, "\0", "\0");
stReadIO.iFd = -1;
stReadIO.pData = NULL;
stReadIO.pEnd = NULL;
BBOX_NOINTR(stReadIO.iFd = sys_open(THREAD_SELF_MAPS_FILE, O_RDONLY, 0));
if (stReadIO.iFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed, stReadIO.iFd = %d.\n", stReadIO.iFd);
return RET_ERR;
}
pstCurSegment = pstSegmentMapping;
while (iVmTotal) {
bbox_print(PRINT_DBG, "iVmTotal = %d.\n", iVmTotal);
iGetChar = BBOX_FillMappingAddress(&stReadIO, pstCurSegment);
if (RET_ERR == iGetChar) {
BBOX_NOINTR(sys_close(stReadIO.iFd));
bbox_print(PRINT_ERR, "BBOX_FillMappingAddress is failed, iGetChar = %d.\n", iGetChar);
return RET_ERR;
}
iGetChar = BBOX_FillMappingFlagsAndOffset(&stReadIO, pstCurSegment);
if (RET_ERR == iGetChar) {
BBOX_NOINTR(sys_close(stReadIO.iFd));
bbox_print(PRINT_ERR, "BBOX_FillMappingFlagsAndOffset is failed, iGetChar = %d.\n", iGetChar);
return RET_ERR;
}
if (iGetChar != '\n') {
iResult = BBOX_SkipToLineEnd(&stReadIO);
if (RET_OK != iResult) {
BBOX_NOINTR(sys_close(stReadIO.iFd));
bbox_print(PRINT_ERR, "BBOX_SkipToLineEnd is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
}
while (_BBOX_FindAddrInBlackList(
(void *)(uintptr_t)pstCurSegment->uiStartAddress, (void *)(uintptr_t)pstCurSegment->uiEndAddress)) {
iResult = BBOX_VmExecludeBlackList(pstCurSegment);
if (RET_OK != iResult) {
BBOX_NOINTR(sys_close(stReadIO.iFd));
bbox_print(PRINT_ERR, "BBOX_VmExecludeBlackList is failed.\n");
return RET_ERR;
}
iNewVmTotal++;
pstCurSegment++;
}
pstCurSegment++;
iVmTotal--;
}
(*piSegmentNum) = (*piSegmentNum) + iNewVmTotal;
bbox_print(PRINT_TIP, "after BL, all segment num is %d.\n", *piSegmentNum);
BBOX_NOINTR(sys_close(stReadIO.iFd));
return RET_OK;
}
* judge if it should be written into core file for every segment in address space,
* and calculate the size to be written in.
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to mapping segment structure.
* int iSegmentNum - count of mapping segment in address space
* int *piValidSegmentNum - count of valid mapping segment in address space,
* which need to be written into core file.
* return RET_OK or RET_ERR.
*/
static int BBOX_VmMappingSizeDump(struct BBOX_VM_MAPS* pstVmMappingSegment, int iSegmentNum, int* piValidSegmentNum)
{
int iCount = 0;
struct BBOX_VM_MAPS* pstVmMapping = NULL;
if (NULL == pstVmMappingSegment || NULL == piValidSegmentNum || iSegmentNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_VmMappingSizeDump parameters is invalid: pstVmMappingSegment, " \
"piValidSegmentNum or iSegmentNum is NULL.\n");
return RET_ERR;
}
*piValidSegmentNum = iSegmentNum;
bbox_print(PRINT_LOG, "write segment to core file:\n");
for (iCount = 0; iCount < iSegmentNum; iCount++) {
pstVmMapping = pstVmMappingSegment + iCount;
if (BBOX_TRUE == pstVmMapping->iIsRemoveFlags) {
pstVmMapping->uiWriteSize = 0;
(*piValidSegmentNum)--;
continue;
}
set the size written to the core file to 0, otherwise the size is calculated */
#if defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH_7A__)) || (defined(__aarch64__))
if ((pstVmMapping->iFlags & (PF_ANONYMOUS | PF_W | PF_R)) == 0 || (pstVmMapping->iFlags & PF_MAPPEDFILE)) {
#else
if ((pstVmMapping->iFlags & (PF_ANONYMOUS | PF_W | PF_R)) == 0 || (pstVmMapping->iFlags & PF_X) ||
(pstVmMapping->iFlags & PF_MAPPEDFILE)) {
#endif
pstVmMapping->uiWriteSize =
((pstVmMapping->iFlags & PF_VDSO) ? (pstVmMapping->uiEndAddress - pstVmMapping->uiStartAddress) : 0);
} else {
pstVmMapping->uiWriteSize = pstVmMapping->uiEndAddress - pstVmMapping->uiStartAddress;
bbox_print(PRINT_DBG, "Segment[%d]: set writesize = %zu.\n", iCount, pstVmMapping->uiWriteSize);
}
if it cannot be read, discribes equipment segment or segment size is 0 or vvar segement */
if (((pstVmMapping->iFlags & PF_R) == 0) || pstVmMapping->uiStartAddress == pstVmMapping->uiEndAddress ||
(pstVmMapping->iFlags & PF_VVAR) ||
(pstVmMapping->iFlags & PF_DEVICE)) {
pstVmMapping->uiWriteSize = 0;
(*piValidSegmentNum)--;
pstVmMapping->iIsRemoveFlags = BBOX_TRUE;
}
if (pstVmMapping->iIsRemoveFlags != BBOX_TRUE) {
bbox_print(PRINT_DBG,
"segment[%d]: %zu %zu %u\n",
iCount,
pstVmMapping->uiOffset,
pstVmMapping->uiWriteSize,
pstVmMapping->iFlags);
}
}
return RET_OK;
}
* fill the structure, which should be written into core file and discribes mapping segment of process address space.
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to mapping segment structure.
* int iSegmentNum - count of mapping segment in address space
* int *piValidSegmentNum - count of valid mapping segment in address space,
* which need to be written into core file.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillVmMappingInfo(struct BBOX_VM_MAPS* pstVmMappingSegment, int* piSegmentNum, int* piValidSegmentNum)
{
int iResult = RET_ERR;
if (NULL == pstVmMappingSegment || NULL == piValidSegmentNum || NULL == piSegmentNum) {
bbox_print(PRINT_ERR,
"BBOX_FillVmMappingInfo parameters is invalid: pstVmMappingSegment, " \
"piValidSegmentNum or piSegmentNum is NULL.\n");
return RET_ERR;
}
iResult = BBOX_GetMappingSegment(pstVmMappingSegment, piSegmentNum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_GetMappingSegment is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
for every segment in process address space. */
iResult = BBOX_VmMappingSizeDump(pstVmMappingSegment, *piSegmentNum, piValidSegmentNum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_VmMappingSizeDump is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Fill Vm mapping segment info success.\n");
return RET_OK;
}
* read /proc/self/auxv and get count of auxv and VDSO address
* in : union BBOX_VM_VDSO *pstVmVDSO - pointer to structure that decribes VDSO segment.
* return : iAuxvNum - count of auxv, it is not a negative.
* RET_ERR
*/
static int BBOX_GetVDSOAndVmAuxvNum(union BBOX_VM_VDSO* pstVmVDSO)
{
int iAuxvFd = -1;
ssize_t iReadSize = RET_ERR;
int iAuxvNum = 0;
BBOX_AUXV_T stAuxv;
errno_t rc = EOK;
if (NULL == pstVmVDSO) {
bbox_print(PRINT_ERR, "BBOX_GetVDSOAndVmAuxvNum parameters is invalid: pstVmVDSO is NULL.\n");
return RET_ERR;
}
pstVmVDSO->pVDSOEhdr = NULL;
BBOX_NOINTR(iAuxvFd = sys_open(THREAD_SELF_AUXV_FILE, O_RDONLY, 0));
if (iAuxvFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed, iAuxvFd = %d.\n", iAuxvFd);
return RET_ERR;
}
do {
iReadSize = RET_ERR;
rc = memset_s(&stAuxv, sizeof(BBOX_AUXV_T), 0, sizeof(BBOX_AUXV_T));
securec_check_c(rc, "\0", "\0");
BBOX_NOINTR(iReadSize = sys_read(iAuxvFd, &stAuxv, sizeof(BBOX_AUXV_T)));
if (RET_ERR == iReadSize) {
bbox_print(PRINT_ERR, "sys_read is failed, iReadSize = %zd.\n", iReadSize);
BBOX_NOINTR(sys_close(iAuxvFd));
return RET_ERR;
}
if (iReadSize != sizeof(BBOX_AUXV_T)) {
break;
}
iAuxvNum++;
if (stAuxv.a_type == AT_SYSINFO_EHDR) {
pstVmVDSO->pVDSOEhdr = (BBOX_EHDR*)stAuxv.a_un.a_val;
}
} while (stAuxv.a_type != AT_NULL);
BBOX_NOINTR(sys_close(iAuxvFd));
return iAuxvNum;
}
* judge if the VDSO address we got is valid
* in : BBOX_EHDR *pstVDSOEhdr - pointer to elf header of VDSO.
* size_t uiStartAddress - start address of a segment in address space.
* size_t uiEndAddress - end address of a segment in address space.
* return : RET_OK - success
* RET_BBOX_VDSO_INVALID - failed
*/
static int BBOX_CheakVDSOEhdr(BBOX_EHDR* pstVDSOEhdr, size_t uiStartAddress, size_t uiEndAddress)
{
int iCount = 0;
BBOX_PHDR* pstVDSOPhdr = NULL;
if (NULL == pstVDSOEhdr) {
bbox_print(PRINT_ERR, "BBOX_CheakVDSOEhdr parameters is invalid: pstVDSOEhdr is NULL.\n");
return RET_ERR;
}
const size_t uiEhdrAddress = (size_t)pstVDSOEhdr;
if (uiEhdrAddress & (sizeof(size_t) - 1)) {
bbox_print(PRINT_ERR, "VDSO is invalid: not aligned properly.\n");
return RET_BBOX_VDSO_INVALID;
}
if (uiEndAddress <= uiEhdrAddress + sizeof(BBOX_EHDR)) {
bbox_print(PRINT_ERR, "VDSO head is invalid: pstVDSOEhdr has Incomplete head.\n");
return RET_BBOX_VDSO_INVALID;
}
if (pstVDSOEhdr->e_phoff & (sizeof(size_t) - 1)) {
bbox_print(PRINT_ERR, "VDSO Ehdr is invalid: not aligned properly.\n");
return RET_BBOX_VDSO_INVALID;
}
pstVDSOPhdr = (BBOX_PHDR*)(uiEhdrAddress + pstVDSOEhdr->e_phoff);
if ((size_t)pstVDSOPhdr <= uiStartAddress || uiEndAddress <= (size_t)(pstVDSOPhdr + pstVDSOEhdr->e_phnum)) {
bbox_print(PRINT_ERR, "VDSO Phdr is invalid: VDSOPhdr is incompleted.\n");
return RET_BBOX_VDSO_INVALID;
}
if (pstVDSOPhdr[0].p_type != PT_LOAD || pstVDSOPhdr[0].p_vaddr != uiStartAddress ||
pstVDSOPhdr[0].p_vaddr + pstVDSOPhdr[0].p_memsz >= uiEndAddress) {
bbox_print(PRINT_ERR, "VDSO Phdr is invalid.\n");
return RET_BBOX_VDSO_INVALID;
}
for (iCount = 1; iCount < pstVDSOEhdr->e_phnum; iCount++) {
if (pstVDSOPhdr[iCount].p_type == PT_LOAD) {
bbox_print(PRINT_ERR, "VDSO Phdr is invalid: VDSO has multiple PT_LOAD segments.\n");
return RET_BBOX_VDSO_INVALID;
}
if (pstVDSOPhdr[0].p_vaddr & (sizeof(size_t) - 1)) {
bbox_print(PRINT_ERR, "VDSO Phdr is invalid: VDSOPhdr is not aligned properly.\n");
return RET_BBOX_VDSO_INVALID;
}
if (pstVDSOPhdr[iCount].p_vaddr != uiStartAddress ||
(pstVDSOPhdr[iCount].p_vaddr + pstVDSOPhdr[iCount].p_memsz >= uiEndAddress)) {
bbox_print(PRINT_ERR, "VDSO Phdr is invalid: Phdr data range is out of bounds.\n");
return RET_BBOX_VDSO_INVALID;
}
}
return RET_OK;
}
* judge if the VDSO address we got is valid and if it need to be written into core file.
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to mapping segment structure.
* int iSegmentNum - count of mapping segment in address space.
* union BBOX_VM_VDSO *pstVmVDSO - pointer to VDSO structure.
* return RET_OK or RET_ERR
*/
static int BBOX_CheckVDSO(struct BBOX_VM_MAPS* pstVmMappingSegment, int iSegmentNum, union BBOX_VM_VDSO* pstVmVDSO)
{
int iCount = 0;
int iResult = RET_ERR;
struct BBOX_VM_MAPS* pstVmMappingTemp = NULL;
if (NULL == pstVmMappingSegment || NULL == pstVmVDSO || iSegmentNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_CheckVDSO parameters is invalid: pstVmMappingSegment or "\
"pstVmVDSO is NULL, iSegmentNum = %d.\n",
iSegmentNum);
return RET_ERR;
}
for (iCount = 0; iCount < iSegmentNum; iCount++) {
pstVmMappingTemp = (pstVmMappingSegment + iCount);
if (BBOX_FALSE == pstVmMappingTemp->iIsRemoveFlags) {
if ((pstVmMappingTemp->iFlags & PF_R) && (pstVmMappingTemp->uiStartAddress <= pstVmVDSO->uiVDSOAddress) &&
(pstVmMappingTemp->uiEndAddress > pstVmVDSO->uiVDSOAddress)) {
iResult = BBOX_CheakVDSOEhdr(
pstVmVDSO->pVDSOEhdr, pstVmMappingTemp->uiStartAddress, pstVmMappingTemp->uiEndAddress);
if (RET_BBOX_VDSO_INVALID == iResult) {
pstVmVDSO->pVDSOEhdr = NULL;
} else if (RET_ERR == iResult) {
bbox_print(PRINT_ERR, "BBOX_CheakVDSOEhdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
break;
}
}
}
if (iCount == iSegmentNum) {
pstVmVDSO->uiVDSOAddress = 0;
}
return RET_OK;
}
* get count of VDSO writen into core file.
* in : union BBOX_VM_VDSO *pstVmVDSO pointer to VDSO union structure.
* return : iExtraPhdrNum - result
* RET_ERR - failed
*/
static int BBOX_GetExtraPhdrNum(union BBOX_VM_VDSO* pstVmVDSO)
{
int iExtraPhdrNum = 0;
int iCount = 0;
BBOX_PHDR* pVDSOPhdr = NULL;
if (NULL == pstVmVDSO) {
bbox_print(PRINT_ERR, "BBOX_GetExtraPhdrNum parameters is invalid: pstVmVDSO is NULL.\n");
return RET_ERR;
} else {
if (0 == pstVmVDSO->uiVDSOAddress) {
return iExtraPhdrNum;
}
pVDSOPhdr = (BBOX_PHDR*)(pstVmVDSO->uiVDSOAddress + pstVmVDSO->pVDSOEhdr->e_phoff);
for (iCount = 0; iCount < pstVmVDSO->pVDSOEhdr->e_phnum; iCount++) {
if (pVDSOPhdr[iCount].p_type != PT_LOAD) {
iExtraPhdrNum++;
}
}
}
bbox_print(PRINT_DBG, "Extra Phdr Num: iExtraPhdrNum = %d.\n", iExtraPhdrNum);
return iExtraPhdrNum;
}
* fill structure that discribe VDSO
* in : int *piAuxvNum - count of Auxv
* int *piExtraPhdrNum - count of VDSO written into core file
* int iSegmentNum - count of mapping segment in address space
* union BBOX_VM_VDSO *pstVmVDSO - pointer to structure that discribe VDSO segment.
* struct BBOX_VM_MAPS *pstVmMappingSegment - pointer to structure that discribes mapping segment.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillVDSOInfo(int* piAuxvNum, int* piExtraPhdrNum, int iSegmentNum, union BBOX_VM_VDSO* pstVmVDSO,
struct BBOX_VM_MAPS* pstVmMappingSegment)
{
int iResult = RET_ERR;
if (NULL == piAuxvNum || NULL == piExtraPhdrNum || NULL == pstVmVDSO || NULL == pstVmMappingSegment ||
iSegmentNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_FillVDSOInfo parameters is invalid: piAuxvNum, piExtraPhdrNum," \
"pstVmVDSO or pstVmMappingSegment is NULL, iSegmentNum = %d.\n",
iSegmentNum);
return RET_ERR;
}
iResult = BBOX_GetVDSOAndVmAuxvNum(pstVmVDSO);
if (RET_ERR == iResult) {
bbox_print(PRINT_ERR, "BBOX_GetVDSOAndVmAuxvNum is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
*piAuxvNum = iResult;
iResult = BBOX_CheckVDSO(pstVmMappingSegment, iSegmentNum, pstVmVDSO);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_CheckVDSO is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_GetExtraPhdrNum(pstVmVDSO);
if (RET_ERR == iResult) {
bbox_print(PRINT_ERR, "BBOX_GetExtraPhdrNum is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
(*piExtraPhdrNum) += iResult;
bbox_print(PRINT_LOG, "Fill VDSO info success.\n");
return RET_OK;
}
* get the process run time and write it into structure.
* in : char *pszReadFile - store the character array read from file.
* int iReadSize - count of character in array.
* struct BBOX_ELF_PRPSSTATUS *pstPrPsStatus - pointer to structure that store process status information.
* return RET_OK or RET_ERR.
*/
static int BBOX_SetPsStatusTime(char* pszReadFile, int iReadSize, struct BBOX_ELF_PRPSSTATUS* pstPrPsStatus)
{
int iFlag = 1;
const int iUTimePos = 13;
const int iSTimePos = 14;
const int iCUTimePos = 15;
const int iCSTimePos = 16;
const int iPendingSigPos = 30;
const int iHeldSigPos = 31;
unsigned int uCount = 0;
unsigned int uItemNum = 0;
char* pcSignalstr = 0;
char* pStatItem[BBOX_STAT_ITEM_NUM];
if (NULL == pszReadFile || NULL == pstPrPsStatus || iReadSize <= 0) {
bbox_print(PRINT_ERR,
"BBOX_SetPsStatusTime parameters is invalid: pszReadFile or pstPrPsStatus is NULL, iReadSize = %d.\n",
iReadSize);
return RET_ERR;
}
for (uCount = 0; uCount < (unsigned int)iReadSize; uCount++) {
if (iFlag) {
pStatItem[uItemNum++] = (pszReadFile + uCount);
iFlag = 0;
}
if (pszReadFile[uCount] == ' ') {
pszReadFile[uCount] = '\0';
iFlag = 1;
}
}
bbox_print(PRINT_DBG, "User Time : %s\n", pStatItem[iUTimePos]);
(void)BBOX_StringToTime(pStatItem[iUTimePos], &(pstPrPsStatus->stUserTime));
bbox_print(PRINT_DBG, "System Time : %s\n", pStatItem[iSTimePos]);
(void)BBOX_StringToTime(pStatItem[iSTimePos], &(pstPrPsStatus->stSystemTime));
bbox_print(PRINT_DBG, "Cumulative user Time : %s\n", pStatItem[iCUTimePos]);
(void)BBOX_StringToTime(pStatItem[iCUTimePos], &(pstPrPsStatus->stCumulativeUserTime));
bbox_print(PRINT_DBG, "Cumulative system : %s\n", pStatItem[iCSTimePos]);
(void)BBOX_StringToTime(pStatItem[iCSTimePos], &(pstPrPsStatus->stCumulativeSystemTime));
pcSignalstr = pStatItem[iPendingSigPos];
pstPrPsStatus->ulSigPend = 0;
while (*pcSignalstr != '\0') {
pstPrPsStatus->ulSigPend = 10 * pstPrPsStatus->ulSigPend + (*pcSignalstr - '0');
pcSignalstr++;
}
pcSignalstr = pStatItem[iHeldSigPos];
pstPrPsStatus->ulSigHold = 0;
while (*pcSignalstr != '\0') {
pstPrPsStatus->ulSigHold = 10 * pstPrPsStatus->ulSigHold + (*pcSignalstr - '0');
pcSignalstr++;
}
return RET_OK;
}
* get the process run time
* in : struct BBOX_ELF_PRPSSTATUS *pstPrPsStatus - pointer to structure that store process status information.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillPsStatusTimeInfo(struct BBOX_ELF_PRPSSTATUS* pstPrPsStatus)
{
ssize_t iReadSize = RET_ERR;
int iStatFileFd = -1;
int iResult = RET_ERR;
char szReadFile[BBOX_BUFF_LITTLE_SIZE];
errno_t rc = EOK;
if (NULL == pstPrPsStatus) {
bbox_print(PRINT_ERR, "BBOX_FillPsStatusTimeInfo parameters is invalid: pstPrPsStatus is NULL.\n");
return RET_ERR;
}
rc = memset_s(szReadFile, sizeof(szReadFile), 0, sizeof(szReadFile));
securec_check_c(rc, "\0", "\0");
BBOX_NOINTR(iStatFileFd = sys_open(THREAD_SELF_STAT_FILE, O_RDONLY, 0));
if (iStatFileFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed iStatFileFd = %d.\n", iStatFileFd);
return RET_ERR;
}
do {
iReadSize = RET_ERR;
rc = memset_s(szReadFile, sizeof(szReadFile), 0, sizeof(szReadFile));
securec_check_c(rc, "\0", "\0");
BBOX_NOINTR(iReadSize = sys_read(iStatFileFd, szReadFile, sizeof(szReadFile)));
if (iReadSize > 0) {
iResult = BBOX_SetPsStatusTime(szReadFile, iReadSize, pstPrPsStatus);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_SetPsStatusTime is failed, iResult = %d.\n", iResult);
BBOX_NOINTR(sys_close(iStatFileFd));
return RET_ERR;
}
} else if (iReadSize < 0) {
bbox_print(PRINT_ERR, "failed to read status file, iResult = %zd.\n", iReadSize);
BBOX_NOINTR(sys_close(iStatFileFd));
return RET_ERR;
}
} while (iReadSize > 0);
BBOX_NOINTR(sys_close(iStatFileFd));
return RET_OK;
}
* get register information of parent process, get user data structure information.
* in : struct BBOX_ELF_PRPSINFO *pstPrPsInfo - pointer to structure that store process status information.
* pid_t tMainPid - main process pid.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillPrPsInfo(struct BBOX_ELF_PRPSINFO* pstPrPsInfo, pid_t tMainPid)
{
char szBuff[BBOX_BUFF_SIZE];
ssize_t iReadSize = 0;
ssize_t iLen = 0;
int iCommandLineFileFd = -1;
char* pExePathName = szBuff;
char* pTemp = NULL;
errno_t rc = EOK;
if (NULL == pstPrPsInfo) {
bbox_print(PRINT_ERR, "BBOX_FillPrPsInfo parameters is invalid: pstPrPsInfo is NULL.\n");
return RET_ERR;
}
rc = memset_s(pstPrPsInfo, sizeof(struct BBOX_ELF_PRPSINFO), 0, sizeof(struct BBOX_ELF_PRPSINFO));
securec_check_c(rc, "\0", "\0");
pstPrPsInfo->cSname = 'R';
pstPrPsInfo->cNice = (signed char)sys_getpriority(PRIO_PROCESS, 0);
#if (defined(__x86_64__)) || (defined(__aarch64__))
pstPrPsInfo->tUid = (uint32_t)sys_geteuid();
pstPrPsInfo->tGid = (uint32_t)sys_getegid();
#elif (defined(__i386__)) || (defined(__ARM_ARCH_5TE__)) || (defined(__ARM_ARCH_7A__))
pstPrPsInfo->tUid = (uint16_t)sys_geteuid();
pstPrPsInfo->tGid = (uint16_t)sys_getegid();
#endif
pstPrPsInfo->tpid = tMainPid;
pstPrPsInfo->tPpid = sys_getppid();
pstPrPsInfo->tPgrp = sys_getpgrp();
pstPrPsInfo->tSid = sys_getsid(0);
rc = memset_s(szBuff, sizeof(szBuff), 0, sizeof(szBuff));
securec_check_c(rc, "\0", "\0");
iReadSize = sys_readlink(THREAD_SELF_EXE_FILE, szBuff, sizeof(szBuff));
iLen = 0;
for (pTemp = szBuff; (*pTemp != '\000') && ((iReadSize--) > 0); pTemp++) {
if (*pTemp == '/') {
pExePathName = pTemp + 1;
iLen = 0;
} else {
iLen++;
}
}
rc = memcpy_s(pstPrPsInfo->cFname,
sizeof(pstPrPsInfo->cFname),
pExePathName,
(iLen > (ssize_t)sizeof(pstPrPsInfo->cFname) ? sizeof(pstPrPsInfo->cFname) : iLen));
securec_check_c(rc, "\0", "\0");
BBOX_NO_INTR(iCommandLineFileFd = sys_open(THREAD_SELF_COMMAND_LINE_FILE, O_RDONLY, 0));
if (iCommandLineFileFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed: iCommandLineFileFd = %d.\n", iCommandLineFileFd);
return RET_ERR;
}
BBOX_NO_INTR(iReadSize = sys_read(iCommandLineFileFd, pstPrPsInfo->cPsargs, sizeof(pstPrPsInfo->cPsargs)));
if (iReadSize < 0) {
BBOX_NO_INTR(sys_close(iCommandLineFileFd));
return RET_ERR;
}
for (pTemp = pstPrPsInfo->cPsargs; (iReadSize--) > 0; pTemp++) {
if (*pTemp == '\000') {
*pTemp = ' ';
}
}
BBOX_NO_INTR(sys_close(iCommandLineFileFd));
bbox_print(PRINT_LOG, "Fill Prpsinfo Info success.\n");
return RET_OK;
}
* get process register content.
* in : Frame *pFrame - pointer for writing core file.
* struct BBOX_ELF_NOTE_INFO *pstNoteInfo - pointer to structure of note segment distription.
* pid_t *ptPids - pointer to process id array.
* int iSegmentNum - count of mapping segment in address space.
* int *piPhdrSum - sum count of mapping segment and VDSO segment in core file.
* int iThreadNum - size of process array.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillPrPsStatusRegs(Frame* pFrame, struct BBOX_ELF_NOTE_INFO* pstNoteInfo, pid_t* ptPids, int iThreadNum)
{
char acBuff[BBOX_BUFF_LITTLE_SIZE];
unsigned int uCount = 0;
errno_t rc = EOK;
if (NULL == pFrame || NULL == pstNoteInfo || NULL == ptPids || iThreadNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_FillPrPsStatusRegs parameters is invalid: pFrame, pstNoteInfo or " \
"ptPids is NULL, iThreadNum = %d.\n",
iThreadNum);
return RET_ERR;
}
struct BBOX_THREAD_NOTE_INFO* pstThreadNoteInfo = pstNoteInfo->pstThreadNoteInfo;
for (uCount = 0; uCount < (unsigned int)iThreadNum; uCount++) {
rc = memset_s(acBuff, BBOX_BUFF_LITTLE_SIZE, 0xFF, sizeof(acBuff));
securec_check_c(rc, "\0", "\0");
#if defined(__aarch64__)
void* pregset = (void*)NT_PRSTATUS;
struct iovec io_vec;
io_vec.iov_base = acBuff;
io_vec.iov_len = sizeof(struct CPURegs);
if (RET_OK == sys_ptrace(PTRACE_GETREGSET, ptPids[uCount], pregset, &io_vec)) {
rc = memcpy_s(&((pstThreadNoteInfo + uCount)->stPrpsstatus.stRegisters),
sizeof(struct CPURegs),
acBuff,
sizeof(struct CPURegs));
securec_check_c(rc, "\0", "\0");
rc = memset_s(acBuff, sizeof(acBuff), 0xFF, sizeof(acBuff));
securec_check_c(rc, "\0", "\0");
}
#else
if (RET_OK == sys_ptrace(PTRACE_GETREGS, ptPids[uCount], acBuff, acBuff)) {
rc = memcpy_s(&((pstThreadNoteInfo + uCount)->stPrpsstatus.stRegisters),
sizeof(struct CPURegs),
acBuff,
sizeof(struct CPURegs));
securec_check_c(rc, "\0", "\0");
if (ptPids[uCount] == pstNoteInfo->tMainPid) {
SET_FRAME(*(Frame*)pFrame, (pstThreadNoteInfo + uCount)->stPrpsstatus.stRegisters);
}
rc = memset_s(acBuff, BBOX_BUFF_LITTLE_SIZE, 0xFF, sizeof(acBuff));
securec_check_c(rc, "\0", "\0");
}
if (RET_OK == sys_ptrace(PTRACE_GETFPREGS, ptPids[uCount], acBuff, acBuff)) {
rc = memcpy_s(&((pstThreadNoteInfo + uCount)->stFpRegisters),
sizeof(struct BBOX_FPREGSET),
acBuff,
sizeof(struct BBOX_FPREGSET));
securec_check_c(rc, "\0", "\0");
rc = memset_s(acBuff, BBOX_BUFF_LITTLE_SIZE, 0xFF, sizeof(acBuff));
securec_check_c(rc, "\0", "\0");
}
#endif
#if (defined(__i386__))
if (RET_OK == sys_ptrace(PTRACE_GETFPXREGS, ptPids[uCount], acBuff, acBuff)) {
rc = memcpy_s(&((pstThreadNoteInfo + uCount)->stFpxRegisters),
sizeof(struct BBOX_FPXREGSET),
acBuff,
sizeof(struct BBOX_FPXREGSET));
securec_check_c(rc, "\0", "\0");
pstNoteInfo->iFpxRegistersFlag = BBOX_TRUE;
} else {
pstNoteInfo->iFpxRegistersFlag = BBOX_FALSE;
}
#else
pstNoteInfo->iFpxRegistersFlag = BBOX_FALSE;
#endif
(pstThreadNoteInfo + uCount)->stPrpsstatus.tpid = ptPids[uCount];
}
return RET_OK;
}
* get user data structure information.
* in : struct BBOX_CORE_USER *pstCoreUser - pointer to strcuture that store user data.
* struct CPURegs *pstThreadRegs - struct pointer that store parent process register information.
* pid_t *ptPids - pointer to process id array.
* return RET_OK or RET_ERR.
*/
static int BBOX_GetParentRegs(struct BBOX_CORE_USER* pstCoreUser, struct CPURegs* pstThreadRegs, pid_t* ptPids)
{
int iCount = 0;
if (NULL == pstCoreUser || NULL == pstThreadRegs || NULL == ptPids) {
bbox_print(PRINT_ERR,
"BBOX_GetParentRegs parameters is invalid: pstCoreUser, " \
"pstThreadRegs or ptPids is NULL.\n");
return RET_ERR;
}
for (iCount = 0; iCount < (int)(sizeof(struct BBOX_CORE_USER) / sizeof(int)); iCount++) {
run if err, try best to create core file. */
(void)sys_ptrace(
PTRACE_PEEKUSER, ptPids[0], (void*)(iCount * sizeof(int)), ((char*)pstCoreUser) + iCount * sizeof(int));
}
errno_t rc = memcpy_s(&(pstCoreUser->stRegisters), sizeof(struct CPURegs), pstThreadRegs, sizeof(struct CPURegs));
securec_check_c(rc, "\0", "\0");
return RET_OK;
}
* fill note segment structure information of core file.
* in : Frame *pFrame - pointer of backstack information
* struct BBOX_ELF_NOTE_INFO *pstNoteInfo - pointer to execute note structure.
* pid_t *ptPids - pointer to process id.
* int iAuxvNum - count of Auxv that need to be written into core file.
* return RET_OK or RET_ERR.
*/
static int BBOX_FillNoteInfo(Frame* pFrame, struct BBOX_ELF_NOTE_INFO* pstNoteInfo, pid_t* ptPids, int iAuxvNum)
{
unsigned int uCount = 0;
int iResult = -1;
struct BBOX_ELF_PRPSSTATUS stTempPrPsStatus;
errno_t rc = EOK;
if (NULL == pFrame || NULL == pstNoteInfo || NULL == ptPids || iAuxvNum < 0) {
bbox_print(PRINT_ERR,
"BBOX_FillNoteInfo parameters is invalid: pFrame, "\
"pstNoteInfo or ptPids is NULL, iAuxvNum = %d.\n",
iAuxvNum);
return RET_ERR;
}
pstNoteInfo->iAuxvNoteInfoNum = iAuxvNum;
rc = memset_s(&(stTempPrPsStatus), sizeof(struct BBOX_ELF_PRPSSTATUS), 0, sizeof(struct BBOX_ELF_PRPSSTATUS));
securec_check_c(rc, "\0", "\0");
rc = memset_s(&(pstNoteInfo->stCoreUser), sizeof(struct BBOX_CORE_USER), 0, sizeof(struct BBOX_CORE_USER));
securec_check_c(rc, "\0", "\0");
rc = memset_s(&(pstNoteInfo->stPrpsinfo), sizeof(struct BBOX_ELF_PRPSINFO), 0, sizeof(struct BBOX_ELF_PRPSINFO));
securec_check_c(rc, "\0", "\0");
struct BBOX_ELF_PRPSINFO* pstPrPsInfo = &(pstNoteInfo->stPrpsinfo);
struct BBOX_THREAD_NOTE_INFO* pstThreadPrpsstatus = pstNoteInfo->pstThreadNoteInfo;
int iThreadNum = pstNoteInfo->iThreadNoteInfoNum;
and record them into struct BBOX_ELF_PRPSINFO. */
iResult = BBOX_FillPrPsInfo(pstPrPsInfo, pstNoteInfo->tMainPid);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillPrPsInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_FillPrPsStatusRegs(pFrame, pstNoteInfo, ptPids, iThreadNum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillPrPsStatusRegs is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult =
BBOX_GetParentRegs(&(pstNoteInfo->stCoreUser), &(pstThreadPrpsstatus[0].stPrpsstatus.stRegisters), ptPids);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_GetParentRegs is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_FillPsStatusTimeInfo(&stTempPrPsStatus);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillPsStatusTimeInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
for (uCount = 0; uCount < (unsigned int)iThreadNum; uCount++) {
(pstThreadPrpsstatus + uCount)->stPrpsstatus.tPpid = pstNoteInfo->stPrpsinfo.tPpid;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.tPgrp = pstNoteInfo->stPrpsinfo.tPgrp;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.tSid = pstNoteInfo->stPrpsinfo.tSid;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.tFpvalid = BBOX_TRUE;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stUserTime.lTvSec = stTempPrPsStatus.stUserTime.lTvSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stUserTime.lTvMicroSec = stTempPrPsStatus.stUserTime.lTvMicroSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stSystemTime.lTvSec = stTempPrPsStatus.stSystemTime.lTvSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stSystemTime.lTvMicroSec =
stTempPrPsStatus.stSystemTime.lTvMicroSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stCumulativeUserTime.lTvSec =
stTempPrPsStatus.stCumulativeUserTime.lTvSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stCumulativeUserTime.lTvMicroSec =
stTempPrPsStatus.stCumulativeUserTime.lTvMicroSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stCumulativeSystemTime.lTvSec =
stTempPrPsStatus.stCumulativeSystemTime.lTvSec;
(pstThreadPrpsstatus + uCount)->stPrpsstatus.stCumulativeSystemTime.lTvMicroSec =
stTempPrPsStatus.stCumulativeSystemTime.lTvMicroSec;
}
return RET_OK;
}
* create symbol table
* in : char *pBuffer - buffer
* unsigned int uiBufLen - buffer size
* return RET_OK or RET_ERR.
*/
int BBOX_GenerateStrTab(char* pBuffer, unsigned int uiBufLen)
{
int iResult = 0;
unsigned int uCount = 0;
unsigned int uiAllStringSz = 0;
char* pacShName[BBOX_SECTION_NUM] = {BBOX_ADDON_INFO, BBOX_LOG, BBOX_STR_TAB};
for (uCount = 0; uCount < BBOX_SECTION_NUM; uCount++) {
iResult = bbox_snprintf(pBuffer, uiBufLen, pacShName[uCount]);
if (iResult <= 0 || iResult > (int)uiBufLen) {
bbox_print(PRINT_ERR, "bbox_snprintf is failed, errno = %d.\n", errno);
return RET_ERR;
}
pBuffer += iResult;
uiBufLen -= iResult;
uiAllStringSz += iResult;
}
return uiAllStringSz;
}
* get content that be written into section.
* return RET_OK or RET_ERR.
*/
void BBOX_FillSectionInfo(void)
{
int iResult = RET_ERR;
errno_t rc = EOK;
iResult = BBOX_GenerateStrTab(g_acBboxStrTabInfo, sizeof(g_acBboxStrTabInfo));
if (iResult < 0) {
bbox_print(PRINT_ERR, "_BBOX_GenerateStrTab is failed.\n");
}
bbox_print(PRINT_LOG, "Generate section string table successful.\n");
iResult = _BBOX_GetAddonInfo(g_acBboxAddonInfo, sizeof(g_acBboxAddonInfo));
if (iResult < 0) {
bbox_print(PRINT_ERR, "_BBOX_GetAddonInfo is failed.\n");
}
bbox_print(PRINT_LOG, "Generate addition system info successful.\n");
g_stElfSectionInfo.uiSectionNum = BBOX_SECTION_NUM;
g_stElfSectionInfo.pstSection = g_stSectionInfo;
g_stSectionInfo[0].uiSectionType = SHT_NOTE;
g_stSectionInfo[0].pacSectionDesc = g_acBboxAddonInfo;
g_stSectionInfo[0].uiSectionDescSize = sizeof(g_acBboxAddonInfo);
g_stSectionInfo[0].uiSectionNameSize = sizeof(BBOX_ADDON_INFO);
rc = strncpy_s(
g_stSectionInfo[0].acSectionName, BBOX_SECTION_NAME_LEN, BBOX_ADDON_INFO, g_stSectionInfo[0].uiSectionNameSize);
securec_check_c(rc, "\0", "\0");
g_stSectionInfo[1].uiSectionType = SHT_NOTE;
g_stSectionInfo[1].pacSectionDesc = g_acBBoxLog;
g_stSectionInfo[1].uiSectionDescSize = sizeof(g_acBBoxLog);
g_stSectionInfo[1].uiSectionNameSize = sizeof(BBOX_LOG);
rc = strncpy_s(
g_stSectionInfo[1].acSectionName, BBOX_SECTION_NAME_LEN, BBOX_LOG, g_stSectionInfo[1].uiSectionNameSize);
securec_check_c(rc, "\0", "\0");
g_stSectionInfo[2].uiSectionType = SHT_STRTAB;
g_stSectionInfo[2].pacSectionDesc = g_acBboxStrTabInfo;
g_stSectionInfo[2].uiSectionDescSize = sizeof(g_acBboxStrTabInfo);
g_stSectionInfo[2].uiSectionNameSize = sizeof(BBOX_STR_TAB);
rc = strncpy_s(
g_stSectionInfo[2].acSectionName, BBOX_SECTION_NAME_LEN, BBOX_STR_TAB, g_stSectionInfo[2].uiSectionNameSize);
securec_check_c(rc, "\0", "\0");
bbox_print(PRINT_LOG, "Fill all section successful.\n");
return;
}
* fill every structure written into core file, include mapping, note, VDSO.
* in : Frame *pFrame - Write the structure pointer to the core file
* struct BBOX_VM_MAPS *pstVmMappingSegment - Pointer to the structure that describes the mapping segment
* int iSegmentNum - The number of mapping segments in the address space
* int *piPhdrSum - Sum of mapping and VDSO in core file
* pid_t *ptPids - A pointer to an array of process Numbers
* struct BBOX_ELF_NOTE_INFO *pstNoteInfo - Pointer to the structure that describes the note segment
* union BBOX_VM_VDSO *pstVmVDSO - Pointer to the structure that describes the VDSO segment
*/
static int BBOX_FillAllInfoOfCoreFile(Frame* pFrame, struct BBOX_VM_MAPS* pstVmMappingSegment, int* piSegmentNum,
int* piPhdrSum, pid_t* ptPids, struct BBOX_ELF_NOTE_INFO* pstNoteInfo, union BBOX_VM_VDSO* pstVmVDSO)
{
int iResult = 1;
int iValidSegmentNum = 0;
int iAuxvNum = 0;
int iExtraPhdrNum = 0;
if (NULL == pFrame || NULL == pstVmMappingSegment || NULL == piPhdrSum || NULL == ptPids || NULL == pstNoteInfo ||
NULL == pstVmVDSO || NULL == piSegmentNum) {
bbox_print(PRINT_ERR,
"BBOX_FillAllInfoOfCoreFile parameters is invalid: pFrame, pstVmMappingSegment, " \
"piPhdrSum, ptPids, pstNoteInfo, pstVmVDSO or piSegmentNum is NULL.\n");
return RET_ERR;
}
iResult = BBOX_FillVmMappingInfo(pstVmMappingSegment, piSegmentNum, &iValidSegmentNum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillVmMappingInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
Determines whether VDSO is written to the core file and the number of segments written,
record it into iSegmentNum */
iResult = BBOX_FillVDSOInfo(&iAuxvNum, &iExtraPhdrNum, *piSegmentNum, pstVmVDSO, pstVmMappingSegment);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillVDSOInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
*piPhdrSum = iValidSegmentNum + iExtraPhdrNum;
bbox_print(PRINT_DBG,
"Get all Phdr numbers success, iValidSegmentNum = %d, iExtraPhdrNum = %d, *piPhdrSum=%d.\n",
iValidSegmentNum,
iExtraPhdrNum,
*piPhdrSum);
iResult = BBOX_FillNoteInfo(pFrame, pstNoteInfo, ptPids, iAuxvNum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillNoteInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
BBOX_FillSectionInfo();
bbox_print(PRINT_LOG, "Fill Note Info success.\n");
return RET_OK;
}
* create and open core file, get fd.
* in : Frame *pFrame - Pointer to the structure of the core file
* char *pFileName - Pointer to an array of core file names
* struct BBOX_WRITE_FDS *pstFileWriteFd - Pointer to a structure that describes the properties of a core file
*/
static int BBOX_OpenCoreFile(Frame* pFrame, const char* pFileName, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
char szCmd[BBOX_CMD_LEN];
errno_t rc = EOK;
if (NULL == pFrame || NULL == pstFileWriteFd) {
bbox_print(PRINT_ERR,
"BBOX_OpenCoreFile parameters is invalid: pFrame or "\
"pstFileWriteFd is NULL.\n");
return RET_ERR;
}
rc = memset_s(szCmd, BBOX_CMD_LEN, 0, sizeof(szCmd));
securec_check_c(rc, "\0", "\0");
if (NULL != pFileName) {
bbox_snprintf(szCmd, BBOX_CMD_LEN, COMPRESSION_CMD, 1, pFileName);
} else {
bbox_snprintf(szCmd, BBOX_CMD_LEN, COMPRESSION_CMD_WITH_FILENAME, 1, ((Frame*)pFrame)->tid);
}
pstFileWriteFd->iWriteFd = sys_popen(szCmd, "w");
if (pstFileWriteFd->iWriteFd < 0) {
bbox_print(PRINT_ERR, "sys_popen is failed, pstFileWriteFd->iWriteFd = %d.\n", pstFileWriteFd->iWriteFd);
return RET_ERR;
}
pstFileWriteFd->uiMaxLength = ~(size_t)0;
bbox_print(PRINT_LOG, "Open core file success.\n");
return RET_OK;
}
* write to file
* in : struct BBOX_WRITE_FDS *pstWriteFds - A pointer to core file.
* void *pWriteData - Points to what will be written to the file
* size_t uiWriteSize - The size of what will be written to the file
*/
static ssize_t BBOX_DoWrite(struct BBOX_WRITE_FDS* pstWriteFds, void* pWriteData, size_t uiWriteSize)
{
ssize_t iRet = 0;
ssize_t iWriteCount = 0;
const ssize_t iMaxSize = (1024 * 1024 * 1024);
size_t uiSize = 0;
if (NULL == pstWriteFds || NULL == pWriteData) {
bbox_print(PRINT_ERR,
"BBOX_DoWrite parameters is invalid: pstWriteFds or "
"pWriteData is NULL.\n");
return RET_ERR;
}
while (uiWriteSize) {
uiSize = uiWriteSize;
if (uiSize > (size_t)iMaxSize) {
uiSize = iMaxSize;
}
BBOX_NOINTR(iRet = sys_write(pstWriteFds->iWriteFd, pWriteData, uiSize));
if (iRet <= 0) {
bbox_print(PRINT_ERR,
"sys_write failed, iRet = %zd, "
"uiSize = %zu, errno = %d.\n",
iRet,
uiSize,
errno);
return iRet;
}
iWriteCount += iRet;
uiWriteSize -= iRet;
pWriteData = (char*)pWriteData + iRet;
}
return iWriteCount;
}
* The file header Ehdr structure that populates the elf file
* in : BBOX_EHDR *pEhdr - The header structure of the core file
* int iPhdrSum - The number of segments written to the core file in the address space
*/
static int BBOX_FillEhdr(BBOX_EHDR* pstEhdr, int iPhdrSum)
{
if (NULL == pstEhdr || iPhdrSum <= 0) {
bbox_print(PRINT_ERR, "BBOX_FillEhdr parameters is invalid: pstEhdr maybe NULL, iPhdrSum = %d.\n", iPhdrSum);
return RET_ERR;
}
pstEhdr->e_ident[0] = ELFMAG0;
pstEhdr->e_ident[1] = (unsigned char)ELFMAG1;
pstEhdr->e_ident[2] = ELFMAG2;
pstEhdr->e_ident[3] = ELFMAG3;
pstEhdr->e_ident[4] = BBOX_ELF_CLASS;
pstEhdr->e_ident[5] = (unsigned char)BBOX_DetermineMsb();
pstEhdr->e_ident[6] = EV_CURRENT;
pstEhdr->e_type = ET_CORE;
pstEhdr->e_machine = ELF_ARCH;
pstEhdr->e_version = EV_CURRENT;
pstEhdr->e_phoff = sizeof(BBOX_EHDR);
pstEhdr->e_ehsize = sizeof(BBOX_EHDR);
pstEhdr->e_phentsize = sizeof(BBOX_PHDR);
#if (defined(__i386__))
pstEhdr->e_phnum = (Elf32_Half)(iPhdrSum + 1);
pstEhdr->e_shnum = (Elf32_Half)(BBOX_SECTION_NUM);
#elif (defined(__x86_64__)) || (defined(__ARM_ARCH_5TE__)) || (defined(__ARM_ARCH_7A__)) || (defined(__aarch64__))
pstEhdr->e_phnum = (Elf64_Half)(iPhdrSum + 1);
pstEhdr->e_shnum = (Elf64_Half)(BBOX_SECTION_NUM);
#endif
pstEhdr->e_shoff = sizeof(BBOX_EHDR) + (iPhdrSum + 1) * sizeof(BBOX_PHDR);
pstEhdr->e_shentsize = sizeof(BBOX_SHDR);
pstEhdr->e_shstrndx = BBOX_SHSTR_INDEX;
bbox_print(PRINT_LOG, "Fill Elf Ehdr success.\n");
return RET_OK;
}
* write file header of core to core file.
* in : int iPhdrSum - The number of segment in the core file
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to core file
*/
static int BBOX_WriteElfEhdr(int iPhdrSum, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
int iResult = RET_ERR;
ssize_t iWriteSize = -1;
BBOX_EHDR stElfCoreHead;
errno_t rc = EOK;
if (NULL == pstFileWriteFd || iPhdrSum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteElfEhdr parameters is invalid: pstFileWriteFd may be NULL, " \
"iPhdrSum = %d.\n",
iPhdrSum);
return RET_ERR;
}
rc = memset_s(&stElfCoreHead, sizeof(BBOX_EHDR), 0, sizeof(BBOX_EHDR));
securec_check_c(rc, "\0", "\0");
iResult = BBOX_FillEhdr(&stElfCoreHead, iPhdrSum);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillEhdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iWriteSize = BBOX_DoWrite(pstFileWriteFd, &stElfCoreHead, sizeof(BBOX_EHDR));
if (iWriteSize == RET_ERR || sizeof(BBOX_EHDR) != iWriteSize) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iWriteSize = %zd\n", iWriteSize);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write Ehdr info to the core file success.\n");
return RET_OK;
}
* Fill the header of the note segment of the core file describes the structure
* in : struct BBOX_ELF_NOTE_INFO *pstNoteInfo - The content structure of the note segment
* int iPhdrSum - The number of segments written to the core file in the address space
* size_t *puiOffset - The starting offset of the next segment
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to core file
*/
static int BBOX_WriteNotePhdr(
struct BBOX_ELF_NOTE_INFO* pstNoteInfo, int iPhdrSum, size_t* puiOffset, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
size_t uiOffSize = 0;
size_t uiFileSize = 0;
size_t uiCoreUserSize = 0;
size_t uiNoteSize = 0;
size_t uiAuxvSize = 0;
size_t uiNoteAlign = 0;
ssize_t iWriteSize = -1;
int iPageSize = sys_sysconf(_SC_PAGESIZE);
BBOX_PHDR stElfPhdr;
if (NULL == pstNoteInfo || NULL == puiOffset || NULL == pstFileWriteFd || iPhdrSum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteNotePhdr parameters is invalid: pstNoteInfo, puiOffset or pstFileWriteFd is NULL, " \
"iPhdrSum = %d.\n",
iPhdrSum);
return RET_ERR;
}
errno_t rc = memset_s(&stElfPhdr, sizeof(BBOX_PHDR), 0, sizeof(BBOX_PHDR));
securec_check_c(rc, "\0", "\0");
uiOffSize = sizeof(BBOX_EHDR) + (iPhdrSum + 1) * sizeof(BBOX_PHDR) + 3 * sizeof(BBOX_SHDR);
uiCoreUserSize = sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_CORE_USER);
#if defined(__aarch64__)
uiNoteSize = (pstNoteInfo->iThreadNoteInfoNum) *
(sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_ELF_PRPSSTATUS));
#else
uiNoteSize = (pstNoteInfo->iThreadNoteInfoNum) *
(sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_ELF_PRPSSTATUS) + sizeof(BBOX_NHDR) +
BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_FPREGSET));
#endif
if (pstNoteInfo->iFpxRegistersFlag) {
uiNoteSize += (pstNoteInfo->iThreadNoteInfoNum) *
(sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_FPXREGSET));
}
uiAuxvSize = sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + (pstNoteInfo->iAuxvNoteInfoNum) * sizeof(BBOX_AUXV_T);
uiFileSize = sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_ELF_PRPSINFO) + uiCoreUserSize +
uiNoteSize + uiAuxvSize;
stElfPhdr.p_type = PT_NOTE;
stElfPhdr.p_offset = uiOffSize;
stElfPhdr.p_filesz = uiFileSize;
*puiOffset = uiOffSize + uiFileSize;
iWriteSize = BBOX_DoWrite(pstFileWriteFd, &stElfPhdr, sizeof(BBOX_PHDR));
if (iWriteSize == RET_ERR || sizeof(BBOX_PHDR) != iWriteSize) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iWriteSize = %zd.\n", iWriteSize);
return RET_ERR;
}
stElfPhdr.p_align = iPageSize;
uiNoteAlign = stElfPhdr.p_align - ((*puiOffset) % stElfPhdr.p_align);
if (uiNoteAlign == stElfPhdr.p_align) {
uiNoteAlign = 0;
}
pstNoteInfo->uiNoteAlign = uiNoteAlign;
(*puiOffset) += uiNoteAlign;
return RET_OK;
}
* Fill the header of the note segment of the core file describes the structure
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - The content structure of the note segment
* int iSegmentNum - The number of segments written to the core file in the address space
* size_t *puiOffset - The starting offset of the next segment
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to core file
*/
static int BBOX_WriteVmSegmentPhdr(
struct BBOX_VM_MAPS* pstVmMappingSegment, int iSegmentNum, size_t* puiOffset, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
size_t uiFileSize = 0;
ssize_t iWriteSize = -1;
unsigned int uCount = 0;
int iPageSize = sys_sysconf(_SC_PAGESIZE);
BBOX_PHDR stElfPhdr;
if (NULL == pstVmMappingSegment || NULL == puiOffset || NULL == pstFileWriteFd || iSegmentNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteVmSegmentPhdr parameters is invalid: pstVmMappingSegment, puiOffset or "
"pstFileWriteFd is NULL, iSegmentNum = %d.\n",
iSegmentNum);
return RET_ERR;
}
errno_t rc = memset_s(&stElfPhdr, sizeof(BBOX_PHDR), 0, sizeof(BBOX_PHDR));
securec_check_c(rc, "\0", "\0");
stElfPhdr.p_type = PT_LOAD;
stElfPhdr.p_align = iPageSize;
stElfPhdr.p_paddr = 0;
for (uCount = 0; uCount < (unsigned int)iSegmentNum; uCount++) {
if (pstVmMappingSegment[uCount].iIsRemoveFlags == 0) {
uiFileSize = (pstVmMappingSegment[uCount].uiEndAddress) - (pstVmMappingSegment[uCount].uiStartAddress);
stElfPhdr.p_offset = *puiOffset;
stElfPhdr.p_vaddr = (pstVmMappingSegment[uCount].uiStartAddress);
stElfPhdr.p_memsz = uiFileSize;
uiFileSize = (pstVmMappingSegment[uCount].uiWriteSize);
stElfPhdr.p_filesz = uiFileSize;
stElfPhdr.p_flags = (pstVmMappingSegment[uCount].iFlags) & PF_MASK;
(*puiOffset) += uiFileSize;
iWriteSize = BBOX_DoWrite(pstFileWriteFd, &stElfPhdr, sizeof(BBOX_PHDR));
if (iWriteSize == RET_ERR || sizeof(BBOX_PHDR) != iWriteSize) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iWriteSize = %zd.\n", iWriteSize);
return RET_ERR;
}
}
}
return RET_OK;
}
* Writes a part of the VDSO segment to the core file
* in : struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to the structure of the core file
* union BBOX_VM_VDSO *pstVmVDSO - The structure that points to the VDSO segment
* size_t *puiOffset - The starting offset pointer of the next segment
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteVDSOPhdr(struct BBOX_WRITE_FDS* pstFileWriteFd, union BBOX_VM_VDSO* pstVmVDSO, size_t* puiOffset)
{
size_t uiFileSize = 0;
ssize_t iWriteSize = -1;
unsigned int uCount = 0;
BBOX_PHDR stElfPhdr;
if (NULL == pstFileWriteFd || NULL == pstVmVDSO || NULL == puiOffset) {
bbox_print(PRINT_ERR,
"BBOX_WriteVDSOPhdr parameters is invalid: pstFileWriteFd, pstVmVDSO or " \
"puiOffset is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfPhdr, sizeof(BBOX_PHDR), 0, sizeof(BBOX_PHDR));
securec_check_c(rc, "\0", "\0");
if (pstVmVDSO->uiVDSOAddress) {
BBOX_PHDR* pstVDSOPhdr = (BBOX_PHDR*)(pstVmVDSO->uiVDSOAddress + pstVmVDSO->pVDSOEhdr->e_phoff);
for (uCount = 0; uCount < pstVmVDSO->pVDSOEhdr->e_phnum; uCount++) {
if (pstVDSOPhdr[uCount].p_type != PT_LOAD) {
rc = memcpy_s(&stElfPhdr, sizeof(BBOX_PHDR), pstVDSOPhdr + uCount, sizeof(BBOX_PHDR));
securec_check_c(rc, "\0", "\0");
uiFileSize = stElfPhdr.p_filesz;
stElfPhdr.p_offset = *puiOffset;
stElfPhdr.p_paddr = 0;
iWriteSize = BBOX_DoWrite(pstFileWriteFd, &stElfPhdr, sizeof(BBOX_PHDR));
if (iWriteSize == RET_ERR || sizeof(BBOX_PHDR) != iWriteSize) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iWriteSize = %zd.\n", iWriteSize);
return RET_ERR;
}
(*puiOffset) += uiFileSize;
}
}
}
return RET_OK;
}
* Writes the header of section to the core file
* in : int iPhdrSum - The number of program headers in the core file
* struct BBOX_ELF_SECTION *pstSectionInfo - The starting offset pointer of the next segment
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteElfShdr(
struct BBOX_ELF_SECTION* pstSectionInfo, size_t* puiOffset, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
size_t uiOffSize = 0;
size_t uiFileSize = 0;
unsigned int uCount = 0;
int iSecNameOffset = 0;
BBOX_SHDR stElfShdr;
BBOX_SECTION_STRU* pstSection = NULL;
for (uCount = 0; uCount < pstSectionInfo->uiSectionNum; uCount++) {
pstSection = (pstSectionInfo->pstSection) + uCount;
errno_t rc = memset_s(&stElfShdr, sizeof(BBOX_SHDR), 0, sizeof(BBOX_SHDR));
securec_check_c(rc, "\0", "\0");
uiOffSize = *puiOffset;
uiFileSize = pstSection->uiSectionDescSize;
stElfShdr.sh_name = iSecNameOffset;
stElfShdr.sh_type = pstSection->uiSectionType;
stElfShdr.sh_offset = uiOffSize;
stElfShdr.sh_size = uiFileSize;
BBOX_WRITE(pstFileWriteFd, &stElfShdr, sizeof(BBOX_SHDR));
bbox_print(PRINT_LOG, "Write section[%s] head to fill successed.\n", pstSection->acSectionName);
*puiOffset = uiOffSize + uiFileSize;
iSecNameOffset += pstSection->uiSectionNameSize;
}
bbox_print(PRINT_LOG, "Write all section head to fill successed.\n");
return RET_OK;
}
* Writes all the progrem header of core file to the core file
* in : int iPhdrSum - The number of program headers in the core file
* struct BBOX_ELF_NOTE_INFO *pstNoteInfo - A pointer to the structure of note segment
* int iSegmentNum - The number of mapping segments in the address space
* union BBOX_VM_VDSO *pstVmVDSO - A pointer to the structure of VDSO segment
* struct BBOX_VM_MAPS *pstVmMappingSegment - A pointer to the structure of mapping segment
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteElfHdr(int iPhdrSum, struct BBOX_ELF_NOTE_INFO* pstNoteInfo, int iSegmentNum,
union BBOX_VM_VDSO* pstVmVDSO, struct BBOX_VM_MAPS* pstVmMappingSegment, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
int iResult = RET_ERR;
size_t uiOffset = 0;
if (NULL == pstNoteInfo || NULL == pstVmMappingSegment || NULL == pstVmVDSO || NULL == pstFileWriteFd ||
iSegmentNum <= 0 || iPhdrSum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteElfPhdr parameters is invalid: pstNoteInfo, pstVmMappingSegment," \
"pstVmVDSO or pstFileWriteFd in NULL, iSegmentNum = %d, iPhdrSum = %d.\n",
iSegmentNum,
iPhdrSum);
return RET_ERR;
}
iResult = BBOX_WriteNotePhdr(pstNoteInfo, iPhdrSum, &uiOffset, pstFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteNotePhdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write Note Phdr info to the core file success.\n");
iResult = BBOX_WriteVmSegmentPhdr(pstVmMappingSegment, iSegmentNum, &uiOffset, pstFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteVmSegmentPhdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write Vm mapping segment Phdr info to the core file success.\n");
iResult = BBOX_WriteVDSOPhdr(pstFileWriteFd, pstVmVDSO, &uiOffset);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteVDSOPhdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write VDSO Phdr info to the core file success.\n");
iResult = BBOX_WriteElfShdr(&g_stElfSectionInfo, &uiOffset, pstFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfShdr is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write section head info to the core file success.\n");
return RET_OK;
}
* Writes the prpsinfo to the core file
* in : struct BBOX_ELF_PRPSINFO *pstPrPsInfo - A pointer to prpsinfo
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WritePrPsinfoToFile(struct BBOX_ELF_PRPSINFO* pstPrPsInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
BBOX_NHDR stElfNhdr;
if (NULL == pstPrPsInfo || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WritePrPsinfoToFile parameters is invalid: pstPrPsInfo or pstFileFds is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_CORE_NAME_LENGTH;
stElfNhdr.n_descsz = sizeof(struct BBOX_ELF_PRPSINFO);
stElfNhdr.n_type = NT_PRPSINFO;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_CORE_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH ||
BBOX_DoWrite(pstFileFds, pstPrPsInfo, sizeof(struct BBOX_ELF_PRPSINFO)) != sizeof(struct BBOX_ELF_PRPSINFO)) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
bbox_print(PRINT_LOG,
"Write Prpsinfo size = %zd to the core file success.\n",
sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_ELF_PRPSINFO));
return RET_OK;
}
* Writes the user data information to the core file
* in : struct BBOX_ELF_PRPSINFO *pPrPsInfo - A pointer to User Core
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteUserRegistersToFile(struct BBOX_CORE_USER* pstCoreUserInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
BBOX_NHDR stElfNhdr;
if (NULL == pstCoreUserInfo || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WriteUserRegistersToFile parameters is invalid: pstCoreUserInfo or pstFileFds is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_CORE_NAME_LENGTH;
stElfNhdr.n_descsz = sizeof(struct BBOX_CORE_USER);
stElfNhdr.n_type = NT_PRXREG;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_CORE_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH ||
BBOX_DoWrite(pstFileFds, pstCoreUserInfo, sizeof(struct BBOX_CORE_USER)) != sizeof(struct BBOX_CORE_USER)) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
bbox_print(PRINT_LOG,
"Write UserRegisters size = %zd to the core file success.\n",
sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_CORE_USER));
return RET_OK;
}
* read /proc/self/auxv, write parts of it to a core file
* in : int iAuxvNum - Number of Auxv structures written to the core file
* struct BBOX_WRITE_FDS *pstWriteFds - pointer to core file.
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteAuxvInfoToFile(int iAuxvNum, struct BBOX_WRITE_FDS* pstFileFds)
{
int iAuxvFd = -1;
ssize_t iReadSize = -1;
unsigned int uCount = 0;
BBOX_NHDR stElfNhdr;
BBOX_AUXV_T stAuxv;
errno_t rc = EOK;
if (NULL == pstFileFds || iAuxvNum < 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteAuxvInfoToFile parameters is invalid: pstFileFds may be NULL," \
"iAuxvNum = %d.\n",
iAuxvNum);
return RET_ERR;
}
rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_CORE_NAME_LENGTH;
stElfNhdr.n_descsz = iAuxvNum * sizeof(BBOX_AUXV_T);
stElfNhdr.n_type = NT_AUXV;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_CORE_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
BBOX_NOINTR(iAuxvFd = sys_open(THREAD_SELF_AUXV_FILE, O_RDONLY, 0));
if (iAuxvFd < 0) {
bbox_print(PRINT_ERR, "sys_open is failed, iAuxvFd = %d.\n", iAuxvFd);
return RET_ERR;
}
for (uCount = 0; uCount < (unsigned int)iAuxvNum; uCount++) {
iReadSize = -1;
rc = memset_s(&stAuxv, sizeof(BBOX_AUXV_T), 0, sizeof(BBOX_AUXV_T));
securec_check_c(rc, "\0", "\0");
BBOX_NOINTR(iReadSize = sys_read(iAuxvFd, &stAuxv, sizeof(BBOX_AUXV_T)));
if (iReadSize != sizeof(BBOX_AUXV_T)) {
bbox_print(PRINT_ERR, "sys_read is failed, iReadSize = %zd.\n", iReadSize);
BBOX_NOINTR(sys_close(iAuxvFd));
return RET_ERR;
}
if (sizeof(BBOX_AUXV_T) != BBOX_DoWrite(pstFileFds, &stAuxv, sizeof(BBOX_AUXV_T))) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
BBOX_NOINTR(sys_close(iAuxvFd));
return RET_ERR;
}
}
BBOX_NOINTR(sys_close(iAuxvFd));
bbox_print(PRINT_LOG,
"Write Auxv size = %zd to the core file success.\n",
sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + stElfNhdr.n_descsz);
return RET_OK;
}
* Writes information of the structure that describes the state of a process to the core file
* in : struct BBOX_ELF_PRPSSTATUS *pstPrPsStatusInfo - A pointer to the structure that describes the state
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WritePrPsStatusToFile(struct BBOX_ELF_PRPSSTATUS* pstPrPsStatusInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
BBOX_NHDR stElfNhdr;
int iResult = -1;
if (NULL == pstPrPsStatusInfo || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WritePrPsStatusToFile parameters is invalid: pstPrPsStatusInfo or pstFileFds is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_CORE_NAME_LENGTH;
stElfNhdr.n_descsz = sizeof(struct BBOX_ELF_PRPSSTATUS);
stElfNhdr.n_type = NT_PRSTATUS;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_CORE_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
iResult = BBOX_DoWrite(pstFileFds, pstPrPsStatusInfo, sizeof(struct BBOX_ELF_PRPSSTATUS));
if (iResult == RET_ERR || sizeof(struct BBOX_ELF_PRPSSTATUS) != iResult) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
return RET_OK;
}
* Writes the FPU register contents to the core file
* in : struct BBOX_FPREGSET *pstFpRegisters - A pointer to an FPU register
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteFpRegistersToFile(struct BBOX_FPREGSET* pstFpRegisters, struct BBOX_WRITE_FDS* pstFileFds)
{
#if !defined(__aarch64__)
BBOX_NHDR stElfNhdr;
if (NULL == pstFpRegisters || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WriteFpRegistersToFile parameters is invalid: pstFpRegisters or pstFileFds is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_CORE_NAME_LENGTH;
stElfNhdr.n_descsz = sizeof(struct BBOX_FPREGSET);
stElfNhdr.n_type = NT_FPREGSET;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_CORE_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH ||
BBOX_DoWrite(pstFileFds, pstFpRegisters, sizeof(struct BBOX_FPREGSET)) != sizeof(struct BBOX_FPREGSET)) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
#endif
return RET_OK;
}
* Writes the SSE structure contents to the core file
* in : struct BBOX_FPXREGSET *pstFpxRegisters - A pointer to an SSE structure
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteFpxRegistersToFile(struct BBOX_FPXREGSET* pstFpxRegisters, struct BBOX_WRITE_FDS* pstFileFds)
{
BBOX_NHDR stElfNhdr;
if (NULL == pstFpxRegisters || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WriteFpxRegistersToFile parameters is invalid: pstFpxRegisters or pstFileFds is NULL.\n");
return RET_ERR;
}
errno_t rc = memset_s(&stElfNhdr, sizeof(BBOX_NHDR), 0, sizeof(BBOX_NHDR));
securec_check_c(rc, "\0", "\0");
stElfNhdr.n_namesz = BBOX_LINUX_NAME_LENGTH;
stElfNhdr.n_descsz = sizeof(struct BBOX_FPXREGSET);
stElfNhdr.n_type = NT_PRXFPREG;
if (BBOX_DoWrite(pstFileFds, &stElfNhdr, sizeof(BBOX_NHDR)) != sizeof(BBOX_NHDR) ||
BBOX_DoWrite(pstFileFds, (void*)BBOX_LINUX_STRING, BBOX_CORE_STRING_LENGTH) != BBOX_CORE_STRING_LENGTH ||
BBOX_DoWrite(pstFileFds, pstFpxRegisters, sizeof(struct BBOX_FPXREGSET)) != sizeof(struct BBOX_FPXREGSET)) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed.\n");
return RET_ERR;
}
return RET_OK;
}
* Writes the prpsstatus information and the register information for the process to the core file
* in : int iFpxRegistersFlag - Whether to write Fpx register information token
* struct BBOX_THREAD_NOTE_INFO *pstThreadPrPsStatusInfo - A pointer to the structure of thread note segment
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
* return RET_OK or RET_ERR.
*/
static int BBOX_WriteThreadNoteToFile(
int iFpxRegistersFlag, struct BBOX_THREAD_NOTE_INFO* pstThreadPrPsStatusInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
int iResult = RET_ERR;
if (NULL == pstThreadPrPsStatusInfo || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WriteThreadNoteToFile parameters is invalid: pstThreadPrPsStatusInfo or pstFileFds is NULL.\n");
return RET_ERR;
}
iResult = BBOX_WritePrPsStatusToFile(&(pstThreadPrPsStatusInfo->stPrpsstatus), pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WritePrPsStatusToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_WriteFpRegistersToFile(&(pstThreadPrPsStatusInfo->stFpRegisters), pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteFpRegistersToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
if (BBOX_TRUE == iFpxRegistersFlag) {
iResult = BBOX_WriteFpxRegistersToFile(&(pstThreadPrPsStatusInfo->stFpxRegisters), pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteFpxRegistersToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
}
return RET_OK;
}
* To align, write 0 to the core file
* in : size_t uiNoteAlign - The number of bytes that need to be written to the file for alignment
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
*/
static int BBOX_CoreFileAlignToPage(size_t uiNoteAlign, struct BBOX_WRITE_FDS* pstFileFds)
{
ssize_t iWriteSize = -1;
size_t iDateSize = 0;
char acNoteAlign[BBOX_BUFF_LITTLE_SIZE];
if (NULL == pstFileFds) {
bbox_print(PRINT_ERR, "BBOX_CoreFileAlignToPage parameters is invalid: pstFileFds is NULL.\n");
return RET_ERR;
}
while (uiNoteAlign > 0) {
if (uiNoteAlign > sizeof(acNoteAlign)) {
iDateSize = sizeof(acNoteAlign);
uiNoteAlign -= sizeof(acNoteAlign);
} else {
iDateSize = uiNoteAlign;
uiNoteAlign = 0;
}
errno_t rc = memset_s(acNoteAlign, BBOX_BUFF_LITTLE_SIZE, 0, sizeof(acNoteAlign));
securec_check_c(rc, "\0", "\0");
iWriteSize = BBOX_DoWrite(pstFileFds, acNoteAlign, iDateSize);
if (iWriteSize == RET_ERR || iDateSize != (size_t)iWriteSize) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iWriteSize = %zd.\n", iWriteSize);
return RET_ERR;
}
}
bbox_print(PRINT_LOG, "Write Note align size = %zu to the core file success.\n", uiNoteAlign);
return RET_OK;
}
* write Note segment into core file.
* in : struct BBOX_ELF_NOTE_INFO *pstNoteInfo - A pointer to the structure of the note segment
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to the structure of the core file
*/
static int BBOX_WriteNoteInfo(struct BBOX_ELF_NOTE_INFO* pstNoteInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
unsigned int uCount = 0;
int iResult = RET_ERR;
if (NULL == pstNoteInfo || NULL == pstFileFds) {
bbox_print(PRINT_ERR,
"BBOX_WriteNoteInfo parameters is invalid: pstNoteInfo or pstFileFds is NULL.\n");
return RET_ERR;
}
int iThreadNum = pstNoteInfo->iThreadNoteInfoNum;
struct BBOX_THREAD_NOTE_INFO* pstThreadPrPsStatusInfo = pstNoteInfo->pstThreadNoteInfo;
struct BBOX_ELF_PRPSINFO* pstPrPsInfo = &(pstNoteInfo->stPrpsinfo);
struct BBOX_CORE_USER* pstCoreUserInfo = &(pstNoteInfo->stCoreUser);
iResult = BBOX_WritePrPsinfoToFile(pstPrPsInfo, pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WritePrPsinfoToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_WriteUserRegistersToFile(pstCoreUserInfo, pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteUserRegistersToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
if (pstNoteInfo->iAuxvNoteInfoNum) {
iResult = BBOX_WriteAuxvInfoToFile(pstNoteInfo->iAuxvNoteInfoNum, pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteAuxvInfoToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
}
for (uCount = 0; uCount < (unsigned int)iThreadNum; uCount++) {
if ((pstThreadPrPsStatusInfo + uCount)->stPrpsstatus.tpid == pstNoteInfo->tMainPid) {
iResult = BBOX_WriteThreadNoteToFile(
pstNoteInfo->iFpxRegistersFlag, (pstThreadPrPsStatusInfo + uCount), pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteThreadNoteToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
}
}
for (uCount = 0; uCount < (unsigned int)iThreadNum; uCount++) {
if ((pstThreadPrPsStatusInfo + uCount)->stPrpsstatus.tpid != pstNoteInfo->tMainPid) {
iResult = BBOX_WriteThreadNoteToFile(
pstNoteInfo->iFpxRegistersFlag, (pstThreadPrPsStatusInfo + uCount), pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteThreadNoteToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
}
}
bbox_print(PRINT_LOG, "Write Prpsstatus and Registers to the core file success.\n");
iResult = BBOX_CoreFileAlignToPage(pstNoteInfo->uiNoteAlign, pstFileFds);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_CoreFileAlignToPage is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Write Note info to the core file success.\n");
return RET_OK;
}
* read content of address space, and write it into core file.
* in : struct BBOX_VM_MAPS *pstVmMappingSegment - A pointer to the structure of the mapping segment
* int iVmMappingNum - The number of mapping segments in the address space
* union BBOX_VM_VDSO *pstVmVDSO - A pointer to the structure of the VDSO segment
* struct BBOX_WRITE_FDS *pstWriteFds - A pointer to core file
* return RET_OK or RET_ERR
*/
static int BBOX_WriteElfVmToFile(struct BBOX_VM_MAPS* pstVmMappingSegment, int iVmMappingNum,
union BBOX_VM_VDSO* pstVmVDSO, struct BBOX_WRITE_FDS* pstFileFds)
{
unsigned int uCount = 0;
size_t uiStartAddress = 0;
size_t uiWriteSize = 0;
ssize_t iResult = RET_ERR;
if (NULL == pstVmMappingSegment || iVmMappingNum < 0 || NULL == pstFileFds || NULL == pstVmVDSO) {
bbox_print(PRINT_ERR,
"BBOX_WriteElfVmToFile parameters is invalid: iVmMappingNum = %d, " \
"pstVmMappingSegment, pstFileFds or pstVmVDSO is NULL.\n",
iVmMappingNum);
return RET_ERR;
}
for (uCount = 0; uCount < (unsigned int)iVmMappingNum; uCount++) {
uiStartAddress = pstVmMappingSegment[uCount].uiStartAddress;
uiWriteSize = pstVmMappingSegment[uCount].uiWriteSize;
if (pstVmMappingSegment[uCount].iIsRemoveFlags == BBOX_FALSE && uiWriteSize > 0) {
iResult = BBOX_DoWrite(pstFileFds, (void*)uiStartAddress, uiWriteSize);
if ((iResult == RET_ERR) || (iResult != (ssize_t)uiWriteSize)) {
bbox_print(PRINT_ERR, "BBOX_DoWrite parameters is failed, iWriteSize = %zu.\n", uiWriteSize);
return RET_ERR;
}
bbox_print(
PRINT_DBG, "pstVmMappingSegment[%u] : write size = %zu to the core file.\n", uCount, uiWriteSize);
}
}
if (pstVmVDSO->uiVDSOAddress) {
BBOX_PHDR* pstVDSOPhdr = (BBOX_PHDR*)(pstVmVDSO->uiVDSOAddress + pstVmVDSO->pVDSOEhdr->e_phoff);
for (uCount = 0; uCount < pstVmVDSO->pVDSOEhdr->e_phnum; uCount++) {
BBOX_PHDR* pstVDSOTempPhdr = pstVDSOPhdr + uCount;
if (PT_LOAD != pstVDSOTempPhdr->p_type) {
iResult = BBOX_DoWrite(pstFileFds, (void*)pstVDSOTempPhdr->p_vaddr, pstVDSOTempPhdr->p_filesz);
if ((iResult == RET_ERR) || (iResult != (ssize_t)(pstVDSOTempPhdr->p_filesz))) {
bbox_print(PRINT_ERR, "BBOX_DoWrite is failed, iResult = %zd.\n", iResult);
return RET_ERR;
}
bbox_print(PRINT_DBG, "VDSO[%u] : write size = %zd to the core file.\n", uCount, iResult);
}
}
}
bbox_print(PRINT_LOG, "Write Vm mapping segment to the core file success.\n");
return RET_OK;
}
* write all segment into core file, include NOTE, mapping, VDSO
* in : struct BBOX_ELF_NOTE_INFO *pstNoteInfo - A pointer to the structure of the note segment
* struct BBOX_VM_MAPS *pstVmMappingSegment - A pointer to the structure of the mapping segment
* int iSegmentNum - The number of mapping segments in the address space
* union BBOX_VM_VDSO *pstVmVDSO - A pointer to the structure of the VDSO segment
* struct BBOX_WRITE_FDS *pstFileWriteFd - A pointer to core file
*/
static int BBOX_WriteElfSegment(struct BBOX_ELF_NOTE_INFO* pstNoteInfo, struct BBOX_VM_MAPS* pstVmMappingSegment,
int iSegmentNum, union BBOX_VM_VDSO* pstVmVDSO, struct BBOX_WRITE_FDS* pstFileWriteFd)
{
int iResult = RET_ERR;
if (NULL == pstNoteInfo || NULL == pstVmMappingSegment || NULL == pstVmVDSO || NULL == pstFileWriteFd ||
iSegmentNum <= 0) {
bbox_print(PRINT_ERR,
"BBOX_WriteElfSegment parameters is invalid: pstNoteInfo, pstVmMappingSegment, " \
"pstVmVDSO or pstFileWriteFd is NULL, iSegmentNum = %d.\n",
iSegmentNum);
return RET_ERR;
}
iResult = BBOX_WriteNoteInfo(pstNoteInfo, pstFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteNoteInfo is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
iResult = BBOX_WriteElfVmToFile(pstVmMappingSegment, iSegmentNum, pstVmVDSO, pstFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfVmToFile is failed, iResult = %d.\n", iResult);
return RET_ERR;
}
return RET_OK;
}
* calculate end time of coredump and print the time coredump take.
*/
static void BBOX_CalculateUsedTime(void)
{
long int iCoreDumpEndTime = 0;
struct kernel_timeval stProgramCoreDumpTime = {0};
sys_gettimeofday(&stProgramCoreDumpTime, NULL);
iCoreDumpEndTime = stProgramCoreDumpTime.tv_sec;
bbox_print(PRINT_TIP, "Coredump probably end at %ld\n", stProgramCoreDumpTime.tv_sec);
bbox_print(PRINT_TIP, "Coredump used time: %ld sec\n", iCoreDumpEndTime - g_iCoreDumpBeginTime);
bbox_print(PRINT_LOG, "Get information success.\n");
bbox_print(PRINT_LOG, "Create core file success.\n");
}
* Write all section into core file.
* in : struct BBOX_ELF_SECTION *pstElfSectionInfo - pointer to the structure of a section
* struct BBOX_WRITE_FDS *pstFileWriteFd - pointer to the core file
* return RET_OK or RET_ERR
*/
static int BBOX_WriteElfSection(struct BBOX_ELF_SECTION* pstElfSectionInfo, struct BBOX_WRITE_FDS* pstFileFds)
{
unsigned int uiCount = 0;
BBOX_SECTION_STRU* pstSection = NULL;
BBOX_CalculateUsedTime();
for (uiCount = 0; uiCount < pstElfSectionInfo->uiSectionNum; uiCount++) {
pstSection = pstElfSectionInfo->pstSection + uiCount;
BBOX_WRITE(pstFileFds, pstSection->pacSectionDesc, pstSection->uiSectionDescSize);
}
bbox_print(PRINT_LOG, "Write all section to fill successed.\n");
return RET_OK;
}
* close core file
* in : struct BBOX_WRITE_FDS *pstFileWriteFd - Pointer to a structure that describes the properties of a core file.
* return RET_OK or RET_ERR
*/
static int BBOX_CloseCoreFile(struct BBOX_WRITE_FDS* pstFileWriteFd)
{
if (NULL == pstFileWriteFd) {
bbox_print(PRINT_ERR, "BBOX_CloseCoreFile parameters is invalid: pstFileWriteFd is NULL.\n");
return RET_ERR;
}
if (pstFileWriteFd->iWriteFd >= 0) {
sys_pclose(pstFileWriteFd->iWriteFd);
pstFileWriteFd->iWriteFd = -1;
}
bbox_print(PRINT_LOG, "Close core file success.\n");
return RET_OK;
}
* create elf core file.
* in : BBOX_GetAllThreadDone pDone - The callback function for thawing
* void *pDoneHandle - The callback function parameter to be thawed
* int iNumThreads - The number of processes, that is, the length of the process number array
* pid_t *pPids - pointer to execute the process number array
* va_list ap - Multiparameter list
* return RET_OK or RET_ERR
*/
int BBOX_DoDumpElfCore(BBOX_GetAllThreadDone pDone, void* pDoneHandle, int iNumThreads, pid_t* ptPids, va_list ap)
{
int iSegmentNum = -1;
int iResult = RET_ERR;
int iCloseFile = RET_ERR;
int iPhdrSum = 0;
pid_t tMainPid = 0;
Frame* pFrame = NULL;
char* pFileName = NULL;
union BBOX_VM_VDSO stVmVDSO;
struct BBOX_ELF_NOTE_INFO stNoteInfo;
struct BBOX_WRITE_FDS stFileWriteFd;
errno_t rc = EOK;
if (NULL == ptPids || NULL == pDone || NULL == pDoneHandle || iNumThreads <= 0) {
bbox_print(PRINT_ERR,
"BBOX_CloseCoreFile parameters is invalid: pDone, ptPids or pDoneHandle is NULL, " \
"iNumThreads = %d.\n",
iNumThreads);
return RET_ERR;
}
while (BBOX_AtomicIncReturn(&g_stLockBlackList) > 1) {
BBOX_AtomicDec(&g_stLockBlackList);
bbox_print(PRINT_DBG, "add blacklist addr is running, waiting.\n");
sleep(1);
}
struct BBOX_THREAD_NOTE_INFO astThreadNoteInfo[iNumThreads];
pFrame = (Frame*)va_arg(ap, Frame*);
if (NULL == pFrame) {
bbox_print(PRINT_ERR, "Get stack frame failed.\n");
BBOX_AtomicDec(&g_stLockBlackList);
return RET_ERR;
}
rc = memset_s(&stVmVDSO, sizeof(union BBOX_VM_VDSO), 0, sizeof(union BBOX_VM_VDSO));
securec_check_c(rc, "\0", "\0");
rc = memset_s(&stNoteInfo, sizeof(struct BBOX_ELF_NOTE_INFO), 0, sizeof(struct BBOX_ELF_NOTE_INFO));
securec_check_c(rc, "\0", "\0");
rc = memset_s(&stFileWriteFd, sizeof(struct BBOX_WRITE_FDS), 0, sizeof(struct BBOX_WRITE_FDS));
securec_check_c(rc, "\0", "\0");
rc = memset_s(astThreadNoteInfo,
iNumThreads * sizeof(struct BBOX_THREAD_NOTE_INFO),
0,
iNumThreads * sizeof(struct BBOX_THREAD_NOTE_INFO));
securec_check_c(rc, "\0", "\0");
stNoteInfo.pstThreadNoteInfo = astThreadNoteInfo;
stNoteInfo.iThreadNoteInfoNum = iNumThreads;
stVmVDSO.uiVDSOAddress = 0;
tMainPid = pFrame->tid;
stNoteInfo.tMainPid = tMainPid;
iSegmentNum = BBOX_GetVmMapsNum();
if (iSegmentNum <= 0) {
bbox_print(PRINT_ERR, "BBOX_GetVmMapsNum is invald iSegmentNum = %d\n", iSegmentNum);
BBOX_AtomicDec(&g_stLockBlackList);
return RET_ERR;
}
bbox_print(PRINT_LOG, "Get Vm mapping number success, iSegmentNum = %d\n", iSegmentNum);
struct BBOX_VM_MAPS astVmMappingSegment[iSegmentNum + BBOX_EXTERN_VM_MAX];
rc = memset_s(astVmMappingSegment,
(iSegmentNum + BBOX_EXTERN_VM_MAX) * sizeof(struct BBOX_VM_MAPS),
0,
(iSegmentNum + BBOX_EXTERN_VM_MAX) * sizeof(struct BBOX_VM_MAPS));
securec_check_c(rc, "\0", "\0");
iResult = BBOX_FillAllInfoOfCoreFile(
pFrame, astVmMappingSegment, &iSegmentNum, &iPhdrSum, ptPids, &stNoteInfo, &stVmVDSO);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_FillAllInfoOfCoreFile is failed, iResult = %d.\n", iResult);
BBOX_AtomicDec(&g_stLockBlackList);
return RET_ERR;
}
pDone(pDoneHandle);
pFileName = (char*)va_arg(ap, char*);
if (CheckFilenameValid(pFileName) == RET_ERR) {
bbox_print(PRINT_ERR, "check core file name failed\n");
return RET_ERR;
}
iResult = BBOX_OpenCoreFile(pFrame, pFileName, &stFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_OpenCoreFile is failed, iResult = %d.\n", iResult);
goto ERR;
}
iResult = BBOX_WriteElfEhdr(iPhdrSum, &stFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfEhdr is failed, iResult = %d.\n", iResult);
goto ERR;
}
iResult = BBOX_WriteElfHdr(iPhdrSum, &stNoteInfo, iSegmentNum, &stVmVDSO, astVmMappingSegment, &stFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfPhdr is failed, iResult = %d.\n", iResult);
goto ERR;
}
iResult = BBOX_WriteElfSegment(&stNoteInfo, astVmMappingSegment, iSegmentNum, &stVmVDSO, &stFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfSegment is failed, iResult = %d.\n", iResult);
goto ERR;
}
iResult = BBOX_WriteElfSection(&g_stElfSectionInfo, &stFileWriteFd);
if (RET_OK != iResult) {
bbox_print(PRINT_ERR, "BBOX_WriteElfSection is failed, iResult = %d.\n", iResult);
goto ERR;
}
bbox_print(PRINT_LOG, "Create core file success.\n");
ERR:
BBOX_AtomicDec(&g_stLockBlackList);
iCloseFile = BBOX_CloseCoreFile(&stFileWriteFd);
if (RET_OK != iCloseFile) {
bbox_print(PRINT_ERR, "BBOX_CloseCoreFile is failed, iCloseFile = %d.\n", iCloseFile);
}
return (iCloseFile == RET_OK) ? iResult : RET_ERR;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif