mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
coredump: Rename dir to coredump
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
parent
308741d059
commit
92486c9015
6 changed files with 0 additions and 0 deletions
40
coredump/criu-coredump
Executable file
40
coredump/criu-coredump
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env python
|
||||
import argparse
|
||||
import os
|
||||
|
||||
import criu_coredump
|
||||
|
||||
def coredump(opts):
|
||||
generator = criu_coredump.coredump_generator()
|
||||
cores = generator(os.path.realpath(opts['in']))
|
||||
for pid in cores:
|
||||
if opts['pid'] and pid != opts['pid']:
|
||||
continue
|
||||
with open(os.path.realpath(opts['out'])+"/core."+str(pid), 'w+') as f:
|
||||
cores[pid].write(f)
|
||||
|
||||
|
||||
def main():
|
||||
desc = 'CRIU core dump'
|
||||
parser = argparse.ArgumentParser(description=desc,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
|
||||
parser.add_argument('-i',
|
||||
'--in',
|
||||
default = '.',
|
||||
help = 'directory where to get images from')
|
||||
parser.add_argument('-p',
|
||||
'--pid',
|
||||
type = int,
|
||||
help = 'generate coredump for specific pid(all pids py default)')
|
||||
parser.add_argument('-o',
|
||||
'--out',
|
||||
default = '.',
|
||||
help = 'directory to write coredumps to')
|
||||
|
||||
opts = vars(parser.parse_args())
|
||||
|
||||
coredump(opts)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
1
coredump/criu_coredump/.gitignore
vendored
Normal file
1
coredump/criu_coredump/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.pyc
|
||||
2
coredump/criu_coredump/__init__.py
Normal file
2
coredump/criu_coredump/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from coredump import *
|
||||
import elf
|
||||
829
coredump/criu_coredump/coredump.py
Normal file
829
coredump/criu_coredump/coredump.py
Normal file
|
|
@ -0,0 +1,829 @@
|
|||
# Functions and classes for creating core dump from criu images.
|
||||
# Code is inspired by outdated google coredumper(RIP) [1] and
|
||||
# fs/binfmt_elf.h from Linux kernel [2].
|
||||
#
|
||||
# [1] https://code.google.com/p/google-coredumper/
|
||||
# probably already dead, so consider trying:
|
||||
# https://github.com/efiop/google-coredumper/
|
||||
# [2] https://www.kernel.org/
|
||||
#
|
||||
# On my x86_64 systems with fresh kernel ~3.17 core dump looks like:
|
||||
#
|
||||
# 1) Elf file header;
|
||||
# 2) PT_NOTE program header describing notes section;
|
||||
# 3) PT_LOAD program headers for (almost?) each vma;
|
||||
# 4) NT_PRPSINFO note with elf_prpsinfo inside;
|
||||
# 5) An array of notes for each thread of the process:
|
||||
# NT_PRSTATUS note with elf_prstatus inside;
|
||||
# NT_FPREGSET note with elf_fpregset inside;
|
||||
# NT_X86_XSTATE note with x86 extended state using xsave;
|
||||
# NT_SIGINFO note with siginfo_t inside;
|
||||
# 6) NT_AUXV note with auxv;
|
||||
# 7) NT_FILE note with mapped files;
|
||||
# 8) VMAs themselves;
|
||||
#
|
||||
# Or, you can represent it in less details as:
|
||||
# 1) Elf file header;
|
||||
# 2) Program table;
|
||||
# 3) Notes;
|
||||
# 4) VMAs contents;
|
||||
#
|
||||
import io
|
||||
import elf
|
||||
import ctypes
|
||||
from pycriu import images
|
||||
|
||||
# Some memory-related constants
|
||||
PAGESIZE = 4096
|
||||
status = {
|
||||
"VMA_AREA_NONE" : 0 << 0,
|
||||
"VMA_AREA_REGULAR" : 1 << 0,
|
||||
"VMA_AREA_STACK" : 1 << 1,
|
||||
"VMA_AREA_VSYSCALL" : 1 << 2,
|
||||
"VMA_AREA_VDSO" : 1 << 3,
|
||||
"VMA_FORCE_READ" : 1 << 4,
|
||||
"VMA_AREA_HEAP" : 1 << 5,
|
||||
"VMA_FILE_PRIVATE" : 1 << 6,
|
||||
"VMA_FILE_SHARED" : 1 << 7,
|
||||
"VMA_ANON_SHARED" : 1 << 8,
|
||||
"VMA_ANON_PRIVATE" : 1 << 9,
|
||||
"VMA_AREA_SYSVIPC" : 1 << 10,
|
||||
"VMA_AREA_SOCKET" : 1 << 11,
|
||||
"VMA_AREA_VVAR" : 1 << 12,
|
||||
"VMA_AREA_AIORING" : 1 << 13,
|
||||
"VMA_AREA_UNSUPP" : 1 << 31
|
||||
}
|
||||
|
||||
prot = {
|
||||
"PROT_READ" : 0x1,
|
||||
"PROT_WRITE" : 0x2,
|
||||
"PROT_EXEC" : 0x4
|
||||
}
|
||||
|
||||
class elf_note:
|
||||
nhdr = None # Elf_Nhdr;
|
||||
owner = None # i.e. CORE or LINUX;
|
||||
data = None # Ctypes structure with note data;
|
||||
|
||||
|
||||
class coredump:
|
||||
"""
|
||||
A class to keep elf core dump components inside and
|
||||
functions to properly write them to file.
|
||||
"""
|
||||
ehdr = None # Elf ehdr;
|
||||
phdrs = [] # Array of Phdrs;
|
||||
notes = [] # Array of elf_notes;
|
||||
vmas = [] # Array of BytesIO with memory content;
|
||||
# FIXME keeping all vmas in memory is a bad idea;
|
||||
|
||||
def write(self, f):
|
||||
"""
|
||||
Write core dump to file f.
|
||||
"""
|
||||
buf = io.BytesIO()
|
||||
buf.write(self.ehdr)
|
||||
|
||||
for phdr in self.phdrs:
|
||||
buf.write(phdr)
|
||||
|
||||
for note in self.notes:
|
||||
buf.write(note.nhdr)
|
||||
buf.write(note.owner)
|
||||
buf.write("\0"*(8-len(note.owner)))
|
||||
buf.write(note.data)
|
||||
|
||||
offset = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
offset += (len(self.vmas) + 1)*ctypes.sizeof(elf.Elf64_Phdr())
|
||||
|
||||
filesz = 0
|
||||
for note in self.notes:
|
||||
filesz += ctypes.sizeof(note.nhdr) + ctypes.sizeof(note.data) + 8
|
||||
|
||||
note_align = PAGESIZE - ((offset + filesz) % PAGESIZE)
|
||||
|
||||
if note_align == PAGESIZE:
|
||||
note_align = 0
|
||||
|
||||
if note_align != 0:
|
||||
scratch = (ctypes.c_char * note_align)()
|
||||
ctypes.memset(ctypes.addressof(scratch), 0, ctypes.sizeof(scratch))
|
||||
buf.write(scratch)
|
||||
|
||||
for vma in self.vmas:
|
||||
buf.write(vma.data)
|
||||
|
||||
buf.seek(0)
|
||||
f.write(buf.read())
|
||||
|
||||
|
||||
class coredump_generator:
|
||||
"""
|
||||
Generate core dump from criu images.
|
||||
"""
|
||||
coredumps = {} # coredumps by pid;
|
||||
|
||||
pstree = {} # process info by pid;
|
||||
cores = {} # cores by pid;
|
||||
mms = {} # mm by pid;
|
||||
reg_files = None # reg-files;
|
||||
pagemaps = {} # pagemap by pid;
|
||||
|
||||
def _img_open_and_strip(self, name, single = False, pid = None):
|
||||
"""
|
||||
Load criu image and strip it from magic and redundant list.
|
||||
"""
|
||||
path = self._imgs_dir + "/" + name
|
||||
if pid:
|
||||
path += "-"+str(pid)
|
||||
path += ".img"
|
||||
|
||||
with open(path) as f:
|
||||
img = images.load(f)
|
||||
|
||||
if single:
|
||||
return img["entries"][0]
|
||||
else:
|
||||
return img["entries"]
|
||||
|
||||
|
||||
def __call__(self, imgs_dir):
|
||||
"""
|
||||
Parse criu images stored in directory imgs_dir to fill core dumps.
|
||||
"""
|
||||
self._imgs_dir = imgs_dir
|
||||
pstree = self._img_open_and_strip("pstree")
|
||||
|
||||
for p in pstree:
|
||||
pid = p['pid']
|
||||
|
||||
self.pstree[pid] = p
|
||||
for tid in p['threads']:
|
||||
self.cores[tid] = self._img_open_and_strip("core", True, tid)
|
||||
self.mms[pid] = self._img_open_and_strip("mm", True, pid)
|
||||
self.pagemaps[pid] = self._img_open_and_strip("pagemap", False, pid)
|
||||
|
||||
self.reg_files = self._img_open_and_strip("reg-files", False)
|
||||
|
||||
for pid in self.pstree:
|
||||
self.coredumps[pid] = self._gen_coredump(pid)
|
||||
|
||||
return self.coredumps
|
||||
|
||||
|
||||
def write(self, coredumps_dir, pid = None):
|
||||
"""
|
||||
Write core dumpt to cores_dir directory. Specify pid to choose
|
||||
core dump of only one process.
|
||||
"""
|
||||
for p in self.coredumps:
|
||||
if pid and p != pid:
|
||||
continue
|
||||
with open(coredumps_dir+"/"+"core."+str(p), 'w+') as f:
|
||||
self.coredumps[p].write(f)
|
||||
|
||||
def _gen_coredump(self, pid):
|
||||
"""
|
||||
Generate core dump for pid.
|
||||
"""
|
||||
cd = coredump()
|
||||
|
||||
# Generate everything backwards so it is easier to calculate offset.
|
||||
cd.vmas = self._gen_vmas(pid)
|
||||
cd.notes = self._gen_notes(pid)
|
||||
cd.phdrs = self._gen_phdrs(pid, cd.notes, cd.vmas)
|
||||
cd.ehdr = self._gen_ehdr(pid, cd.phdrs)
|
||||
|
||||
return cd
|
||||
|
||||
def _gen_ehdr(self, pid, phdrs):
|
||||
"""
|
||||
Generate elf header for process pid with program headers phdrs.
|
||||
"""
|
||||
ehdr = elf.Elf64_Ehdr()
|
||||
|
||||
ctypes.memset(ctypes.addressof(ehdr), 0, ctypes.sizeof(ehdr))
|
||||
ehdr.e_ident[elf.EI_MAG0] = elf.ELFMAG0
|
||||
ehdr.e_ident[elf.EI_MAG1] = elf.ELFMAG1
|
||||
ehdr.e_ident[elf.EI_MAG2] = elf.ELFMAG2
|
||||
ehdr.e_ident[elf.EI_MAG3] = elf.ELFMAG3
|
||||
ehdr.e_ident[elf.EI_CLASS] = elf.ELFCLASS64
|
||||
ehdr.e_ident[elf.EI_DATA] = elf.ELFDATA2LSB
|
||||
ehdr.e_ident[elf.EI_VERSION] = elf.EV_CURRENT
|
||||
|
||||
ehdr.e_type = elf.ET_CORE
|
||||
ehdr.e_machine = elf.EM_X86_64
|
||||
ehdr.e_version = elf.EV_CURRENT
|
||||
ehdr.e_phoff = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
ehdr.e_ehsize = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
ehdr.e_phentsize = ctypes.sizeof(elf.Elf64_Phdr())
|
||||
#FIXME Case len(phdrs) > PN_XNUM should be handled properly.
|
||||
# See fs/binfmt_elf.c from linux kernel.
|
||||
ehdr.e_phnum = len(phdrs)
|
||||
|
||||
return ehdr
|
||||
|
||||
def _gen_phdrs(self, pid, notes, vmas):
|
||||
"""
|
||||
Generate program headers for process pid.
|
||||
"""
|
||||
phdrs = []
|
||||
|
||||
offset = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
offset += (len(vmas) + 1)*ctypes.sizeof(elf.Elf64_Phdr())
|
||||
|
||||
filesz = 0
|
||||
for note in notes:
|
||||
filesz += ctypes.sizeof(note.nhdr) + ctypes.sizeof(note.data) + 8
|
||||
|
||||
# PT_NOTE
|
||||
phdr = elf.Elf64_Phdr()
|
||||
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
|
||||
phdr.p_type = elf.PT_NOTE
|
||||
phdr.p_offset = offset
|
||||
phdr.p_filesz = filesz
|
||||
|
||||
phdrs.append(phdr)
|
||||
|
||||
note_align = PAGESIZE - ((offset + filesz) % PAGESIZE)
|
||||
|
||||
if note_align == PAGESIZE:
|
||||
note_align = 0
|
||||
|
||||
offset += note_align
|
||||
|
||||
# VMA phdrs
|
||||
|
||||
for vma in vmas:
|
||||
offset += filesz
|
||||
filesz = vma.filesz
|
||||
phdr = elf.Elf64_Phdr()
|
||||
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
|
||||
phdr.p_type = elf.PT_LOAD
|
||||
phdr.p_align = PAGESIZE
|
||||
phdr.p_paddr = 0
|
||||
phdr.p_offset = offset
|
||||
phdr.p_vaddr = vma.start
|
||||
phdr.p_memsz = vma.memsz
|
||||
phdr.p_filesz = vma.filesz
|
||||
phdr.p_flags = vma.flags
|
||||
|
||||
phdrs.append(phdr)
|
||||
|
||||
return phdrs
|
||||
|
||||
def _gen_prpsinfo(self, pid):
|
||||
"""
|
||||
Generate NT_PRPSINFO note for process pid.
|
||||
"""
|
||||
pstree = self.pstree[pid]
|
||||
core = self.cores[pid]
|
||||
|
||||
prpsinfo = elf.elf_prpsinfo()
|
||||
ctypes.memset(ctypes.addressof(prpsinfo), 0, ctypes.sizeof(prpsinfo))
|
||||
|
||||
# FIXME TASK_ALIVE means that it is either running or sleeping, need to
|
||||
# teach criu to distinguish them.
|
||||
TASK_ALIVE = 0x1
|
||||
# XXX A bit of confusion here, as in ps "dead" and "zombie"
|
||||
# state are two separate states, and we use TASK_DEAD for zombies.
|
||||
TASK_DEAD = 0x2
|
||||
TASK_STOPPED = 0x3
|
||||
if core["tc"]["task_state"] == TASK_ALIVE:
|
||||
prpsinfo.pr_state = 0
|
||||
if core["tc"]["task_state"] == TASK_DEAD:
|
||||
prpsinfo.pr_state = 4
|
||||
if core["tc"]["task_state"] == TASK_STOPPED:
|
||||
prpsinfo.pr_state = 3
|
||||
# Don't even ask me why it is so, just borrowed from linux
|
||||
# source and made pr_state match.
|
||||
prpsinfo.pr_sname = '.' if prpsinfo.pr_state > 5 else "RSDTZW"[prpsinfo.pr_state]
|
||||
prpsinfo.pr_zomb = 1 if prpsinfo.pr_state == 4 else 0
|
||||
prpsinfo.pr_nice = core["thread_core"]["sched_prio"] if "sched_prio" in core["thread_core"] else 0
|
||||
prpsinfo.pr_flag = core["tc"]["flags"]
|
||||
prpsinfo.pr_uid = core["thread_core"]["creds"]["uid"]
|
||||
prpsinfo.pr_gid = core["thread_core"]["creds"]["gid"]
|
||||
prpsinfo.pr_pid = pid
|
||||
prpsinfo.pr_ppid = pstree["ppid"]
|
||||
prpsinfo.pr_pgrp = pstree["pgid"]
|
||||
prpsinfo.pr_sid = pstree["sid"]
|
||||
prpsinfo.pr_fname = core["tc"]["comm"]
|
||||
prpsinfo.pr_psargs = self._gen_cmdline(pid)
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.elf_prpsinfo())
|
||||
nhdr.n_type = elf.NT_PRPSINFO
|
||||
|
||||
note = elf_note()
|
||||
note.data = prpsinfo
|
||||
note.owner = "CORE"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_prstatus(self, pid, tid):
|
||||
"""
|
||||
Generate NT_PRSTATUS note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
regs = core["thread_info"]["gpregs"]
|
||||
pstree = self.pstree[pid]
|
||||
|
||||
prstatus = elf.elf_prstatus()
|
||||
|
||||
ctypes.memset(ctypes.addressof(prstatus), 0, ctypes.sizeof(prstatus))
|
||||
|
||||
#FIXME setting only some of the fields for now. Revisit later.
|
||||
prstatus.pr_pid = tid
|
||||
prstatus.pr_ppid = pstree["ppid"]
|
||||
prstatus.pr_pgrp = pstree["pgid"]
|
||||
prstatus.pr_sid = pstree["sid"]
|
||||
|
||||
prstatus.pr_reg.r15 = regs["r15"]
|
||||
prstatus.pr_reg.r14 = regs["r14"]
|
||||
prstatus.pr_reg.r13 = regs["r13"]
|
||||
prstatus.pr_reg.r12 = regs["r12"]
|
||||
prstatus.pr_reg.rbp = regs["bp"]
|
||||
prstatus.pr_reg.rbx = regs["bx"]
|
||||
prstatus.pr_reg.r11 = regs["r11"]
|
||||
prstatus.pr_reg.r10 = regs["r10"]
|
||||
prstatus.pr_reg.r9 = regs["r9"]
|
||||
prstatus.pr_reg.r8 = regs["r8"]
|
||||
prstatus.pr_reg.rax = regs["ax"]
|
||||
prstatus.pr_reg.rcx = regs["cx"]
|
||||
prstatus.pr_reg.rdx = regs["dx"]
|
||||
prstatus.pr_reg.rsi = regs["si"]
|
||||
prstatus.pr_reg.rdi = regs["di"]
|
||||
prstatus.pr_reg.orig_rax = regs["orig_ax"]
|
||||
prstatus.pr_reg.rip = regs["ip"]
|
||||
prstatus.pr_reg.cs = regs["cs"]
|
||||
prstatus.pr_reg.eflags = regs["flags"]
|
||||
prstatus.pr_reg.rsp = regs["sp"]
|
||||
prstatus.pr_reg.ss = regs["ss"]
|
||||
prstatus.pr_reg.fs_base = regs["fs_base"]
|
||||
prstatus.pr_reg.gs_base = regs["gs_base"]
|
||||
prstatus.pr_reg.ds = regs["ds"]
|
||||
prstatus.pr_reg.es = regs["es"]
|
||||
prstatus.pr_reg.fs = regs["fs"]
|
||||
prstatus.pr_reg.gs = regs["gs"]
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.elf_prstatus())
|
||||
nhdr.n_type = elf.NT_PRSTATUS
|
||||
|
||||
note = elf_note()
|
||||
note.data = prstatus
|
||||
note.owner = "CORE"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_fpregset(self, pid, tid):
|
||||
"""
|
||||
Generate NT_FPREGSET note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
regs = core["thread_info"]["fpregs"]
|
||||
|
||||
fpregset = elf.elf_fpregset_t()
|
||||
ctypes.memset(ctypes.addressof(fpregset), 0, ctypes.sizeof(fpregset))
|
||||
|
||||
fpregset.cwd = regs["cwd"]
|
||||
fpregset.swd = regs["swd"]
|
||||
fpregset.ftw = regs["twd"]
|
||||
fpregset.fop = regs["fop"]
|
||||
fpregset.rip = regs["rip"]
|
||||
fpregset.rdp = regs["rdp"]
|
||||
fpregset.mxcsr = regs["mxcsr"]
|
||||
fpregset.mxcr_mask = regs["mxcsr_mask"]
|
||||
fpregset.st_space = (ctypes.c_uint * len(regs["st_space"]))(*regs["st_space"])
|
||||
fpregset.xmm_space = (ctypes.c_uint * len(regs["xmm_space"]))(*regs["xmm_space"])
|
||||
#fpregset.padding = regs["padding"] unused
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.elf_fpregset_t())
|
||||
nhdr.n_type = elf.NT_FPREGSET
|
||||
|
||||
note = elf_note()
|
||||
note.data = fpregset
|
||||
note.owner = "CORE"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_x86_xstate(self, pid, tid):
|
||||
"""
|
||||
Generate NT_X86_XSTATE note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
fpregs = core["thread_info"]["fpregs"]
|
||||
|
||||
data = elf.elf_xsave_struct()
|
||||
ctypes.memset(ctypes.addressof(data), 0, ctypes.sizeof(data))
|
||||
|
||||
data.i387.cwd = fpregs["cwd"]
|
||||
data.i387.swd = fpregs["swd"]
|
||||
data.i387.twd = fpregs["twd"]
|
||||
data.i387.fop = fpregs["fop"]
|
||||
data.i387.rip = fpregs["rip"]
|
||||
data.i387.rdp = fpregs["rdp"]
|
||||
data.i387.mxcsr = fpregs["mxcsr"]
|
||||
data.i387.mxcsr_mask = fpregs["mxcsr_mask"]
|
||||
data.i387.st_space = (ctypes.c_uint * len(fpregs["st_space"]))(*fpregs["st_space"])
|
||||
data.i387.xmm_space = (ctypes.c_uint * len(fpregs["xmm_space"]))(*fpregs["xmm_space"])
|
||||
|
||||
if "xsave" in fpregs:
|
||||
data.xsave_hdr.xstate_bv = fpregs["xsave"]["xstate_bv"]
|
||||
data.ymmh.ymmh_space = (ctypes.c_uint * len(fpregs["xsave"]["ymmh_space"]))(*fpregs["xsave"]["ymmh_space"])
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 6
|
||||
nhdr.n_descsz = ctypes.sizeof(data)
|
||||
nhdr.n_type = elf.NT_X86_XSTATE
|
||||
|
||||
note = elf_note()
|
||||
note.data = data
|
||||
note.owner = "LINUX"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_siginfo(self, pid, tid):
|
||||
"""
|
||||
Generate NT_SIGINFO note for thread tid of process pid.
|
||||
"""
|
||||
siginfo = elf.siginfo_t()
|
||||
# FIXME zeroify everything for now
|
||||
ctypes.memset(ctypes.addressof(siginfo), 0, ctypes.sizeof(siginfo))
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.siginfo_t())
|
||||
nhdr.n_type = elf.NT_SIGINFO
|
||||
|
||||
note = elf_note()
|
||||
note.data = siginfo
|
||||
note.owner = "CORE"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_auxv(self, pid):
|
||||
"""
|
||||
Generate NT_AUXV note for thread tid of process pid.
|
||||
"""
|
||||
mm = self.mms[pid]
|
||||
num_auxv = len(mm["mm_saved_auxv"])/2
|
||||
|
||||
class elf_auxv(ctypes.Structure):
|
||||
_fields_ = [("auxv", elf.Elf64_auxv_t*num_auxv)]
|
||||
|
||||
auxv = elf_auxv()
|
||||
for i in range(num_auxv):
|
||||
auxv.auxv[i].a_type = mm["mm_saved_auxv"][i]
|
||||
auxv.auxv[i].a_val = mm["mm_saved_auxv"][i+1]
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf_auxv())
|
||||
nhdr.n_type = elf.NT_AUXV
|
||||
|
||||
note = elf_note()
|
||||
note.data = auxv
|
||||
note.owner = "CORE"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_files(self, pid):
|
||||
"""
|
||||
Generate NT_FILE note for process pid.
|
||||
"""
|
||||
mm = self.mms[pid]
|
||||
|
||||
class mmaped_file_info:
|
||||
start = None
|
||||
end = None
|
||||
file_ofs = None
|
||||
name = None
|
||||
|
||||
infos = []
|
||||
for vma in mm["vmas"]:
|
||||
if vma["shmid"] == 0:
|
||||
# shmid == 0 means that it is not a file
|
||||
continue
|
||||
|
||||
shmid = vma["shmid"]
|
||||
size = vma["end"] - vma["start"]
|
||||
off = vma["pgoff"]/PAGESIZE
|
||||
|
||||
files = self.reg_files
|
||||
fname = filter(lambda x: x["id"] == shmid, files)[0]["name"]
|
||||
|
||||
info = mmaped_file_info()
|
||||
info.start = vma["start"]
|
||||
info.end = vma["end"]
|
||||
info.file_ofs = off
|
||||
info.name = fname
|
||||
|
||||
infos.append(info)
|
||||
|
||||
# /*
|
||||
# * Format of NT_FILE note:
|
||||
# *
|
||||
# * long count -- how many files are mapped
|
||||
# * long page_size -- units for file_ofs
|
||||
# * array of [COUNT] elements of
|
||||
# * long start
|
||||
# * long end
|
||||
# * long file_ofs
|
||||
# * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL...
|
||||
# */
|
||||
fields = []
|
||||
fields.append(("count", ctypes.c_long))
|
||||
fields.append(("page_size", ctypes.c_long))
|
||||
for i in range(len(infos)):
|
||||
fields.append(("start"+str(i), ctypes.c_long))
|
||||
fields.append(("end"+str(i), ctypes.c_long))
|
||||
fields.append(("file_ofs"+str(i), ctypes.c_long))
|
||||
for i in range(len(infos)):
|
||||
fields.append(("name"+str(i), ctypes.c_char*(len(infos[i].name)+1)))
|
||||
|
||||
class elf_files(ctypes.Structure):
|
||||
_fields_ = fields
|
||||
|
||||
data = elf_files()
|
||||
data.count = len(infos)
|
||||
data.page_size = PAGESIZE
|
||||
for i in range(len(infos)):
|
||||
info = infos[i]
|
||||
setattr(data, "start"+str(i), info.start)
|
||||
setattr(data, "end"+str(i), info.end)
|
||||
setattr(data, "file_ofs"+str(i), info.file_ofs)
|
||||
setattr(data, "name"+str(i), info.name)
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
|
||||
nhdr.n_namesz = 5#XXX strlen + 1
|
||||
nhdr.n_descsz = ctypes.sizeof(elf_files())
|
||||
nhdr.n_type = elf.NT_FILE
|
||||
|
||||
note = elf_note()
|
||||
note.nhdr = nhdr
|
||||
note.owner = "CORE"
|
||||
note.data = data
|
||||
|
||||
return note
|
||||
|
||||
def _gen_thread_notes(self, pid, tid):
|
||||
notes = []
|
||||
|
||||
notes.append(self._gen_prstatus(pid, tid))
|
||||
notes.append(self._gen_fpregset(pid, tid))
|
||||
notes.append(self._gen_x86_xstate(pid, tid))
|
||||
notes.append(self._gen_siginfo(pid, tid))
|
||||
|
||||
return notes
|
||||
|
||||
def _gen_notes(self, pid):
|
||||
"""
|
||||
Generate notes for core dump of process pid.
|
||||
"""
|
||||
notes = []
|
||||
|
||||
notes.append(self._gen_prpsinfo(pid))
|
||||
|
||||
threads = self.pstree[pid]["threads"]
|
||||
|
||||
# Main thread first
|
||||
notes += self._gen_thread_notes(pid, pid)
|
||||
|
||||
# Then other threads
|
||||
for tid in threads:
|
||||
if tid == pid:
|
||||
continue
|
||||
|
||||
notes += self._gen_thread_notes(pid, tid)
|
||||
|
||||
notes.append(self._gen_auxv(pid))
|
||||
notes.append(self._gen_files(pid))
|
||||
|
||||
return notes
|
||||
|
||||
def _get_page(self, pid, page_no):
|
||||
"""
|
||||
Try to find memory page page_no in pages.img image for process pid.
|
||||
"""
|
||||
pagemap = self.pagemaps[pid]
|
||||
|
||||
# First entry is pagemap_head, we will need it later to open
|
||||
# proper pages.img.
|
||||
pages_id = pagemap[0]["pages_id"]
|
||||
off = 0# in pages
|
||||
for m in pagemap[1:]:
|
||||
found = False
|
||||
for i in xrange(m["nr_pages"]):
|
||||
if m["vaddr"] + i*PAGESIZE == page_no*PAGESIZE:
|
||||
found = True
|
||||
break
|
||||
off += 1
|
||||
|
||||
if not found:
|
||||
continue
|
||||
|
||||
if "in_parent" in m and m["in_parent"] == True:
|
||||
ppid = self.pstree[pid]["ppid"]
|
||||
return self._get_page(ppid, page_no)
|
||||
else:
|
||||
with open(self._imgs_dir+"/"+"pages-"+str(pages_id)+".img") as f:
|
||||
f.seek(off*PAGESIZE)
|
||||
return f.read(PAGESIZE)
|
||||
|
||||
return None
|
||||
|
||||
def _gen_mem_chunk(self, pid, vma, size):
|
||||
"""
|
||||
Obtain vma contents for process pid.
|
||||
"""
|
||||
f = None
|
||||
|
||||
if size == 0:
|
||||
return ""
|
||||
|
||||
if vma["status"] & status["VMA_AREA_VVAR"]:
|
||||
#FIXME this is what gdb does, as vvar vma
|
||||
# is not readable from userspace?
|
||||
return "\0"*size
|
||||
elif vma["status"] & status["VMA_AREA_VSYSCALL"]:
|
||||
#FIXME need to dump it with criu or read from
|
||||
# current process.
|
||||
return "\0"*size
|
||||
|
||||
if vma["status"] & status["VMA_FILE_SHARED"] or \
|
||||
vma["status"] & status["VMA_FILE_PRIVATE"]:
|
||||
# Open file before iterating vma pages
|
||||
shmid = vma["shmid"]
|
||||
off = vma["pgoff"]
|
||||
|
||||
files = self.reg_files
|
||||
fname = filter(lambda x: x["id"] == shmid, files)[0]["name"]
|
||||
|
||||
f = open(fname)
|
||||
f.seek(off)
|
||||
|
||||
start = vma["start"]
|
||||
end = vma["start"] + size
|
||||
|
||||
# Split requested memory chunk into pages, so it could be
|
||||
# pictured as:
|
||||
#
|
||||
# "----" -- part of page with memory outside of our vma;
|
||||
# "XXXX" -- memory from our vma;
|
||||
#
|
||||
# Start page Pages in the middle End page
|
||||
# [-----XXXXX]...[XXXXXXXXXX][XXXXXXXXXX]...[XXX-------]
|
||||
#
|
||||
# Each page could be found in pages.img or in a standalone
|
||||
# file described by shmid field in vma entry and
|
||||
# corresponding entry in reg-files.img.
|
||||
# For VMA_FILE_PRIVATE vma, unchanged pages are taken from
|
||||
# a file, and changed ones -- from pages.img.
|
||||
# Finally, if no page is found neither in pages.img nor
|
||||
# in file, hole in inserted -- a page filled with zeroes.
|
||||
start_page = start/PAGESIZE
|
||||
end_page = end/PAGESIZE
|
||||
|
||||
buf = ""
|
||||
for page_no in range(start_page, end_page+1):
|
||||
page = None
|
||||
|
||||
# Search for needed page in pages.img and reg-files.img
|
||||
# and choose appropriate.
|
||||
page_mem = self._get_page(pid, page_no)
|
||||
|
||||
if f != None:
|
||||
page = f.read(PAGESIZE)
|
||||
|
||||
if page_mem != None:
|
||||
# Page from pages.img has higher priority
|
||||
# than one from maped file on disk.
|
||||
page = page_mem
|
||||
|
||||
if page == None:
|
||||
# Hole
|
||||
page = PAGESIZE*"\0"
|
||||
|
||||
# If it is a start or end page, we need to read
|
||||
# only part of it.
|
||||
if page_no == start_page:
|
||||
n_skip = start - page_no*PAGESIZE
|
||||
if start_page == end_page:
|
||||
n_read = size
|
||||
else:
|
||||
n_read = PAGESIZE - n_skip
|
||||
elif page_no == end_page:
|
||||
n_skip = 0
|
||||
n_read = end - page_no*PAGESIZE
|
||||
else:
|
||||
n_skip = 0
|
||||
n_read = PAGESIZE
|
||||
|
||||
buf += page[n_skip : n_skip + n_read]
|
||||
|
||||
# Don't forget to close file.
|
||||
if f != None:
|
||||
f.close()
|
||||
|
||||
return buf
|
||||
|
||||
def _gen_cmdline(self, pid):
|
||||
"""
|
||||
Generate full command with arguments.
|
||||
"""
|
||||
mm = self.mms[pid]
|
||||
|
||||
vma = {}
|
||||
vma["start"] = mm["mm_arg_start"]
|
||||
vma["end"] = mm["mm_arg_end"]
|
||||
# Dummy flags and status.
|
||||
vma["flags"] = 0
|
||||
vma["status"] = 0
|
||||
size = vma["end"] - vma["start"]
|
||||
|
||||
chunk = self._gen_mem_chunk(pid, vma, size)
|
||||
|
||||
# Replace all '\0's with spaces.
|
||||
return chunk.replace('\0', ' ')
|
||||
|
||||
def _get_vma_dump_size(self, vma):
|
||||
"""
|
||||
Calculate amount of vma to put into core dump.
|
||||
"""
|
||||
if vma["status"] & status["VMA_AREA_VVAR"] or \
|
||||
vma["status"] & status["VMA_AREA_VSYSCALL"] or \
|
||||
vma["status"] & status["VMA_AREA_VDSO"]:
|
||||
size = vma["end"] - vma["start"]
|
||||
elif vma["prot"] == 0:
|
||||
size = 0
|
||||
elif vma["prot"] & prot["PROT_READ"] and \
|
||||
vma["prot"] & prot["PROT_EXEC"]:
|
||||
size = PAGESIZE
|
||||
elif vma["status"] & status["VMA_ANON_SHARED"] or \
|
||||
vma["status"] & status["VMA_FILE_SHARED"] or \
|
||||
vma["status"] & status["VMA_ANON_PRIVATE"] or \
|
||||
vma["status"] & status["VMA_FILE_PRIVATE"]:
|
||||
size = vma["end"] - vma["start"]
|
||||
else:
|
||||
size = 0
|
||||
|
||||
return size
|
||||
|
||||
def _get_vma_flags(self, vma):
|
||||
"""
|
||||
Convert vma flags int elf flags.
|
||||
"""
|
||||
flags = 0
|
||||
|
||||
if vma['prot'] & prot["PROT_READ"]:
|
||||
flags = flags | elf.PF_R
|
||||
|
||||
if vma['prot'] & prot["PROT_WRITE"]:
|
||||
flags = flags | elf.PF_W
|
||||
|
||||
if vma['prot'] & prot["PROT_EXEC"]:
|
||||
flags = flags | elf.PF_X
|
||||
|
||||
return flags
|
||||
|
||||
def _gen_vmas(self, pid):
|
||||
"""
|
||||
Generate vma contents for core dump for process pid.
|
||||
"""
|
||||
mm = self.mms[pid]
|
||||
|
||||
class vma_class:
|
||||
data = None
|
||||
filesz = None
|
||||
memsz = None
|
||||
flags = None
|
||||
start = None
|
||||
|
||||
vmas = []
|
||||
for vma in mm["vmas"]:
|
||||
size = self._get_vma_dump_size(vma)
|
||||
|
||||
chunk = self._gen_mem_chunk(pid, vma, size)
|
||||
|
||||
v = vma_class()
|
||||
v.filesz = self._get_vma_dump_size(vma)
|
||||
v.data = self._gen_mem_chunk(pid, vma, v.filesz)
|
||||
v.memsz = vma["end"] - vma["start"]
|
||||
v.start = vma["start"]
|
||||
v.flags = self._get_vma_flags(vma)
|
||||
|
||||
vmas.append(v)
|
||||
|
||||
return vmas
|
||||
526
coredump/criu_coredump/elf.py
Normal file
526
coredump/criu_coredump/elf.py
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
# Define structures and constants for generating elf file.
|
||||
from ctypes import *
|
||||
|
||||
Elf64_Half = c_uint16 # typedef uint16_t Elf64_Half;
|
||||
Elf64_Word = c_uint32 # typedef uint32_t Elf64_Word;
|
||||
Elf64_Addr = c_uint64 # typedef uint64_t Elf64_Addr;
|
||||
Elf64_Off = c_uint64 # typedef uint64_t Elf64_Off;
|
||||
Elf64_Xword = c_uint64 # typedef uint64_t Elf64_Xword;
|
||||
|
||||
# Elf64_Ehdr related constants.
|
||||
|
||||
# e_ident size.
|
||||
EI_NIDENT = 16 # #define EI_NIDENT (16)
|
||||
|
||||
EI_MAG0 = 0 # #define EI_MAG0 0 /* File identification byte 0 index */
|
||||
ELFMAG0 = 0x7f # #define ELFMAG0 0x7f /* Magic number byte 0 */
|
||||
|
||||
EI_MAG1 = 1 # #define EI_MAG1 1 /* File identification byte 1 index */
|
||||
ELFMAG1 = ord('E') # #define ELFMAG1 'E' /* Magic number byte 1 */
|
||||
|
||||
EI_MAG2 = 2 # #define EI_MAG2 2 /* File identification byte 2 index */
|
||||
ELFMAG2 = ord('L') # #define ELFMAG2 'L' /* Magic number byte 2 */
|
||||
|
||||
EI_MAG3 = 3 # #define EI_MAG3 3 /* File identification byte 3 index */
|
||||
ELFMAG3 = ord('F') # #define ELFMAG3 'F' /* Magic number byte 3 */
|
||||
|
||||
EI_CLASS = 4 # #define EI_CLASS 4 /* File class byte index */
|
||||
|
||||
EI_DATA = 5 # #define EI_DATA 5 /* Data encoding byte index */
|
||||
|
||||
EI_VERSION = 6 # #define EI_VERSION 6 /* File version byte index */
|
||||
|
||||
ELFDATA2LSB = 1 # #define ELFDATA2LSB 1 /* 2's complement, little endian */
|
||||
|
||||
ELFCLASS64 = 2 # #define ELFCLASS64 2 /* 64-bit objects */
|
||||
|
||||
# Legal values for e_type (object file type).
|
||||
ET_CORE = 4 # #define ET_CORE 4 /* Core file */
|
||||
|
||||
# Legal values for e_machine (architecture).
|
||||
EM_X86_64 = 62 # #define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||
|
||||
# Legal values for e_version (version).
|
||||
EV_CURRENT = 1 # #define EV_CURRENT 1 /* Current version */
|
||||
|
||||
class Elf64_Ehdr(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("e_ident", c_ubyte*EI_NIDENT), # unsigned char e_ident[EI_NIDENT];
|
||||
("e_type", Elf64_Half), # Elf64_Half e_type;
|
||||
("e_machine", Elf64_Half), # Elf64_Half e_machine;
|
||||
("e_version", Elf64_Word), # Elf64_Word e_version;
|
||||
("e_entry", Elf64_Addr), # Elf64_Addr e_entry;
|
||||
("e_phoff", Elf64_Off), # Elf64_Off e_phoff;
|
||||
("e_shoff", Elf64_Off), # Elf64_Off e_shoff;
|
||||
("e_flags", Elf64_Word), # Elf64_Word e_flags;
|
||||
("e_ehsize", Elf64_Half), # Elf64_Half e_ehsize;
|
||||
("e_phentsize", Elf64_Half), # Elf64_Half e_phentsize;
|
||||
("e_phnum", Elf64_Half), # Elf64_Half e_phnum;
|
||||
("e_shentsize", Elf64_Half), # Elf64_Half e_shentsize;
|
||||
("e_shnum", Elf64_Half), # Elf64_Half e_shnum;
|
||||
("e_shstrndx", Elf64_Half) # Elf64_Half e_shstrndx;
|
||||
] # } Elf64_Ehdr;
|
||||
|
||||
|
||||
# Elf64_Phdr related constants.
|
||||
|
||||
# Legal values for p_type (segment type).
|
||||
PT_LOAD = 1 # #define PT_LOAD 1 /* Loadable program segment */
|
||||
PT_NOTE = 4 # #define PT_NOTE 4 /* Auxiliary information */
|
||||
|
||||
# Legal values for p_flags (segment flags).
|
||||
PF_X = 1 # #define PF_X (1 << 0) /* Segment is executable */
|
||||
PF_W = 1 << 1 # #define PF_W (1 << 1) /* Segment is writable */
|
||||
PF_R = 1 << 2 # #define PF_R (1 << 2) /* Segment is readable */
|
||||
|
||||
class Elf64_Phdr(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("p_type", Elf64_Word), # Elf64_Word p_type;
|
||||
("p_flags", Elf64_Word), # Elf64_Word p_flags;
|
||||
("p_offset", Elf64_Off), # Elf64_Off p_offset;
|
||||
("p_vaddr", Elf64_Addr), # Elf64_Addr p_vaddr;
|
||||
("p_paddr", Elf64_Addr), # Elf64_Addr p_paddr;
|
||||
("p_filesz", Elf64_Xword), # Elf64_Xword p_filesz;
|
||||
("p_memsz", Elf64_Xword), # Elf64_Xword p_memsz;
|
||||
("p_align", Elf64_Xword), # Elf64_Xword p_align;
|
||||
] # } Elf64_Phdr;
|
||||
|
||||
|
||||
# Elf64_auxv_t related constants.
|
||||
|
||||
class _Elf64_auxv_t_U(Union):
|
||||
_fields_ = [
|
||||
("a_val", c_uint64)
|
||||
]
|
||||
|
||||
class Elf64_auxv_t(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("a_type", c_uint64), # uint64_t a_type; /* Entry type */
|
||||
("a_un", _Elf64_auxv_t_U) # union
|
||||
# {
|
||||
# uint64_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;
|
||||
] # } Elf64_auxv_t;
|
||||
|
||||
|
||||
# Elf64_Nhdr related constants.
|
||||
|
||||
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_PRPSINFO = 3 # #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
|
||||
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_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 */
|
||||
|
||||
class Elf64_Nhdr(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("n_namesz", Elf64_Word), # Elf64_Word n_namesz; /* Length of the note's name. */
|
||||
("n_descsz", Elf64_Word), # Elf64_Word n_descsz; /* Length of the note's descriptor. */
|
||||
("n_type", Elf64_Word), # Elf64_Word n_type; /* Type of the note. */
|
||||
] # } Elf64_Nhdr;
|
||||
|
||||
|
||||
# Elf64_Shdr related constants.
|
||||
|
||||
class Elf64_Shdr(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("sh_name", Elf64_Word), # Elf64_Word sh_name; /* Section name (string tbl index) */
|
||||
("sh_type", Elf64_Word), # Elf64_Word sh_type; /* Section type */
|
||||
("sh_flags", Elf64_Xword), # Elf64_Xword sh_flags; /* Section flags */
|
||||
("sh_addr", Elf64_Addr), # Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||
("sh_offset", Elf64_Off), # Elf64_Off sh_offset; /* Section file offset */
|
||||
("sh_size", Elf64_Xword), # Elf64_Xword sh_size; /* Section size in bytes */
|
||||
("sh_link", Elf64_Word), # Elf64_Word sh_link; /* Link to another section */
|
||||
("sh_info", Elf64_Word), # Elf64_Word sh_info; /* Additional section information */
|
||||
("sh_addralign",Elf64_Xword), # Elf64_Xword sh_addralign; /* Section alignment */
|
||||
("sh_entsize", Elf64_Xword) # Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||
] # } Elf64_Shdr;
|
||||
|
||||
|
||||
# elf_prstatus related constants.
|
||||
|
||||
# Signal info.
|
||||
class elf_siginfo(Structure): # struct elf_siginfo
|
||||
_fields_ = [ # {
|
||||
("si_signo", c_int), # int si_signo; /* Signal number. */
|
||||
("si_code", c_int), # int si_code; /* Extra code. */
|
||||
("si_errno", c_int) # int si_errno; /* Errno. */
|
||||
] # };
|
||||
|
||||
# A time value that is accurate to the nearest
|
||||
# microsecond but also has a range of years.
|
||||
class timeval(Structure): # struct timeval
|
||||
_fields_ = [ # {
|
||||
("tv_sec", c_long), # __time_t tv_sec; /* Seconds. */
|
||||
("tv_usec", c_long) # __suseconds_t tv_usec; /* Microseconds. */
|
||||
] # };
|
||||
|
||||
class user_regs_struct(Structure): # struct user_regs_struct
|
||||
_fields_ = [ # {
|
||||
("r15", c_ulonglong), # __extension__ unsigned long long int r15;
|
||||
("r14", c_ulonglong), # __extension__ unsigned long long int r14;
|
||||
("r13", c_ulonglong), # __extension__ unsigned long long int r13;
|
||||
("r12", c_ulonglong), # __extension__ unsigned long long int r12;
|
||||
("rbp", c_ulonglong), # __extension__ unsigned long long int rbp;
|
||||
("rbx", c_ulonglong), # __extension__ unsigned long long int rbx;
|
||||
("r11", c_ulonglong), # __extension__ unsigned long long int r11;
|
||||
("r10", c_ulonglong), # __extension__ unsigned long long int r10;
|
||||
("r9", c_ulonglong), # __extension__ unsigned long long int r9;
|
||||
("r8", c_ulonglong), # __extension__ unsigned long long int r8;
|
||||
("rax", c_ulonglong), # __extension__ unsigned long long int rax;
|
||||
("rcx", c_ulonglong), # __extension__ unsigned long long int rcx;
|
||||
("rdx", c_ulonglong), # __extension__ unsigned long long int rdx;
|
||||
("rsi", c_ulonglong), # __extension__ unsigned long long int rsi;
|
||||
("rdi", c_ulonglong), # __extension__ unsigned long long int rdi;
|
||||
("orig_rax", c_ulonglong), # __extension__ unsigned long long int orig_rax;
|
||||
("rip", c_ulonglong), # __extension__ unsigned long long int rip;
|
||||
("cs", c_ulonglong), # __extension__ unsigned long long int cs;
|
||||
("eflags", c_ulonglong), # __extension__ unsigned long long int eflags;
|
||||
("rsp", c_ulonglong), # __extension__ unsigned long long int rsp;
|
||||
("ss", c_ulonglong), # __extension__ unsigned long long int ss;
|
||||
("fs_base", c_ulonglong), # __extension__ unsigned long long int fs_base;
|
||||
("gs_base", c_ulonglong), # __extension__ unsigned long long int gs_base;
|
||||
("ds", c_ulonglong), # __extension__ unsigned long long int ds;
|
||||
("es", c_ulonglong), # __extension__ unsigned long long int es;
|
||||
("fs", c_ulonglong), # __extension__ unsigned long long int fs;
|
||||
("gs", c_ulonglong) # __extension__ unsigned long long int gs;
|
||||
] # };
|
||||
|
||||
#elf_greg_t = c_ulonglong
|
||||
#ELF_NGREG = sizeof(user_regs_struct)/sizeof(elf_greg_t)
|
||||
#elf_gregset_t = elf_greg_t*ELF_NGREG
|
||||
elf_gregset_t = user_regs_struct
|
||||
|
||||
class elf_prstatus(Structure): # struct elf_prstatus
|
||||
_fields_ = [ # {
|
||||
("pr_info", elf_siginfo), # struct elf_siginfo pr_info; /* Info associated with signal. */
|
||||
("pr_cursig", c_short), # short int pr_cursig; /* Current signal. */
|
||||
("pr_sigpend", c_ulong), # unsigned long int pr_sigpend; /* Set of pending signals. */
|
||||
("pr_sighold", c_ulong), # unsigned long int pr_sighold; /* Set of held signals. */
|
||||
("pr_pid", c_int), # __pid_t pr_pid;
|
||||
("pr_ppid", c_int), # __pid_t pr_ppid;
|
||||
("pr_pgrp", c_int), # __pid_t pr_pgrp;
|
||||
("pr_sid", c_int), # __pid_t pr_sid;
|
||||
("pr_utime", timeval), # struct timeval pr_utime; /* User time. */
|
||||
("pr_stime", timeval), # struct timeval pr_stime; /* System time. */
|
||||
("pr_cutime", timeval), # struct timeval pr_cutime; /* Cumulative user time. */
|
||||
("pr_cstime", timeval), # struct timeval pr_cstime; /* Cumulative system time. */
|
||||
("pr_reg", elf_gregset_t), # elf_gregset_t pr_reg; /* GP registers. */
|
||||
("pr_fpvalid", c_int) # int pr_fpvalid; /* True if math copro being used. */
|
||||
] # };
|
||||
|
||||
|
||||
# elf_prpsinfo related constants.
|
||||
|
||||
ELF_PRARGSZ = 80 # #define ELF_PRARGSZ (80) /* Number of chars for args. */
|
||||
|
||||
class elf_prpsinfo(Structure): # struct elf_prpsinfo
|
||||
_fields_ = [ # {
|
||||
("pr_state", c_byte), # char pr_state; /* Numeric process state. */
|
||||
("pr_sname", c_char), # char pr_sname; /* Char for pr_state. */
|
||||
("pr_zomb", c_byte), # char pr_zomb; /* Zombie. */
|
||||
("pr_nice", c_byte), # char pr_nice; /* Nice val. */
|
||||
("pr_flag", c_ulong), # unsigned long int pr_flag; /* Flags. */
|
||||
# #if __WORDSIZE == 32
|
||||
# unsigned short int pr_uid;
|
||||
# unsigned short int pr_gid;
|
||||
# #else
|
||||
("pr_uid", c_uint), # unsigned int pr_uid;
|
||||
("pr_gid", c_uint), # unsigned int pr_gid;
|
||||
# #endif
|
||||
("pr_pid", c_int), # int pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
("pr_ppid", c_int),
|
||||
("pr_pgrp", c_int),
|
||||
("pr_sid", c_int),
|
||||
# /* Lots missing */
|
||||
("pr_fname", c_char*16), # char pr_fname[16]; /* Filename of executable. */
|
||||
("pr_psargs", c_char*ELF_PRARGSZ) # char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */
|
||||
] # };
|
||||
|
||||
|
||||
class user_fpregs_struct(Structure): # struct user_fpregs_struct
|
||||
_fields_ = [ # {
|
||||
("cwd", c_ushort), # unsigned short int cwd;
|
||||
("swd", c_ushort), # unsigned short int swd;
|
||||
("ftw", c_ushort), # unsigned short int ftw;
|
||||
("fop", c_ushort), # unsigned short int fop;
|
||||
("rip", c_ulonglong), # __extension__ unsigned long long int rip;
|
||||
("rdp", c_ulonglong), # __extension__ unsigned long long int rdp;
|
||||
("mxcsr", c_uint), # unsigned int mxcsr;
|
||||
("mxcr_mask", c_uint), # unsigned int mxcr_mask;
|
||||
("st_space", c_uint*32), # unsigned int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */
|
||||
("xmm_space", c_uint*64), # unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */
|
||||
("padding", c_uint*24), # unsigned int padding[24];
|
||||
] # };
|
||||
|
||||
|
||||
elf_fpregset_t = user_fpregs_struct
|
||||
|
||||
|
||||
# siginfo_t related constants.
|
||||
|
||||
_SI_MAX_SIZE = 128
|
||||
_SI_PAD_SIZE = (_SI_MAX_SIZE/sizeof(c_int)) - 4
|
||||
|
||||
# /* kill(). */
|
||||
class _siginfo_t_U_kill(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_pid", c_int), # __pid_t si_pid; /* Sending process ID. */
|
||||
("si_uid", c_uint) # __uid_t si_uid; /* Real user ID of sending process. */
|
||||
] # } _kill;
|
||||
|
||||
|
||||
|
||||
# Type for data associated with a signal.
|
||||
class sigval_t(Union): # typedef union sigval
|
||||
_fields_ = [ # {
|
||||
("sival_int", c_int), # int sival_int;
|
||||
("sical_ptr", c_void_p), # void *sival_ptr;
|
||||
] # } sigval_t;
|
||||
|
||||
# /* POSIX.1b timers. */
|
||||
class _siginfo_t_U_timer(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_tid", c_int), # int si_tid; /* Timer ID. */
|
||||
("si_overrun", c_int), # int si_overrun; /* Overrun count. */
|
||||
("si_sigval", sigval_t) # sigval_t si_sigval; /* Signal value. */
|
||||
] # } _timer;
|
||||
|
||||
|
||||
# /* POSIX.1b signals. */
|
||||
class _siginfo_t_U_rt(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_pid", c_int), # __pid_t si_pid; /* Sending process ID. */
|
||||
("si_uid", c_uint), # __uid_t si_uid; /* Real user ID of sending process. */
|
||||
("si_sigval", sigval_t) # sigval_t si_sigval; /* Signal value. */
|
||||
] # } _rt;
|
||||
|
||||
|
||||
# /* SIGCHLD. */
|
||||
class _siginfo_t_U_sigchld(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_pid", c_int), # __pid_t si_pid; /* Which child. */
|
||||
("si_uid", c_uint), # __uid_t si_uid; /* Real user ID of sending process. */
|
||||
("si_status", c_int), # int si_status; /* Exit value or signal. */
|
||||
("si_utime", c_long), # __sigchld_clock_t si_utime;
|
||||
("si_stime", c_long) # __sigchld_clock_t si_stime;
|
||||
] # } _sigchld;
|
||||
|
||||
# /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
|
||||
class _siginfo_t_U_sigfault(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_addr", c_void_p), # void *si_addr; /* Faulting insn/memory ref. */
|
||||
("si_addr_lsb", c_short) # short int si_addr_lsb; /* Valid LSB of the reported address. */
|
||||
] # } _sigfault;
|
||||
|
||||
# /* SIGPOLL. */
|
||||
class _siginfo_t_U_sigpoll(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("si_band", c_long), # long int si_band; /* Band event for SIGPOLL. */
|
||||
("si_fd", c_int) # int si_fd;
|
||||
] # } _sigpoll;
|
||||
|
||||
|
||||
# /* SIGSYS. */
|
||||
class _siginfo_t_U_sigsys(Structure): # struct
|
||||
_fields_ = [ # {
|
||||
("_call_addr", c_void_p), # void *_call_addr; /* Calling user insn. */
|
||||
("_syscall", c_int), # int _syscall; /* Triggering system call number. */
|
||||
("_arch", c_uint) # unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
|
||||
] # } _sigsys;
|
||||
|
||||
|
||||
class _siginfo_t_U(Union): # union
|
||||
_fields_ = [ # {
|
||||
("_pad", c_int*_SI_PAD_SIZE), # int _pad[__SI_PAD_SIZE];
|
||||
#
|
||||
# /* kill(). */
|
||||
("_kill", _siginfo_t_U_kill), # struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Sending process ID. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# } _kill;
|
||||
#
|
||||
# /* POSIX.1b timers. */
|
||||
("_timer", _siginfo_t_U_timer), # struct
|
||||
# {
|
||||
# int si_tid; /* Timer ID. */
|
||||
# int si_overrun; /* Overrun count. */
|
||||
# sigval_t si_sigval; /* Signal value. */
|
||||
# } _timer;
|
||||
#
|
||||
# /* POSIX.1b signals. */
|
||||
("_rt", _siginfo_t_U_rt), # struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Sending process ID. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# sigval_t si_sigval; /* Signal value. */
|
||||
# } _rt;
|
||||
#
|
||||
# /* SIGCHLD. */
|
||||
("_sigchld", _siginfo_t_U_sigchld), # struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Which child. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# int si_status; /* Exit value or signal. */
|
||||
# __sigchld_clock_t si_utime;
|
||||
# __sigchld_clock_t si_stime;
|
||||
# } _sigchld;
|
||||
#
|
||||
# /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
|
||||
("_sigfault", _siginfo_t_U_sigfault), # struct
|
||||
# {
|
||||
# void *si_addr; /* Faulting insn/memory ref. */
|
||||
# short int si_addr_lsb; /* Valid LSB of the reported address. */
|
||||
# } _sigfault;
|
||||
#
|
||||
# /* SIGPOLL. */
|
||||
("_sigpoll", _siginfo_t_U_sigpoll), # struct
|
||||
# {
|
||||
# long int si_band; /* Band event for SIGPOLL. */
|
||||
# int si_fd;
|
||||
# } _sigpoll;
|
||||
#
|
||||
# /* SIGSYS. */
|
||||
("_sigsys", _siginfo_t_U_sigpoll) # struct
|
||||
# {
|
||||
# void *_call_addr; /* Calling user insn. */
|
||||
# int _syscall; /* Triggering system call number. */
|
||||
# unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
|
||||
# } _sigsys;
|
||||
] # } _sifields;
|
||||
|
||||
class siginfo_t(Structure): # typedef struct
|
||||
_fields_ = [ # {
|
||||
("si_signo", c_int), # int si_signo; /* Signal number. */
|
||||
("si_errno", c_int), # int si_errno; /* If non-zero, an errno value associated with
|
||||
# this signal, as defined in <errno.h>. */
|
||||
("si_code", c_int), # int si_code; /* Signal code. */
|
||||
#
|
||||
("_sifields", _siginfo_t_U) # union
|
||||
# {
|
||||
# int _pad[__SI_PAD_SIZE];
|
||||
#
|
||||
# /* kill(). */
|
||||
# struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Sending process ID. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# } _kill;
|
||||
#
|
||||
# /* POSIX.1b timers. */
|
||||
# struct
|
||||
# {
|
||||
# int si_tid; /* Timer ID. */
|
||||
# int si_overrun; /* Overrun count. */
|
||||
# sigval_t si_sigval; /* Signal value. */
|
||||
# } _timer;
|
||||
#
|
||||
# /* POSIX.1b signals. */
|
||||
# struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Sending process ID. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# sigval_t si_sigval; /* Signal value. */
|
||||
# } _rt;
|
||||
#
|
||||
# /* SIGCHLD. */
|
||||
# struct
|
||||
# {
|
||||
# __pid_t si_pid; /* Which child. */
|
||||
# __uid_t si_uid; /* Real user ID of sending process. */
|
||||
# int si_status; /* Exit value or signal. */
|
||||
# __sigchld_clock_t si_utime;
|
||||
# __sigchld_clock_t si_stime;
|
||||
# } _sigchld;
|
||||
#
|
||||
# /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
|
||||
# struct
|
||||
# {
|
||||
# void *si_addr; /* Faulting insn/memory ref. */
|
||||
# short int si_addr_lsb; /* Valid LSB of the reported address. */
|
||||
# } _sigfault;
|
||||
#
|
||||
# /* SIGPOLL. */
|
||||
# struct
|
||||
# {
|
||||
# long int si_band; /* Band event for SIGPOLL. */
|
||||
# int si_fd;
|
||||
# } _sigpoll;
|
||||
#
|
||||
# /* SIGSYS. */
|
||||
# struct
|
||||
# {
|
||||
# void *_call_addr; /* Calling user insn. */
|
||||
# int _syscall; /* Triggering system call number. */
|
||||
# unsigned int _arch; /* AUDIT_ARCH_* of syscall. */
|
||||
# } _sigsys;
|
||||
# } _sifields;
|
||||
] # } siginfo_t __SI_ALIGNMENT;
|
||||
|
||||
|
||||
# xsave related.
|
||||
|
||||
class ymmh_struct(Structure): # struct ymmh_struct {
|
||||
_fields_ = [
|
||||
("ymmh_space", 64*c_uint) # u32 ymmh_space[64];
|
||||
] # } __packed;
|
||||
|
||||
|
||||
class xsave_hdr_struct(Structure): # struct xsave_hdr_struct {
|
||||
_fields_ = [
|
||||
("xstate_bv", c_ulonglong), # u64 xstate_bv;
|
||||
("reserved1", c_ulonglong*2), # u64 reserved1[2];
|
||||
("reserved2", c_ulonglong*5) # u64 reserved2[5];
|
||||
] # } __packed;
|
||||
|
||||
|
||||
class i387_fxsave_struct(Structure): # struct i387_fxsave_struct {
|
||||
_fields_ = [
|
||||
("cwd", c_ushort), # u16 cwd; /* Control Word */
|
||||
("swd", c_ushort), # u16 swd; /* Status Word */
|
||||
("twd", c_ushort), # u16 twd; /* Tag Word */
|
||||
("fop", c_ushort), # u16 fop; /* Last Instruction Opcode */
|
||||
# union {
|
||||
# struct {
|
||||
("rip", c_ulonglong), # u64 rip; /* Instruction Pointer */
|
||||
("rdp", c_ulonglong), # u64 rdp; /* Data Pointer */
|
||||
# };
|
||||
# struct {
|
||||
# u32 fip; /* FPU IP Offset */
|
||||
# u32 fcs; /* FPU IP Selector */
|
||||
# u32 foo; /* FPU Operand Offset */
|
||||
# u32 fos; /* FPU Operand Selector */
|
||||
# };
|
||||
# };
|
||||
("mxcsr", c_uint), # u32 mxcsr; /* MXCSR Register State */
|
||||
("mxcsr_mask", c_uint), # u32 mxcsr_mask; /* MXCSR Mask */
|
||||
#
|
||||
# /* 8*16 bytes for each FP-reg = 128 bytes */
|
||||
("st_space", c_uint*32), # u32 st_space[32];
|
||||
#
|
||||
# /* 16*16 bytes for each XMM-reg = 256 bytes */
|
||||
("xmm_space", c_uint*64), # u32 xmm_space[64];
|
||||
#
|
||||
("padding", c_uint*12), # u32 padding[12];
|
||||
#
|
||||
# union {
|
||||
("padding1", c_uint*12) # u32 padding1[12];
|
||||
# u32 sw_reserved[12];
|
||||
# };
|
||||
#
|
||||
] # } __aligned(16);
|
||||
|
||||
|
||||
class elf_xsave_struct(Structure): # struct xsave_struct {
|
||||
_fields_ = [
|
||||
("i387", i387_fxsave_struct), # struct i387_fxsave_struct i387;
|
||||
("xsave_hdr", xsave_hdr_struct), # struct xsave_hdr_struct xsave_hdr;
|
||||
("ymmh", ymmh_struct) # struct ymmh_struct ymmh;
|
||||
] # } __aligned(FP_MIN_ALIGN_BYTES) __packed;
|
||||
1
coredump/pycriu
Symbolic link
1
coredump/pycriu
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../lib/py/
|
||||
Loading…
Add table
Add a link
Reference in a new issue