gencore: finish reintegration into arch-independent code
Change-Id: Ic2fc935aeec17c54931817bf43f67ef6da78adc8 Fujitsu: POSTK_DEBUG_ARCH_DEP_18
This commit is contained in:
@ -14,9 +14,6 @@ IHK_OBJS += memcpy.o memset.o
|
||||
IHK_OBJS += cpufeature.o
|
||||
|
||||
IHK_OBJS += imp-sysreg.o
|
||||
|
||||
# POSTK_DEBUG_ARCH_DEP_18 coredump arch separation.
|
||||
# IHK_OBJS added coredump.o
|
||||
IHK_OBJS += coredump.o
|
||||
|
||||
$(VDSO_SO_O): $(VDSO_BUILDDIR)/vdso.so
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* coredump.c COPYRIGHT FUJITSU LIMITED 2015-2016 */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#include <process.h>
|
||||
#include <elfcore.h>
|
||||
#include <string.h>
|
||||
@ -31,5 +30,3 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
/* copy unaligned prstatus addr */
|
||||
memcpy(prstatus, &tmp_prstatus, sizeof(*prstatus));
|
||||
}
|
||||
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
@ -1,92 +0,0 @@
|
||||
/* elfcore.h COPYRIGHT FUJITSU LIMITED 2015 */
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#ifndef __HEADER_ARM64_COMMON_ELFCORE_H
|
||||
#define __HEADER_ARM64_COMMON_ELFCORE_H
|
||||
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
#define EI_OSABI 7
|
||||
#define EI_ABIVERSION 8
|
||||
#define EI_PAD 9
|
||||
|
||||
|
||||
#define ELFMAG0 0x7f
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
#define ELFCLASS64 2 /* 64-bit object */
|
||||
#define ELFDATA2LSB 1 /* LSB */
|
||||
#define El_VERSION 1 /* defined to be the same as EV CURRENT */
|
||||
#define ELFOSABI_NONE 0 /* unspecied */
|
||||
#define El_ABIVERSION_NONE 0 /* unspecied */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
#define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||
#define EM_K10M 181 /* Intel K10M */
|
||||
#define EV_CURRENT 1 /* Current version */
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word p_type;
|
||||
Elf64_Word p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
Elf64_Xword p_filesz;
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
#define PT_LOAD 1
|
||||
#define PT_NOTE 4
|
||||
|
||||
#define PF_X 1 /* executable bit */
|
||||
#define PF_W 2 /* writable bit */
|
||||
#define PF_R 4 /* readable bit */
|
||||
|
||||
struct note {
|
||||
Elf64_Word namesz;
|
||||
Elf64_Word descsz;
|
||||
Elf64_Word type;
|
||||
/* name char[namesz] and desc[descsz] */
|
||||
};
|
||||
|
||||
#define NT_PRSTATUS 1
|
||||
#define NT_PRFRPREG 2
|
||||
#define NT_PRPSINFO 3
|
||||
#define NT_AUXV 6
|
||||
#define NT_X86_STATE 0x202
|
||||
|
||||
#include "elfcoregpl.h"
|
||||
|
||||
#endif /* !__HEADER_ARM64_COMMON_ELFCORE_H */
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -1,98 +0,0 @@
|
||||
/* elfcoregpl.h COPYRIGHT FUJITSU LIMITED 2015 */
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#ifndef __HEADER_ARM64_COMMON_ELFCOREGPL_H
|
||||
#define __HEADER_ARM64_COMMON_ELFCOREGPL_H
|
||||
|
||||
#define pid_t int
|
||||
|
||||
/* From /usr/include/linux/elfcore.h of Linux */
|
||||
|
||||
#define ELF_PRARGSZ (80)
|
||||
|
||||
/* From /usr/include/linux/elfcore.h fro Linux */
|
||||
|
||||
struct elf_siginfo
|
||||
{
|
||||
int si_signo;
|
||||
int si_code;
|
||||
int si_errno;
|
||||
};
|
||||
|
||||
/* From bfd/hosts/x86-64linux.h of gdb. */
|
||||
|
||||
typedef uint64_t __attribute__ ((__aligned__ (8))) a8_uint64_t;
|
||||
typedef a8_uint64_t elf_greg64_t;
|
||||
|
||||
struct user_regs64_struct
|
||||
{
|
||||
a8_uint64_t r15;
|
||||
a8_uint64_t r14;
|
||||
a8_uint64_t r13;
|
||||
a8_uint64_t r12;
|
||||
a8_uint64_t rbp;
|
||||
a8_uint64_t rbx;
|
||||
a8_uint64_t r11;
|
||||
a8_uint64_t r10;
|
||||
a8_uint64_t r9;
|
||||
a8_uint64_t r8;
|
||||
a8_uint64_t rax;
|
||||
a8_uint64_t rcx;
|
||||
a8_uint64_t rdx;
|
||||
a8_uint64_t rsi;
|
||||
a8_uint64_t rdi;
|
||||
a8_uint64_t orig_rax;
|
||||
a8_uint64_t rip;
|
||||
a8_uint64_t cs;
|
||||
a8_uint64_t eflags;
|
||||
a8_uint64_t rsp;
|
||||
a8_uint64_t ss;
|
||||
a8_uint64_t fs_base;
|
||||
a8_uint64_t gs_base;
|
||||
a8_uint64_t ds;
|
||||
a8_uint64_t es;
|
||||
a8_uint64_t fs;
|
||||
a8_uint64_t gs;
|
||||
};
|
||||
|
||||
#define ELF_NGREG64 (sizeof (struct user_regs64_struct) / sizeof(elf_greg64_t))
|
||||
|
||||
typedef elf_greg64_t elf_gregset64_t[ELF_NGREG64];
|
||||
|
||||
struct prstatus64_timeval
|
||||
{
|
||||
a8_uint64_t tv_sec;
|
||||
a8_uint64_t tv_usec;
|
||||
};
|
||||
struct elf_prstatus64
|
||||
{
|
||||
struct elf_siginfo pr_info;
|
||||
short int pr_cursig;
|
||||
a8_uint64_t pr_sigpend;
|
||||
a8_uint64_t pr_sighold;
|
||||
pid_t pr_pid;
|
||||
pid_t pr_ppid;
|
||||
pid_t pr_pgrp;
|
||||
pid_t pr_sid;
|
||||
struct prstatus64_timeval pr_utime;
|
||||
struct prstatus64_timeval pr_stime;
|
||||
struct prstatus64_timeval pr_cutime;
|
||||
struct prstatus64_timeval pr_cstime;
|
||||
elf_gregset64_t pr_reg;
|
||||
int pr_fpvalid;
|
||||
};
|
||||
struct elf_prpsinfo64
|
||||
{
|
||||
char pr_state;
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
a8_uint64_t pr_flag;
|
||||
unsigned int pr_uid;
|
||||
unsigned int pr_gid;
|
||||
int pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
};
|
||||
|
||||
#endif /* !__HEADER_ARM64_COMMON_ELFCOREGPL_H */
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -20,13 +20,11 @@ typedef uint64_t size_t;
|
||||
typedef int64_t ssize_t;
|
||||
typedef int64_t off_t;
|
||||
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
typedef int32_t key_t;
|
||||
typedef uint32_t uid_t;
|
||||
typedef uint32_t gid_t;
|
||||
typedef int64_t time_t;
|
||||
typedef int32_t pid_t;
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
IHK_OBJS += cpu.o interrupt.o memory.o trampoline.o local.o context.o
|
||||
IHK_OBJS += perfctr.o syscall.o vsyscall.o
|
||||
IHK_OBJS += perfctr.o syscall.o vsyscall.o coredump.o
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* coredump.c COPYRIGHT FUJITSU LIMITED 2018 */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#include <process.h>
|
||||
#include <elfcore.h>
|
||||
|
||||
@ -56,5 +55,3 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
|
||||
prstatus->pr_fpvalid = 0; /* We assume no fp */
|
||||
}
|
||||
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
@ -1,550 +0,0 @@
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#include <ihk/debug.h>
|
||||
#include <kmalloc.h>
|
||||
#include <cls.h>
|
||||
#include <list.h>
|
||||
#include <process.h>
|
||||
#include <string.h>
|
||||
#include <elfcore.h>
|
||||
#include <debug.h>
|
||||
|
||||
#define align32(x) ((((x) + 3) / 4) * 4)
|
||||
#define alignpage(x) ((((x) + (PAGE_SIZE) - 1) / (PAGE_SIZE)) * (PAGE_SIZE))
|
||||
|
||||
//#define DEBUG_PRINT_GENCORE
|
||||
|
||||
#ifdef DEBUG_PRINT_GENCORE
|
||||
#undef DDEBUG_DEFAULT
|
||||
#define DDEBUG_DEFAULT DDEBUG_PRINT
|
||||
#endif
|
||||
|
||||
/* Exclude reserved (mckernel's internal use), device file,
|
||||
* hole created by mprotect
|
||||
*/
|
||||
#define GENCORE_RANGE_IS_INACCESSIBLE(range) \
|
||||
((range->flag & (VR_RESERVED | VR_MEMTYPE_UC | VR_DONTDUMP)))
|
||||
|
||||
/*
|
||||
* Generate a core file image, which consists of many chunks.
|
||||
* Returns an allocated table, an etnry of which is a pair of the address
|
||||
* of a chunk and its length.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Fill the elf header.
|
||||
*
|
||||
* \param eh An Elf64_Ehdr structure.
|
||||
* \param segs Number of segments of the core file.
|
||||
*/
|
||||
|
||||
void fill_elf_header(Elf64_Ehdr *eh, int segs)
|
||||
{
|
||||
eh->e_ident[EI_MAG0] = 0x7f;
|
||||
eh->e_ident[EI_MAG1] = 'E';
|
||||
eh->e_ident[EI_MAG2] = 'L';
|
||||
eh->e_ident[EI_MAG3] = 'F';
|
||||
eh->e_ident[EI_CLASS] = ELFCLASS64;
|
||||
eh->e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
eh->e_ident[EI_VERSION] = El_VERSION;
|
||||
eh->e_ident[EI_OSABI] = ELFOSABI_NONE;
|
||||
eh->e_ident[EI_ABIVERSION] = El_ABIVERSION_NONE;
|
||||
|
||||
eh->e_type = ET_CORE;
|
||||
#ifdef CONFIG_MIC
|
||||
eh->e_machine = EM_K10M;
|
||||
#else
|
||||
eh->e_machine = EM_X86_64;
|
||||
#endif
|
||||
eh->e_version = EV_CURRENT;
|
||||
eh->e_entry = 0; /* Do we really need this? */
|
||||
eh->e_phoff = 64; /* fixed */
|
||||
eh->e_shoff = 0; /* no section header */
|
||||
eh->e_flags = 0;
|
||||
eh->e_ehsize = 64; /* fixed */
|
||||
eh->e_phentsize = 56; /* fixed */
|
||||
eh->e_phnum = segs;
|
||||
eh->e_shentsize = 0;
|
||||
eh->e_shnum = 0;
|
||||
eh->e_shstrndx = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the prstatus entry of the NOTE segment.
|
||||
*
|
||||
*/
|
||||
|
||||
int get_prstatus_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ align32(sizeof(struct elf_prstatus64));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill a prstatus structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs0 A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
{
|
||||
void *name;
|
||||
struct elf_prstatus64 *prstatus;
|
||||
struct x86_user_context *uctx = regs0;
|
||||
struct x86_basic_regs *regs = &uctx->gpr;
|
||||
register unsigned long _r12 asm("r12");
|
||||
register unsigned long _r13 asm("r13");
|
||||
register unsigned long _r14 asm("r14");
|
||||
register unsigned long _r15 asm("r15");
|
||||
|
||||
head->namesz = sizeof("CORE");
|
||||
head->descsz = sizeof(struct elf_prstatus64);
|
||||
head->type = NT_PRSTATUS;
|
||||
name = (void *) (head + 1);
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
prstatus = (struct elf_prstatus64 *)(name + align32(sizeof("CORE")));
|
||||
|
||||
/*
|
||||
We ignore following entries for now.
|
||||
|
||||
struct elf_siginfo pr_info;
|
||||
short int pr_cursig;
|
||||
a8_uint64_t pr_sigpend;
|
||||
a8_uint64_t pr_sighold;
|
||||
pid_t pr_pid;
|
||||
pid_t pr_ppid;
|
||||
pid_t pr_pgrp;
|
||||
pid_t pr_sid;
|
||||
struct prstatus64_timeval pr_utime;
|
||||
struct prstatus64_timeval pr_stime;
|
||||
struct prstatus64_timeval pr_cutime;
|
||||
struct prstatus64_timeval pr_cstime;
|
||||
*/
|
||||
|
||||
prstatus->pr_reg[0] = _r15;
|
||||
prstatus->pr_reg[1] = _r14;
|
||||
prstatus->pr_reg[2] = _r13;
|
||||
prstatus->pr_reg[3] = _r12;
|
||||
prstatus->pr_reg[4] = regs->rbp;
|
||||
prstatus->pr_reg[5] = regs->rbx;
|
||||
prstatus->pr_reg[6] = regs->r11;
|
||||
prstatus->pr_reg[7] = regs->r10;
|
||||
prstatus->pr_reg[8] = regs->r9;
|
||||
prstatus->pr_reg[9] = regs->r8;
|
||||
prstatus->pr_reg[10] = regs->rax;
|
||||
prstatus->pr_reg[11] = regs->rcx;
|
||||
prstatus->pr_reg[12] = regs->rdx;
|
||||
prstatus->pr_reg[13] = regs->rsi;
|
||||
prstatus->pr_reg[14] = regs->rdi;
|
||||
prstatus->pr_reg[15] = regs->rax; /* ??? */
|
||||
prstatus->pr_reg[16] = regs->rip;
|
||||
prstatus->pr_reg[17] = regs->cs;
|
||||
prstatus->pr_reg[18] = regs->rflags;
|
||||
prstatus->pr_reg[19] = regs->rsp;
|
||||
prstatus->pr_reg[20] = regs->ss;
|
||||
prstatus->pr_reg[21] = rdmsr(MSR_FS_BASE);
|
||||
prstatus->pr_reg[22] = rdmsr(MSR_GS_BASE);
|
||||
/* There is no ds, es, fs and gs. */
|
||||
|
||||
prstatus->pr_fpvalid = 0; /* We assume no fp */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the prpsinfo entry of the NOTE segment.
|
||||
*
|
||||
*/
|
||||
|
||||
int get_prpsinfo_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ align32(sizeof(struct elf_prpsinfo64));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill a prpsinfo structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
{
|
||||
void *name;
|
||||
struct elf_prpsinfo64 *prpsinfo;
|
||||
|
||||
head->namesz = sizeof("CORE");
|
||||
head->descsz = sizeof(struct elf_prpsinfo64);
|
||||
head->type = NT_PRPSINFO;
|
||||
name = (void *) (head + 1);
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
prpsinfo = (struct elf_prpsinfo64 *)(name + align32(sizeof("CORE")));
|
||||
|
||||
prpsinfo->pr_state = thread->status;
|
||||
prpsinfo->pr_pid = thread->proc->pid;
|
||||
|
||||
/*
|
||||
We leave most of the fields unfilled.
|
||||
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
a8_uint64_t pr_flag;
|
||||
unsigned int pr_uid;
|
||||
unsigned int pr_gid;
|
||||
int pr_ppid, pr_pgrp, pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the AUXV entry of the NOTE segment.
|
||||
*
|
||||
*/
|
||||
|
||||
int get_auxv_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ sizeof(unsigned long) * AUXV_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill an AUXV structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void fill_auxv(struct note *head, struct thread *thread, void *regs)
|
||||
{
|
||||
void *name;
|
||||
void *auxv;
|
||||
|
||||
head->namesz = sizeof("CORE");
|
||||
head->descsz = sizeof(unsigned long) * AUXV_LEN;
|
||||
head->type = NT_AUXV;
|
||||
name = (void *) (head + 1);
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
auxv = name + align32(sizeof("CORE"));
|
||||
memcpy(auxv, thread->proc->saved_auxv, sizeof(unsigned long) * AUXV_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the whole NOTE segment.
|
||||
*
|
||||
*/
|
||||
|
||||
int get_note_size(void)
|
||||
{
|
||||
return get_prstatus_size() + get_prpsinfo_size()
|
||||
+ get_auxv_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill the NOTE segment.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void fill_note(void *note, struct thread *thread, void *regs)
|
||||
{
|
||||
fill_prstatus(note, thread, regs);
|
||||
note += get_prstatus_size();
|
||||
fill_prpsinfo(note, thread, regs);
|
||||
note += get_prpsinfo_size();
|
||||
fill_auxv(note, thread, regs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate an image of the core file.
|
||||
*
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
* \param coretable(out) An array of core chunks.
|
||||
* \param chunks(out) Number of the entires of coretable.
|
||||
*
|
||||
* A core chunk is represented by a pair of a physical
|
||||
* address of memory region and its size. If there are
|
||||
* no corresponding physical address for a VM area
|
||||
* (an unallocated demand-paging page, e.g.), the address
|
||||
* should be zero.
|
||||
*/
|
||||
|
||||
/*@
|
||||
@ requires \valid(thread);
|
||||
@ requires \valid(regs);
|
||||
@ requires \valid(coretable);
|
||||
@ requires \valid(chunks);
|
||||
@ behavior success:
|
||||
@ ensures \result == 0;
|
||||
@ assigns coretable;
|
||||
@ behavior failure:
|
||||
@ ensures \result == -1;
|
||||
@*/
|
||||
int gencore(struct thread *thread, void *regs,
|
||||
struct coretable **coretable, int *chunks)
|
||||
{
|
||||
struct coretable *ct = NULL;
|
||||
Elf64_Ehdr eh;
|
||||
Elf64_Phdr *ph = NULL;
|
||||
void *note = NULL;
|
||||
struct vm_range *range, *next;
|
||||
struct process_vm *vm = thread->vm;
|
||||
int segs = 1; /* the first one is for NOTE */
|
||||
int notesize, phsize, alignednotesize;
|
||||
unsigned int offset = 0;
|
||||
int i;
|
||||
|
||||
*chunks = 3; /* Elf header , header table and NOTE segment */
|
||||
|
||||
if (vm == NULL) {
|
||||
dkprintf("no vm found.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
next = lookup_process_memory_range(vm, 0, -1);
|
||||
while ((range = next)) {
|
||||
next = next_process_memory_range(vm, range);
|
||||
|
||||
dkprintf("start:%lx end:%lx flag:%lx objoff:%lx\n",
|
||||
range->start, range->end, range->flag, range->objoff);
|
||||
|
||||
if (GENCORE_RANGE_IS_INACCESSIBLE(range)) {
|
||||
continue;
|
||||
}
|
||||
/* We need a chunk for each page for a demand paging area.
|
||||
This can be optimized for spacial complexity but we would
|
||||
lose simplicity instead. */
|
||||
if (range->flag & VR_DEMAND_PAGING) {
|
||||
unsigned long p, phys;
|
||||
int prevzero = 0;
|
||||
for (p = range->start; p < range->end; p += PAGE_SIZE) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
prevzero = 1;
|
||||
} else {
|
||||
if (prevzero == 1)
|
||||
(*chunks)++;
|
||||
(*chunks)++;
|
||||
prevzero = 0;
|
||||
}
|
||||
}
|
||||
if (prevzero == 1)
|
||||
(*chunks)++;
|
||||
} else {
|
||||
(*chunks)++;
|
||||
}
|
||||
segs++;
|
||||
}
|
||||
dkprintf("we have %d segs and %d chunks.\n\n", segs, *chunks);
|
||||
|
||||
{
|
||||
struct vm_regions region = thread->vm->region;
|
||||
|
||||
dkprintf("text: %lx-%lx\n", region.text_start, region.text_end);
|
||||
dkprintf("data: %lx-%lx\n", region.data_start, region.data_end);
|
||||
dkprintf("brk: %lx-%lx\n", region.brk_start, region.brk_end);
|
||||
dkprintf("map: %lx-%lx\n", region.map_start, region.map_end);
|
||||
dkprintf("stack: %lx-%lx\n", region.stack_start, region.stack_end);
|
||||
dkprintf("user: %lx-%lx\n\n", region.user_start, region.user_end);
|
||||
}
|
||||
|
||||
dkprintf("now generate a core file image\n");
|
||||
|
||||
offset += sizeof(eh);
|
||||
fill_elf_header(&eh, segs);
|
||||
|
||||
/* program header table */
|
||||
phsize = sizeof(Elf64_Phdr) * segs;
|
||||
ph = kmalloc(phsize, IHK_MC_AP_NOWAIT);
|
||||
if (ph == NULL) {
|
||||
dkprintf("could not alloc a program header table.\n");
|
||||
goto fail;
|
||||
}
|
||||
memset(ph, 0, phsize);
|
||||
|
||||
offset += phsize;
|
||||
|
||||
/* NOTE segment
|
||||
* To align the next segment page-sized, we prepare a padded
|
||||
* region for our NOTE segment.
|
||||
*/
|
||||
notesize = get_note_size();
|
||||
alignednotesize = alignpage(notesize + offset) - offset;
|
||||
note = kmalloc(alignednotesize, IHK_MC_AP_NOWAIT);
|
||||
if (note == NULL) {
|
||||
dkprintf("could not alloc NOTE for core.\n");
|
||||
goto fail;
|
||||
}
|
||||
memset(note, 0, alignednotesize);
|
||||
fill_note(note, thread, regs);
|
||||
|
||||
/* prgram header for NOTE segment is exceptional */
|
||||
ph[0].p_type = PT_NOTE;
|
||||
ph[0].p_flags = 0;
|
||||
ph[0].p_offset = offset;
|
||||
ph[0].p_vaddr = 0;
|
||||
ph[0].p_paddr = 0;
|
||||
ph[0].p_filesz = notesize;
|
||||
ph[0].p_memsz = notesize;
|
||||
ph[0].p_align = 0;
|
||||
|
||||
offset += alignednotesize;
|
||||
|
||||
/* program header for each memory chunk */
|
||||
i = 1;
|
||||
next = lookup_process_memory_range(vm, 0, -1);
|
||||
while ((range = next)) {
|
||||
next = next_process_memory_range(vm, range);
|
||||
|
||||
unsigned long flag = range->flag;
|
||||
unsigned long size = range->end - range->start;
|
||||
|
||||
if (GENCORE_RANGE_IS_INACCESSIBLE(range)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ph[i].p_type = PT_LOAD;
|
||||
ph[i].p_flags = ((flag & VR_PROT_READ) ? PF_R : 0)
|
||||
| ((flag & VR_PROT_WRITE) ? PF_W : 0)
|
||||
| ((flag & VR_PROT_EXEC) ? PF_X : 0);
|
||||
ph[i].p_offset = offset;
|
||||
ph[i].p_vaddr = range->start;
|
||||
ph[i].p_paddr = 0;
|
||||
ph[i].p_filesz = size;
|
||||
ph[i].p_memsz = size;
|
||||
ph[i].p_align = PAGE_SIZE;
|
||||
i++;
|
||||
offset += size;
|
||||
}
|
||||
|
||||
/* coretable to send to host */
|
||||
ct = kmalloc(sizeof(struct coretable) * (*chunks), IHK_MC_AP_NOWAIT);
|
||||
if (!ct) {
|
||||
dkprintf("could not alloc a coretable.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ct[0].addr = virt_to_phys(&eh); /* ELF header */
|
||||
ct[0].len = 64;
|
||||
dkprintf("coretable[0]: %lx@%lx(%lx)\n", ct[0].len, ct[0].addr, &eh);
|
||||
|
||||
ct[1].addr = virt_to_phys(ph); /* program header table */
|
||||
ct[1].len = phsize;
|
||||
dkprintf("coretable[1]: %lx@%lx(%lx)\n", ct[1].len, ct[1].addr, ph);
|
||||
|
||||
ct[2].addr = virt_to_phys(note); /* NOTE segment */
|
||||
ct[2].len = alignednotesize;
|
||||
dkprintf("coretable[2]: %lx@%lx(%lx)\n", ct[2].len, ct[2].addr, note);
|
||||
|
||||
i = 3; /* memory segments */
|
||||
next = lookup_process_memory_range(vm, 0, -1);
|
||||
while ((range = next)) {
|
||||
next = next_process_memory_range(vm, range);
|
||||
|
||||
unsigned long phys;
|
||||
|
||||
if (GENCORE_RANGE_IS_INACCESSIBLE(range)) {
|
||||
continue;
|
||||
}
|
||||
if (range->flag & VR_DEMAND_PAGING) {
|
||||
/* Just an ad hoc kluge. */
|
||||
unsigned long p, start, phys;
|
||||
int prevzero = 0;
|
||||
unsigned long size = 0;
|
||||
|
||||
for (start = p = range->start;
|
||||
p < range->end; p += PAGE_SIZE) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
if (prevzero == 0) {
|
||||
/* We begin a new chunk */
|
||||
size = PAGE_SIZE;
|
||||
start = p;
|
||||
} else {
|
||||
/* We extend the previous chunk */
|
||||
size += PAGE_SIZE;
|
||||
}
|
||||
prevzero = 1;
|
||||
} else {
|
||||
if (prevzero == 1) {
|
||||
/* Flush out an empty chunk */
|
||||
ct[i].addr = 0;
|
||||
ct[i].len = size;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, start);
|
||||
i++;
|
||||
|
||||
}
|
||||
ct[i].addr = phys;
|
||||
ct[i].len = PAGE_SIZE;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, p);
|
||||
i++;
|
||||
prevzero = 0;
|
||||
}
|
||||
}
|
||||
if (prevzero == 1) {
|
||||
/* An empty chunk */
|
||||
ct[i].addr = 0;
|
||||
ct[i].len = size;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, start);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
if ((thread->vm->region.user_start <= range->start) &&
|
||||
(range->end <= thread->vm->region.user_end)) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)range->start, &phys) != 0) {
|
||||
dkprintf("could not convert user virtual address %lx"
|
||||
"to physical address", range->start);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
phys = virt_to_phys((void *)range->start);
|
||||
}
|
||||
ct[i].addr = phys;
|
||||
ct[i].len = range->end - range->start;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, range->start);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
*coretable = ct;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ct)
|
||||
kfree(ct);
|
||||
if (ph)
|
||||
kfree(ph);
|
||||
if (note)
|
||||
kfree(note);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Free all the allocated spaces for an image of the core file.
|
||||
*
|
||||
* \param coretable An array of core chunks.
|
||||
*/
|
||||
|
||||
/*@
|
||||
@ requires \valid(coretable);
|
||||
@ assigns \nothing;
|
||||
@*/
|
||||
void freecore(struct coretable **coretable)
|
||||
{
|
||||
struct coretable *ct = *coretable;
|
||||
kfree(phys_to_virt(ct[2].addr)); /* NOTE segment */
|
||||
kfree(phys_to_virt(ct[1].addr)); /* ph */
|
||||
kfree(*coretable);
|
||||
}
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -1,5 +1,4 @@
|
||||
/* elf.h COPYRIGHT FUJITSU LIMITED 2018 */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#ifndef __HEADER_X86_COMMON_ELF_H
|
||||
#define __HEADER_X86_COMMON_ELF_H
|
||||
|
||||
@ -57,4 +56,3 @@ struct user_regs64_struct
|
||||
typedef elf_greg64_t elf_gregset64_t[ELF_NGREG64];
|
||||
|
||||
#endif /* __HEADER_S64FX_COMMON_ELF_H */
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
@ -1,95 +0,0 @@
|
||||
/* elfcore.h COPYRIGHT FUJITSU LIMITED 2018 */
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
/*
|
||||
* Structures and definitions for ELF core file.
|
||||
* Extracted from
|
||||
* System V Application Binary Interface - DRAFT - 10 June 2013,
|
||||
* http://www.sco.com/developers/gabi/latest/contents.html
|
||||
*/
|
||||
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
#define EI_OSABI 7
|
||||
#define EI_ABIVERSION 8
|
||||
#define EI_PAD 9
|
||||
|
||||
|
||||
#define ELFMAG0 0x7f
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
#define ELFCLASS64 2 /* 64-bit object */
|
||||
#define ELFDATA2LSB 1 /* LSB */
|
||||
#define El_VERSION 1 /* defined to be the same as EV CURRENT */
|
||||
#define ELFOSABI_NONE 0 /* unspecied */
|
||||
#define El_ABIVERSION_NONE 0 /* unspecied */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
#define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||
#define EM_K10M 181 /* Intel K10M */
|
||||
#define EV_CURRENT 1 /* Current version */
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word p_type;
|
||||
Elf64_Word p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
Elf64_Xword p_filesz;
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
#define PT_LOAD 1
|
||||
#define PT_NOTE 4
|
||||
|
||||
#define PF_X 1 /* executable bit */
|
||||
#define PF_W 2 /* writable bit */
|
||||
#define PF_R 4 /* readable bit */
|
||||
|
||||
struct note {
|
||||
Elf64_Word namesz;
|
||||
Elf64_Word descsz;
|
||||
Elf64_Word type;
|
||||
/* name char[namesz] and desc[descsz] */
|
||||
};
|
||||
|
||||
#define NT_PRSTATUS 1
|
||||
#define NT_PRFRPREG 2
|
||||
#define NT_PRPSINFO 3
|
||||
#define NT_AUXV 6
|
||||
#define NT_X86_STATE 0x202
|
||||
|
||||
#include "elfcoregpl.h"
|
||||
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -1,97 +0,0 @@
|
||||
/* elfcoregpl.h COPYRIGHT FUJITSU LIMITED 2018 */
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
/*
|
||||
* Structures and defines from GPLed file.
|
||||
*/
|
||||
|
||||
#define pid_t int
|
||||
|
||||
/* From /usr/include/linux/elfcore.h of Linux */
|
||||
|
||||
#define ELF_PRARGSZ (80)
|
||||
|
||||
/* From /usr/include/linux/elfcore.h fro Linux */
|
||||
|
||||
struct elf_siginfo
|
||||
{
|
||||
int si_signo;
|
||||
int si_code;
|
||||
int si_errno;
|
||||
};
|
||||
|
||||
/* From bfd/hosts/x86-64linux.h of gdb. */
|
||||
|
||||
typedef uint64_t __attribute__ ((__aligned__ (8))) a8_uint64_t;
|
||||
typedef a8_uint64_t elf_greg64_t;
|
||||
|
||||
struct user_regs64_struct
|
||||
{
|
||||
a8_uint64_t r15;
|
||||
a8_uint64_t r14;
|
||||
a8_uint64_t r13;
|
||||
a8_uint64_t r12;
|
||||
a8_uint64_t rbp;
|
||||
a8_uint64_t rbx;
|
||||
a8_uint64_t r11;
|
||||
a8_uint64_t r10;
|
||||
a8_uint64_t r9;
|
||||
a8_uint64_t r8;
|
||||
a8_uint64_t rax;
|
||||
a8_uint64_t rcx;
|
||||
a8_uint64_t rdx;
|
||||
a8_uint64_t rsi;
|
||||
a8_uint64_t rdi;
|
||||
a8_uint64_t orig_rax;
|
||||
a8_uint64_t rip;
|
||||
a8_uint64_t cs;
|
||||
a8_uint64_t eflags;
|
||||
a8_uint64_t rsp;
|
||||
a8_uint64_t ss;
|
||||
a8_uint64_t fs_base;
|
||||
a8_uint64_t gs_base;
|
||||
a8_uint64_t ds;
|
||||
a8_uint64_t es;
|
||||
a8_uint64_t fs;
|
||||
a8_uint64_t gs;
|
||||
};
|
||||
|
||||
#define ELF_NGREG64 (sizeof (struct user_regs64_struct) / sizeof(elf_greg64_t))
|
||||
|
||||
typedef elf_greg64_t elf_gregset64_t[ELF_NGREG64];
|
||||
|
||||
struct prstatus64_timeval
|
||||
{
|
||||
a8_uint64_t tv_sec;
|
||||
a8_uint64_t tv_usec;
|
||||
};
|
||||
struct elf_prstatus64
|
||||
{
|
||||
struct elf_siginfo pr_info;
|
||||
short int pr_cursig;
|
||||
a8_uint64_t pr_sigpend;
|
||||
a8_uint64_t pr_sighold;
|
||||
pid_t pr_pid;
|
||||
pid_t pr_ppid;
|
||||
pid_t pr_pgrp;
|
||||
pid_t pr_sid;
|
||||
struct prstatus64_timeval pr_utime;
|
||||
struct prstatus64_timeval pr_stime;
|
||||
struct prstatus64_timeval pr_cutime;
|
||||
struct prstatus64_timeval pr_cstime;
|
||||
elf_gregset64_t pr_reg;
|
||||
int pr_fpvalid;
|
||||
};
|
||||
struct elf_prpsinfo64
|
||||
{
|
||||
char pr_state;
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
a8_uint64_t pr_flag;
|
||||
unsigned int pr_uid;
|
||||
unsigned int pr_gid;
|
||||
int pr_pid, pr_ppid, pr_pgrp, pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
};
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -30,13 +30,11 @@ typedef uint64_t size_t;
|
||||
typedef int64_t ssize_t;
|
||||
typedef int64_t off_t;
|
||||
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
typedef int32_t key_t;
|
||||
typedef uint32_t uid_t;
|
||||
typedef uint32_t gid_t;
|
||||
typedef int64_t time_t;
|
||||
typedef int32_t pid_t;
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
#define NULL ((void *)0)
|
||||
|
||||
|
||||
2
ihk
2
ihk
Submodule ihk updated: f5ab8770a4...83d5ec53cb
@ -7,16 +7,9 @@ OBJS = init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o host.o
|
||||
OBJS += process.o copy.o waitq.o futex.o timer.o plist.o fileobj.o shmobj.o
|
||||
OBJS += zeroobj.o procfs.o devobj.o sysfs.o xpmem.o profile.o freeze.o
|
||||
OBJS += rbtree.o hugefileobj.o
|
||||
OBJS += pager.o
|
||||
OBJS += pager.o gencore.o
|
||||
DEPSRCS=$(wildcard $(SRC)/*.c)
|
||||
|
||||
# OBJS added gencore.o
|
||||
ifeq ($(ARCH), arm64)
|
||||
OBJS += gencore.o
|
||||
# POSTK_DEBUG_ARCH_DEP_18 coredump arch separation, delete unnecessary code.
|
||||
#DEPSRCS += $(SRC)/../arch/arm64/kernel/gencore.c
|
||||
endif
|
||||
|
||||
CFLAGS += -I$(SRC)/include -I@abs_builddir@/../ -I@abs_builddir@/include -D__KERNEL__ -g -fno-omit-frame-pointer -fno-inline -fno-inline-small-functions
|
||||
ifneq ($(ARCH), arm64)
|
||||
CFLAGS += -mcmodel=large -mno-red-zone -mno-sse
|
||||
@ -77,10 +70,6 @@ $(IHKOBJ): FORCE
|
||||
%.o: $(SRC)/%.c
|
||||
$(cc_cmd)
|
||||
|
||||
# POSTK_DEBUG_ARCH_DEP_18 coredump arch separation, delete unnecessary code.
|
||||
#gencore.o: ../arch/arm64/kernel/gencore.c
|
||||
# $(cc_cmd)
|
||||
|
||||
FORCE:
|
||||
|
||||
-include Makefile.dep
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* gencore.c COPYRIGHT FUJITSU LIMITED 2015-2018 */
|
||||
#ifndef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
/* gencore.c COPYRIGHT FUJITSU LIMITED 2015-2019 */
|
||||
#include <ihk/debug.h>
|
||||
#include <kmalloc.h>
|
||||
#include <cls.h>
|
||||
@ -7,7 +6,6 @@
|
||||
#include <process.h>
|
||||
#include <string.h>
|
||||
#include <elfcore.h>
|
||||
#include <debug.h>
|
||||
|
||||
#define align32(x) ((((x) + 3) / 4) * 4)
|
||||
#define alignpage(x) ((((x) + (PAGE_SIZE) - 1) / (PAGE_SIZE)) * (PAGE_SIZE))
|
||||
@ -25,9 +23,8 @@
|
||||
#define GENCORE_RANGE_IS_INACCESSIBLE(range) \
|
||||
((range->flag & (VR_RESERVED | VR_MEMTYPE_UC | VR_DONTDUMP)))
|
||||
|
||||
/*
|
||||
* Generate a core file image, which consists of many chunks.
|
||||
* Returns an allocated table, an etnry of which is a pair of the address
|
||||
/* Generate a core file image, which consists of many chunks.
|
||||
* Returns an allocated table, an etnry of which is a pair of the address
|
||||
* of a chunk and its length.
|
||||
*/
|
||||
|
||||
@ -44,18 +41,14 @@ void fill_elf_header(Elf64_Ehdr *eh, int segs)
|
||||
eh->e_ident[EI_MAG1] = 'E';
|
||||
eh->e_ident[EI_MAG2] = 'L';
|
||||
eh->e_ident[EI_MAG3] = 'F';
|
||||
eh->e_ident[EI_CLASS] = ELFCLASS64;
|
||||
eh->e_ident[EI_DATA] = ELFDATA2LSB;
|
||||
eh->e_ident[EI_CLASS] = ELF_CLASS;
|
||||
eh->e_ident[EI_DATA] = ELF_DATA;
|
||||
eh->e_ident[EI_VERSION] = El_VERSION;
|
||||
eh->e_ident[EI_OSABI] = ELFOSABI_NONE;
|
||||
eh->e_ident[EI_ABIVERSION] = El_ABIVERSION_NONE;
|
||||
eh->e_ident[EI_OSABI] = ELF_OSABI;
|
||||
eh->e_ident[EI_ABIVERSION] = ELF_ABIVERSION;
|
||||
|
||||
eh->e_type = ET_CORE;
|
||||
#ifdef CONFIG_MIC
|
||||
eh->e_machine = EM_K10M;
|
||||
#else
|
||||
eh->e_machine = EM_X86_64;
|
||||
#endif
|
||||
eh->e_machine = ELF_ARCH;
|
||||
eh->e_version = EV_CURRENT;
|
||||
eh->e_entry = 0; /* Do we really need this? */
|
||||
eh->e_phoff = 64; /* fixed */
|
||||
@ -76,23 +69,10 @@ void fill_elf_header(Elf64_Ehdr *eh, int segs)
|
||||
|
||||
int get_prstatus_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ align32(sizeof(struct elf_prstatus64));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill a prstatus structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs0 A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
{
|
||||
/* TODO(pka_idle) */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the prpsinfo entry of the NOTE segment.
|
||||
*
|
||||
@ -100,16 +80,38 @@ void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
|
||||
int get_prpsinfo_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ align32(sizeof(struct elf_prpsinfo64));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill a prstatus structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param proc A pointer to the current process structure.
|
||||
* \param regs0 A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
{
|
||||
void *name;
|
||||
struct elf_prstatus64 *prstatus;
|
||||
|
||||
head->namesz = sizeof("CORE");
|
||||
head->descsz = sizeof(struct elf_prstatus64);
|
||||
head->type = NT_PRSTATUS;
|
||||
name = (void *) (head + 1);
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
prstatus = (struct elf_prstatus64 *)(name + align32(sizeof("CORE")));
|
||||
|
||||
arch_fill_prstatus(prstatus, thread, regs0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill a prpsinfo structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
* \param proc A pointer to the current process structure.
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
@ -127,20 +129,18 @@ void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
prpsinfo->pr_state = thread->status;
|
||||
prpsinfo->pr_pid = thread->proc->pid;
|
||||
|
||||
/*
|
||||
We leave most of the fields unfilled.
|
||||
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
a8_uint64_t pr_flag;
|
||||
unsigned int pr_uid;
|
||||
unsigned int pr_gid;
|
||||
int pr_ppid, pr_pgrp, pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
*/
|
||||
}
|
||||
/* TODO: Fill the following fields:
|
||||
* char pr_sname;
|
||||
* char pr_zomb;
|
||||
* char pr_nice;
|
||||
* a8_uint64_t pr_flag;
|
||||
* unsigned int pr_uid;
|
||||
* unsigned int pr_gid;
|
||||
* int pr_ppid, pr_pgrp, pr_sid;
|
||||
* char pr_fname[16];
|
||||
* char pr_psargs[ELF_PRARGSZ];
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the AUXV entry of the NOTE segment.
|
||||
@ -149,7 +149,7 @@ void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
|
||||
int get_auxv_size(void)
|
||||
{
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
return sizeof(struct note) + align32(sizeof("CORE"))
|
||||
+ sizeof(unsigned long) * AUXV_LEN;
|
||||
}
|
||||
|
||||
@ -157,8 +157,8 @@ int get_auxv_size(void)
|
||||
* \brief Fill an AUXV structure.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
* \param proc A pointer to the current process structure.
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_auxv(struct note *head, struct thread *thread, void *regs)
|
||||
@ -172,8 +172,9 @@ void fill_auxv(struct note *head, struct thread *thread, void *regs)
|
||||
name = (void *) (head + 1);
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
auxv = name + align32(sizeof("CORE"));
|
||||
memcpy(auxv, thread->proc->saved_auxv, sizeof(unsigned long) * AUXV_LEN);
|
||||
}
|
||||
memcpy(auxv, thread->proc->saved_auxv,
|
||||
sizeof(unsigned long) * AUXV_LEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the size of the whole NOTE segment.
|
||||
@ -190,8 +191,8 @@ int get_note_size(void)
|
||||
* \brief Fill the NOTE segment.
|
||||
*
|
||||
* \param head A pointer to a note structure.
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
* \param proc A pointer to the current process structure.
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_note(void *note, struct thread *thread, void *regs)
|
||||
@ -206,23 +207,27 @@ void fill_note(void *note, struct thread *thread, void *regs)
|
||||
/**
|
||||
* \brief Generate an image of the core file.
|
||||
*
|
||||
* \param thread A pointer to the current thread structure.
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
* \param proc A pointer to the current process structure.
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
* \param coretable(out) An array of core chunks.
|
||||
* \param chunks(out) Number of the entires of coretable.
|
||||
*
|
||||
* A core chunk is represented by a pair of a physical
|
||||
* A core chunk is represented by a pair of a physical
|
||||
* address of memory region and its size. If there are
|
||||
* no corresponding physical address for a VM area
|
||||
* no corresponding physical address for a VM area
|
||||
* (an unallocated demand-paging page, e.g.), the address
|
||||
* should be zero.
|
||||
*/
|
||||
|
||||
int gencore(struct thread *thread, void *regs,
|
||||
int gencore(struct thread *thread, void *regs,
|
||||
struct coretable **coretable, int *chunks)
|
||||
{
|
||||
struct coretable *ct = NULL;
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_39
|
||||
Elf64_Ehdr *eh = NULL;
|
||||
#else
|
||||
Elf64_Ehdr eh;
|
||||
#endif /*POSTK_DEBUG_TEMP_FIX_39*/
|
||||
Elf64_Phdr *ph = NULL;
|
||||
void *note = NULL;
|
||||
struct vm_range *range, *next;
|
||||
@ -243,20 +248,22 @@ int gencore(struct thread *thread, void *regs,
|
||||
while ((range = next)) {
|
||||
next = next_process_memory_range(vm, range);
|
||||
|
||||
dkprintf("start:%lx end:%lx flag:%lx objoff:%lx\n",
|
||||
dkprintf("start:%lx end:%lx flag:%lx objoff:%lx\n",
|
||||
range->start, range->end, range->flag, range->objoff);
|
||||
|
||||
if (GENCORE_RANGE_IS_INACCESSIBLE(range)) {
|
||||
continue;
|
||||
}
|
||||
/* We need a chunk for each page for a demand paging area.
|
||||
This can be optimized for spacial complexity but we would
|
||||
lose simplicity instead. */
|
||||
* This can be optimized for spacial complexity but we would
|
||||
* lose simplicity instead.
|
||||
*/
|
||||
if (range->flag & VR_DEMAND_PAGING) {
|
||||
unsigned long p, phys;
|
||||
int prevzero = 0;
|
||||
|
||||
for (p = range->start; p < range->end; p += PAGE_SIZE) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
prevzero = 1;
|
||||
} else {
|
||||
@ -278,18 +285,36 @@ int gencore(struct thread *thread, void *regs,
|
||||
{
|
||||
struct vm_regions region = thread->vm->region;
|
||||
|
||||
dkprintf("text: %lx-%lx\n", region.text_start, region.text_end);
|
||||
dkprintf("data: %lx-%lx\n", region.data_start, region.data_end);
|
||||
dkprintf("text: %lx-%lx\n", region.text_start,
|
||||
region.text_end);
|
||||
dkprintf("data: %lx-%lx\n", region.data_start,
|
||||
region.data_end);
|
||||
dkprintf("brk: %lx-%lx\n", region.brk_start, region.brk_end);
|
||||
dkprintf("map: %lx-%lx\n", region.map_start, region.map_end);
|
||||
dkprintf("stack: %lx-%lx\n", region.stack_start, region.stack_end);
|
||||
dkprintf("user: %lx-%lx\n\n", region.user_start, region.user_end);
|
||||
dkprintf("stack: %lx-%lx\n", region.stack_start,
|
||||
region.stack_end);
|
||||
dkprintf("user: %lx-%lx\n\n", region.user_start,
|
||||
region.user_end);
|
||||
}
|
||||
|
||||
dkprintf("now generate a core file image\n");
|
||||
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_39
|
||||
eh = kmalloc(sizeof(*eh), IHK_MC_AP_NOWAIT);
|
||||
if (eh == NULL) {
|
||||
dkprintf("could not alloc a elf header table.\n");
|
||||
goto fail;
|
||||
}
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_63 /* Add core table and elf header initialization */
|
||||
memset(eh, 0, sizeof(*eh));
|
||||
#endif /* POSTK_DEBUG_TEMP_FIX_63 */
|
||||
|
||||
offset += sizeof(*eh);
|
||||
fill_elf_header(eh, segs);
|
||||
#else
|
||||
offset += sizeof(eh);
|
||||
fill_elf_header(&eh, segs);
|
||||
#endif /* POSTK_DEBUG_TEMP_FIX_39 */
|
||||
|
||||
/* program header table */
|
||||
phsize = sizeof(Elf64_Phdr) * segs;
|
||||
@ -361,10 +386,19 @@ int gencore(struct thread *thread, void *regs,
|
||||
dkprintf("could not alloc a coretable.\n");
|
||||
goto fail;
|
||||
}
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_63 /* Add core table and elf header initialization */
|
||||
memset(ct, 0, sizeof(*ct));
|
||||
#endif /* POSTK_DEBUG_TEMP_FIX_63 */
|
||||
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_39
|
||||
ct[0].addr = virt_to_phys(eh); /* ELF header */
|
||||
ct[0].len = 64;
|
||||
dkprintf("coretable[0]: %lx@%lx(%lx)\n", ct[0].len, ct[0].addr, eh);
|
||||
#else
|
||||
ct[0].addr = virt_to_phys(&eh); /* ELF header */
|
||||
ct[0].len = 64;
|
||||
ct[0].len = 64;
|
||||
dkprintf("coretable[0]: %lx@%lx(%lx)\n", ct[0].len, ct[0].addr, &eh);
|
||||
#endif /* POSTK_DEBUG_TEMP_FIX_39 */
|
||||
|
||||
ct[1].addr = virt_to_phys(ph); /* program header table */
|
||||
ct[1].len = phsize;
|
||||
@ -384,22 +418,23 @@ int gencore(struct thread *thread, void *regs,
|
||||
if (GENCORE_RANGE_IS_INACCESSIBLE(range)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (range->flag & VR_DEMAND_PAGING) {
|
||||
/* Just an ad hoc kluge. */
|
||||
unsigned long p, start, phys;
|
||||
int prevzero = 0;
|
||||
unsigned long size = 0;
|
||||
|
||||
for (start = p = range->start;
|
||||
for (start = p = range->start;
|
||||
p < range->end; p += PAGE_SIZE) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
if (prevzero == 0) {
|
||||
/* We begin a new chunk */
|
||||
/* Start a new chunk */
|
||||
size = PAGE_SIZE;
|
||||
start = p;
|
||||
} else {
|
||||
/* We extend the previous chunk */
|
||||
/* Extend the previous chunk */
|
||||
size += PAGE_SIZE;
|
||||
}
|
||||
prevzero = 1;
|
||||
@ -408,15 +443,16 @@ int gencore(struct thread *thread, void *regs,
|
||||
/* Flush out an empty chunk */
|
||||
ct[i].addr = 0;
|
||||
ct[i].len = size;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, start);
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n",
|
||||
i, ct[i].len,
|
||||
ct[i].addr, start);
|
||||
i++;
|
||||
|
||||
}
|
||||
ct[i].addr = phys;
|
||||
ct[i].len = PAGE_SIZE;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, p);
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n",
|
||||
i, ct[i].len, ct[i].addr, p);
|
||||
i++;
|
||||
prevzero = 0;
|
||||
}
|
||||
@ -425,17 +461,20 @@ int gencore(struct thread *thread, void *regs,
|
||||
/* An empty chunk */
|
||||
ct[i].addr = 0;
|
||||
ct[i].len = size;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, start);
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n",
|
||||
i, ct[i].len, ct[i].addr, start);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((thread->vm->region.user_start <= range->start) &&
|
||||
(range->end <= thread->vm->region.user_end)) {
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)range->start, &phys) != 0) {
|
||||
dkprintf("could not convert user virtual address %lx"
|
||||
"to physical address", range->start);
|
||||
if (ihk_mc_pt_virt_to_phys(thread->vm->address_space->page_table,
|
||||
(void *)range->start,
|
||||
&phys) != 0) {
|
||||
dkprintf("could not convert user "
|
||||
"virtual address %lx "
|
||||
"to physical address\n",
|
||||
range->start);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@ -443,7 +482,7 @@ int gencore(struct thread *thread, void *regs,
|
||||
}
|
||||
ct[i].addr = phys;
|
||||
ct[i].len = range->end - range->start;
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
dkprintf("coretable[%d]: %lx@%lx(%lx)\n", i,
|
||||
ct[i].len, ct[i].addr, range->start);
|
||||
i++;
|
||||
}
|
||||
@ -452,13 +491,10 @@ int gencore(struct thread *thread, void *regs,
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ct)
|
||||
kfree(ct);
|
||||
if (ph)
|
||||
kfree(ph);
|
||||
if (note)
|
||||
kfree(note);
|
||||
fail:
|
||||
kfree(ct);
|
||||
kfree(ph);
|
||||
kfree(note);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -471,8 +507,11 @@ int gencore(struct thread *thread, void *regs,
|
||||
void freecore(struct coretable **coretable)
|
||||
{
|
||||
struct coretable *ct = *coretable;
|
||||
|
||||
kfree(phys_to_virt(ct[2].addr)); /* NOTE segment */
|
||||
kfree(phys_to_virt(ct[1].addr)); /* ph */
|
||||
#ifdef POSTK_DEBUG_TEMP_FIX_39
|
||||
kfree(phys_to_virt(ct[0].addr)); /* eh */
|
||||
#endif /*POSTK_DEBUG_TEMP_FIX_39*/
|
||||
kfree(*coretable);
|
||||
}
|
||||
#endif /* !POSTK_DEBUG_ARCH_DEP_18 */
|
||||
@ -1,5 +1,4 @@
|
||||
/* elfcore.h COPYRIGHT FUJITSU LIMITED 2015-2016 */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#ifndef __HEADER_ELFCORE_H
|
||||
#define __HEADER_ELFCORE_H
|
||||
|
||||
@ -101,11 +100,7 @@ struct note {
|
||||
};
|
||||
|
||||
#define NT_PRSTATUS 1
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#define NT_PRFPREG 2
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
#define NT_PRFRPREG 2
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
#define NT_PRPSINFO 3
|
||||
#define NT_AUXV 6
|
||||
|
||||
@ -116,10 +111,3 @@ struct thread;
|
||||
extern void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread, void *regs0);
|
||||
|
||||
#endif /* __HEADER_ELFCORE_H */
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
#ifdef __x86_64
|
||||
#include "../../arch/x86_64/kernel/include/elfcore.h"
|
||||
#elif __aarch64__
|
||||
#include "../../arch/arm64/kernel/include/elfcore.h"
|
||||
#endif
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
/* elfcoregpl.h COPYRIGHT FUJITSU LIMITED 2015-2016 */
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#ifndef __HEADER_ELFCOREGPL_H
|
||||
#define __HEADER_ELFCOREGPL_H
|
||||
|
||||
@ -64,10 +63,3 @@ struct elf_prpsinfo64
|
||||
};
|
||||
|
||||
#endif /* __HEADER_ELFCOREGPL_H */
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
#ifdef __x86_64
|
||||
#include "../../arch/x86/kernel/include/elfcoregpl.h"
|
||||
#elif __aarch64__
|
||||
#include "../../arch/arm64/kernel/include/elfcoregpl.h"
|
||||
#endif
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
@ -21,17 +21,6 @@
|
||||
#include <list.h>
|
||||
#include <pager.h>
|
||||
|
||||
#ifdef POSTK_DEBUG_ARCH_DEP_18 /* coredump arch separation. */
|
||||
#else /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
/* begin types.h */
|
||||
typedef int32_t key_t;
|
||||
typedef uint32_t uid_t;
|
||||
typedef uint32_t gid_t;
|
||||
typedef int64_t time_t;
|
||||
typedef int32_t pid_t;
|
||||
/* end types.h */
|
||||
#endif /* POSTK_DEBUG_ARCH_DEP_18 */
|
||||
|
||||
enum {
|
||||
/* for memobj.flags */
|
||||
MF_HAS_PAGER = 0x0001,
|
||||
|
||||
Reference in New Issue
Block a user