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 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) if self.x86 is True: offset = ctypes.sizeof(elf.Elf32_Ehdr()) offset += (len(self.vmas) + 1) * ctypes.sizeof(elf.Elf32_Phdr()) else: 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())