* 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.h
*
* IDENTIFICATION
* src/gausskernel/cbb/bbox/bbox_elf_dump.h
*
* -------------------------------------------------------------------------
*/
#include <elf.h>
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#if (defined WITH_OPENEULER_OS) || (defined OPENEULER_MAJOR)
#include <linux/sysctl.h>
#else
#include <sys/sysctl.h>
#endif
#include <sys/ptrace.h>
#include <asm/ptrace.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stddef.h>
#include "bbox_elf_dump_base.h"
#include "bbox_syscall_support.h"
#include "bbox_print.h"
#include "bbox_threads.h"
#include "bbox_lib.h"
#ifndef __BBOX_ELF_DUMP_H__
#define __BBOX_ELF_DUMP_H__
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#if __WORDSIZE == 64
#define BBOX_ELF_CLASS ELFCLASS64
#define BBOX_EHDR Elf64_Ehdr
#define BBOX_PHDR Elf64_Phdr
#define BBOX_SHDR Elf64_Shdr
#define BBOX_NHDR Elf64_Nhdr
#define BBOX_AUXV_T Elf64_auxv_t
#else
#define BBOX_ELF_CLASS ELFCLASS32
#define BBOX_EHDR Elf32_Ehdr
#define BBOX_PHDR Elf32_Phdr
#define BBOX_SHDR Elf32_Shdr
#define BBOX_NHDR Elf32_Nhdr
#define BBOX_AUXV_T Elf32_auxv_t
#endif
#define RET_BBOX_VDSO_INVALID (1)
#define COMPRESSION_CMD "lz4 -%u > \"%s\""
#define COMPRESSION_CMD_WITH_FILENAME "lz4 -%u > core.%d.lz4"
#define BBOX_FALSE (0)
#define BBOX_TRUE (1)
#define BBOX_CORE_STRING "CORE\0\0\0\0"
#define BBOX_CORE_NAME_LENGTH (5)
#define BBOX_LINUX_STRING "LINUX\000\000"
#define BBOX_LINUX_NAME_LENGTH (8)
#define BBOX_CORE_STRING_LENGTH (8)
#define THREAD_SELF_MAPS_FILE "/proc/self/maps"
#define THREAD_SELF_EXE_FILE "/proc/self/exe"
#define THREAD_SELF_AUXV_FILE "/proc/self/auxv"
#define THREAD_SELF_STAT_FILE "/proc/self/stat"
#define THREAD_SELF_COMMAND_LINE_FILE "/proc/self/cmdline"
#define VDSO_NAME_STRING "[vdso]"
#define VVAR_NAME_STRING "[vvar]"
#define DEVICE_ZERO_NAME_STRING "/dev/zero"
#define DEVICE_PREFIX_LEN 5
#define DEVICE_AND_NODE_FIELD_NUM 2
#define BBOX_BUFF_SIZE (4096)
#define BBOX_CMD_LEN (256)
#define BBOX_STAT_ITEM_NUM (64)
#define PF_MASK 0x00000007
#define PF_ANONYMOUS 0x80000000
#define PF_DEVICE 0x40000000
#define PF_VDSO 0x20000000
#define PF_MAPPEDFILE 0x10000000
#define PF_VVAR 0x08000000
#define BBOX_SECTION_NUM 3
#define BBOX_SHSTR_INDEX 2
#define BBOX_ADDON_INFO "BBOX_ADDON_INFO"
#define BBOX_LOG "BBOX_LOG"
#define BBOX_STR_TAB ".shstrtab"
#define BBOX_ADDON_INFO_SIZE (128 * 1024)
#define BBOX_SH_STR_TAB_SIZE (1024)
#define BBOX_NO_INTR(fn) \
do { \
} while ((fn) < 0 && errno == EINTR)
#define BBOX_WRITE(fd, pData, size) \
do { \
if (BBOX_DoWrite(fd, pData, size) != size) { \
bbox_print(PRINT_ERR, "BBOX_DoWrite failed, errno = %d.\n", errno); \
return RET_ERR; \
} \
} while (0)
#if defined(__x86_64__)
#define ELF_ARCH EM_X86_64
#elif defined(__i386__)
#define ELF_ARCH EM_386
#elif defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH_7A__))
#define ELF_ARCH EM_ARM
#elif defined(__aarch64__)
#define ELF_ARCH EM_AARCH64
#endif
#ifndef AT_SYSINFO_EHDR
#define AT_SYSINFO_EHDR 33
#endif
#if (defined(__x86_64__))
struct amd64_regs {
#define BP rbp
#define SP rsp
#define IP rip
uint64_t r15, r14, r13, r12;
uint64_t rbp, rbx, r11, r10;
uint64_t r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
uint64_t rip, cs;
uint64_t eflags;
uint64_t rsp, ss;
uint64_t fs_base, gs_base;
uint64_t ds, es, fs, gs;
};
#define CPURegs amd64_regs
typedef struct Frame {
struct CPURegs uregs;
int errno_;
pid_t tid;
} Frame;
#define FRAME(fm) \
Frame fm; \
do { \
fm.errno_ = errno; \
fm.tid = sys_gettid(); \
__asm__ volatile("push %%rbp\n" \
"push %%rbx\n" \
"mov %%r15,0(%%rax)\n" \
"mov %%r14,8(%%rax)\n" \
"mov %%r12,24(%%rax)\n" \
"mov %%r13,16(%%rax)\n" \
"mov %%rbp,32(%%rax)\n" \
"mov %%rbx,40(%%rax)\n" \
"mov %%r11,48(%%rax)\n" \
"mov %%r9,64(%%rax)\n" \
"mov %%r10,56(%%rax)\n" \
"mov %%r8,72(%%rax)\n" \
"mov %%rax,80(%%rax)\n" \
"mov %%rdx,96(%%rax)\n" \
"mov %%rcx,88(%%rax)\n" \
"mov %%rsi,104(%%rax)\n" \
"mov %%rdi,112(%%rax)\n" \
"mov %%ds,%%rbx\n" \
"mov %%rbx,192(%%rax)\n" \
"mov %%fs,%%rbx\n" \
"mov %%rbx,184(%%rax)\n" \
"mov %%es,%%rbx\n" \
"mov %%rbx,200(%%rax)\n" \
"mov %%gs,%%rbx\n" \
"mov %%rbx,208(%%rax)\n" \
"call 0f\n" \
"0:pop %%rbx\n" \
"add $1f-0b,%%rbx\n" \
"mov %%rbx,0x80(%%rax)\n" \
"mov %%cs,%%rbx\n" \
"mov %%rbx,136(%%rax)\n" \
"pushf\n" \
"pop %%rbx\n" \
"mov %%rbx,0x90(%%rax)\n" \
"mov %%rsp,%%rbx\n" \
"add $16,%%ebx\n" \
"mov %%rbx,0x98(%%rax)\n" \
"mov %%ss,%%rbx\n" \
"mov %%rbx,0xa0(%%rax)\n" \
"pop %%rbx\n" \
"pop %%rbp\n" \
"1:" \
: \
: "a"(&fm) \
: "memory"); \
} while (0)
#define SET_FRAME(f, r) \
do { \
errno = (f).errno_; \
(f).uregs.fs_base = (r).fs_base; \
(f).uregs.gs_base = (r).gs_base; \
(r) = (f).uregs; \
} while (0)
#elif (defined(__i386__))
struct i386_regs {
#define BP ebp
#define SP esp
#define IP eip
uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
uint16_t ds, __ds;
uint16_t es, __es;
uint16_t fs, __fs;
uint16_t gs, __gs;
uint32_t orig_eax, eip;
uint16_t cs, __cs;
uint32_t eflags;
uint32_t esp;
uint16_t ss, __ss;
};
#define CPURegs i386_regs
typedef struct Frame {
struct CPURegs uregs;
int errno_;
pid_t tid;
} Frame;
#define FRAME(fm) \
Frame fm; \
do { \
fm.errno_ = errno; \
fm.tid = sys_gettid(); \
__asm__ volatile("push %%ebp\n" \
"push %%ebx\n" \
"mov %%ebx,0(%%eax)\n" \
"mov %%ecx,4(%%eax)\n" \
"mov %%edx,8(%%eax)\n" \
"mov %%edi,16(%%eax)\n" \
"mov %%esi,12(%%eax)\n" \
"mov %%eax,24(%%eax)\n" \
"mov %%ebp,20(%%eax)\n" \
"mov %%ds,%%ebx\n" \
"mov %%ebx,28(%%eax)\n" \
"mov %%es,%%ebx\n" \
"mov %%ebx,32(%%eax)\n" \
"mov %%gs,%%ebx\n" \
"mov %%ebx, 40(%%eax)\n" \
"mov %%fs,%%ebx\n" \
"mov %%ebx,36(%%eax)\n" \
"call 0f\n" \
"0:pop %%ebx\n" \
"add $1f-0b,%%ebx\n" \
"mov %%ebx,0x30(%%eax)\n" \
"mov %%cs,%%ebx\n" \
"mov %%ebx,0x34(%%eax)\n" \
"pushf\n" \
"pop %%ebx\n" \
"mov %%ebx,0x38(%%eax)\n" \
"mov %%esp,%%ebx\n" \
"add $8,%%ebx\n" \
"mov %%ebx,0x3c(%%eax)\n" \
"mov %%ss,%%ebx\n" \
"mov %%ebx,0x40(%%eax)\n" \
"pop %%ebx\n" \
"pop %%ebp\n" \
"1:" \
: \
: "a"(&fm) \
: "memory"); \
} while (0)
#define SET_FRAME(f, r) \
do { \
errno = (f).errno_; \
(r) = (f).uregs; \
} while (0)
#elif defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH_7A__))
struct arm_regs {
#define BP uregs[11]
#define SP uregs[13]
#define IP uregs[15]
#define LR uregs[14]
long uregs[18];
};
#define CPURegs arm_regs
typedef struct Frame {
struct arm_regs arm;
int errno_;
pid_t tid;
} Frame;
#define FRAME(fm) \
Frame fm; \
do { \
long cpsr; \
fm.errno_ = errno; \
fm.tid = sys_gettid(); \
__asm__ volatile("stmia %0, {r0-r15}\n" \
: \
: "r"(&fm.arm) \
: "memory"); \
fm.arm.uregs[16] = 0; \
__asm__ volatile("mrs %0, cpsr\n" \
: "=r"(cpsr)); \
fm.arm.uregs[17] = cpsr; \
} while (0)
#define SET_FRAME(fm, reg) \
do { \
\
\
\
\
long fps = (fm).arm.uregs[16]; \
errno = (fm).errno_; \
(reg) = (fm).arm; \
(reg).uregs[16] = fps; \
} while (0)
#elif defined(__aarch64__)
#define CPURegs user_pt_regs
typedef struct Frame {
struct user_pt_regs arm;
int errno_;
pid_t tid;
} Frame;
#define FRAME(fm) \
Frame fm; \
label_bbox: \
do { \
__asm__ __volatile__("stp x0, x1, [%0, #16 * 0]\n" \
"stp x2,x3, [%0, #16 * 1]\n" \
"stp x4,x5, [%0, #16 * 2]\n" \
"stp x6,x7, [%0, #16 * 3]\n" \
"stp x8,x9, [%0, #16 * 4]\n" \
"stp x10,x11, [%0, #16 * 5]\n" \
"stp x12,x13, [%0, #16 * 6]\n" \
"stp x14,x15, [%0, #16 * 7]\n" \
"stp x16,x17, [%0, #16 * 8]\n" \
"stp x18,x19, [%0, #16 * 9]\n" \
"stp x20,x21, [%0, #16 * 10]\n" \
"stp x22,x23, [%0, #16 * 11]\n" \
"stp x24,x25, [%0, #16 * 12]\n" \
"stp x26,x27, [%0, #16 * 13]\n" \
"stp x28,x29, [%0, #16 * 14]\n" \
"mov x21, sp\n" \
"stp x30, x21, [%0, #16 * 15]\n" \
: \
: "r"(&fm.arm) \
: "x21", "memory"); \
fm.errno_ = errno; \
fm.tid = sys_gettid(); \
fm.arm.pc = (u64) && label_bbox; \
} while (0)
#define SET_FRAME(fm, reg) \
do { \
\
\
\
\
errno = (fm).errno_; \
(reg) = (fm).arm; \
} while (0)
#else
#define CPURegs
#endif
struct BBOX_ELF_SIGINFO {
int32_t iSigno;
int32_t iCode;
int32_t iErrno;
};
struct BBOX_ELF_PRPSINFO {
unsigned char ucState;
char cSname;
unsigned char ucZomb;
signed char cNice;
unsigned long ulLlag;
#if (defined(__x86_64__)) || (defined(__aarch64__))
uint32_t tUid;
uint32_t tGid;
#else
uint16_t tUid;
uint16_t tGid;
#endif
pid_t tpid;
pid_t tPpid;
pid_t tPgrp;
pid_t tSid;
char cFname[16];
char cPsargs[80];
};
#if defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH_7A__))
struct BBOX_FPXREGSET {
};
struct BBOX_FP_REGSET {
unsigned int _sign1 : 1;
unsigned int _unused : 15;
unsigned int _sign2 : 1;
unsigned int _exponent : 14;
unsigned int _j : 1;
unsigned int _mantissa1 : 31;
unsigned int _mantissa0 : 32;
};
struct BBOX_FPREGSET {
struct BBOX_FP_REGSET _fpregs[8];
unsigned int _fpsr : 32;
unsigned int _fpcr : 32;
unsigned char _ftype[8];
unsigned int _init_flag;
};
#elif defined(__i386__)
struct BBOX_FPREGSET {
uint32_t _cwd;
uint32_t _swd;
uint32_t _twd;
uint32_t _fip;
uint32_t _fcs;
uint32_t _foo;
uint32_t _fos;
uint32_t _st_space[20];
};
struct BBOX_FPXREGSET {
uint16_t _cwd;
uint16_t _swd;
uint16_t _twd;
uint16_t _fop;
uint32_t _fip;
uint32_t _fcs;
uint32_t _foo;
uint32_t _fos;
uint32_t _mxcsr;
uint32_t _mxcsr_mask;
uint32_t _st_space[32];
uint32_t _xmm_space[64];
uint32_t _padding[24];
};
#elif defined(__x86_64__)
struct BBOX_FPXREGSET {
};
struct BBOX_FPREGSET {
uint16_t _cwd;
uint16_t _swd;
uint16_t _twd;
uint16_t _fop;
uint32_t _fip;
uint32_t _fcs;
uint32_t _foo;
uint32_t _fos;
uint32_t _mxcsr;
uint32_t _mxcsr_mask;
uint32_t _st_space[32];
uint32_t _xmm_space[64];
uint32_t _padding[24];
};
#elif defined(__aarch64__)
struct BBOX_FPXREGSET {
};
struct BBOX_FPREGSET {
};
#endif
struct BBOX_ELF_PRPSSTATUS {
struct BBOX_ELF_SIGINFO stSigInfo;
uint16_t tCurSig;
unsigned long ulSigPend;
unsigned long ulSigHold;
pid_t tpid;
pid_t tPpid;
pid_t tPgrp;
pid_t tSid;
struct BBOX_ELF_TIMEVAL stUserTime;
struct BBOX_ELF_TIMEVAL stSystemTime;
struct BBOX_ELF_TIMEVAL stCumulativeUserTime;
struct BBOX_ELF_TIMEVAL stCumulativeSystemTime;
struct CPURegs stRegisters;
uint32_t tFpvalid;
};
struct BBOX_ELF_NOTE {
char* pName;
int iNoteType;
unsigned int uiDataSize;
void* pData;
};
struct BBOX_CORE_USER {
struct CPURegs stRegisters;
unsigned long ulFpvalid;
#if defined(__i386__) || defined(__x86_64__)
struct BBOX_FPREGSET stFpregs;
#endif
unsigned long ulTextSegmentSize;
unsigned long ulDateSegmentSize;
unsigned long ulStackSegmentSize;
unsigned long ulStartCodeAddress;
unsigned long ulStartStackAddress;
unsigned long ulSignal;
unsigned long ulReserved;
struct CPURegs* pstRegs;
#if defined(__i386__) || defined(__x86_64__)
struct BBOX_FPREGSET* pstFpregs;
#endif
unsigned long ulCoreFileMagic;
char acUserCommand[32];
unsigned long ulDebugReg[8];
#if (defined(__i386__) || defined(__x86_64__))
unsigned long ulErrorCode;
unsigned long ulFaultAddress;
#elif defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH_7A__))
struct BBOX_FPREGSET stFpregs;
struct BBOX_FPREGSET* pstFpregs;
#endif
};
struct BBOX_ELF_NOTE_INFO {
pid_t tMainPid;
int iCoreUserFlags;
int iThreadNoteInfoNum;
int iAuxvNoteInfoNum;
int iFpxRegistersFlag;
int iExtraNoteNum;
size_t uiNoteAlign;
struct BBOX_ELF_PRPSINFO stPrpsinfo;
struct BBOX_CORE_USER stCoreUser;
struct BBOX_THREAD_NOTE_INFO* pstThreadNoteInfo;
struct BBOX_EXTRA_NOTE* pstExtraNoteInfo;
};
struct BBOX_THREAD_NOTE_INFO {
struct BBOX_ELF_PRPSSTATUS stPrpsstatus;
struct BBOX_FPREGSET stFpRegisters;
struct BBOX_FPXREGSET stFpxRegisters;
pid_t tPid;
};
struct BBOX_VM_MAPS {
size_t uiStartAddress;
size_t uiEndAddress;
size_t uiOffset;
size_t uiWriteSize;
unsigned int iFlags;
int iIsRemoveFlags;
};
union BBOX_VM_VDSO {
size_t uiVDSOAddress;
BBOX_EHDR* pVDSOEhdr;
};
struct BBOX_WRITE_FDS {
size_t uiMaxLength;
int iWriteFd;
};
typedef struct BBOX_SECTION {
unsigned int uiSectionType;
unsigned int uiSectionNameSize;
unsigned int uiSectionDescSize;
char acSectionName[BBOX_SECTION_NAME_LEN];
char* pacSectionDesc;
} BBOX_SECTION_STRU;
struct BBOX_ELF_SECTION {
unsigned int uiSectionNum;
BBOX_SECTION_STRU* pstSection;
};
extern s32 BBOX_DoDumpElfCore(
BBOX_GetAllThreadDone pDone, void* pDoneHandle, s32 iNumThreads, pid_t* pPids, va_list ap);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif