coredump: Support threads

Change-Id: Id75ade6c87b15abcff5d772d90f77950376a32c1
Refs: #1219
This commit is contained in:
Masamichi Takagi
2019-02-19 17:08:39 +09:00
parent 12aef0b578
commit 11ef2f8092
33 changed files with 1438 additions and 76 deletions

2
.gitignore vendored
View File

@@ -13,6 +13,8 @@ old_timestamp
CMakeFiles
CMakeCache.txt
Makefile
!test/*/*/Makefile
!test/*/*/*.cmd
Kbuild
cmake_install.cmake
config.h

View File

@@ -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, &regs->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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)

View File

@@ -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: {

View File

@@ -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;
}
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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);

View File

@@ -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
View 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
View 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
View 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していることを確認。

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) info threads"
info threads
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) backtrace"
backtrace
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) info register"
info register
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) thread 6"
thread 6
quit

View File

@@ -0,0 +1,5 @@
thread 6
p "TESTOUT_START result of (gdb) backtrace"
backtrace
quit

View File

@@ -0,0 +1,5 @@
thread 6
p "TESTOUT_START result of (gdb) info register"
info register
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) info threads"
info threads
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) backtrace"
backtrace
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) info register"
info register
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) thread 6"
thread 6
quit

View File

@@ -0,0 +1,5 @@
thread 6
p "TESTOUT_START result of (gdb) backtrace"
backtrace
quit

View File

@@ -0,0 +1,5 @@
thread 6
p "TESTOUT_START result of (gdb) info register"
info register
quit

View File

@@ -0,0 +1,4 @@
p "TESTOUT_START result of (gdb) info threads"
info threads
quit

View 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 ******************************

View 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 ******************************

View 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);
}

View 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);
}

View 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);
}