From 11ef2f8092f7980d35c3850a8ecbb09ae1d5bd94 Mon Sep 17 00:00:00 2001 From: Masamichi Takagi Date: Tue, 19 Feb 2019 17:08:39 +0900 Subject: [PATCH] coredump: Support threads Change-Id: Id75ade6c87b15abcff5d772d90f77950376a32c1 Refs: #1219 --- .gitignore | 2 + arch/arm64/kernel/coredump.c | 8 +- arch/arm64/kernel/syscall.c | 48 ++++- arch/x86_64/kernel/coredump.c | 7 +- arch/x86_64/kernel/syscall.c | 45 ++++- executer/kernel/mcctrl/syscall.c | 32 +++- kernel/gencore.c | 154 ++++++++++----- kernel/include/process.h | 7 + kernel/include/syscall.h | 5 + kernel/mem.c | 156 ++++++++++++++- kernel/process.c | 2 + kernel/syscall.c | 4 + test/issues/1219/C1219.sh | 285 ++++++++++++++++++++++++++++ test/issues/1219/Makefile | 11 ++ test/issues/1219/README | 80 ++++++++ test/issues/1219/cmd/C1219T01.cmd | 4 + test/issues/1219/cmd/C1219T02.cmd | 4 + test/issues/1219/cmd/C1219T03.cmd | 4 + test/issues/1219/cmd/C1219T04.cmd | 4 + test/issues/1219/cmd/C1219T05.cmd | 5 + test/issues/1219/cmd/C1219T06.cmd | 5 + test/issues/1219/cmd/C1219T07.cmd | 4 + test/issues/1219/cmd/C1219T08.cmd | 4 + test/issues/1219/cmd/C1219T09.cmd | 4 + test/issues/1219/cmd/C1219T10.cmd | 4 + test/issues/1219/cmd/C1219T11.cmd | 5 + test/issues/1219/cmd/C1219T12.cmd | 5 + test/issues/1219/cmd/C1219T13.cmd | 4 + test/issues/1219/result_aarch64.log | 256 +++++++++++++++++++++++++ test/issues/1219/result_x86_64.log | 206 ++++++++++++++++++++ test/issues/1219/segv_after_join.c | 47 +++++ test/issues/1219/segv_in_main.c | 47 +++++ test/issues/1219/segv_in_sub.c | 56 ++++++ 33 files changed, 1438 insertions(+), 76 deletions(-) create mode 100755 test/issues/1219/C1219.sh create mode 100644 test/issues/1219/Makefile create mode 100644 test/issues/1219/README create mode 100644 test/issues/1219/cmd/C1219T01.cmd create mode 100644 test/issues/1219/cmd/C1219T02.cmd create mode 100644 test/issues/1219/cmd/C1219T03.cmd create mode 100644 test/issues/1219/cmd/C1219T04.cmd create mode 100644 test/issues/1219/cmd/C1219T05.cmd create mode 100644 test/issues/1219/cmd/C1219T06.cmd create mode 100644 test/issues/1219/cmd/C1219T07.cmd create mode 100644 test/issues/1219/cmd/C1219T08.cmd create mode 100644 test/issues/1219/cmd/C1219T09.cmd create mode 100644 test/issues/1219/cmd/C1219T10.cmd create mode 100644 test/issues/1219/cmd/C1219T11.cmd create mode 100644 test/issues/1219/cmd/C1219T12.cmd create mode 100644 test/issues/1219/cmd/C1219T13.cmd create mode 100644 test/issues/1219/result_aarch64.log create mode 100644 test/issues/1219/result_x86_64.log create mode 100644 test/issues/1219/segv_after_join.c create mode 100644 test/issues/1219/segv_in_main.c create mode 100644 test/issues/1219/segv_in_sub.c diff --git a/.gitignore b/.gitignore index 3022b671..a395b512 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ old_timestamp CMakeFiles CMakeCache.txt Makefile +!test/*/*/Makefile +!test/*/*/*.cmd Kbuild cmake_install.cmake config.h diff --git a/arch/arm64/kernel/coredump.c b/arch/arm64/kernel/coredump.c index 6424be24..9ed2dd98 100644 --- a/arch/arm64/kernel/coredump.c +++ b/arch/arm64/kernel/coredump.c @@ -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) diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 7e58e654..c73e8407 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -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 \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); diff --git a/arch/x86_64/kernel/coredump.c b/arch/x86_64/kernel/coredump.c index ab26ffca..6cab6fa3 100644 --- a/arch/x86_64/kernel/coredump.c +++ b/arch/x86_64/kernel/coredump.c @@ -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; diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index 23d14151..bcf17ca4 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -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 \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) diff --git a/executer/kernel/mcctrl/syscall.c b/executer/kernel/mcctrl/syscall.c index 0e3266b3..445ed04e 100644 --- a/executer/kernel/mcctrl/syscall.c +++ b/executer/kernel/mcctrl/syscall.c @@ -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: { diff --git a/kernel/gencore.c b/kernel/gencore.c index 3e747db6..6590b63c 100644 --- a/kernel/gencore.c +++ b/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; } /** diff --git a/kernel/include/process.h b/kernel/include/process.h index f1ab4874..8a4a0f59 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -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 diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 3fb94fe8..c01d57d1 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -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 diff --git a/kernel/mem.c b/kernel/mem.c index 4ce73bda..65c7ff82 100644 --- a/kernel/mem.c +++ b/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, diff --git a/kernel/process.c b/kernel/process.c index 0413e19c..61dc3f90 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -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); diff --git a/kernel/syscall.c b/kernel/syscall.c index 222468fd..6517f84a 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -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) { diff --git a/test/issues/1219/C1219.sh b/test/issues/1219/C1219.sh new file mode 100755 index 00000000..262f6a8d --- /dev/null +++ b/test/issues/1219/C1219.sh @@ -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 "" + diff --git a/test/issues/1219/Makefile b/test/issues/1219/Makefile new file mode 100644 index 00000000..182be826 --- /dev/null +++ b/test/issues/1219/Makefile @@ -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 diff --git a/test/issues/1219/README b/test/issues/1219/README new file mode 100644 index 00000000..157ce64b --- /dev/null +++ b/test/issues/1219/README @@ -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していることを確認。 diff --git a/test/issues/1219/cmd/C1219T01.cmd b/test/issues/1219/cmd/C1219T01.cmd new file mode 100644 index 00000000..941683f3 --- /dev/null +++ b/test/issues/1219/cmd/C1219T01.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) info threads" +info threads +quit + diff --git a/test/issues/1219/cmd/C1219T02.cmd b/test/issues/1219/cmd/C1219T02.cmd new file mode 100644 index 00000000..e790c5fe --- /dev/null +++ b/test/issues/1219/cmd/C1219T02.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) backtrace" +backtrace +quit + diff --git a/test/issues/1219/cmd/C1219T03.cmd b/test/issues/1219/cmd/C1219T03.cmd new file mode 100644 index 00000000..e7774396 --- /dev/null +++ b/test/issues/1219/cmd/C1219T03.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) info register" +info register +quit + diff --git a/test/issues/1219/cmd/C1219T04.cmd b/test/issues/1219/cmd/C1219T04.cmd new file mode 100644 index 00000000..06a2b0b2 --- /dev/null +++ b/test/issues/1219/cmd/C1219T04.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) thread 6" +thread 6 +quit + diff --git a/test/issues/1219/cmd/C1219T05.cmd b/test/issues/1219/cmd/C1219T05.cmd new file mode 100644 index 00000000..4c9408f7 --- /dev/null +++ b/test/issues/1219/cmd/C1219T05.cmd @@ -0,0 +1,5 @@ +thread 6 +p "TESTOUT_START result of (gdb) backtrace" +backtrace +quit + diff --git a/test/issues/1219/cmd/C1219T06.cmd b/test/issues/1219/cmd/C1219T06.cmd new file mode 100644 index 00000000..589539d8 --- /dev/null +++ b/test/issues/1219/cmd/C1219T06.cmd @@ -0,0 +1,5 @@ +thread 6 +p "TESTOUT_START result of (gdb) info register" +info register +quit + diff --git a/test/issues/1219/cmd/C1219T07.cmd b/test/issues/1219/cmd/C1219T07.cmd new file mode 100644 index 00000000..941683f3 --- /dev/null +++ b/test/issues/1219/cmd/C1219T07.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) info threads" +info threads +quit + diff --git a/test/issues/1219/cmd/C1219T08.cmd b/test/issues/1219/cmd/C1219T08.cmd new file mode 100644 index 00000000..e790c5fe --- /dev/null +++ b/test/issues/1219/cmd/C1219T08.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) backtrace" +backtrace +quit + diff --git a/test/issues/1219/cmd/C1219T09.cmd b/test/issues/1219/cmd/C1219T09.cmd new file mode 100644 index 00000000..e7774396 --- /dev/null +++ b/test/issues/1219/cmd/C1219T09.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) info register" +info register +quit + diff --git a/test/issues/1219/cmd/C1219T10.cmd b/test/issues/1219/cmd/C1219T10.cmd new file mode 100644 index 00000000..06a2b0b2 --- /dev/null +++ b/test/issues/1219/cmd/C1219T10.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) thread 6" +thread 6 +quit + diff --git a/test/issues/1219/cmd/C1219T11.cmd b/test/issues/1219/cmd/C1219T11.cmd new file mode 100644 index 00000000..4c9408f7 --- /dev/null +++ b/test/issues/1219/cmd/C1219T11.cmd @@ -0,0 +1,5 @@ +thread 6 +p "TESTOUT_START result of (gdb) backtrace" +backtrace +quit + diff --git a/test/issues/1219/cmd/C1219T12.cmd b/test/issues/1219/cmd/C1219T12.cmd new file mode 100644 index 00000000..589539d8 --- /dev/null +++ b/test/issues/1219/cmd/C1219T12.cmd @@ -0,0 +1,5 @@ +thread 6 +p "TESTOUT_START result of (gdb) info register" +info register +quit + diff --git a/test/issues/1219/cmd/C1219T13.cmd b/test/issues/1219/cmd/C1219T13.cmd new file mode 100644 index 00000000..941683f3 --- /dev/null +++ b/test/issues/1219/cmd/C1219T13.cmd @@ -0,0 +1,4 @@ +p "TESTOUT_START result of (gdb) info threads" +info threads +quit + diff --git a/test/issues/1219/result_aarch64.log b/test/issues/1219/result_aarch64.log new file mode 100644 index 00000000..c32347fa --- /dev/null +++ b/test/issues/1219/result_aarch64.log @@ -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 +fpcr +*** 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 +cpsr 0x20000000 [ EL=0 C ] +fpsr +fpcr +*** 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 +cpsr 0x20000000 [ EL=0 C ] +fpsr +fpcr +*** 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 +cpsr 0x80000000 [ EL=0 N ] +fpsr +fpcr +*** 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 ****************************** diff --git a/test/issues/1219/result_x86_64.log b/test/issues/1219/result_x86_64.log new file mode 100644 index 00000000..7a8825af --- /dev/null +++ b/test/issues/1219/result_x86_64.log @@ -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 +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 +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 +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 +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 ****************************** diff --git a/test/issues/1219/segv_after_join.c b/test/issues/1219/segv_after_join.c new file mode 100644 index 00000000..466b4eae --- /dev/null +++ b/test/issues/1219/segv_after_join.c @@ -0,0 +1,47 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#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); +} + diff --git a/test/issues/1219/segv_in_main.c b/test/issues/1219/segv_in_main.c new file mode 100644 index 00000000..ac0774b8 --- /dev/null +++ b/test/issues/1219/segv_in_main.c @@ -0,0 +1,47 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#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); +} + diff --git a/test/issues/1219/segv_in_sub.c b/test/issues/1219/segv_in_sub.c new file mode 100644 index 00000000..a62369cb --- /dev/null +++ b/test/issues/1219/segv_in_sub.c @@ -0,0 +1,56 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#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); +} +