Added code for generating core image.

modified:   arch/x86/kernel/gencore.c
	modified:   arch/x86/kernel/include/elfcore.h
	modified:   kernel/include/process.h
	modified:   kernel/process.c
This commit is contained in:
Naoki Hamada
2014-07-10 15:55:35 +09:00
parent 0d7d1ebbd5
commit 1d45444d54
4 changed files with 219 additions and 45 deletions

View File

@ -3,8 +3,11 @@
#include <cls.h>
#include <list.h>
#include <process.h>
#include <string.h>
#include <elfcore.h>
#define align32(x) ((((x) + 3) / 4) * 4)
#define DEBUG_PRINT_GENCORE
#ifdef DEBUG_PRINT_GENCORE
@ -21,6 +24,184 @@
* of a chunk and its length.
*/
/* ELF header */
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;
eh->e_machine = EM_K10M;
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;
}
/* prstatus NOTE */
int get_prstatus_size(void)
{
return sizeof(struct note) + align32(sizeof("CORE"))
+ align32(sizeof(struct elf_prstatus64));
}
void fill_prstatus(struct note *head, struct process *proc, void *regs0)
{
void *name;
struct elf_prstatus64 *prstatus;
struct x86_regs *regs = regs0;
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 */
}
/* prpsinfo NOTE */
int get_prpsinfo_size(void)
{
return sizeof(struct note) + align32(sizeof("CORE"))
+ align32(sizeof(struct elf_prpsinfo64));
}
void fill_prpsinfo(struct note *head, struct process *proc, 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 = proc->status;
prpsinfo->pr_pid = proc->pid;
/*
We leave most of the fields unfilled.
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_ppid, pr_pgrp, pr_sid;
char pr_fname[16];
char pr_psargs[ELF_PRARGSZ];
*/
}
/* auxv NOTE */
int get_auxv_size(void)
{
return sizeof(struct note) + align32(sizeof("CORE"))
+ sizeof(unsigned long) * AUXV_LEN;
}
void fill_auxv(struct note *head, struct process *proc, 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, proc->saved_auxv, sizeof(unsigned long) * AUXV_LEN);
}
/* whole NOTE segment */
int get_note_size(void)
{
return get_prstatus_size() + get_prpsinfo_size()
+ get_auxv_size();
}
void fill_note(void *note, struct process *proc, void *regs)
{
fill_prstatus(note, proc, regs);
note += get_prstatus_size();
fill_prpsinfo(note, proc, regs);
note += get_prpsinfo_size();
fill_auxv(note, proc, regs);
}
/* whole core image */
int gencore(struct process *proc, void *regs,
struct coretable **coretable, int *chunks)
{
@ -30,7 +211,7 @@ int gencore(struct process *proc, void *regs,
void *note;
struct vm_range *range;
struct process_vm *vm = proc->vm;
int segs = 1; /* the first one is for NOTES */
int segs = 1; /* the first one is for NOTE */
int notesize, phsize;
unsigned int offset = 0;
int i;
@ -43,10 +224,13 @@ int gencore(struct process *proc, void *regs,
list_for_each_entry(range, &vm->vm_range_list, list) {
dkprintf("start:%x end:%x flag:%x objoff:%x\n",
range->start, range->end, range->flag, range->objoff);
if ((range->flag && VR_RESERVED) == 0)
segs++;
/* We omit reserved areas because they are only for
mckernel's internal use. */
if ((range->flag && VR_RESERVED) != 0)
continue;
segs++;
}
dkprintf("we have %d segs including one for NOTES.\n\n", segs);
dkprintf("we have %d segs including one for NOTE.\n\n", segs);
{
struct vm_regions region = proc->vm->region;
@ -57,7 +241,6 @@ int gencore(struct process *proc, void *regs,
dkprintf("map: %x-%x\n", region.map_start, region.map_end);
dkprintf("stack: %x-%x\n", region.stack_start, region.stack_end);
dkprintf("user: %x-%x\n\n", region.user_start, region.user_end);
}
dkprintf("now generate a core file image\n");
@ -66,37 +249,18 @@ int gencore(struct process *proc, void *regs,
#ifndef DUMMY
/* ELF header */
offset += sizeof(eh);
fill_elf_header(&eh, 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;
eh.e_machine = EM_K10M;
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;
offset += 64;
notesize = 1024; /* dummy */
notesize = get_note_size();
note = kmalloc(notesize, IHK_MC_AP_NOWAIT);
if (note == NULL) {
dkprintf("could not alloc NOTE for core.\n");
goto fail;
}
fill_note(note, proc, regs);
/* program header table */
phsize = sizeof(Elf64_Phdr) * segs;
ph = kmalloc(phsize, IHK_MC_AP_NOWAIT);
if (ph == NULL) {
@ -107,7 +271,6 @@ int gencore(struct process *proc, void *regs,
offset += phsize;
/* prgram header for NOTE segment is exceptional */
ph[0].p_type = PT_NOTE;
ph[0].p_flags = 0;
ph[0].p_offset = offset;
@ -123,8 +286,10 @@ int gencore(struct process *proc, void *regs,
unsigned long flag = range->flag;
unsigned long size = range->end - range->start;
if ((range->flag && VR_RESERVED) != 0)
continue;
ph[i].p_type = PT_LOAD;
/* xxx */
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);
@ -138,14 +303,6 @@ int gencore(struct process *proc, void *regs,
offset += size;
}
/* note */
note = kmalloc(notesize, IHK_MC_AP_NOWAIT);
if (note == NULL) {
dkprintf("could not alloc note.\n");
goto fail;
}
/* coretable to send to host */
ct = kmalloc(sizeof(struct coretable) * (segs + 2), IHK_MC_AP_NOWAIT);
if (!ct) {
@ -164,6 +321,8 @@ int gencore(struct process *proc, void *regs,
i = 3; /* memory segments */
list_for_each_entry(range, &vm->vm_range_list, list) {
if ((range->flag && VR_RESERVED) != 0)
continue;
ct[i].addr = virt_to_phys(range->start);
ct[i].len = range->end - range->start;
i++;

View File

@ -74,12 +74,18 @@ typedef struct {
#define PF_W 2 /* writable bit */
#define PF_R 4 /* readable bit */
typedef struct note {
struct note {
Elf64_Xword namesz;
Elf64_Xword descsz;
Elf64_Xword type;
char *contents; /* name char[namesz] and desc[descsz] */
} Elf64_Nhdr;
};
#define NT_PRSTATUS 1
#define NT_PRFRPREG 2
#define NT_PRPSINFO 3
#define NT_AUXV 6
#define NT_X86_STATE 0x202
#include "elfcoregpl.h"