coredump: Support threads
Change-Id: Id75ade6c87b15abcff5d772d90f77950376a32c1 Refs: #1219
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,6 +13,8 @@ old_timestamp
|
||||
CMakeFiles
|
||||
CMakeCache.txt
|
||||
Makefile
|
||||
!test/*/*/Makefile
|
||||
!test/*/*/*.cmd
|
||||
Kbuild
|
||||
cmake_install.cmake
|
||||
config.h
|
||||
|
||||
@@ -19,8 +19,6 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
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;
|
||||
@@ -28,12 +26,18 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
struct prstatus64_timeval pr_cutime;
|
||||
struct prstatus64_timeval pr_cstime;
|
||||
*/
|
||||
|
||||
/* copy x0-30, sp, pc, pstate */
|
||||
memcpy(&tmp_prstatus.pr_reg, ®s->user_regs, sizeof(tmp_prstatus.pr_reg));
|
||||
tmp_prstatus.pr_fpvalid = 0; /* We assume no fp */
|
||||
|
||||
/* copy unaligned prstatus addr */
|
||||
memcpy(prstatus, &tmp_prstatus, sizeof(*prstatus));
|
||||
|
||||
prstatus->pr_pid = thread->tid;
|
||||
if (thread->proc->parent) {
|
||||
prstatus->pr_ppid = thread->proc->parent->pid;
|
||||
}
|
||||
}
|
||||
|
||||
int arch_get_thread_core_info_size(void)
|
||||
|
||||
@@ -127,10 +127,18 @@ extern unsigned long do_fork(int clone_flags, unsigned long newsp,
|
||||
|
||||
SYSCALL_DECLARE(clone)
|
||||
{
|
||||
struct process *proc = cpu_local_var(current)->proc;
|
||||
struct mcs_rwlock_node_irqsave lock_dump;
|
||||
unsigned long ret;
|
||||
|
||||
/* mutex coredump */
|
||||
mcs_rwlock_reader_lock(&proc->coredump_lock, &lock_dump);
|
||||
|
||||
if ((int)ihk_mc_syscall_arg0(ctx) & CLONE_VFORK) {
|
||||
return do_fork(CLONE_VFORK|SIGCHLD, 0, 0, 0, 0, ihk_mc_syscall_pc(ctx), ihk_mc_syscall_sp(ctx));
|
||||
ret = do_fork(CLONE_VFORK|SIGCHLD, 0, 0, 0, 0,
|
||||
ihk_mc_syscall_pc(ctx), ihk_mc_syscall_sp(ctx));
|
||||
} else {
|
||||
return do_fork((int)ihk_mc_syscall_arg0(ctx), /* clone_flags */
|
||||
ret = do_fork((int)ihk_mc_syscall_arg0(ctx), /* clone_flags */
|
||||
ihk_mc_syscall_arg1(ctx), /* newsp */
|
||||
ihk_mc_syscall_arg2(ctx), /* parent_tidptr */
|
||||
ihk_mc_syscall_arg4(ctx), /* child_tidptr (swap arg3) */
|
||||
@@ -138,6 +146,9 @@ SYSCALL_DECLARE(clone)
|
||||
ihk_mc_syscall_pc(ctx), /* curpc */
|
||||
ihk_mc_syscall_sp(ctx)); /* cursp */
|
||||
}
|
||||
mcs_rwlock_reader_unlock(&proc->coredump_lock, &lock_dump);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(rt_sigaction)
|
||||
@@ -657,7 +668,7 @@ void set_single_step(struct thread *thread)
|
||||
set_regs_spsr_ss(thread->uctx);
|
||||
}
|
||||
|
||||
extern void coredump(struct thread *thread, void *regs);
|
||||
extern int coredump(struct thread *thread, void *regs, int sig);
|
||||
|
||||
static int
|
||||
isrestart(int syscallno, unsigned long rc, int sig, int restart)
|
||||
@@ -1096,6 +1107,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
struct mcs_rwlock_node_irqsave lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
int restart = 0;
|
||||
int ret;
|
||||
|
||||
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||
dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig);
|
||||
@@ -1290,9 +1302,31 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
case SIGXCPU:
|
||||
case SIGXFSZ:
|
||||
core:
|
||||
dkprintf("do_signal,default,core,sig=%d\n", sig);
|
||||
coredump(thread, regs);
|
||||
coredumped = 0x80;
|
||||
thread->coredump_regs =
|
||||
kmalloc(sizeof(struct pt_regs),
|
||||
IHK_MC_AP_NOWAIT);
|
||||
if (!thread->coredump_regs) {
|
||||
kprintf("%s: Out of memory\n", __func__);
|
||||
goto skip;
|
||||
}
|
||||
memcpy(thread->coredump_regs, regs,
|
||||
sizeof(struct pt_regs));
|
||||
|
||||
ret = coredump(thread, regs, sig);
|
||||
switch (ret) {
|
||||
case -EBUSY:
|
||||
kprintf("%s: INFO: coredump not performed, try ulimit -c <non-zero>\n",
|
||||
__func__);
|
||||
break;
|
||||
case 0:
|
||||
coredumped = 0x80;
|
||||
break;
|
||||
default:
|
||||
kprintf("%s: ERROR: coredump failed (%d)\n",
|
||||
__func__, ret);
|
||||
break;
|
||||
}
|
||||
skip:
|
||||
terminate(0, sig | coredumped);
|
||||
break;
|
||||
case SIGCHLD:
|
||||
@@ -1870,7 +1904,7 @@ set_signal(int sig, void *regs0, siginfo_t *info)
|
||||
}
|
||||
|
||||
if ((__sigmask(sig) & thread->sigmask.__val[0])) {
|
||||
coredump(thread, regs0);
|
||||
coredump(thread, regs0, sig);
|
||||
terminate(0, sig | 0x80);
|
||||
}
|
||||
do_kill(thread, thread->proc->pid, thread->tid, sig, info, 0);
|
||||
|
||||
@@ -18,8 +18,6 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
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;
|
||||
@@ -28,6 +26,11 @@ void arch_fill_prstatus(struct elf_prstatus64 *prstatus, struct thread *thread,
|
||||
struct prstatus64_timeval pr_cstime;
|
||||
*/
|
||||
|
||||
prstatus->pr_pid = thread->tid;
|
||||
if (thread->proc->parent) {
|
||||
prstatus->pr_ppid = thread->proc->parent->pid;
|
||||
}
|
||||
|
||||
prstatus->pr_reg[0] = _r15;
|
||||
prstatus->pr_reg[1] = _r14;
|
||||
prstatus->pr_reg[2] = _r13;
|
||||
|
||||
@@ -573,7 +573,7 @@ long ptrace_write_regset(struct thread *thread, long type, struct iovec *iov)
|
||||
return rc;
|
||||
}
|
||||
|
||||
extern void coredump(struct thread *thread, void *regs);
|
||||
extern int coredump(struct thread *thread, void *regs, int sig);
|
||||
|
||||
void ptrace_report_signal(struct thread *thread, int sig)
|
||||
{
|
||||
@@ -741,6 +741,7 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
struct mcs_rwlock_node_irqsave lock;
|
||||
struct mcs_rwlock_node_irqsave mcs_rw_node;
|
||||
int restart = 0;
|
||||
int ret;
|
||||
|
||||
for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1);
|
||||
dkprintf("do_signal(): tid=%d, pid=%d, sig=%d\n", thread->tid, proc->pid, sig);
|
||||
@@ -1006,9 +1007,31 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi
|
||||
case SIGXCPU:
|
||||
case SIGXFSZ:
|
||||
core:
|
||||
dkprintf("do_signal,default,core,sig=%d\n", sig);
|
||||
coredump(thread, regs);
|
||||
coredumped = 0x80;
|
||||
thread->coredump_regs =
|
||||
kmalloc(sizeof(struct x86_user_context),
|
||||
IHK_MC_AP_NOWAIT);
|
||||
if (!thread->coredump_regs) {
|
||||
kprintf("%s: Out of memory\n", __func__);
|
||||
goto skip;
|
||||
}
|
||||
memcpy(thread->coredump_regs, regs,
|
||||
sizeof(struct x86_user_context));
|
||||
|
||||
ret = coredump(thread, regs, sig);
|
||||
switch (ret) {
|
||||
case -EBUSY:
|
||||
kprintf("%s: INFO: coredump not performed, try ulimit -c <non-zero>\n",
|
||||
__func__);
|
||||
break;
|
||||
case 0:
|
||||
coredumped = 0x80;
|
||||
break;
|
||||
default:
|
||||
kprintf("%s: ERROR: coredump failed (%d)\n",
|
||||
__func__, ret);
|
||||
break;
|
||||
}
|
||||
skip:
|
||||
terminate(0, sig | coredumped);
|
||||
break;
|
||||
case SIGCHLD:
|
||||
@@ -1609,7 +1632,7 @@ set_signal(int sig, void *regs0, siginfo_t *info)
|
||||
}
|
||||
|
||||
if ((__sigmask(sig) & thread->sigmask.__val[0])) {
|
||||
coredump(thread, regs0);
|
||||
coredump(thread, regs0, sig);
|
||||
terminate(0, sig | 0x80);
|
||||
}
|
||||
do_kill(thread, thread->proc->pid, thread->tid, sig, info, 0);
|
||||
@@ -1763,10 +1786,20 @@ out:
|
||||
|
||||
SYSCALL_DECLARE(clone)
|
||||
{
|
||||
return do_fork((int)ihk_mc_syscall_arg0(ctx), ihk_mc_syscall_arg1(ctx),
|
||||
struct process *proc = cpu_local_var(current)->proc;
|
||||
struct mcs_rwlock_node_irqsave lock_dump;
|
||||
unsigned long ret;
|
||||
|
||||
/* mutex coredump */
|
||||
mcs_rwlock_reader_lock(&proc->coredump_lock, &lock_dump);
|
||||
|
||||
ret = do_fork((int)ihk_mc_syscall_arg0(ctx), ihk_mc_syscall_arg1(ctx),
|
||||
ihk_mc_syscall_arg2(ctx), ihk_mc_syscall_arg3(ctx),
|
||||
ihk_mc_syscall_arg4(ctx), ihk_mc_syscall_pc(ctx),
|
||||
ihk_mc_syscall_sp(ctx));
|
||||
|
||||
mcs_rwlock_reader_unlock(&proc->coredump_lock, &lock_dump);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DECLARE(fork)
|
||||
|
||||
@@ -1922,7 +1922,10 @@ int release_user_space(uintptr_t start, uintptr_t len)
|
||||
* \param chunks The number of chunks which make a core file image in the whole.
|
||||
*/
|
||||
|
||||
static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) {
|
||||
static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks,
|
||||
unsigned long cmdline_rphys, unsigned long cmdline_len)
|
||||
{
|
||||
char *fn = NULL;
|
||||
struct file *file;
|
||||
struct coretable *coretable;
|
||||
int i, tablesize, error = 0;
|
||||
@@ -1931,22 +1934,43 @@ static int writecore(ihk_os_t os, unsigned long rcoretable, int chunks) {
|
||||
unsigned long phys, tablephys, rphys;
|
||||
ihk_device_t dev = ihk_os_to_dev(os);
|
||||
char *pt;
|
||||
unsigned long cmdline_phys;
|
||||
char *cmdline;
|
||||
|
||||
dprintk("coredump called as a pseudo syscall\n");
|
||||
|
||||
fn = kmalloc(PATH_MAX, GFP_ATOMIC);
|
||||
if (!fn) {
|
||||
dprintk("%s: ERROR: allocating file name\n", __func__);
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (chunks <= 0) {
|
||||
dprintk("no core data found!(%d)\n", chunks);
|
||||
error = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cmdline_phys = ihk_device_map_memory(dev, cmdline_rphys, cmdline_len);
|
||||
cmdline = ihk_device_map_virtual(dev, cmdline_phys, cmdline_len, NULL,
|
||||
0);
|
||||
sprintf(fn, "mccore-%s.%d",
|
||||
strrchr(cmdline, '/') ?
|
||||
strrchr(cmdline, '/') + 1 : cmdline,
|
||||
task_tgid_vnr(current));
|
||||
pr_info("%s: fn=%s\n", __func__, fn);
|
||||
|
||||
ihk_device_unmap_virtual(dev, cmdline, cmdline_len);
|
||||
ihk_device_unmap_memory(dev, cmdline_phys, cmdline_len);
|
||||
|
||||
/* Every Linux documentation insists we should not
|
||||
* open a file in the kernel module, but our karma
|
||||
* leads us here. Precisely, Here we emulate the core
|
||||
* dump routine of the Linux kernel in linux/fs/exec.c.
|
||||
* So we have a legitimate reason to do this.
|
||||
*/
|
||||
file = filp_open("core", O_CREAT | O_RDWR | O_LARGEFILE | O_TRUNC, 0600);
|
||||
file = filp_open(fn, O_CREAT | O_RDWR | O_LARGEFILE | O_TRUNC, 0600);
|
||||
if (IS_ERR(file) || !file->f_op) {
|
||||
dprintk("cannot open core file\n");
|
||||
error = PTR_ERR(file);
|
||||
@@ -2016,6 +2040,7 @@ fail:
|
||||
/* make sure we do not travel to user land */
|
||||
error = -EINVAL;
|
||||
}
|
||||
kfree(fn);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -2071,7 +2096,8 @@ int __do_in_kernel_syscall(ihk_os_t os, struct ikc_scd_packet *packet)
|
||||
}
|
||||
|
||||
case __NR_coredump:
|
||||
ret = writecore(os, sc->args[1], sc->args[0]);
|
||||
ret = writecore(os, sc->args[1], sc->args[0], sc->args[2],
|
||||
sc->args[3]);
|
||||
break;
|
||||
|
||||
case __NR_sched_setparam: {
|
||||
|
||||
154
kernel/gencore.c
154
kernel/gencore.c
@@ -91,7 +91,7 @@ int get_prpsinfo_size(void)
|
||||
* \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 fill_prstatus(struct note *head, struct thread *thread)
|
||||
{
|
||||
void *name;
|
||||
struct elf_prstatus64 *prstatus;
|
||||
@@ -103,7 +103,7 @@ void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
prstatus = (struct elf_prstatus64 *)(name + align32(sizeof("CORE")));
|
||||
|
||||
arch_fill_prstatus(prstatus, thread, regs0);
|
||||
arch_fill_prstatus(prstatus, thread, thread->coredump_regs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ void fill_prstatus(struct note *head, struct thread *thread, void *regs0)
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
void fill_prpsinfo(struct note *head, struct process *proc, char *cmdline)
|
||||
{
|
||||
void *name;
|
||||
struct elf_prpsinfo64 *prpsinfo;
|
||||
@@ -126,8 +126,10 @@ void fill_prpsinfo(struct note *head, struct thread *thread, void *regs)
|
||||
memcpy(name, "CORE", sizeof("CORE"));
|
||||
prpsinfo = (struct elf_prpsinfo64 *)(name + align32(sizeof("CORE")));
|
||||
|
||||
prpsinfo->pr_state = thread->status;
|
||||
prpsinfo->pr_pid = thread->proc->pid;
|
||||
prpsinfo->pr_state = proc->status;
|
||||
prpsinfo->pr_pid = proc->pid;
|
||||
|
||||
memcpy(prpsinfo->pr_fname, cmdline, 16);
|
||||
|
||||
/* TODO: Fill the following fields:
|
||||
* char pr_sname;
|
||||
@@ -161,7 +163,7 @@ int get_auxv_size(void)
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_auxv(struct note *head, struct thread *thread, void *regs)
|
||||
void fill_auxv(struct note *head, struct process *proc)
|
||||
{
|
||||
void *name;
|
||||
void *auxv;
|
||||
@@ -172,7 +174,7 @@ 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,
|
||||
memcpy(auxv, proc->saved_auxv,
|
||||
sizeof(unsigned long) * AUXV_LEN);
|
||||
}
|
||||
|
||||
@@ -181,10 +183,25 @@ void fill_auxv(struct note *head, struct thread *thread, void *regs)
|
||||
*
|
||||
*/
|
||||
|
||||
int get_note_size(void)
|
||||
int get_note_size(struct process *proc)
|
||||
{
|
||||
return get_prstatus_size() + arch_get_thread_core_info_size()
|
||||
+ get_prpsinfo_size() + get_auxv_size();
|
||||
int note = 0;
|
||||
struct thread *thread_iter;
|
||||
struct mcs_rwlock_node lock;
|
||||
|
||||
mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &lock);
|
||||
list_for_each_entry(thread_iter, &proc->threads_list, siblings_list) {
|
||||
note += get_prstatus_size();
|
||||
note += arch_get_thread_core_info_size();
|
||||
if (thread_iter->tid == proc->pid) {
|
||||
note += get_prpsinfo_size();
|
||||
note += get_auxv_size();
|
||||
}
|
||||
}
|
||||
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &lock);
|
||||
|
||||
|
||||
return note;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,18 +212,48 @@ int get_note_size(void)
|
||||
* \param regs A pointer to a ihk_mc_user_context_t structure.
|
||||
*/
|
||||
|
||||
void fill_note(void *note, struct thread *thread, void *regs)
|
||||
void fill_note(void *note, struct process *proc, char *cmdline)
|
||||
{
|
||||
fill_prstatus(note, thread, regs);
|
||||
note += get_prstatus_size();
|
||||
struct thread *thread_iter;
|
||||
struct mcs_rwlock_node lock;
|
||||
|
||||
arch_fill_thread_core_info(note, thread, regs);
|
||||
note += arch_get_thread_core_info_size();
|
||||
mcs_rwlock_reader_lock_noirq(&proc->threads_lock, &lock);
|
||||
list_for_each_entry(thread_iter, &proc->threads_list, siblings_list) {
|
||||
fill_prstatus(note, thread_iter);
|
||||
note += get_prstatus_size();
|
||||
|
||||
fill_prpsinfo(note, thread, regs);
|
||||
note += get_prpsinfo_size();
|
||||
arch_fill_thread_core_info(note, thread_iter,
|
||||
thread_iter->coredump_regs);
|
||||
note += arch_get_thread_core_info_size();
|
||||
|
||||
if (thread_iter->tid == proc->pid) {
|
||||
fill_prpsinfo(note, proc, cmdline);
|
||||
note += get_prpsinfo_size();
|
||||
|
||||
#if 0
|
||||
fill_siginfo(note, proc);
|
||||
note += get_siginfo_size();
|
||||
#endif
|
||||
|
||||
fill_auxv(note, proc);
|
||||
note += get_auxv_size();
|
||||
|
||||
#if 0
|
||||
fill_file(note, proc);
|
||||
note += get_file_size();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
fill_fpregset(note, thread);
|
||||
note += get_fpregset_size();
|
||||
|
||||
fill_x86_xstate(note, thread);
|
||||
note += get_x86_xstate_size();
|
||||
#endif
|
||||
}
|
||||
mcs_rwlock_reader_unlock_noirq(&proc->threads_lock, &lock);
|
||||
|
||||
fill_auxv(note, thread, regs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,15 +271,16 @@ void fill_note(void *note, struct thread *thread, void *regs)
|
||||
* should be zero.
|
||||
*/
|
||||
|
||||
int gencore(struct thread *thread, void *regs,
|
||||
struct coretable **coretable, int *chunks)
|
||||
int gencore(struct process *proc, struct coretable **coretable, int *chunks,
|
||||
char *cmdline)
|
||||
{
|
||||
int error = 0;
|
||||
struct coretable *ct = NULL;
|
||||
Elf64_Ehdr *eh = NULL;
|
||||
Elf64_Phdr *ph = NULL;
|
||||
void *note = NULL;
|
||||
struct vm_range *range, *next;
|
||||
struct process_vm *vm = thread->vm;
|
||||
struct process_vm *vm = proc->vm;
|
||||
int segs = 1; /* the first one is for NOTE */
|
||||
int notesize, phsize, alignednotesize;
|
||||
unsigned int offset = 0;
|
||||
@@ -241,8 +289,9 @@ int gencore(struct thread *thread, void *regs,
|
||||
*chunks = 3; /* Elf header , header table and NOTE segment */
|
||||
|
||||
if (vm == NULL) {
|
||||
dkprintf("no vm found.\n");
|
||||
return -1;
|
||||
kprintf("%s: ERROR: vm not found\n", __func__);
|
||||
error = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
next = lookup_process_memory_range(vm, 0, -1);
|
||||
@@ -264,8 +313,9 @@ int gencore(struct thread *thread, void *regs,
|
||||
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) {
|
||||
if (ihk_mc_pt_virt_to_phys(
|
||||
vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
prevzero = 1;
|
||||
} else {
|
||||
if (prevzero == 1)
|
||||
@@ -284,7 +334,7 @@ int gencore(struct thread *thread, void *regs,
|
||||
dkprintf("we have %d segs and %d chunks.\n\n", segs, *chunks);
|
||||
|
||||
{
|
||||
struct vm_regions region = thread->vm->region;
|
||||
struct vm_regions region = vm->region;
|
||||
|
||||
dkprintf("text: %lx-%lx\n", region.text_start,
|
||||
region.text_end);
|
||||
@@ -303,6 +353,7 @@ int gencore(struct thread *thread, void *regs,
|
||||
eh = kmalloc(sizeof(*eh), IHK_MC_AP_NOWAIT);
|
||||
if (eh == NULL) {
|
||||
dkprintf("could not alloc a elf header table.\n");
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(eh, 0, sizeof(*eh));
|
||||
@@ -314,7 +365,8 @@ int gencore(struct thread *thread, void *regs,
|
||||
phsize = sizeof(Elf64_Phdr) * segs;
|
||||
ph = kmalloc(phsize, IHK_MC_AP_NOWAIT);
|
||||
if (ph == NULL) {
|
||||
dkprintf("could not alloc a program header table.\n");
|
||||
kprintf("%s: ERROR: allocating program header\n", __func__);
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(ph, 0, phsize);
|
||||
@@ -325,15 +377,16 @@ int gencore(struct thread *thread, void *regs,
|
||||
* To align the next segment page-sized, we prepare a padded
|
||||
* region for our NOTE segment.
|
||||
*/
|
||||
notesize = get_note_size();
|
||||
notesize = get_note_size(proc);
|
||||
alignednotesize = alignpage(notesize + offset) - offset;
|
||||
note = kmalloc(alignednotesize, IHK_MC_AP_NOWAIT);
|
||||
if (note == NULL) {
|
||||
dkprintf("could not alloc NOTE for core.\n");
|
||||
kprintf("%s: ERROR: allocating NOTE\n", __func__);
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(note, 0, alignednotesize);
|
||||
fill_note(note, thread, regs);
|
||||
fill_note(note, proc, cmdline);
|
||||
|
||||
/* prgram header for NOTE segment is exceptional */
|
||||
ph[0].p_type = PT_NOTE;
|
||||
@@ -377,10 +430,11 @@ int gencore(struct thread *thread, void *regs,
|
||||
/* coretable to send to host */
|
||||
ct = kmalloc(sizeof(struct coretable) * (*chunks), IHK_MC_AP_NOWAIT);
|
||||
if (!ct) {
|
||||
dkprintf("could not alloc a coretable.\n");
|
||||
kprintf("%s: ERROR: allocating coretable\n", __func__);
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
memset(ct, 0, sizeof(*ct));
|
||||
memset(ct, 0, sizeof(struct coretable) * (*chunks));
|
||||
|
||||
ct[0].addr = virt_to_phys(eh); /* ELF header */
|
||||
ct[0].len = 64;
|
||||
@@ -406,6 +460,7 @@ int gencore(struct thread *thread, void *regs,
|
||||
}
|
||||
|
||||
if (range->flag & VR_DEMAND_PAGING) {
|
||||
|
||||
/* Just an ad hoc kluge. */
|
||||
unsigned long p, start, phys;
|
||||
int prevzero = 0;
|
||||
@@ -413,8 +468,9 @@ int gencore(struct thread *thread, void *regs,
|
||||
|
||||
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 (ihk_mc_pt_virt_to_phys(
|
||||
vm->address_space->page_table,
|
||||
(void *)p, &phys) != 0) {
|
||||
if (prevzero == 0) {
|
||||
/* Start a new chunk */
|
||||
size = PAGE_SIZE;
|
||||
@@ -452,16 +508,21 @@ int gencore(struct thread *thread, void *regs,
|
||||
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\n",
|
||||
range->start);
|
||||
goto fail;
|
||||
if ((vm->region.user_start <= range->start) &&
|
||||
(range->end <= vm->region.user_end)) {
|
||||
error = ihk_mc_pt_virt_to_phys(
|
||||
vm->address_space->page_table,
|
||||
(void *)range->start, &phys);
|
||||
if (error) {
|
||||
if (error != -EFAULT) {
|
||||
kprintf("%s: error: ihk_mc_pt_virt_to_phys for %lx failed (%d)\n",
|
||||
__func__, range->start,
|
||||
error);
|
||||
goto fail;
|
||||
}
|
||||
/* VR_PROT_NONE range */
|
||||
phys = 0;
|
||||
error = 0;
|
||||
}
|
||||
} else {
|
||||
phys = virt_to_phys((void *)range->start);
|
||||
@@ -475,13 +536,14 @@ int gencore(struct thread *thread, void *regs,
|
||||
}
|
||||
*coretable = ct;
|
||||
|
||||
return 0;
|
||||
return error;
|
||||
|
||||
fail:
|
||||
kfree(eh);
|
||||
kfree(ct);
|
||||
kfree(ph);
|
||||
kfree(note);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -573,6 +573,8 @@ struct process {
|
||||
#endif // PROFILE_ENABLE
|
||||
int nr_processes; /* For partitioned execution */
|
||||
int process_rank; /* Rank in partition */
|
||||
int coredump_barrier_count, coredump_barrier_count2;
|
||||
mcs_rwlock_lock_t coredump_lock; // lock for coredump
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -722,6 +724,11 @@ struct thread {
|
||||
// for performance counter
|
||||
unsigned long pmc_alloc_map;
|
||||
unsigned long extra_reg_alloc_map;
|
||||
|
||||
/* coredump */
|
||||
void *coredump_regs;
|
||||
struct waitq coredump_wq;
|
||||
int coredump_status;
|
||||
};
|
||||
|
||||
#define VM_RANGE_CACHE_SIZE 4
|
||||
|
||||
@@ -622,4 +622,9 @@ extern long (*linux_wait_event)(void *_resp, unsigned long nsec_timeout);
|
||||
extern int (*linux_printk)(const char *fmt, ...);
|
||||
extern int (*linux_clock_gettime)(clockid_t clk_id, struct timespec *tp);
|
||||
|
||||
/* coredump */
|
||||
#define COREDUMP_RUNNING 0
|
||||
#define COREDUMP_DESCHEDULED 1
|
||||
#define COREDUMP_TO_BE_WOKEN 2
|
||||
|
||||
#endif
|
||||
|
||||
156
kernel/mem.c
156
kernel/mem.c
@@ -957,8 +957,44 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = {
|
||||
.priv = NULL,
|
||||
};
|
||||
|
||||
int gencore(struct thread *, void *, struct coretable **, int *);
|
||||
int gencore(struct process *proc, struct coretable **coretable,
|
||||
int *chunks, char *cmdline);
|
||||
void freecore(struct coretable **);
|
||||
struct siginfo;
|
||||
typedef struct siginfo siginfo_t;
|
||||
unsigned long do_kill(struct thread *thread, int pid, int tid,
|
||||
int sig, siginfo_t *info, int ptracecont);
|
||||
|
||||
void coredump_wait(struct thread *thread)
|
||||
{
|
||||
unsigned long flags;
|
||||
DECLARE_WAITQ_ENTRY(coredump_wq_entry, cpu_local_var(current));
|
||||
|
||||
if (__sync_bool_compare_and_swap(&thread->coredump_status,
|
||||
COREDUMP_RUNNING,
|
||||
COREDUMP_DESCHEDULED)) {
|
||||
flags = cpu_disable_interrupt_save();
|
||||
dkprintf("%s: sleeping,tid=%d\n", __func__, thread->tid);
|
||||
waitq_init(&thread->coredump_wq);
|
||||
waitq_prepare_to_wait(&thread->coredump_wq, &coredump_wq_entry,
|
||||
PS_INTERRUPTIBLE);
|
||||
cpu_restore_interrupt(flags);
|
||||
schedule();
|
||||
waitq_finish_wait(&thread->coredump_wq, &coredump_wq_entry);
|
||||
thread->coredump_status = COREDUMP_RUNNING;
|
||||
dkprintf("%s: woken up,tid=%d\n", __func__, thread->tid);
|
||||
}
|
||||
}
|
||||
|
||||
void coredump_wakeup(struct thread *thread)
|
||||
{
|
||||
if (__sync_bool_compare_and_swap(&thread->coredump_status,
|
||||
COREDUMP_DESCHEDULED,
|
||||
COREDUMP_TO_BE_WOKEN)) {
|
||||
dkprintf("%s: waking up tid %d\n", __func__, thread->tid);
|
||||
waitq_wakeup(&thread->coredump_wq);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate a core file and tell the host to write it out.
|
||||
@@ -967,33 +1003,133 @@ void freecore(struct coretable **);
|
||||
* \param regs A pointer to a x86_regs structure.
|
||||
*/
|
||||
|
||||
void coredump(struct thread *thread, void *regs)
|
||||
int coredump(struct thread *thread, void *regs, int sig)
|
||||
{
|
||||
struct process *proc = thread->proc;
|
||||
struct syscall_request request IHK_DMA_ALIGN;
|
||||
int ret;
|
||||
struct coretable *coretable;
|
||||
int chunks;
|
||||
struct mcs_rwlock_node_irqsave lock, lock_dump;
|
||||
struct thread *thread_iter;
|
||||
int i, n, rank;
|
||||
int *ids = NULL;
|
||||
|
||||
if (thread->proc->rlimit[MCK_RLIMIT_CORE].rlim_cur == 0) {
|
||||
return;
|
||||
dkprintf("%s: pid=%d,tid=%d,coredump_barrier_count=%d\n",
|
||||
__func__, proc->pid, thread->tid, proc->coredump_barrier_count);
|
||||
|
||||
if (proc->rlimit[MCK_RLIMIT_CORE].rlim_cur == 0) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = gencore(thread, regs, &coretable, &chunks);
|
||||
if (ret != 0) {
|
||||
dkprintf("could not generate a core file image\n");
|
||||
return;
|
||||
/* Wait until all threads save its register. */
|
||||
/* mutex coredump */
|
||||
mcs_rwlock_reader_lock(&proc->coredump_lock, &lock_dump);
|
||||
rank = __sync_fetch_and_add(&proc->coredump_barrier_count, 1);
|
||||
if (rank == 0) {
|
||||
n = 0;
|
||||
|
||||
mcs_rwlock_reader_lock(&proc->threads_lock, &lock);
|
||||
list_for_each_entry(thread_iter, &proc->threads_list,
|
||||
siblings_list) {
|
||||
if (thread_iter != thread) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (n) {
|
||||
ids = kmalloc(sizeof(int) * n, IHK_MC_AP_NOWAIT);
|
||||
if (!ids) {
|
||||
mcs_rwlock_reader_unlock(&proc->threads_lock,
|
||||
&lock);
|
||||
kprintf("%s: ERROR: allocating tid table\n",
|
||||
__func__);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
i = 0;
|
||||
list_for_each_entry(thread_iter, &proc->threads_list,
|
||||
siblings_list) {
|
||||
if (thread_iter != thread) {
|
||||
ids[i] = thread_iter->tid;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
|
||||
/* Note that when the target is sleeping on the source CPU,
|
||||
* it will wake up and handle the signal when this thread yields
|
||||
* in coredump_wait()
|
||||
*/
|
||||
for (i = 0; i < n; i++) {
|
||||
dkprintf("%s: calling do_kill, target tid=%d\n",
|
||||
__func__, ids[i]);
|
||||
do_kill(thread, proc->pid, ids[i], sig, NULL, 0);
|
||||
}
|
||||
}
|
||||
mcs_rwlock_reader_unlock(&proc->coredump_lock, &lock_dump);
|
||||
|
||||
while (1) {
|
||||
n = 0;
|
||||
mcs_rwlock_reader_lock(&proc->threads_lock, &lock);
|
||||
list_for_each_entry(thread_iter, &proc->threads_list,
|
||||
siblings_list) {
|
||||
n++;
|
||||
}
|
||||
mcs_rwlock_reader_unlock(&proc->threads_lock, &lock);
|
||||
if (n == proc->coredump_barrier_count) {
|
||||
list_for_each_entry(thread_iter, &proc->threads_list,
|
||||
siblings_list) {
|
||||
coredump_wakeup(thread_iter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
coredump_wait(thread);
|
||||
}
|
||||
|
||||
/* Followers wait until dump is done to keep struct thread alive */
|
||||
if (rank != 0) {
|
||||
ret = 0;
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if ((ret = gencore(proc, &coretable, &chunks, proc->saved_cmdline))) {
|
||||
kprintf("%s: ERROR: gencore returned %d\n", __func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
request.number = __NR_coredump;
|
||||
request.args[0] = chunks;
|
||||
request.args[1] = virt_to_phys(coretable);
|
||||
request.args[2] = virt_to_phys(thread->proc->saved_cmdline);
|
||||
request.args[3] = (unsigned long)thread->proc->saved_cmdline_len;
|
||||
|
||||
/* no data for now */
|
||||
ret = do_syscall(&request, thread->cpu_id);
|
||||
if (ret == 0) {
|
||||
kprintf("dumped core.\n");
|
||||
kprintf("%s: INFO: coredump done\n", __func__);
|
||||
} else {
|
||||
kprintf("core dump failed.\n");
|
||||
kprintf("%s: ERROR: do_syscall failed (%d)\n",
|
||||
__func__, ret);
|
||||
}
|
||||
freecore(&coretable);
|
||||
|
||||
skip:
|
||||
__sync_fetch_and_add(&proc->coredump_barrier_count2, 1);
|
||||
while (1) {
|
||||
if (n == proc->coredump_barrier_count2) {
|
||||
list_for_each_entry(thread_iter, &proc->threads_list,
|
||||
siblings_list) {
|
||||
coredump_wakeup(thread_iter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
coredump_wait(thread);
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(ids);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void remote_flush_tlb_cpumask(struct process_vm *vm,
|
||||
|
||||
@@ -128,6 +128,7 @@ init_process(struct process *proc, struct process *parent)
|
||||
INIT_LIST_HEAD(&proc->ptraced_children_list);
|
||||
mcs_rwlock_init(&proc->threads_lock);
|
||||
mcs_rwlock_init(&proc->children_lock);
|
||||
mcs_rwlock_init(&proc->coredump_lock);
|
||||
ihk_mc_spinlock_init(&proc->mckfd_lock);
|
||||
waitq_init(&proc->waitpid_q);
|
||||
ihk_atomic_set(&proc->refcount, 2);
|
||||
@@ -2854,6 +2855,7 @@ void destroy_thread(struct thread *thread)
|
||||
if (thread->fp_regs) {
|
||||
release_fp_regs(thread);
|
||||
}
|
||||
kfree(thread->coredump_regs);
|
||||
|
||||
release_sigcommon(thread->sigcommon);
|
||||
|
||||
|
||||
@@ -2713,6 +2713,10 @@ unsigned long do_fork(int clone_flags, unsigned long newsp,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (oldproc->coredump_barrier_count) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* N-th creation put the new on Linux CPU. It's turned off when zero is
|
||||
set to uti_thread_rank. */
|
||||
if (oldproc->uti_thread_rank) {
|
||||
|
||||
285
test/issues/1219/C1219.sh
Executable file
285
test/issues/1219/C1219.sh
Executable file
@@ -0,0 +1,285 @@
|
||||
#!/bin/sh
|
||||
|
||||
USELTP=0
|
||||
USEOSTEST=0
|
||||
|
||||
. ../../common.sh
|
||||
|
||||
TP_SUB=./segv_in_sub
|
||||
TP_MAIN=./segv_in_main
|
||||
|
||||
NUM_THREADS=6
|
||||
arch=`uname -p`
|
||||
|
||||
# clean corefils
|
||||
rm ./mccore* ./core.*
|
||||
|
||||
ulimit_c_bk=`ulimit -Sc`
|
||||
# set ulimit -c unlimited to dump core
|
||||
ulimit -c unlimited
|
||||
|
||||
${MCEXEC} ./segv_in_sub
|
||||
|
||||
# Find mccore*
|
||||
CORE=`ls -1 | grep "^mccore"`
|
||||
|
||||
if [ ! -z $CORE ]; then
|
||||
echo "[ OK ] core for McKernel process found"
|
||||
else
|
||||
echo "[ NG ] core for McKernel process not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
issue=1219
|
||||
tid=01
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check number of threads"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "LWP" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -eq ${NUM_THREADS} ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=02
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check backtrace"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "^#[0-9]*\s* 0x[0-9]*" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=03
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check info register"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
if [ "${arch}" == "x86_64" ]; then
|
||||
num=`grep "^rip\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
elif [ "${arch}" == "aarch64" ]; then
|
||||
num=`grep "^pc\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
else
|
||||
num=0
|
||||
fi
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=04
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "Switching to thread ${NUM_THREADS}" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=05
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check backtrace after switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "^#[0-9]*\s* 0x[0-9]*" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=06
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check info register after switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
if [ "${arch}" == "x86_64" ]; then
|
||||
num=`grep "^rip\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
elif [ "${arch}" == "aarch64" ]; then
|
||||
num=`grep "^pc\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
else
|
||||
num=0
|
||||
fi
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# clean corefils
|
||||
rm ./mccore* ./core.*
|
||||
|
||||
${MCEXEC} ./segv_in_main
|
||||
|
||||
# Find mccore*
|
||||
CORE=`ls -1 | grep "^mccore"`
|
||||
|
||||
if [ ! -z $CORE ]; then
|
||||
echo "[ OK ] core for McKernel process found"
|
||||
else
|
||||
echo "[ NG ] core for McKernel process not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tid=07
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check number of threads"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "LWP" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -eq ${NUM_THREADS} ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=08
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check backtrace"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "^#[0-9]*\s* 0x[0-9]*" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=09
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check info register"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
if [ "${arch}" == "x86_64" ]; then
|
||||
num=`grep "^rip\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
elif [ "${arch}" == "aarch64" ]; then
|
||||
num=`grep "^pc\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
else
|
||||
num=0
|
||||
fi
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=10
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "Switching to thread ${NUM_THREADS}" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=11
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check backtrace after switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "^#[0-9]*\s* 0x[0-9]*" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
tid=12
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check info register after switching thread"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
if [ "${arch}" == "x86_64" ]; then
|
||||
num=`grep "^rip\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
elif [ "${arch}" == "aarch64" ]; then
|
||||
num=`grep "^pc\s*0x.*" ./C${issue}T${tid}.txt | wc -l`
|
||||
else
|
||||
num=0
|
||||
fi
|
||||
|
||||
if [ ${num} -gt 0 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# clean corefils
|
||||
rm ./mccore* ./core.*
|
||||
|
||||
${MCEXEC} ./segv_after_join
|
||||
|
||||
# restore ulimit -c
|
||||
ulimit -c ${ulimit_c_bk}
|
||||
|
||||
# Find mccore*
|
||||
CORE=`ls -1 | grep "^mccore"`
|
||||
|
||||
if [ ! -z $CORE ]; then
|
||||
echo "[ OK ] core for McKernel process found"
|
||||
else
|
||||
echo "[ NG ] core for McKernel process not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tid=13
|
||||
echo "*** C${issue}T${tid} start *******************************"
|
||||
echo "** Check number of threads"
|
||||
gdb ${TP_SUB} --core=./${CORE} -x ./cmd/C${issue}T${tid}.cmd 2>/dev/null \
|
||||
| sed -n '/TESTOUT_START/,$p' | tee ./C${issue}T${tid}.txt
|
||||
|
||||
num=`grep "LWP" ./C${issue}T${tid}.txt | wc -l`
|
||||
|
||||
if [ ${num} -eq 1 ]; then
|
||||
echo "*** C${issue}T${tid} PASSED ******************************"
|
||||
else
|
||||
echo "*** C${issue}T${tid} FAILED ******************************"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
11
test/issues/1219/Makefile
Normal file
11
test/issues/1219/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
CFLAGS=-g
|
||||
LDFLAGS=-lpthread
|
||||
|
||||
TARGET=segv_in_sub segv_in_main segv_after_join
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
test: all
|
||||
./C1219.sh
|
||||
clean:
|
||||
rm -f $(TARGET) *.o mccore* core.* *.txt
|
||||
80
test/issues/1219/README
Normal file
80
test/issues/1219/README
Normal file
@@ -0,0 +1,80 @@
|
||||
【Issue#1219 動作確認】
|
||||
□ テスト内容
|
||||
1. 複数スレッドを持つコアダンプファイルのgdb操作の確認
|
||||
◆5個のサブスレッドを作成し、サブスレッド中でSEGVが
|
||||
発生した際のコアダンプファイルについて、以下を確認
|
||||
|
||||
C1219T01: スレッド数の確認
|
||||
gdbで下記の操作を実行し、6個のスレッドが表示されることを確認
|
||||
(gdb) info threads
|
||||
|
||||
C1219T02: 初期スレッドのbacktraceの確認
|
||||
gdbで下記の操作を実行し、backtraceの結果が表示されることを確認
|
||||
(gdb) backtrace
|
||||
|
||||
C1219T03: 初期スレッドのレジスタ情報の確認
|
||||
gdbで下記の操作を実行し、レジスタの情報が表示されることを確認
|
||||
(gdb) info register
|
||||
|
||||
C1219T04: スレッド切り替えの確認
|
||||
gdbで下記の操作を実行し、スレッドの切り替わることを確認
|
||||
(gdb) thread 6
|
||||
|
||||
C1219T05: スレッド切り替え後のbacktraceの確認
|
||||
gdbで下記の操作を実行し、backtraceの結果が表示されることを確認
|
||||
(gdb) thread 6
|
||||
(gdb) backtrace
|
||||
|
||||
C1219T06: スレッド切り替え後のレジスタ情報の確認
|
||||
gdbで下記の操作を実行し、レジスタの情報が表示されることを確認
|
||||
(gdb) thread 6
|
||||
(gdb) info register
|
||||
|
||||
◆5個のサブスレッドを作成し、メインスレッド中でSEGVが
|
||||
発生した際のコアダンプファイルについて、以下を確認
|
||||
|
||||
C1219T07: スレッド数の確認
|
||||
gdbで下記の操作を実行し、6個のスレッドが表示されることを確認
|
||||
(gdb) info threads
|
||||
|
||||
C1219T08: 初期スレッドのbacktraceの確認
|
||||
gdbで下記の操作を実行し、backtraceの結果が表示されることを確認
|
||||
(gdb) backtrace
|
||||
|
||||
C1219T09: 初期スレッドのレジスタ情報の確認
|
||||
gdbで下記の操作を実行し、レジスタの情報が表示されることを確認
|
||||
(gdb) info register
|
||||
|
||||
C1219T10: スレッド切り替えの確認
|
||||
gdbで下記の操作を実行し、スレッドの切り替わることを確認
|
||||
(gdb) thread 6
|
||||
|
||||
C1219T11: スレッド切り替え後のbacktraceの確認
|
||||
gdbで下記の操作を実行し、backtraceの結果が表示されることを確認
|
||||
(gdb) thread 6
|
||||
(gdb) backtrace
|
||||
|
||||
C1219T12: スレッド切り替え後のレジスタ情報の確認
|
||||
gdbで下記の操作を実行し、レジスタの情報が表示されることを確認
|
||||
(gdb) thread 6
|
||||
(gdb) info register
|
||||
|
||||
◆5個のサブスレッドを作成し、すべてのサブスレッドが終了した後に
|
||||
メインスレッドでSEGVが発生した際のコアダンプファイルについて、以下を確認
|
||||
|
||||
C1219T13: スレッド数の確認
|
||||
gdbで下記の操作を実行し、1個のスレッドが表示されることを確認
|
||||
(gdb) info threads
|
||||
|
||||
|
||||
□ 実行手順
|
||||
$ make test
|
||||
|
||||
McKernelのインストール先や、OSTEST, LTPの配置場所は、
|
||||
$HOME/.mck_test_config を参照している
|
||||
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
|
||||
$HOMEにコピーし、適宜編集する
|
||||
|
||||
□ 実行結果
|
||||
result.log 参照。
|
||||
すべての項目をPASSしていることを確認。
|
||||
4
test/issues/1219/cmd/C1219T01.cmd
Normal file
4
test/issues/1219/cmd/C1219T01.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) info threads"
|
||||
info threads
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T02.cmd
Normal file
4
test/issues/1219/cmd/C1219T02.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) backtrace"
|
||||
backtrace
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T03.cmd
Normal file
4
test/issues/1219/cmd/C1219T03.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) info register"
|
||||
info register
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T04.cmd
Normal file
4
test/issues/1219/cmd/C1219T04.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) thread 6"
|
||||
thread 6
|
||||
quit
|
||||
|
||||
5
test/issues/1219/cmd/C1219T05.cmd
Normal file
5
test/issues/1219/cmd/C1219T05.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
thread 6
|
||||
p "TESTOUT_START result of (gdb) backtrace"
|
||||
backtrace
|
||||
quit
|
||||
|
||||
5
test/issues/1219/cmd/C1219T06.cmd
Normal file
5
test/issues/1219/cmd/C1219T06.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
thread 6
|
||||
p "TESTOUT_START result of (gdb) info register"
|
||||
info register
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T07.cmd
Normal file
4
test/issues/1219/cmd/C1219T07.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) info threads"
|
||||
info threads
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T08.cmd
Normal file
4
test/issues/1219/cmd/C1219T08.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) backtrace"
|
||||
backtrace
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T09.cmd
Normal file
4
test/issues/1219/cmd/C1219T09.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) info register"
|
||||
info register
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T10.cmd
Normal file
4
test/issues/1219/cmd/C1219T10.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) thread 6"
|
||||
thread 6
|
||||
quit
|
||||
|
||||
5
test/issues/1219/cmd/C1219T11.cmd
Normal file
5
test/issues/1219/cmd/C1219T11.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
thread 6
|
||||
p "TESTOUT_START result of (gdb) backtrace"
|
||||
backtrace
|
||||
quit
|
||||
|
||||
5
test/issues/1219/cmd/C1219T12.cmd
Normal file
5
test/issues/1219/cmd/C1219T12.cmd
Normal file
@@ -0,0 +1,5 @@
|
||||
thread 6
|
||||
p "TESTOUT_START result of (gdb) info register"
|
||||
info register
|
||||
quit
|
||||
|
||||
4
test/issues/1219/cmd/C1219T13.cmd
Normal file
4
test/issues/1219/cmd/C1219T13.cmd
Normal file
@@ -0,0 +1,4 @@
|
||||
p "TESTOUT_START result of (gdb) info threads"
|
||||
info threads
|
||||
quit
|
||||
|
||||
256
test/issues/1219/result_aarch64.log
Normal file
256
test/issues/1219/result_aarch64.log
Normal file
@@ -0,0 +1,256 @@
|
||||
SEGV in sub thread!!
|
||||
pthread_create done!! Let's join!!!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 21: 19924 Segmentation fault (core dumped) ${MCEXEC} ./segv_in_sub
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T01 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
* 1 LWP 19924 0x000008000000d590 in _dl_fixup () from /lib/ld-linux-aarch64.so.1
|
||||
2 LWP 19940 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
3 LWP 19939 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
4 LWP 19938 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
5 LWP 19937 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
6 LWP 19936 0x0000000000400808 in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
*** C1219T01 PASSED ******************************
|
||||
|
||||
*** C1219T02 start *******************************
|
||||
** Check backtrace
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x000008000000d590 in _dl_fixup () from /lib/ld-linux-aarch64.so.1
|
||||
#1 0x00000800000132d8 in _dl_runtime_resolve () from /lib/ld-linux-aarch64.so.1
|
||||
#2 0x0000000000400938 in main () at segv_in_sub.c:50
|
||||
*** C1219T02 PASSED ******************************
|
||||
|
||||
*** C1219T03 start *******************************
|
||||
** Check info register
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
x0 0x80000031170 8796093223280
|
||||
x1 0x400360 4195168
|
||||
x2 0x100000002a60 17592186055264
|
||||
x3 0x7 7
|
||||
x4 0x3 3
|
||||
x5 0x4003d8 4195288
|
||||
x6 0x18 24
|
||||
x7 0x6420657461657263 7214878153572184675
|
||||
x8 0x40 64
|
||||
x9 0x6e696f6a20732774 7956012718328326004
|
||||
x10 0x616572635f646165 7018141365454528869
|
||||
x11 0x21656e6f64206574 2406451000599668084
|
||||
x12 0x20732774654c2021 2338256012404596769
|
||||
x13 0x212121216e696f6a 2387225704953114474
|
||||
x14 0x23 35
|
||||
x15 0x1 1
|
||||
x16 0x41fff8 4325368
|
||||
x17 0x80000013294 8796093100692
|
||||
x18 0x10f 271
|
||||
x19 0x400968 4196712
|
||||
x20 0x420028 4325416
|
||||
x21 0x4006d0 4196048
|
||||
x22 0x0 0
|
||||
x23 0x0 0
|
||||
x24 0x0 0
|
||||
x25 0x0 0
|
||||
x26 0x0 0
|
||||
x27 0x0 0
|
||||
x28 0x0 0
|
||||
x29 0x3ffffffffb40 70368744176448
|
||||
x30 0x800000132d8 8796093100760
|
||||
sp 0x3ffffffffb40 0x3ffffffffb40
|
||||
pc 0x8000000d590 0x8000000d590 <_dl_fixup+120>
|
||||
cpsr 0x40000000 [ EL=0 Z ]
|
||||
fpsr <unavailable>
|
||||
fpcr <unavailable>
|
||||
*** C1219T03 PASSED ******************************
|
||||
|
||||
*** C1219T04 start *******************************
|
||||
** Check switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) thread 6"
|
||||
[Switching to thread 6 (LWP 19936)]
|
||||
#0 0x0000000000400808 in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
20 *ptr = 0xdead;
|
||||
*** C1219T04 PASSED ******************************
|
||||
|
||||
*** C1219T05 start *******************************
|
||||
** Check backtrace after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x0000000000400808 in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
#1 0x000010000000b7f8 in start_thread () from /usr/lib64/libpthread.so.0
|
||||
#2 0x0000000000000000 in ?? ()
|
||||
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
|
||||
*** C1219T05 PASSED ******************************
|
||||
|
||||
*** C1219T06 start *******************************
|
||||
** Check info register after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
x0 0x0 0
|
||||
x1 0xdead 57005
|
||||
x2 0x1000032001e0 17592238473696
|
||||
x3 0x10101011 269488145
|
||||
x4 0x1000031ff9d0 17592238471632
|
||||
x5 0x1000130fe9c1 17592505854401
|
||||
x6 0x38 56
|
||||
x7 0x0 0
|
||||
x8 0x63 99
|
||||
x9 0x0 0
|
||||
x10 0x10000000b658 17592186091096
|
||||
x11 0x3d0f00 4001536
|
||||
x12 0x1000032001e0 17592238473696
|
||||
x13 0x80000030000 8796093218816
|
||||
x14 0x0 0
|
||||
x15 0x1 1
|
||||
x16 0x100000034028 17592186257448
|
||||
x17 0x10000006b9c0 17592186485184
|
||||
x18 0x10f 271
|
||||
x19 0x1000032001e0 17592238473696
|
||||
x20 0x3ffffffffc20 70368744176672
|
||||
x21 0x3ffffffffc1e 70368744176670
|
||||
x22 0x3ffffffffc1f 70368744176671
|
||||
x23 0x4007f4 4196340
|
||||
x24 0x1000032001e0 17592238473696
|
||||
x25 0x1000 4096
|
||||
x26 0x100000034000 17592186257408
|
||||
x27 0x3ffffffffc20 70368744176672
|
||||
x28 0x1000032001e0 17592238473696
|
||||
x29 0x1000031ff9d0 17592238471632
|
||||
x30 0x10000000b7f8 17592186091512
|
||||
sp 0x1000031ff9b0 0x1000031ff9b0
|
||||
pc 0x400808 0x400808 <thread_fn_dump+20>
|
||||
cpsr 0x20000000 [ EL=0 C ]
|
||||
fpsr <unavailable>
|
||||
fpcr <unavailable>
|
||||
*** C1219T06 PASSED ******************************
|
||||
|
||||
rm: cannot remove './core.*': No such file or directory
|
||||
SEGV in main thread!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 145: 19994 Segmentation fault (core dumped) ${MCEXEC} ./segv_in_main
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T07 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
* 1 LWP 19994 0x00000000004008a8 in main () at segv_in_sub.c:38
|
||||
2 LWP 20010 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
3 LWP 20009 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
4 LWP 20008 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
5 LWP 20007 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
6 LWP 20006 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
*** C1219T07 PASSED ******************************
|
||||
|
||||
*** C1219T08 start *******************************
|
||||
** Check backtrace
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x00000000004008a8 in main () at segv_in_sub.c:38
|
||||
*** C1219T08 PASSED ******************************
|
||||
|
||||
*** C1219T09 start *******************************
|
||||
** Check info register
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
x0 0x0 0
|
||||
x1 0xdead 57005
|
||||
x2 0x0 0
|
||||
x3 0x1000032008e0 17592238475488
|
||||
x4 0x0 0
|
||||
x5 0x1000032008e0 17592238475488
|
||||
x6 0x1000032002b0 17592238473904
|
||||
x7 0x0 0
|
||||
x8 0xdc 220
|
||||
x9 0x0 0
|
||||
x10 0x10000000b658 17592186091096
|
||||
x11 0x3d0f00 4001536
|
||||
x12 0x1000032001e0 17592238473696
|
||||
x13 0x80000030000 8796093218816
|
||||
x14 0x0 0
|
||||
x15 0x1 1
|
||||
x16 0x100000034228 17592186257960
|
||||
x17 0x10000010a490 17592187135120
|
||||
x18 0x10f 271
|
||||
x19 0x400908 4196616
|
||||
x20 0x0 0
|
||||
x21 0x4006d0 4196048
|
||||
x22 0x0 0
|
||||
x23 0x0 0
|
||||
x24 0x0 0
|
||||
x25 0x0 0
|
||||
x26 0x0 0
|
||||
x27 0x0 0
|
||||
x28 0x0 0
|
||||
x29 0x3ffffffffc60 70368744176736
|
||||
x30 0x40083c 4196412
|
||||
sp 0x3ffffffffc60 0x3ffffffffc60
|
||||
pc 0x4008a8 0x4008a8 <main+144>
|
||||
cpsr 0x20000000 [ EL=0 C ]
|
||||
fpsr <unavailable>
|
||||
fpcr <unavailable>
|
||||
*** C1219T09 PASSED ******************************
|
||||
|
||||
*** C1219T10 start *******************************
|
||||
** Check switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) thread 6"
|
||||
[Switching to thread 6 (LWP 20006)]
|
||||
#0 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
*** C1219T10 PASSED ******************************
|
||||
|
||||
*** C1219T11 start *******************************
|
||||
** Check backtrace after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x00001000000dc610 in nanosleep () from /usr/lib64/libc.so.6
|
||||
#1 0x0000000000000000 in ?? ()
|
||||
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
|
||||
*** C1219T11 PASSED ******************************
|
||||
|
||||
*** C1219T12 start *******************************
|
||||
** Check info register after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
x0 0xfffffffffffffffc -4
|
||||
x1 0x1000031ff998 17592238471576
|
||||
x2 0x0 0
|
||||
x3 0x0 0
|
||||
x4 0x1000032002e8 17592238473960
|
||||
x5 0x1000032008e0 17592238475488
|
||||
x6 0x1000032000e0 17592238473440
|
||||
x7 0x0 0
|
||||
x8 0x65 101
|
||||
x9 0x0 0
|
||||
x10 0x10000000b658 17592186091096
|
||||
x11 0x3d0f00 4001536
|
||||
x12 0x1000032001e0 17592238473696
|
||||
x13 0x80000030000 8796093218816
|
||||
x14 0x0 0
|
||||
x15 0x1 1
|
||||
x16 0x420010 4325392
|
||||
x17 0x1000000dc468 17592186946664
|
||||
x18 0x10f 271
|
||||
x19 0x1000031ff998 17592238471576
|
||||
x20 0x1000031ff998 17592238471576
|
||||
x21 0x1000032008e0 17592238475488
|
||||
x22 0x0 0
|
||||
x23 0x4007d4 4196308
|
||||
x24 0x1000032001e0 17592238473696
|
||||
x25 0x1000 4096
|
||||
x26 0x100000034000 17592186257408
|
||||
x27 0x3ffffffffc20 70368744176672
|
||||
x28 0x1000032001e0 17592238473696
|
||||
x29 0x1000031ff940 17592238471488
|
||||
x30 0x1000000dc5fc 17592186947068
|
||||
sp 0x1000031ff940 0x1000031ff940
|
||||
pc 0x1000000dc610 0x1000000dc610 <nanosleep+96>
|
||||
cpsr 0x80000000 [ EL=0 N ]
|
||||
fpsr <unavailable>
|
||||
fpcr <unavailable>
|
||||
*** C1219T12 PASSED ******************************
|
||||
|
||||
rm: cannot remove './core.*': No such file or directory
|
||||
SEGV after join!!
|
||||
pthread_create done!! Let's join!!!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 268: 20066 Segmentation fault (core dumped) ${MCEXEC} ./segv_after_join
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T13 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
* 1 LWP 20066 0x00000000004008ec in main () at segv_in_sub.c:43
|
||||
*** C1219T13 PASSED ******************************
|
||||
206
test/issues/1219/result_x86_64.log
Normal file
206
test/issues/1219/result_x86_64.log
Normal file
@@ -0,0 +1,206 @@
|
||||
SEGV in sub thread!!
|
||||
pthread_create done!! Let's join!!!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 21: 30749 Segmentation fault (core dumped) ${MCEXEC} ./segv_in_sub
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T01 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
6 Thread 0x2aaaae200700 (LWP 30775) 0x000000000040079e in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
5 Thread 0x2aaaad800700 (LWP 30776) 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
4 Thread 0x2aaaace00700 (LWP 30777) 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
3 Thread 0x2aaaac400700 (LWP 30778) 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
2 Thread 0x2aaaaba00700 (LWP 30779) 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
* 1 Thread 0x2aaaab003b80 (LWP 30749) 0x00002aaaaaa22f97 in pthread_join () from /lib64/libpthread.so.0
|
||||
*** C1219T01 PASSED ******************************
|
||||
|
||||
*** C1219T02 start *******************************
|
||||
** Check backtrace
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x00002aaaaaa22f97 in pthread_join () from /lib64/libpthread.so.0
|
||||
#1 0x000000000040088f in main () at segv_in_sub.c:50
|
||||
*** C1219T02 PASSED ******************************
|
||||
|
||||
*** C1219T03 start *******************************
|
||||
** Check info register
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
rax 0xca 202
|
||||
rbx 0x2aaaaba00700 46912512198400
|
||||
rcx 0x2aaaaaa22f97 46912495562647
|
||||
rdx 0x783b 30779
|
||||
rsi 0x0 0
|
||||
rdi 0x2aaaaba009d0 46912512199120
|
||||
rbp 0x2aaaab003b80 0x2aaaab003b80
|
||||
rsp 0x547ffffffb70 0x547ffffffb70
|
||||
r8 0x0 0
|
||||
r9 0x654c202121656e6f 7299244422727036527
|
||||
r10 0x0 0
|
||||
r11 0x246 582
|
||||
r12 0xffff88041af2f020 -131923763335136
|
||||
r13 0xffff88041af82000 -131923762995200
|
||||
r14 0xfffffffffe8551d0 -24817200
|
||||
r15 0xfffffffffe849810 -24864752
|
||||
rip 0x2aaaaaa22f97 0x2aaaaaa22f97 <pthread_join+167>
|
||||
eflags 0x246 [ PF ZF IF ]
|
||||
cs 0x33 51
|
||||
ss 0x3b 59
|
||||
ds 0x0 0
|
||||
es 0x0 0
|
||||
fs 0x0 0
|
||||
gs 0x0 0
|
||||
*** C1219T03 PASSED ******************************
|
||||
|
||||
*** C1219T04 start *******************************
|
||||
** Check switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) thread 6"
|
||||
[Switching to thread 6 (Thread 0x2aaaae200700 (LWP 30775))]
|
||||
#0 0x000000000040079e in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
20 *ptr = 0xdead;
|
||||
*** C1219T04 PASSED ******************************
|
||||
|
||||
*** C1219T05 start *******************************
|
||||
** Check backtrace after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x000000000040079e in thread_fn_dump (arg=0x0) at segv_in_sub.c:20
|
||||
#1 0x00002aaaaaa21e25 in start_thread () from /lib64/libpthread.so.0
|
||||
#2 0x00002aaaaad34bad in clone () from /lib64/libc.so.6
|
||||
*** C1219T05 PASSED ******************************
|
||||
|
||||
*** C1219T06 start *******************************
|
||||
** Check info register after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
rax 0x0 0
|
||||
rbx 0x0 0
|
||||
rcx 0x2aaaaaa21dc4 46912495558084
|
||||
rdx 0x55557c1fde620000 6148957342561075200
|
||||
rsi 0x0 0
|
||||
rdi 0x0 0
|
||||
rbp 0x2aaaae1fff10 0x2aaaae1fff10
|
||||
rsp 0x2aaaae1fff10 0x2aaaae1fff10
|
||||
r8 0x2aaaae200700 46912554141440
|
||||
r9 0x2aaaae200700 46912554141440
|
||||
r10 0x2aaaae2009d0 46912554142160
|
||||
r11 0x202 514
|
||||
r12 0xffff88041af2f020 -131923763335136
|
||||
r13 0xffff88041b362000 -131923758931968
|
||||
r14 0xfffffffffe8551d0 -24817200
|
||||
r15 0xfffffffffe849810 -24864752
|
||||
rip 0x40079e 0x40079e <thread_fn_dump+20>
|
||||
eflags 0x10246 [ PF ZF IF RF ]
|
||||
cs 0x33 51
|
||||
ss 0x3b 59
|
||||
ds 0x0 0
|
||||
es 0x0 0
|
||||
fs 0x0 0
|
||||
gs 0x0 0
|
||||
*** C1219T06 PASSED ******************************
|
||||
|
||||
SEGV in main thread!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 145: 30826 Segmentation fault (core dumped) ${MCEXEC} ./segv_in_main
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T07 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
6 LWP 30852 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
5 LWP 30853 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
4 LWP 30854 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
3 LWP 30855 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
2 LWP 30856 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
* 1 LWP 30826 0x0000000000400814 in main () at segv_in_sub.c:38
|
||||
*** C1219T07 PASSED ******************************
|
||||
|
||||
*** C1219T08 start *******************************
|
||||
** Check backtrace
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x0000000000400814 in main () at segv_in_sub.c:38
|
||||
*** C1219T08 PASSED ******************************
|
||||
|
||||
*** C1219T09 start *******************************
|
||||
** Check info register
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
rax 0x0 0
|
||||
rbx 0x0 0
|
||||
rcx 0x0 0
|
||||
rdx 0x4 4
|
||||
rsi 0x2aaaae1fffb0 46912554139568
|
||||
rdi 0x3d0f00 4001536
|
||||
rbp 0x547ffffffc20 0x547ffffffc20
|
||||
rsp 0x547ffffffbc0 0x547ffffffbc0
|
||||
r8 0x2aaaae200700 46912554141440
|
||||
r9 0x2aaaae200700 46912554141440
|
||||
r10 0x2aaaae2009d0 46912554142160
|
||||
r11 0x202 514
|
||||
r12 0xffff88041afe0620 -131923762608608
|
||||
r13 0xffff88041b38c000 -131923758759936
|
||||
r14 0xfffffffffe8551d0 -24817200
|
||||
r15 0xfffffffffe849810 -24864752
|
||||
rip 0x400814 0x400814 <main+110>
|
||||
eflags 0x10202 [ IF RF ]
|
||||
cs 0x33 51
|
||||
ss 0x3b 59
|
||||
ds 0x0 0
|
||||
es 0x0 0
|
||||
fs 0x0 0
|
||||
gs 0x0 0
|
||||
*** C1219T09 PASSED ******************************
|
||||
|
||||
*** C1219T10 start *******************************
|
||||
** Check switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) thread 6"
|
||||
[Switching to thread 6 (LWP 30852)]
|
||||
#0 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
*** C1219T10 PASSED ******************************
|
||||
|
||||
*** C1219T11 start *******************************
|
||||
** Check backtrace after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) backtrace"
|
||||
#0 0x00002aaaaacfb56d in nanosleep () from /lib64/libc.so.6
|
||||
#1 0x00002aaaaacfb404 in sleep () from /lib64/libc.so.6
|
||||
#2 0x0000000000400788 in thread_fn_nop (arg=0x0) at segv_in_sub.c:14
|
||||
#3 0x00002aaaaaa21e25 in start_thread () from /lib64/libpthread.so.0
|
||||
#4 0x00002aaaaad34bad in clone () from /lib64/libc.so.6
|
||||
*** C1219T11 PASSED ******************************
|
||||
|
||||
*** C1219T12 start *******************************
|
||||
** Check info register after switching thread
|
||||
$1 = "TESTOUT_START result of (gdb) info register"
|
||||
rax 0x23 35
|
||||
rbx 0x2aaaae1ffd30 46912554138928
|
||||
rcx 0x2aaaaacfb56d 46912498546029
|
||||
rdx 0x0 0
|
||||
rsi 0x2aaaae1ffd20 46912554138912
|
||||
rdi 0x2aaaae1ffd20 46912554138912
|
||||
rbp 0xffffffff 0xffffffff
|
||||
rsp 0x2aaaae1ffd10 0x2aaaae1ffd10
|
||||
r8 0x2aaaae1ffe30 46912554139184
|
||||
r9 0x2aaaae1ffc70 46912554138736
|
||||
r10 0x8 8
|
||||
r11 0x293 659
|
||||
r12 0xffff88041afe0620 -131923762608608
|
||||
r13 0xffff88041bd08000 -131923748814848
|
||||
r14 0xfffffffffe8551d0 -24817200
|
||||
r15 0xfffffffffe849810 -24864752
|
||||
rip 0x2aaaaacfb56d 0x2aaaaacfb56d <nanosleep+45>
|
||||
eflags 0x293 [ CF AF SF IF ]
|
||||
cs 0x33 51
|
||||
ss 0x3b 59
|
||||
ds 0x0 0
|
||||
es 0x0 0
|
||||
fs 0x0 0
|
||||
gs 0x0 0
|
||||
*** C1219T12 PASSED ******************************
|
||||
|
||||
SEGV after join!!
|
||||
pthread_create done!! Let's join!!!!
|
||||
Terminate by signal 11
|
||||
./C1219.sh: line 268: 30903 Segmentation fault (core dumped) ${MCEXEC} ./segv_after_join
|
||||
[ OK ] core for McKernel process found
|
||||
*** C1219T13 start *******************************
|
||||
** Check number of threads
|
||||
$1 = "TESTOUT_START result of (gdb) info threads"
|
||||
Id Target Id Frame
|
||||
* 1 LWP 30903 0x0000000000400848 in main () at segv_in_sub.c:43
|
||||
*** C1219T13 PASSED ******************************
|
||||
47
test/issues/1219/segv_after_join.c
Normal file
47
test/issues/1219/segv_after_join.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <memory.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sched.h>
|
||||
|
||||
#define NUM_THREADS 5
|
||||
|
||||
void *thread_fn_nop(void *arg)
|
||||
{
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pthread_t threads[NUM_THREADS];
|
||||
int i, j;
|
||||
int rets[NUM_THREADS];
|
||||
int *ptr = NULL;
|
||||
|
||||
printf("SEGV after join!!\n");
|
||||
|
||||
/* Create threads */
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
rets[i] = pthread_create(&threads[i], NULL,
|
||||
thread_fn_nop, NULL);
|
||||
|
||||
if (rets[i] != 0) {
|
||||
printf("pthread_create: %d\n", rets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("pthread_create done!! Let's join!!!!\n");
|
||||
|
||||
for (j = 0; j < NUM_THREADS; j++) {
|
||||
pthread_join(threads[j], NULL);
|
||||
}
|
||||
|
||||
*ptr = 0xdead;
|
||||
|
||||
printf("All threads are done.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
47
test/issues/1219/segv_in_main.c
Normal file
47
test/issues/1219/segv_in_main.c
Normal file
@@ -0,0 +1,47 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <memory.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sched.h>
|
||||
|
||||
#define NUM_THREADS 5
|
||||
|
||||
void *thread_fn_nop(void *arg)
|
||||
{
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pthread_t threads[NUM_THREADS];
|
||||
int i, j;
|
||||
int rets[NUM_THREADS];
|
||||
int *ptr = NULL;
|
||||
|
||||
printf("SEGV in main thread!!\n");
|
||||
|
||||
/* Create threads */
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
rets[i] = pthread_create(&threads[i], NULL,
|
||||
thread_fn_nop, NULL);
|
||||
|
||||
if (rets[i] != 0) {
|
||||
printf("pthread_create: %d\n", rets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = 0xdead;
|
||||
|
||||
printf("pthread_create done!! Let's join!!!!\n");
|
||||
|
||||
for (j = 0; j < NUM_THREADS; j++) {
|
||||
pthread_join(threads[j], NULL);
|
||||
}
|
||||
|
||||
printf("All threads are done.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
56
test/issues/1219/segv_in_sub.c
Normal file
56
test/issues/1219/segv_in_sub.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <memory.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sched.h>
|
||||
|
||||
#define NUM_THREADS 5
|
||||
|
||||
void *thread_fn_nop(void *arg)
|
||||
{
|
||||
sleep(10);
|
||||
}
|
||||
void *thread_fn_dump(void *arg)
|
||||
{
|
||||
int *ptr = NULL;
|
||||
|
||||
*ptr = 0xdead;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pthread_t threads[NUM_THREADS];
|
||||
int i, j;
|
||||
int rets[NUM_THREADS];
|
||||
|
||||
printf("SEGV in sub thread!!\n");
|
||||
|
||||
/* Create threads */
|
||||
for (i = 0; i < NUM_THREADS; i++) {
|
||||
if (i == NUM_THREADS - 1) {
|
||||
/* SEGV thread */
|
||||
rets[i] = pthread_create(&threads[i], NULL,
|
||||
thread_fn_dump, NULL);
|
||||
} else {
|
||||
rets[i] = pthread_create(&threads[i], NULL,
|
||||
thread_fn_nop, NULL);
|
||||
}
|
||||
|
||||
if (rets[i] != 0) {
|
||||
printf("pthread_create: %d\n", rets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
printf("pthread_create done!! Let's join!!!!\n");
|
||||
|
||||
for (j = 0; j < NUM_THREADS; j++) {
|
||||
pthread_join(threads[j], NULL);
|
||||
}
|
||||
|
||||
printf("All threads are done.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user