Commit af647ce0 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov

dump: Dump threads params as well

We only need registers at the moment
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
parent 9fcecfe1
...@@ -12,3 +12,10 @@ Some things which are to be done ...@@ -12,3 +12,10 @@ Some things which are to be done
- 'crtools show' should support showing only a subset of resources dumped such as - 'crtools show' should support showing only a subset of resources dumped such as
pipes/vma/ and etc... pipes/vma/ and etc...
- add bash completion file - add bash completion file
Some notes on code
------------------
- need to handle out cr_fdset(s), they are getting used more frequently
than I initially thought, including the usage only of a few file descriptors
while the whole set is always allocated
...@@ -67,7 +67,6 @@ static FILE *fopen_proc(char *fmt, char *mode, ...) ...@@ -67,7 +67,6 @@ static FILE *fopen_proc(char *fmt, char *mode, ...)
} }
static char big_buffer[PATH_MAX]; static char big_buffer[PATH_MAX];
static struct parasite_ctl *parasite_ctl;
static char loc_buf[PAGE_SIZE]; static char loc_buf[PAGE_SIZE];
...@@ -619,28 +618,14 @@ err: ...@@ -619,28 +618,14 @@ err:
return ret; return ret;
} }
static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset) static int get_task_regs(pid_t pid, struct core_entry *core)
{ {
struct core_entry *core = xzalloc(sizeof(*core));
user_fpregs_struct_t fpregs = {-1}; user_fpregs_struct_t fpregs = {-1};
user_regs_struct_t regs = {-1}; user_regs_struct_t regs = {-1};
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
int ret = -1; int ret = -1;
unsigned long brk;
pr_info("\n");
pr_info("Dumping core (pid: %d)\n", pid);
pr_info("----------------------------------------\n");
if (!core)
goto err;
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
jerr(ptrace(PTRACE_GETREGS, pid, NULL, &regs), err_free); jerr(ptrace(PTRACE_GETREGS, pid, NULL, &regs), err);
jerr(ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs), err_free); jerr(ptrace(PTRACE_GETFPREGS, pid, NULL, &fpregs), err);
pr_info("Dumping GP/FPU registers ... ");
assign_reg(core->u.arch.gpregs, regs, r15); assign_reg(core->u.arch.gpregs, regs, r15);
assign_reg(core->u.arch.gpregs, regs, r14); assign_reg(core->u.arch.gpregs, regs, r14);
...@@ -684,6 +669,33 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset) ...@@ -684,6 +669,33 @@ static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
assign_array(core->u.arch.fpregs, fpregs, padding); assign_array(core->u.arch.fpregs, fpregs, padding);
pr_info("OK\n"); pr_info("OK\n");
ret = 0;
err:
return ret;
}
static int dump_task_core_seized(pid_t pid, struct cr_fdset *cr_fdset)
{
struct core_entry *core = xzalloc(sizeof(*core));
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
int ret = -1;
unsigned long brk;
pr_info("\n");
pr_info("Dumping core (pid: %d)\n", pid);
pr_info("----------------------------------------\n");
if (!core)
goto err;
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
pr_info("Dumping GP/FPU registers ... ");
ret = get_task_regs(pid, core);
if (ret)
goto err_free;
pr_info("OK\n");
pr_info("Obtainting TLS ... "); pr_info("Obtainting TLS ... ");
ret = dump_task_tls(pid, core->u.arch.tls_array, ARRAY_SIZE(core->u.arch.tls_array)); ret = dump_task_tls(pid, core->u.arch.tls_array, ARRAY_SIZE(core->u.arch.tls_array));
...@@ -907,6 +919,7 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset ...@@ -907,6 +919,7 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset
e.pid = item->pid; e.pid = item->pid;
e.nr_children = item->nr_children; e.nr_children = item->nr_children;
e.nr_threads = item->nr_threads;
write_ptr_safe(cr_fdset->desc[CR_FD_PSTREE].fd, &e, err); write_ptr_safe(cr_fdset->desc[CR_FD_PSTREE].fd, &e, err);
...@@ -917,6 +930,14 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset ...@@ -917,6 +930,14 @@ static int dump_pstree(pid_t pid, struct list_head *pstree_list, struct cr_fdset
&item->children[i], err); &item->children[i], err);
} }
pr_info("\n"); pr_info("\n");
pr_info("Threads:\n");
for (i = 0; i < item->nr_threads; i++) {
pr_info(" %d", item->threads[i]);
write_ptr_safe(cr_fdset->desc[CR_FD_PSTREE].fd,
&item->threads[i], err);
}
pr_info("\n");
} }
ret = 0; ret = 0;
...@@ -1056,6 +1077,58 @@ err_strno: ...@@ -1056,6 +1077,58 @@ err_strno:
goto err; goto err;
} }
static int dump_task_thread(pid_t pid, struct cr_fdset *cr_fdset)
{
struct core_entry *core = xzalloc(sizeof(*core));
int fd_core = cr_fdset->desc[CR_FD_CORE].fd;
int ret = -1;
pr_info("\n");
pr_info("Dumping core for thread (pid: %d)\n", pid);
pr_info("----------------------------------------\n");
if (!core)
goto err;
lseek(fd_core, MAGIC_OFFSET, SEEK_SET);
ret = seize_task(pid);
if (ret) {
pr_err("Failed to seize thread (pid: %d) with %d\n",
pid, ret);
goto err_free;
}
pr_info("Dumping GP/FPU registers ... ");
ret = get_task_regs(pid, core);
if (ret)
goto err_free;
pr_info("OK\n");
ret = unseize_task(pid);
if (ret) {
pr_err("Can't unsieze thread (pid: %d)\n", pid);
goto err_free;
}
pr_info("Dumping header ... ");
core->header.version = HEADER_VERSION;
core->header.arch = HEADER_ARCH_X86_64;
core->header.flags = 0;
write_ptr_safe(fd_core, core, err_free);
pr_info("OK\n");
ret = 0;
err_free:
free(core);
err:
pr_info("----------------------------------------\n");
return ret;
}
static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset) static int dump_one_task(pid_t pid, struct cr_fdset *cr_fdset)
{ {
LIST_HEAD(vma_area_list); LIST_HEAD(vma_area_list);
...@@ -1138,7 +1211,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts) ...@@ -1138,7 +1211,7 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
LIST_HEAD(pstree_list); LIST_HEAD(pstree_list);
struct cr_fdset *cr_fdset = NULL; struct cr_fdset *cr_fdset = NULL;
struct pstree_item *item; struct pstree_item *item;
int ret = -1; int i, ret = -1;
pr_info("========================================\n"); pr_info("========================================\n");
if (!opts->leader_only) if (!opts->leader_only)
...@@ -1184,6 +1257,21 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts) ...@@ -1184,6 +1257,21 @@ int cr_dump_tasks(pid_t pid, struct cr_options *opts)
close_cr_fdset(cr_fdset); close_cr_fdset(cr_fdset);
free_cr_fdset(&cr_fdset); free_cr_fdset(&cr_fdset);
if (item->nr_threads > 1) {
for (i = 0; i < item->nr_threads; i++) {
/* Leader is already dumped */
if (item->pid == item->threads[i])
continue;
cr_fdset = alloc_cr_fdset(item->threads[i]);
if (!cr_fdset)
goto err;
if (prep_cr_fdset_for_dump(cr_fdset, CR_FD_DESC_CORE))
goto err;
if (dump_task_thread(item->threads[i], cr_fdset))
goto err;
}
}
if (opts->leader_only) if (opts->leader_only)
break; break;
} }
......
...@@ -58,7 +58,8 @@ struct cr_fdset { ...@@ -58,7 +58,8 @@ struct cr_fdset {
}; };
#define CR_FD_DESC_USE(type) ((1 << (type))) #define CR_FD_DESC_USE(type) ((1 << (type)))
#define CR_FD_DESC_ALL ((1 << CR_FD_MAX) - 1) #define CR_FD_DESC_ALL (CR_FD_DESC_USE(CR_FD_MAX) - 1)
#define CR_FD_DESC_CORE CR_FD_DESC_USE(CR_FD_CORE)
#define CR_FD_DESC_NOPSTREE (CR_FD_DESC_ALL & ~(CR_FD_DESC_USE(CR_FD_PSTREE))) #define CR_FD_DESC_NOPSTREE (CR_FD_DESC_ALL & ~(CR_FD_DESC_USE(CR_FD_PSTREE)))
#define CR_FD_DESC_NONE (0) #define CR_FD_DESC_NONE (0)
......
...@@ -36,7 +36,10 @@ struct shmem_entry { ...@@ -36,7 +36,10 @@ struct shmem_entry {
struct pstree_entry { struct pstree_entry {
u32 pid; u32 pid;
u32 nr_children; u32 nr_children;
u32 nr_threads;
u32 children[0]; u32 children[0];
u32 threads[0];
} __packed; } __packed;
struct pipe_entry { struct pipe_entry {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment