2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00

coredump: enable coredump generation on arm

Add relevant elf header constants and notes for the arm platform
to enable coredump generation.

Signed-off-by: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
This commit is contained in:
समीर सिंह Sameer Singh 2025-02-17 18:06:10 +05:30 committed by Andrei Vagin
parent da90b33a42
commit 38b9807cd5
4 changed files with 288 additions and 30 deletions

View File

@ -6,7 +6,7 @@ import sys
import criu_coredump import criu_coredump
PLATFORMS = ["aarch64", "x86_64"] PLATFORMS = ["aarch64", "armv7l", "x86_64"]
def coredump(opts): def coredump(opts):

View File

@ -95,8 +95,13 @@ class coredump:
buf.write(b"\0" * (8 - len(note.owner))) buf.write(b"\0" * (8 - len(note.owner)))
buf.write(note.data) buf.write(note.data)
offset = ctypes.sizeof(elf.Elf64_Ehdr()) bits = platform.architecture()[0] # 32 or 64 bits
offset += (len(self.vmas) + 1) * ctypes.sizeof(elf.Elf64_Phdr())
ehdr = {"32bit": elf.Elf32_Ehdr, "64bit": elf.Elf64_Ehdr}
phdr = {"32bit": elf.Elf32_Phdr, "64bit": elf.Elf64_Phdr}
offset = ctypes.sizeof(ehdr[bits]())
offset += (len(self.vmas) + 1) * ctypes.sizeof(phdr[bits]())
filesz = 0 filesz = 0
for note in self.notes: for note in self.notes:
@ -132,9 +137,18 @@ class coredump_generator:
pagemaps = {} # pagemap by pid; pagemaps = {} # pagemap by pid;
# thread info key based on the current arch # thread info key based on the current arch
thread_info_key = {"aarch64": "ti_aarch64", "x86_64": "thread_info"} thread_info_key = {
"aarch64": "ti_aarch64",
"armv7l": "ti_arm",
"x86_64": "thread_info",
}
machine = platform.machine() # current arch machine = platform.machine() # current arch
bits = platform.architecture()[0] # 32 or 64 bits
ehdr = {"32bit": elf.Elf32_Ehdr, "64bit": elf.Elf64_Ehdr} # 32 or 64 bits Ehdr
nhdr = {"32bit": elf.Elf32_Nhdr, "64bit": elf.Elf64_Nhdr} # 32 or 64 bits Nhdr
phdr = {"32bit": elf.Elf32_Phdr, "64bit": elf.Elf64_Phdr} # 32 or 64 bits Phdr
def _img_open_and_strip(self, name, single=False, pid=None): def _img_open_and_strip(self, name, single=False, pid=None):
""" """
@ -207,23 +221,30 @@ class coredump_generator:
""" """
Generate elf header for process pid with program headers phdrs. Generate elf header for process pid with program headers phdrs.
""" """
ehdr = elf.Elf64_Ehdr() ei_class = {"32bit": elf.ELFCLASS32, "64bit": elf.ELFCLASS64}
ehdr = self.ehdr[self.bits]()
ctypes.memset(ctypes.addressof(ehdr), 0, ctypes.sizeof(ehdr)) ctypes.memset(ctypes.addressof(ehdr), 0, ctypes.sizeof(ehdr))
ehdr.e_ident[elf.EI_MAG0] = elf.ELFMAG0 ehdr.e_ident[elf.EI_MAG0] = elf.ELFMAG0
ehdr.e_ident[elf.EI_MAG1] = elf.ELFMAG1 ehdr.e_ident[elf.EI_MAG1] = elf.ELFMAG1
ehdr.e_ident[elf.EI_MAG2] = elf.ELFMAG2 ehdr.e_ident[elf.EI_MAG2] = elf.ELFMAG2
ehdr.e_ident[elf.EI_MAG3] = elf.ELFMAG3 ehdr.e_ident[elf.EI_MAG3] = elf.ELFMAG3
ehdr.e_ident[elf.EI_CLASS] = elf.ELFCLASS64 ehdr.e_ident[elf.EI_CLASS] = ei_class[self.bits]
ehdr.e_ident[elf.EI_DATA] = elf.ELFDATA2LSB ehdr.e_ident[elf.EI_DATA] = elf.ELFDATA2LSB
ehdr.e_ident[elf.EI_VERSION] = elf.EV_CURRENT ehdr.e_ident[elf.EI_VERSION] = elf.EV_CURRENT
if self.machine == "armv7l":
ehdr.e_ident[elf.EI_OSABI] = elf.ELFOSABI_ARM
else:
ehdr.e_ident[elf.EI_OSABI] = elf.ELFOSABI_NONE
ehdr.e_type = elf.ET_CORE ehdr.e_type = elf.ET_CORE
ehdr.e_machine = self._get_e_machine() ehdr.e_machine = self._get_e_machine()
ehdr.e_version = elf.EV_CURRENT ehdr.e_version = elf.EV_CURRENT
ehdr.e_phoff = ctypes.sizeof(elf.Elf64_Ehdr()) ehdr.e_phoff = ctypes.sizeof(self.ehdr[self.bits]())
ehdr.e_ehsize = ctypes.sizeof(elf.Elf64_Ehdr()) ehdr.e_ehsize = ctypes.sizeof(self.ehdr[self.bits]())
ehdr.e_phentsize = ctypes.sizeof(elf.Elf64_Phdr()) ehdr.e_phentsize = ctypes.sizeof(self.phdr[self.bits]())
# FIXME Case len(phdrs) > PN_XNUM should be handled properly. # FIXME Case len(phdrs) > PN_XNUM should be handled properly.
# See fs/binfmt_elf.c from linux kernel. # See fs/binfmt_elf.c from linux kernel.
ehdr.e_phnum = len(phdrs) ehdr.e_phnum = len(phdrs)
@ -234,7 +255,11 @@ class coredump_generator:
""" """
Get the e_machine field based on the current architecture. Get the e_machine field based on the current architecture.
""" """
e_machine_dict = {"aarch64": elf.EM_AARCH64, "x86_64": elf.EM_X86_64} e_machine_dict = {
"aarch64": elf.EM_AARCH64,
"armv7l": elf.EM_ARM,
"x86_64": elf.EM_X86_64,
}
return e_machine_dict[self.machine] return e_machine_dict[self.machine]
def _gen_phdrs(self, pid, notes, vmas): def _gen_phdrs(self, pid, notes, vmas):
@ -243,15 +268,15 @@ class coredump_generator:
""" """
phdrs = [] phdrs = []
offset = ctypes.sizeof(elf.Elf64_Ehdr()) offset = ctypes.sizeof(self.ehdr[self.bits]())
offset += (len(vmas) + 1) * ctypes.sizeof(elf.Elf64_Phdr()) offset += (len(vmas) + 1) * ctypes.sizeof(self.phdr[self.bits]())
filesz = 0 filesz = 0
for note in notes: for note in notes:
filesz += ctypes.sizeof(note.nhdr) + ctypes.sizeof(note.data) + 8 filesz += ctypes.sizeof(note.nhdr) + ctypes.sizeof(note.data) + 8
# PT_NOTE # PT_NOTE
phdr = elf.Elf64_Phdr() phdr = self.phdr[self.bits]()
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr)) ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
phdr.p_type = elf.PT_NOTE phdr.p_type = elf.PT_NOTE
phdr.p_offset = offset phdr.p_offset = offset
@ -271,7 +296,7 @@ class coredump_generator:
for vma in vmas: for vma in vmas:
offset += filesz offset += filesz
filesz = vma.filesz filesz = vma.filesz
phdr = elf.Elf64_Phdr() phdr = self.phdr[self.bits]()
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr)) ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
phdr.p_type = elf.PT_LOAD phdr.p_type = elf.PT_LOAD
phdr.p_align = PAGESIZE phdr.p_align = PAGESIZE
@ -328,7 +353,7 @@ class coredump_generator:
prpsinfo.pr_psargs = self._gen_cmdline(pid)[:80] prpsinfo.pr_psargs = self._gen_cmdline(pid)[:80]
prpsinfo.pr_fname = core["tc"]["comm"].encode() prpsinfo.pr_fname = core["tc"]["comm"].encode()
nhdr = elf.Elf64_Nhdr() nhdr = self.nhdr[self.bits]()
nhdr.n_namesz = 5 nhdr.n_namesz = 5
nhdr.n_descsz = ctypes.sizeof(elf.elf_prpsinfo()) nhdr.n_descsz = ctypes.sizeof(elf.elf_prpsinfo())
nhdr.n_type = elf.NT_PRPSINFO nhdr.n_type = elf.NT_PRPSINFO
@ -360,7 +385,7 @@ class coredump_generator:
self._set_pr_regset(prstatus.pr_reg, regs) self._set_pr_regset(prstatus.pr_reg, regs)
nhdr = elf.Elf64_Nhdr() nhdr = self.nhdr[self.bits]()
nhdr.n_namesz = 5 nhdr.n_namesz = 5
nhdr.n_descsz = ctypes.sizeof(elf.elf_prstatus()) nhdr.n_descsz = ctypes.sizeof(elf.elf_prstatus())
nhdr.n_type = elf.NT_PRSTATUS nhdr.n_type = elf.NT_PRSTATUS
@ -390,6 +415,25 @@ class coredump_generator:
pr_reg.sp = regs["sp"] pr_reg.sp = regs["sp"]
pr_reg.pc = regs["pc"] pr_reg.pc = regs["pc"]
pr_reg.pstate = regs["pstate"] pr_reg.pstate = regs["pstate"]
elif self.machine == "armv7l":
pr_reg.r0 = regs["r0"]
pr_reg.r1 = regs["r1"]
pr_reg.r2 = regs["r2"]
pr_reg.r3 = regs["r3"]
pr_reg.r4 = regs["r4"]
pr_reg.r5 = regs["r5"]
pr_reg.r6 = regs["r6"]
pr_reg.r7 = regs["r7"]
pr_reg.r8 = regs["r8"]
pr_reg.r9 = regs["r9"]
pr_reg.r10 = regs["r10"]
pr_reg.fp = regs["fp"]
pr_reg.ip = regs["ip"]
pr_reg.sp = regs["sp"]
pr_reg.lr = regs["lr"]
pr_reg.pc = regs["pc"]
pr_reg.cpsr = regs["cpsr"]
pr_reg.orig_r0 = regs["orig_r0"]
elif self.machine == "x86_64": elif self.machine == "x86_64":
pr_reg.r15 = regs["r15"] pr_reg.r15 = regs["r15"]
pr_reg.r14 = regs["r14"] pr_reg.r14 = regs["r14"]
@ -495,6 +539,34 @@ class coredump_generator:
return note return note
def _gen_arm_vfp(self, tid):
"""
Generate NT_ARM_VFP note for thread tid of process pid.
"""
core = self.cores[tid]
fpstate = core["ti_arm"]["fpstate"]
data = elf.vfp_hard_struct()
ctypes.memset(ctypes.addressof(data), 0, ctypes.sizeof(data))
data.vfp_regs = (ctypes.c_uint64 * len(fpstate["vfp_regs"]))(*fpstate["vfp_regs"])
data.fpexc = fpstate["fpexc"]
data.fpscr = fpstate["fpscr"]
data.fpinst = fpstate["fpinst"]
data.fpinst2 = fpstate["fpinst2"]
nhdr = elf.Elf32_Nhdr()
nhdr.n_namesz = 6
nhdr.n_descsz = ctypes.sizeof(data)
nhdr.n_type = elf.NT_ARM_VFP
note = elf_note()
note.data = data
note.owner = b"LINUX"
note.nhdr = nhdr
return note
def _gen_x86_xstate(self, pid, tid): def _gen_x86_xstate(self, pid, tid):
""" """
Generate NT_X86_XSTATE note for thread tid of process pid. Generate NT_X86_XSTATE note for thread tid of process pid.
@ -544,7 +616,7 @@ class coredump_generator:
# FIXME zeroify everything for now # FIXME zeroify everything for now
ctypes.memset(ctypes.addressof(siginfo), 0, ctypes.sizeof(siginfo)) ctypes.memset(ctypes.addressof(siginfo), 0, ctypes.sizeof(siginfo))
nhdr = elf.Elf64_Nhdr() nhdr = self.nhdr[self.bits]()
nhdr.n_namesz = 5 nhdr.n_namesz = 5
nhdr.n_descsz = ctypes.sizeof(elf.siginfo_t()) nhdr.n_descsz = ctypes.sizeof(elf.siginfo_t())
nhdr.n_type = elf.NT_SIGINFO nhdr.n_type = elf.NT_SIGINFO
@ -563,17 +635,22 @@ class coredump_generator:
mm = self.mms[pid] mm = self.mms[pid]
num_auxv = len(mm["mm_saved_auxv"]) // 2 num_auxv = len(mm["mm_saved_auxv"]) // 2
class elf_auxv(ctypes.Structure): class elf32_auxv(ctypes.Structure):
_fields_ = [("auxv", elf.Elf32_auxv_t * num_auxv)]
class elf64_auxv(ctypes.Structure):
_fields_ = [("auxv", elf.Elf64_auxv_t * num_auxv)] _fields_ = [("auxv", elf.Elf64_auxv_t * num_auxv)]
auxv = elf_auxv() elf_auxv = {"32bit": elf32_auxv(), "64bit": elf64_auxv()}
auxv = elf_auxv[self.bits]
for i in range(num_auxv): for i in range(num_auxv):
auxv.auxv[i].a_type = mm["mm_saved_auxv"][i] auxv.auxv[i].a_type = mm["mm_saved_auxv"][i]
auxv.auxv[i].a_val = mm["mm_saved_auxv"][i + 1] auxv.auxv[i].a_val = mm["mm_saved_auxv"][i + 1]
nhdr = elf.Elf64_Nhdr() nhdr = self.nhdr[self.bits]()
nhdr.n_namesz = 5 nhdr.n_namesz = 5
nhdr.n_descsz = ctypes.sizeof(elf_auxv()) nhdr.n_descsz = ctypes.sizeof(elf_auxv[self.bits])
nhdr.n_type = elf.NT_AUXV nhdr.n_type = elf.NT_AUXV
note = elf_note() note = elf_note()
@ -650,7 +727,7 @@ class coredump_generator:
setattr(data, "file_ofs" + str(i), info.file_ofs) setattr(data, "file_ofs" + str(i), info.file_ofs)
setattr(data, "name" + str(i), info.name.encode()) setattr(data, "name" + str(i), info.name.encode())
nhdr = elf.Elf64_Nhdr() nhdr = self.nhdr[self.bits]()
nhdr.n_namesz = 5 # strlen + 1 nhdr.n_namesz = 5 # strlen + 1
nhdr.n_descsz = ctypes.sizeof(elf_files()) nhdr.n_descsz = ctypes.sizeof(elf_files())
@ -667,10 +744,13 @@ class coredump_generator:
notes = [] notes = []
notes.append(self._gen_prstatus(pid, tid)) notes.append(self._gen_prstatus(pid, tid))
if self.machine != "armv7l":
notes.append(self._gen_fpregset(pid, tid)) notes.append(self._gen_fpregset(pid, tid))
notes.append(self._gen_siginfo(pid, tid)) notes.append(self._gen_siginfo(pid, tid))
if self.machine == "aarch64": if self.machine == "aarch64":
notes.append(self._gen_arm_tls(tid)) notes.append(self._gen_arm_tls(tid))
elif self.machine == "armv7l":
notes.append(self._gen_arm_vfp(tid))
elif self.machine == "x86_64": elif self.machine == "x86_64":
notes.append(self._gen_x86_xstate(pid, tid)) notes.append(self._gen_x86_xstate(pid, tid))

View File

@ -4,13 +4,19 @@ import platform
MACHINE = platform.machine() MACHINE = platform.machine()
Elf32_Half = ctypes.c_uint16 # typedef uint16_t Elf32_Half;
Elf32_Word = ctypes.c_uint32 # typedef uint32_t Elf32_Word;
Elf32_Addr = ctypes.c_uint32 # typedef uint32_t Elf32_Addr;
Elf32_Off = ctypes.c_uint32 # typedef uint32_t Elf32_Off;
Elf32_Xword = ctypes.c_uint64 # typedef uint64_t Elf32_Xword;
Elf64_Half = ctypes.c_uint16 # typedef uint16_t Elf64_Half; Elf64_Half = ctypes.c_uint16 # typedef uint16_t Elf64_Half;
Elf64_Word = ctypes.c_uint32 # typedef uint32_t Elf64_Word; Elf64_Word = ctypes.c_uint32 # typedef uint32_t Elf64_Word;
Elf64_Addr = ctypes.c_uint64 # typedef uint64_t Elf64_Addr; Elf64_Addr = ctypes.c_uint64 # typedef uint64_t Elf64_Addr;
Elf64_Off = ctypes.c_uint64 # typedef uint64_t Elf64_Off; Elf64_Off = ctypes.c_uint64 # typedef uint64_t Elf64_Off;
Elf64_Xword = ctypes.c_uint64 # typedef uint64_t Elf64_Xword; Elf64_Xword = ctypes.c_uint64 # typedef uint64_t Elf64_Xword;
# Elf64_Ehdr related constants. # Elf_Ehdr related constants.
# e_ident size. # e_ident size.
EI_NIDENT = 16 # #define EI_NIDENT (16) EI_NIDENT = 16 # #define EI_NIDENT (16)
@ -31,22 +37,50 @@ EI_CLASS = 4 # #define EI_CLASS 4 /* File class byte index
EI_DATA = 5 # #define EI_DATA 5 /* Data encoding byte index */ EI_DATA = 5 # #define EI_DATA 5 /* Data encoding byte index */
EI_OSABI = 7 # #define EI_OSABI 7 /* OS ABI identification */
EI_VERSION = 6 # #define EI_VERSION 6 /* File version byte index */ EI_VERSION = 6 # #define EI_VERSION 6 /* File version byte index */
ELFDATA2LSB = 1 # #define ELFDATA2LSB 1 /* 2's complement, little endian */ ELFDATA2LSB = 1 # #define ELFDATA2LSB 1 /* 2's complement, little endian */
ELFCLASS32 = 1 # #define ELFCLASS32 1 /* 32-bit objects */
ELFCLASS64 = 2 # #define ELFCLASS64 2 /* 64-bit objects */ ELFCLASS64 = 2 # #define ELFCLASS64 2 /* 64-bit objects */
# Legal values for e_type (object file type). # Legal values for e_type (object file type).
ET_CORE = 4 # #define ET_CORE 4 /* Core file */ ET_CORE = 4 # #define ET_CORE 4 /* Core file */
# Legal values for e_machine (architecture). # Legal values for e_machine (architecture).
EM_ARM = 40 # #define EM_ARM 40 /* ARM */
EM_X86_64 = 62 # #define EM_X86_64 62 /* AMD x86-64 architecture */ EM_X86_64 = 62 # #define EM_X86_64 62 /* AMD x86-64 architecture */
EM_AARCH64 = 183 # #define EM_AARCH64 183 /* ARM AARCH64 */ EM_AARCH64 = 183 # #define EM_AARCH64 183 /* ARM AARCH64 */
# Legal values for e_version (version). # Legal values for e_version (version).
EV_CURRENT = 1 # #define EV_CURRENT 1 /* Current version */ EV_CURRENT = 1 # #define EV_CURRENT 1 /* Current version */
# Legal values for e_osabi
ELFOSABI_NONE = 0 # #define ELFOSABI_NONE 0 /* UNIX System V ABI */
ELFOSABI_ARM = 97 # #define ELFOSABI_ARM 97 /* ARM */
class Elf32_Ehdr(ctypes.Structure): # typedef struct
_fields_ = [
("e_ident",
ctypes.c_ubyte * EI_NIDENT), # unsigned char e_ident[EI_NIDENT];
("e_type", Elf32_Half), # Elf32_Half e_type;
("e_machine", Elf32_Half), # Elf32_Half e_machine;
("e_version", Elf32_Word), # Elf32_Word e_version;
("e_entry", Elf32_Addr), # Elf32_Addr e_entry;
("e_phoff", Elf32_Off), # Elf32_Off e_phoff;
("e_shoff", Elf32_Off), # Elf32_Off e_shoff;
("e_flags", Elf32_Word), # Elf32_Word e_flags;
("e_ehsize", Elf32_Half), # Elf32_Half e_ehsize;
("e_phentsize", Elf32_Half), # Elf32_Half e_phentsize;
("e_phnum", Elf32_Half), # Elf32_Half e_phnum;
("e_shentsize", Elf32_Half), # Elf32_Half e_shentsize;
("e_shnum", Elf32_Half), # Elf32_Half e_shnum;
("e_shstrndx", Elf32_Half) # Elf32_Half e_shstrndx;
] # } Elf32_Ehdr;
class Elf64_Ehdr(ctypes.Structure): # typedef struct class Elf64_Ehdr(ctypes.Structure): # typedef struct
_fields_ = [ _fields_ = [
@ -68,7 +102,7 @@ class Elf64_Ehdr(ctypes.Structure): # typedef struct
] # } Elf64_Ehdr; ] # } Elf64_Ehdr;
# Elf64_Phdr related constants. # Elf_Phdr related constants.
# Legal values for p_type (segment type). # Legal values for p_type (segment type).
PT_LOAD = 1 # #define PT_LOAD 1 /* Loadable program segment */ PT_LOAD = 1 # #define PT_LOAD 1 /* Loadable program segment */
@ -80,6 +114,19 @@ PF_W = 1 << 1 # #define PF_W (1 << 1) /* Segment is writable
PF_R = 1 << 2 # #define PF_R (1 << 2) /* Segment is readable */ PF_R = 1 << 2 # #define PF_R (1 << 2) /* Segment is readable */
class Elf32_Phdr(ctypes.Structure): # typedef struct
_fields_ = [
("p_type", Elf32_Word), # Elf32_Word p_type;
("p_offset", Elf32_Off), # Elf32_Off p_offset;
("p_vaddr", Elf32_Addr), # Elf32_Addr p_vaddr;
("p_paddr", Elf32_Addr), # Elf32_Addr p_paddr;
("p_filesz", Elf32_Word), # Elf32_Word p_filesz;
("p_memsz", Elf32_Word), # Elf32_Word p_memsz;
("p_flags", Elf32_Word), # Elf32_Word p_flags;
("p_align", Elf32_Word), # Elf32_Word p_align;
] # } Elf32_Phdr;
class Elf64_Phdr(ctypes.Structure): # typedef struct class Elf64_Phdr(ctypes.Structure): # typedef struct
_fields_ = [ _fields_ = [
("p_type", Elf64_Word), # Elf64_Word p_type; ("p_type", Elf64_Word), # Elf64_Word p_type;
@ -93,7 +140,25 @@ class Elf64_Phdr(ctypes.Structure): # typedef struct
] # } Elf64_Phdr; ] # } Elf64_Phdr;
# Elf64_auxv_t related constants. # Elf_auxv_t related constants.
class _Elf32_auxv_t_U(ctypes.Union):
_fields_ = [("a_val", ctypes.c_uint32)]
class Elf32_auxv_t(ctypes.Structure): # typedef struct
_fields_ = [
("a_type",
ctypes.c_uint32), # uint32_t a_type; /* Entry type */
("a_un", _Elf32_auxv_t_U) # union
# uint32_t a_val; /* Integer value */
# /* We use to have pointer elements added here. We cannot do that,
# though, since it does not work when using 32-bit definitions
# on 64-bit platforms and vice versa. */
# } a_un;
] # } Elf32_auxv_t;
class _Elf64_auxv_t_U(ctypes.Union): class _Elf64_auxv_t_U(ctypes.Union):
@ -114,7 +179,7 @@ class Elf64_auxv_t(ctypes.Structure): # typedef struct
] # } Elf64_auxv_t; ] # } Elf64_auxv_t;
# Elf64_Nhdr related constants. # Elf_Nhdr related constants.
NT_PRSTATUS = 1 # #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ NT_PRSTATUS = 1 # #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
NT_FPREGSET = 2 # #define NT_FPREGSET 2 /* Contains copy of fpregset struct */ NT_FPREGSET = 2 # #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
@ -123,9 +188,24 @@ NT_AUXV = 6 # #define NT_AUXV 6 /* Contains copy of auxv array */
NT_SIGINFO = 0x53494749 # #define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, size might increase */ NT_SIGINFO = 0x53494749 # #define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, size might increase */
NT_FILE = 0x46494c45 # #define NT_FILE 0x46494c45 /* Contains information about mapped files */ NT_FILE = 0x46494c45 # #define NT_FILE 0x46494c45 /* Contains information about mapped files */
NT_X86_XSTATE = 0x202 # #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ NT_X86_XSTATE = 0x202 # #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
NT_ARM_VFP = 0x400 # #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
NT_ARM_TLS = 0x401 # #define NT_ARM_TLS 0x401 /* ARM TLS register */ NT_ARM_TLS = 0x401 # #define NT_ARM_TLS 0x401 /* ARM TLS register */
class Elf32_Nhdr(ctypes.Structure): # typedef struct
_fields_ = [
(
"n_namesz", Elf32_Word
), # Elf32_Word n_namesz; /* Length of the note's name. */
(
"n_descsz", Elf32_Word
), # Elf32_Word n_descsz; /* Length of the note's descriptor. */
(
"n_type", Elf32_Word
), # Elf32_Word n_type; /* Type of the note. */
] # } Elf32_Nhdr;
class Elf64_Nhdr(ctypes.Structure): # typedef struct class Elf64_Nhdr(ctypes.Structure): # typedef struct
_fields_ = [ _fields_ = [
( (
@ -139,7 +219,52 @@ class Elf64_Nhdr(ctypes.Structure): # typedef struct
] # } Elf64_Nhdr; ] # } Elf64_Nhdr;
# Elf64_Shdr related constants. # Elf_Shdr related constants.
class Elf32_Shdr(ctypes.Structure):
_fields_ = [
(
# Section name (string tbl index)
"sh_name", Elf32_Word
),
(
# Section type
"sh_type", Elf32_Word
),
(
# Section flags
"sh_flags", Elf32_Word
),
(
# Section virtual addr at execution
"sh_addr", Elf32_Addr
),
(
# Section file offset
"sh_offset", Elf32_Off
),
(
# Section size in bytes
"sh_size", Elf32_Word
),
(
# Link to another section
"sh_link", Elf32_Word
),
(
# Additional section information
"sh_info", Elf32_Word
),
(
# Section alignment
"sh_addralign", Elf32_Word
),
(
# Entry size if section holds table
"sh_entsize", Elf32_Word
)
]
class Elf64_Shdr(ctypes.Structure): class Elf64_Shdr(ctypes.Structure):
@ -295,11 +420,53 @@ class aarch64_user_regs_struct(ctypes.Structure): # struct aarch64_user_regs_st
] ]
class arm_user_regs_struct(ctypes.Structure): # struct arm_user_regs_struct
_fields_ = [
("r0",
ctypes.c_ulong), # unsigned ulong int r0;
("r1",
ctypes.c_ulong), # unsigned ulong int r1;
("r2",
ctypes.c_ulong), # unsigned ulong int r2;
("r3",
ctypes.c_ulong), # unsigned ulong int r3;
("r4",
ctypes.c_ulong), # unsigned ulong int r4;
("r5",
ctypes.c_ulong), # unsigned ulong int r5;
("r6",
ctypes.c_ulong), # unsigned ulong int r6;
("r7",
ctypes.c_ulong), # unsigned ulong int r7;
("r8",
ctypes.c_ulong), # unsigned ulong int r8;
("r9",
ctypes.c_ulong), # unsigned ulong int r9;
("r10",
ctypes.c_ulong), # unsigned ulong int r10;
("fp",
ctypes.c_ulong), # unsigned ulong int fp;
("ip",
ctypes.c_ulong), # unsigned ulong int ip;
("sp",
ctypes.c_ulong), # unsigned ulong int sp;
("lr",
ctypes.c_ulong), # unsigned ulong int lr;
("pc",
ctypes.c_ulong), # unsigned ulong int pc;
("cpsr",
ctypes.c_ulong), # unsigned ulong int cpsr;
("orig_r0",
ctypes.c_ulong), # unsigned ulong int orig_r0;
]
# elf_greg_t = ctypes.c_ulonglong # elf_greg_t = ctypes.c_ulonglong
# ELF_NGREG = ctypes.sizeof(user_regs_struct)/ctypes.sizeof(elf_greg_t) # ELF_NGREG = ctypes.sizeof(user_regs_struct)/ctypes.sizeof(elf_greg_t)
# elf_gregset_t = elf_greg_t*ELF_NGREG # elf_gregset_t = elf_greg_t*ELF_NGREG
user_regs_dict = { user_regs_dict = {
"aarch64": aarch64_user_regs_struct, "aarch64": aarch64_user_regs_struct,
"armv7l": arm_user_regs_struct,
"x86_64": x86_64_user_regs_struct, "x86_64": x86_64_user_regs_struct,
} }
@ -488,6 +655,7 @@ class aarch64_user_fpregs_struct(ctypes.Structure): # struct aarch64_user_fpreg
user_fpregs_dict = { user_fpregs_dict = {
"aarch64": aarch64_user_fpregs_struct, "aarch64": aarch64_user_fpregs_struct,
"armv7l": None,
"x86_64": x86_64_user_fpregs_struct, "x86_64": x86_64_user_fpregs_struct,
} }
@ -889,3 +1057,13 @@ class elf_xsave_struct(ctypes.Structure): # struct xsave_struct {
# struct ymmh_struct ymmh; # struct ymmh_struct ymmh;
("ymmh", ymmh_struct) ("ymmh", ymmh_struct)
] # } __aligned(FP_MIN_ALIGN_BYTES) __packed; ] # } __aligned(FP_MIN_ALIGN_BYTES) __packed;
class vfp_hard_struct(ctypes.Structure): # struct vfp_hard_struct {
_fields_ = [
("vfp_regs", ctypes.c_ulonglong * 32), # __u64 fpregs[32];
("fpexc", ctypes.c_ulong), # __u32 fpexc;
("fpscr", ctypes.c_ulong), # __u32 fpscr;
("fpinst", ctypes.c_ulong), # __u32 fpinst;
("fpinst2", ctypes.c_ulong), # __u32 fpinst2;
] # };

View File

@ -45,8 +45,8 @@ function run_test {
UNAME_M=$(uname -m) UNAME_M=$(uname -m)
if [[ "$UNAME_M" != "aarch64" && "$UNAME_M" != "x86_64" ]]; then if [[ "$UNAME_M" != "aarch64" && "$UNAME_M" != "armv7l" &&"$UNAME_M" != "x86_64" ]]; then
echo "criu-coredump only supports aarch64 and x86_64. skipping." echo "criu-coredump only supports aarch64 armv7l, and x86_64. skipping."
exit 0 exit 0
fi fi