diff --git a/src/gausskernel/cbb/bbox/bbox_elf_dump.cpp b/src/gausskernel/cbb/bbox/bbox_elf_dump.cpp deleted file mode 100644 index 2862c30ca..000000000 --- a/src/gausskernel/cbb/bbox/bbox_elf_dump.cpp +++ /dev/null @@ -1,2892 +0,0 @@ -/* - * 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 */