LLiHengsync code
de223dd1创建于 2022年3月4日历史提交
/*
 * 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 /* __cplusplus */

extern long int g_iCoreDumpBeginTime; /* begin time of coredump */

struct BBOX_ELF_SECTION g_stElfSectionInfo;          /* information of all section. */
BBOX_SECTION_STRU g_stSectionInfo[BBOX_SECTION_NUM]; /* array to record section information. */
char g_acBboxAddonInfo[BBOX_ADDON_INFO_SIZE];        /* record system information. */
char g_acBboxStrTabInfo[BBOX_SH_STR_TAB_SIZE];       /* record string symbol table. */

/*
 * 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;
    }

    /* compare and determine if it is a device */
    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; /* set flag of equipment. */

        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; /* set VDSO flag. */

        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; /* set VVAR flag */

            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;
    }

    /* read ELF header */
    retval = sys_read(fd, &ehdr, sizeof(ehdr));
    if (retval < 0) {
        bbox_print(PRINT_ERR, "read elf failed, errno = %d\n", errno);
        goto errout;
    }

    /* check if the file is ELF file. */
    if (bbox_strncmp(ELFMAG, (char*)ehdr.e_ident, SELFMAG)) {
        pstSegmentMapping->iFlags |= PF_MAPPEDFILE;
        bbox_print(PRINT_DBG, "not an elf file.\n");
        /* this is map file instead of dynamic library file. */
        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++;

    /* read mapping file path after reading all address. */
    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;
    }

    /* read flags and set '-' to 0 after reading all address. */
    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;

    /* read offset */
    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;
    }

    /* ignore the feild that discribe equipment and node which are not needed. */
    iGetChar = BBOX_SkipDeviceAndNodeField(pstReadIO);
    if (RET_ERR == iGetChar) {
        bbox_print(PRINT_ERR, "BBOX_SkipDeviceAndNodeField is failed, iGetChar= %d.\n", iGetChar);
        return RET_ERR;
    }

    /* judge the next field is start with '[' or is end, if yes, mark it as a anonymity equipment. */
    iIsMappingAnonymousFlag = ((iGetChar == '\n') || (iGetChar == '['));
    if (BBOX_TRUE == iIsMappingAnonymousFlag) {
        pstSegmentMapping->iFlags |= PF_ANONYMOUS;
        /* judge where it is VDSO segment, if yes, mark it. */
        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;
    }

    /* judge if it is discribing someone equipment. */
    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;
    }

    /* judge if it has mapping file. */
    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;
    }

    /* read characters from file and convert it to interger until get '-'. 
	   This is start address and then ready to read end address. */
    iGetChar = BBOX_StringSwitchInt(pstReadIO, &(pstSegmentMapping->uiStartAddress));
    if ('-' == iGetChar) {
        /* read characters from file and convert it to interger until get '-'. This is end address. */
        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 {
        /* do nothing */
    }

    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);

        /* get start address and end address of every segment in process address space. */
        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;
        }

        /* get jurisdiction flag and offset of every segment in process address space. */
        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') {
            /* ignore other information and skip to the end of line for preparing to read next line. */
            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;
        }

        /* If the segment is a code segment or a non-anonymous segment that cannot be read or written,
           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);
        }

        /* mark a segment not write into core file
           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;
    }

    /* read /proc/self/maps and fill struct BBOX_VM_MAPS. */
    iResult = BBOX_GetMappingSegment(pstVmMappingSegment, piSegmentNum);
    if (RET_OK != iResult) {
        bbox_print(PRINT_ERR, "BBOX_GetMappingSegment is failed, iResult = %d.\n", iResult);
        return RET_ERR;
    }

    /* judge if it need to be written into core file and the size to be written in
       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;

    /* read /proc/self/auxv, get count of Auxv written into core file and load address of VDSO. */
    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) {
            /* get VDSO load address from AT_SYSINFO_EHDR of Auxv. */
            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)) {
        /* not aligned properly */
        bbox_print(PRINT_ERR, "VDSO is invalid: not aligned properly.\n");
        return RET_BBOX_VDSO_INVALID;
    }

    if (uiEndAddress <= uiEhdrAddress + sizeof(BBOX_EHDR)) {
        /* pstVDSOEhdr has Incomplete head */
        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)) {
        /* not aligned properly */
        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)) {
        /* VDSOPhdr is incompleted */
        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++) {
        /* VDSO has multiple PT_LOAD segments. */
        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;
        }

        /* VDSOPhdr is not aligned properly. */
        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;
        }

        /* Phdr data range is out of bounds */
        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) {
            /* traverse segment, and judge if VDSO address is in segment scope. */
            if ((pstVmMappingTemp->iFlags & PF_R) && (pstVmMappingTemp->uiStartAddress <= pstVmVDSO->uiVDSOAddress) &&
                (pstVmMappingTemp->uiEndAddress > pstVmVDSO->uiVDSOAddress)) {
                /* judge if VDSO address is valid. */
                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;
        }

        /* if segment in VDSO is not PT_LOAD, add it into core file. */
        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;
    }

    /* get VDSO, load address of VDSO segment and count of Auxv be written into core file. */
    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;

    /* check if VDSO is valid */
    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;
    }

    /* get the number of additional segments, which means that add VDSO into segment. */
    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;      /* the 13th is User time */
    const int iSTimePos = 14;      /* the 14th is System time */
    const int iCUTimePos = 15;     /* the 15th is Cumulative user time */
    const int iCSTimePos = 16;     /* the 16th is Cumulative system time */
    const int iPendingSigPos = 30; /* the 30th is Pending signals */
    const int iHeldSigPos = 31;    /* the 31th is Held signals */
    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++) {
        /* use pointer to record the string be divided. */
        if (iFlag) {
            pStatItem[uItemNum++] = (pszReadFile + uCount);
            iFlag = 0;
        }

        /* convert ' ' to '\0' */
        if (pszReadFile[uCount] == ' ') {
            pszReadFile[uCount] = '\0';
            iFlag = 1;
        }
    }

    /* the 13th is User time */
    bbox_print(PRINT_DBG, "User Time : %s\n", pStatItem[iUTimePos]);
    (void)BBOX_StringToTime(pStatItem[iUTimePos], &(pstPrPsStatus->stUserTime));

    /* the 14th is System time */
    bbox_print(PRINT_DBG, "System Time : %s\n", pStatItem[iSTimePos]);
    (void)BBOX_StringToTime(pStatItem[iSTimePos], &(pstPrPsStatus->stSystemTime));

    /* the 15th is Cumulative user time */
    bbox_print(PRINT_DBG, "Cumulative user Time : %s\n", pStatItem[iCUTimePos]);
    (void)BBOX_StringToTime(pStatItem[iCUTimePos], &(pstPrPsStatus->stCumulativeUserTime));

    /* the 16th is Cumulative system time */
    bbox_print(PRINT_DBG, "Cumulative system : %s\n", pStatItem[iCSTimePos]);
    (void)BBOX_StringToTime(pStatItem[iCSTimePos], &(pstPrPsStatus->stCumulativeSystemTime));

    /* the 30th is Pending signals */
    pcSignalstr = pStatItem[iPendingSigPos];
    pstPrPsStatus->ulSigPend = 0;
    while (*pcSignalstr != '\0') {
        pstPrPsStatus->ulSigPend = 10 * pstPrPsStatus->ulSigPend + (*pcSignalstr - '0');
        pcSignalstr++;
    }

    /* the 31th is Held signals */
    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");

    /* read /proc/self/stat */
    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++) {
        /* get the command name of the program to run (/bin/bash --> bash) */
        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");

    /* read /proc/self/command, get parameter list of command. */
    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++) {
        /* convert '\0' to ' ' so that all of it can be print out one time. */
        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__)
        /* get cpu register information of pid[i], run if err, try best to create core file. */
        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
        /* get cpu register information of pid[i], run if err, try best to create core file. */
        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");
        }

        /* get fpu register information of pid[i], run if err, try best to create core file. */
        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__))

        /* get sse register information of pid[i], run if err, try best to create core file. */
        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

        /* sse register information is stored in sse structure in x86-64. */
        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++) {
        /* get register information of parent process and copy it into user data structure,
           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;

    /* get run status, priority, group id, parent process id of a process
       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;
    }

    /* get register, FPU and SSE information of process and record them into struct BBOX_THREAD_NOTE_INFO. */
    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;
    }

    /* get user data structure information and record it into struct BBOX_CORE_USER. */
    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;
    }

    /* get process time information and record it into struct BBOX_ELF_PRPSSTATUS. */
    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;

    /* string symbol table */
    char* pacShName[BBOX_SECTION_NUM] = {BBOX_ADDON_INFO, BBOX_LOG, BBOX_STR_TAB};

    /* concatenate the above strings into the buffer, take care '\0'. */
    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;

    /* create symbol table, if occur err, don't return ,run and try best to create core file. */
    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");

    /* Get system information, continue if failed, try best to create core file. */
    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;

    /* BBOX_ADDONINFO */
    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");

    /* BBOX_LOG */
    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");

    /* .shstrtab */
    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;
    }

    /* read /proc/self/maps, fill structure that discribes process address space information. */
    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;
    }

    /* get number of auxv written into core file in /proc/self/auxv, record VDSO address.
       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;
    }

    /* calculate all segment that need to be written into core file except note segment */
    *piPhdrSum = iValidSegmentNum + iExtraPhdrNum;
    bbox_print(PRINT_DBG,
        "Get all Phdr numbers success, iValidSegmentNum = %d, iExtraPhdrNum = %d, *piPhdrSum=%d.\n",
        iValidSegmentNum,
        iExtraPhdrNum,
        *piPhdrSum);

    /* Fill struct BBOX_ELF_NOTE_INFO */
    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;
    }

    /* fill section */
    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 the user does not define the file name, set it to core.tid.lz4 */
    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);
    }

    /* create core file using the way of compression while writing */
    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);  // 1G
    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(); /* Determine whether the system is large or small */
    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); /* Number of memory address space segments plus note segments */
    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); /* Number of memory address space segments plus note segments */
    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); /* Gets the system page size */
    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");

    /* Calculates the starting position and size of the note segment in the core file */
    uiOffSize = sizeof(BBOX_EHDR) + (iPhdrSum + 1) * sizeof(BBOX_PHDR) + 3 * sizeof(BBOX_SHDR);

    /* Calculate the size of the user data */
    uiCoreUserSize = sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_CORE_USER);

    /* Calculate the size of the BBOX_ELF_PRPSSTATUS */
#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) {
        /* If the SSE register exists, add its size */
        uiNoteSize += (pstNoteInfo->iThreadNoteInfoNum) *
                      (sizeof(BBOX_NHDR) + BBOX_CORE_STRING_LENGTH + sizeof(struct BBOX_FPXREGSET));
    }

    /* Calculates the size of the Auxv written */
    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;
    }

    /* Calculate the size of the page alignment to fill, and calculate the starting position of the next segment */
    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) {
            /* calculate size */
            uiFileSize = (pstVmMappingSegment[uCount].uiEndAddress) - (pstVmMappingSegment[uCount].uiStartAddress);
            stElfPhdr.p_offset = *puiOffset;                                  /* offset */
            stElfPhdr.p_vaddr = (pstVmMappingSegment[uCount].uiStartAddress); /* start address in address space of segment */
            stElfPhdr.p_memsz = uiFileSize;                                   /* size of segment in address space */

            uiFileSize = (pstVmMappingSegment[uCount].uiWriteSize); /* size of segment in file */
            stElfPhdr.p_filesz = uiFileSize;
            stElfPhdr.p_flags = (pstVmMappingSegment[uCount].iFlags) & PF_MASK;

            (*puiOffset) += uiFileSize; /* next offset of segment. */

            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) {
                /* Write the non-load segment of VDSO to the core file */
                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;

        /* name of section, it is not a string and it's value is the offset of string in string table. */
        stElfShdr.sh_name = iSecNameOffset;
        stElfShdr.sh_type = pstSection->uiSectionType; /* type of section */
        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;
    }

    /* write Phdr of Note to core file. */
    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");

    /* write Phdr of process address space to core file. */
    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");

    /* write Phdr of VDSO to core file. */
    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");

    /* write Shdr of section to core file. */
    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;
    }

    /* read /proc/self/Auxv, write to core file. */
    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)
{
/* since ptrace() doesn't support to obtain float registers' context in aarch64, don't dump it out. */
#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;
    }

    /* Write CPU register information to core file */
    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;
    }

    /* Write FPU register information to core file */
    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) {
        /* Write SSE information into core file if exist. */
        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);

    /* write BBOX_ELF_PRPSINFO into core file */
    iResult = BBOX_WritePrPsinfoToFile(pstPrPsInfo, pstFileFds);
    if (RET_OK != iResult) {
        bbox_print(PRINT_ERR, "BBOX_WritePrPsinfoToFile is failed, iResult = %d.\n", iResult);
        return RET_ERR;
    }

    /* write user data into core file */
    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) {
        /* write Auxv into core */
        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) {
            /* write primary process register information into core file. */
            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) {
            /* write all non-primary process register information into core file. */
            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");

    /* align the Note segment */
    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;
    }

    /* read content from start address to end address in address space, and write it into core file. */
    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++) {
            /* wirte VDSO information into core file */
            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;
    }

    /* write Note segment into core file */
    iResult = BBOX_WriteNoteInfo(pstNoteInfo, pstFileWriteFd);
    if (RET_OK != iResult) {

        bbox_print(PRINT_ERR, "BBOX_WriteNoteInfo is failed, iResult = %d.\n", iResult);

        return RET_ERR;
    }

    /* write process address space information into core file. */
    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};

    /* calculate time. */
    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;

    /* print time and end information of core file. */
    BBOX_CalculateUsedTime();

    /* Write section into core file. */
    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;
    }

    /* Atomic variable lock to prevent reentry. */
    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; /* count of thread */
    stVmVDSO.uiVDSOAddress = 0;
    tMainPid = pFrame->tid;
    stNoteInfo.tMainPid = tMainPid;

    /* Get count of line in /proc/self/maps, it also is segment num. */
    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);

    /* define variable to record start address, end address, jurisdiction, offset and so on of segment in /proc/self/maps */
    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");

    /* Fill BBOX_VM_MAPS, BBOX_ELF_NOTE_INFO, BBOX_VM_VDSO, and write them into core file. */
    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;
    }

    /* Notifie the thread module that the data retrieval is complete. */
    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); /* create core file. */
    if (RET_OK != iResult) {
        bbox_print(PRINT_ERR, "BBOX_OpenCoreFile is failed, iResult = %d.\n", iResult);

        goto ERR;
    }

    /* fill core file header and write it into core file. */
    iResult = BBOX_WriteElfEhdr(iPhdrSum, &stFileWriteFd);
    if (RET_OK != iResult) {
        bbox_print(PRINT_ERR, "BBOX_WriteElfEhdr is failed, iResult = %d.\n", iResult);
        goto ERR;
    }

    /* Fill ElfPhdr and write it into core file. */
    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;
    }

    /* Write Note segment and process address content into core file. */
    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;
    }

    /* Write BBOX_ELF_PRPSINFO into core file */
    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 /* __cplusplus */