2011-09-23 12:00:45 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2012-02-29 16:07:11 +03:00
|
|
|
#include <ctype.h>
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "list.h"
|
2012-01-26 15:27:00 +04:00
|
|
|
#include "namespaces.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
#include "compiler.h"
|
|
|
|
#include "crtools.h"
|
|
|
|
#include "util.h"
|
2011-12-26 22:12:03 +04:00
|
|
|
#include "sockets.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
#include "image.h"
|
2012-01-31 11:29:23 +03:00
|
|
|
#include "uts_ns.h"
|
2012-01-31 22:29:11 +04:00
|
|
|
#include "ipc_ns.h"
|
2012-06-26 14:51:00 +04:00
|
|
|
#include "pstree.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-07-12 13:06:00 +04:00
|
|
|
#include "protobuf.h"
|
|
|
|
#include "protobuf/fdinfo.pb-c.h"
|
2012-07-17 07:17:02 +04:00
|
|
|
#include "protobuf/regfile.pb-c.h"
|
2012-07-17 07:17:51 +04:00
|
|
|
#include "protobuf/ghost-file.pb-c.h"
|
2012-07-17 07:18:40 +04:00
|
|
|
#include "protobuf/fifo.pb-c.h"
|
2012-07-12 13:07:00 +04:00
|
|
|
#include "protobuf/remap-file-path.pb-c.h"
|
2012-07-17 07:24:52 +04:00
|
|
|
#include "protobuf/fown.pb-c.h"
|
2012-07-17 07:28:38 +04:00
|
|
|
#include "protobuf/fs.pb-c.h"
|
2012-07-17 07:29:36 +04:00
|
|
|
#include "protobuf/pstree.pb-c.h"
|
2012-07-12 17:56:00 +04:00
|
|
|
#include "protobuf/pipe.pb-c.h"
|
2012-07-17 14:50:23 +04:00
|
|
|
#include "protobuf/pipe-data.pb-c.h"
|
2012-07-18 16:25:06 +04:00
|
|
|
#include "protobuf/sa.pb-c.h"
|
2012-07-18 16:27:01 +04:00
|
|
|
#include "protobuf/itimer.pb-c.h"
|
2012-07-18 20:54:00 +04:00
|
|
|
#include "protobuf/mm.pb-c.h"
|
2012-07-19 12:43:36 +04:00
|
|
|
#include "protobuf/vma.pb-c.h"
|
2012-07-19 12:35:25 +04:00
|
|
|
#include "protobuf/creds.pb-c.h"
|
2012-07-19 13:23:01 +04:00
|
|
|
#include "protobuf/core.pb-c.h"
|
2012-07-12 13:06:00 +04:00
|
|
|
|
2011-11-21 20:27:47 +04:00
|
|
|
#define DEF_PAGES_PER_LINE 6
|
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
#ifndef CONFIG_X86_64
|
|
|
|
# error No x86-32 support yet
|
|
|
|
#endif
|
|
|
|
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
#define PR_SYMBOL(sym) \
|
2012-02-29 16:07:11 +03:00
|
|
|
(isprint(sym) ? sym : '.')
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
static LIST_HEAD(pstree_list);
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_files(int fd_files, struct cr_options *o)
|
2011-09-23 12:00:45 +04:00
|
|
|
{
|
2012-08-21 16:30:37 +04:00
|
|
|
pb_show_plain_pretty(fd_files, PB_FDINFO, "2:%#o 4:%d");
|
2012-03-25 20:24:53 +04:00
|
|
|
}
|
|
|
|
|
2012-07-19 09:39:00 +04:00
|
|
|
void show_fown_cont(void *p)
|
2012-07-17 07:24:52 +04:00
|
|
|
{
|
|
|
|
FownEntry *fown = p;
|
|
|
|
pr_msg("fown: uid: %#x euid: %#x signum: %#x pid_type: %#x pid: %u",
|
|
|
|
fown->uid, fown->euid, fown->signum, fown->pid_type, fown->pid);
|
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_reg_files(int fd_reg_files, struct cr_options *o)
|
2012-03-25 20:24:53 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd_reg_files, PB_REG_FILES);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-04-13 17:54:36 +04:00
|
|
|
void show_remap_files(int fd, struct cr_options *o)
|
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd, PB_REMAP_FPATH);
|
2012-04-13 17:54:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void show_ghost_file(int fd, struct cr_options *o)
|
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_vertical(fd, PB_GHOST_FILE);
|
2012-04-13 17:54:36 +04:00
|
|
|
}
|
|
|
|
|
2012-07-26 12:43:00 +04:00
|
|
|
static void pipe_data_handler(int fd, void *obj, int show_pages_content)
|
2012-04-05 20:02:00 +04:00
|
|
|
{
|
2012-07-25 18:33:29 +04:00
|
|
|
PipeDataEntry *e = obj;
|
2012-07-26 12:43:00 +04:00
|
|
|
|
|
|
|
if (show_pages_content) {
|
|
|
|
pr_msg("\n");
|
|
|
|
print_image_data(fd, e->bytes);
|
|
|
|
} else
|
|
|
|
lseek(fd, e->bytes, SEEK_CUR);
|
2012-06-26 02:36:13 +04:00
|
|
|
}
|
2012-04-05 20:02:00 +04:00
|
|
|
|
2012-07-25 18:33:29 +04:00
|
|
|
void show_pipes_data(int fd, struct cr_options *o)
|
2012-06-26 02:36:13 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain_payload(fd, PB_PIPES_DATA,
|
2012-07-26 12:43:00 +04:00
|
|
|
pipe_data_handler, o->show_pages_content);
|
2012-04-05 20:02:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_pipes(int fd_pipes, struct cr_options *o)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd_pipes, PB_PIPES);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-06-26 02:36:13 +04:00
|
|
|
void show_fifo_data(int fd, struct cr_options *o)
|
|
|
|
{
|
2012-07-25 18:33:29 +04:00
|
|
|
show_pipes_data(fd, o);
|
2012-06-26 02:36:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void show_fifo(int fd, struct cr_options *o)
|
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd, PB_FIFO);
|
2012-06-26 02:36:13 +04:00
|
|
|
}
|
|
|
|
|
2012-04-09 13:41:05 +04:00
|
|
|
void show_fs(int fd_fs, struct cr_options *o)
|
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_vertical(fd_fs, PB_FS);
|
2012-04-09 13:41:05 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_vmas(int fd_vma, struct cr_options *o)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd_vma, PB_VMAS);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-04-29 09:05:21 +04:00
|
|
|
static int nice_width_for(unsigned long addr)
|
|
|
|
{
|
|
|
|
int ret = 3;
|
|
|
|
|
|
|
|
while (addr) {
|
|
|
|
addr >>= 4;
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-02-29 16:07:11 +03:00
|
|
|
void print_data(unsigned long addr, unsigned char *data, size_t size)
|
|
|
|
{
|
2012-04-29 09:05:21 +04:00
|
|
|
int i, j, addr_len;
|
|
|
|
|
|
|
|
addr_len = nice_width_for(addr + size);
|
2012-02-29 16:07:11 +03:00
|
|
|
|
2012-08-11 22:19:34 +04:00
|
|
|
for (i = 0; i < size; i += 16) {
|
2012-04-29 09:05:21 +04:00
|
|
|
pr_msg("%#0*lx: ", addr_len, addr + i);
|
2012-02-29 16:07:11 +03:00
|
|
|
for (j = 0; j < 8; j++)
|
2012-04-13 19:44:00 +04:00
|
|
|
pr_msg("0x%02x ", data[i + j]);
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg(" ");
|
2012-02-29 16:07:11 +03:00
|
|
|
for (j = 8; j < 16; j++)
|
2012-04-13 19:44:00 +04:00
|
|
|
pr_msg("0x%02x ", data[i + j]);
|
2012-02-29 16:07:11 +03:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg(" |");
|
2012-02-29 16:07:11 +03:00
|
|
|
for (j = 0; j < 8; j++)
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("%c ", PR_SYMBOL(data[i + j]));
|
|
|
|
pr_msg(" ");
|
2012-02-29 16:07:11 +03:00
|
|
|
for (j = 8; j < 16; j++)
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("%c ", PR_SYMBOL(data[i + j]));
|
2012-02-29 16:07:11 +03:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("|\n");
|
2012-02-29 16:07:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-25 18:33:04 +04:00
|
|
|
void print_image_data(int fd, unsigned int length)
|
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
data = xmalloc(length);
|
|
|
|
if (!data)
|
|
|
|
return;
|
|
|
|
ret = read_img_buf(fd, (unsigned char *)data, length);
|
|
|
|
if (ret < 0) {
|
|
|
|
xfree(data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
print_data(0, (unsigned char *)data, length);
|
|
|
|
xfree(data);
|
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_pages(int fd_pages, struct cr_options *o)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2012-01-12 15:16:33 +04:00
|
|
|
pr_img_head(CR_FD_PAGES);
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
if (o->show_pages_content) {
|
2011-12-05 15:57:47 +04:00
|
|
|
while (1) {
|
|
|
|
struct page_entry e;
|
|
|
|
|
2012-04-05 12:57:29 +04:00
|
|
|
if (read_img_eof(fd_pages, &e) <= 0)
|
2011-12-05 15:57:47 +04:00
|
|
|
break;
|
|
|
|
|
2012-02-29 16:07:11 +03:00
|
|
|
print_data(e.va, e.data, PAGE_IMAGE_SIZE);
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("\n --- End of page ---\n\n");
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (1) {
|
|
|
|
struct page_entry e;
|
2012-05-18 15:39:00 +04:00
|
|
|
int i;
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("\t");
|
2011-12-05 15:57:47 +04:00
|
|
|
for (i = 0; i < DEF_PAGES_PER_LINE; i++) {
|
2012-04-05 12:57:29 +04:00
|
|
|
if (read_img_eof(fd_pages, &e) <= 0) {
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("\n");
|
2011-12-05 15:57:47 +04:00
|
|
|
goto out;
|
|
|
|
}
|
2012-04-05 12:57:29 +04:00
|
|
|
|
2012-04-13 19:44:00 +04:00
|
|
|
pr_msg("0x%16lx ", e.va);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("\n");
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2012-01-12 15:16:33 +04:00
|
|
|
pr_img_tail(CR_FD_PAGES);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_sigacts(int fd_sigacts, struct cr_options *o)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_plain(fd_sigacts, PB_SIGACT);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-07-18 16:27:01 +04:00
|
|
|
static void show_itimer(char *n, ItimerEntry *ie)
|
2012-01-24 16:45:19 +04:00
|
|
|
{
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("%s: int %lu.%lu val %lu.%lu\n", n,
|
|
|
|
(unsigned long)ie->isec, (unsigned long)ie->iusec,
|
|
|
|
(unsigned long)ie->vsec, (unsigned long)ie->vusec);
|
2012-01-24 16:45:19 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_itimers(int fd, struct cr_options *o)
|
2012-01-24 16:45:19 +04:00
|
|
|
{
|
2012-07-18 16:27:01 +04:00
|
|
|
ItimerEntry *ie;
|
|
|
|
int ret;
|
2012-01-24 16:45:19 +04:00
|
|
|
|
|
|
|
pr_img_head(CR_FD_ITIMERS);
|
2012-07-18 16:27:01 +04:00
|
|
|
|
2012-08-07 02:42:58 +04:00
|
|
|
ret = pb_read_one(fd, &ie, PB_ITIMERS);
|
2012-07-18 16:27:01 +04:00
|
|
|
if (ret < 0)
|
2012-01-24 16:45:19 +04:00
|
|
|
goto out;
|
2012-07-18 16:27:01 +04:00
|
|
|
show_itimer("real", ie);
|
|
|
|
itimer_entry__free_unpacked(ie, NULL);
|
2012-01-24 16:45:19 +04:00
|
|
|
|
2012-08-07 02:42:58 +04:00
|
|
|
ret = pb_read_one(fd, &ie, PB_ITIMERS);
|
2012-07-18 16:27:01 +04:00
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
show_itimer("virt", ie);
|
|
|
|
itimer_entry__free_unpacked(ie, NULL);
|
|
|
|
|
2012-08-07 02:42:58 +04:00
|
|
|
ret = pb_read_one(fd, &ie, PB_ITIMERS);
|
2012-07-18 16:27:01 +04:00
|
|
|
if (ret < 0)
|
|
|
|
goto out;
|
|
|
|
show_itimer("prof", ie);
|
|
|
|
itimer_entry__free_unpacked(ie, NULL);
|
2012-01-24 16:45:19 +04:00
|
|
|
out:
|
|
|
|
pr_img_tail(CR_FD_ITIMERS);
|
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_creds(int fd, struct cr_options *o)
|
2012-01-27 21:43:32 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_vertical(fd, PB_CREDS);
|
2012-01-27 21:43:32 +04:00
|
|
|
}
|
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
static void pstree_handler(int fd, void *obj, int collect)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2012-07-28 09:07:27 +04:00
|
|
|
PstreeEntry *e = obj;
|
|
|
|
struct pstree_item *item = NULL;
|
2012-01-12 21:53:46 +04:00
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
if (!collect)
|
|
|
|
return;
|
2012-01-12 21:53:46 +04:00
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
item = xzalloc(sizeof(struct pstree_item));
|
|
|
|
if (!item)
|
|
|
|
return;
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
item->pid.virt = e->pid;
|
|
|
|
item->nr_threads = e->n_threads;
|
|
|
|
item->threads = xzalloc(sizeof(u32) * e->n_threads);
|
|
|
|
if (!item->threads) {
|
|
|
|
xfree(item);
|
|
|
|
return;
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
list_add_tail(&item->list, &pstree_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void show_collect_pstree(int fd, int collect)
|
|
|
|
{
|
2012-08-14 14:49:40 +04:00
|
|
|
pb_show_plain_payload_pretty(fd, PB_PSTREE, pstree_handler,
|
|
|
|
collect, "1:%d 2:%d 3:%d 4:%d 5:%d");
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|
|
|
|
|
2012-07-28 09:07:27 +04:00
|
|
|
void show_pstree(int fd, struct cr_options *o)
|
2012-03-27 12:01:14 +04:00
|
|
|
{
|
2012-07-28 09:07:27 +04:00
|
|
|
show_collect_pstree(fd, 0);
|
2012-03-27 12:01:14 +04:00
|
|
|
}
|
|
|
|
|
2012-01-22 20:24:04 +04:00
|
|
|
static inline char *task_state_str(int state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case TASK_ALIVE:
|
|
|
|
return "running/sleeping";
|
|
|
|
case TASK_DEAD:
|
|
|
|
return "zombie";
|
|
|
|
default:
|
|
|
|
return "UNKNOWN";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-19 13:23:01 +04:00
|
|
|
static void show_core_regs(UserX86RegsEntry *regs)
|
|
|
|
{
|
|
|
|
#define pr_regs4(s, n1, n2, n3, n4) \
|
|
|
|
pr_msg("\t%8s: 0x%-16lx " \
|
|
|
|
"%8s: 0x%-16lx " \
|
|
|
|
"%8s: 0x%-16lx " \
|
|
|
|
"%8s: 0x%-16lx\n", \
|
|
|
|
#n1, s->n1, \
|
|
|
|
#n2, s->n2, \
|
|
|
|
#n3, s->n3, \
|
|
|
|
#n4, s->n4)
|
|
|
|
|
|
|
|
#define pr_regs3(s, n1, n2, n3) \
|
|
|
|
pr_msg("\t%8s: 0x%-16lx " \
|
|
|
|
"%8s: 0x%-16lx " \
|
|
|
|
"%8s: 0x%-16lx\n", \
|
|
|
|
#n1, s->n1, \
|
|
|
|
#n2, s->n2, \
|
|
|
|
#n3, s->n3)
|
|
|
|
|
|
|
|
pr_msg("\t---[ GP registers set ]---\n");
|
2011-11-21 20:19:35 +04:00
|
|
|
|
2012-07-19 13:23:01 +04:00
|
|
|
pr_regs4(regs, cs, ip, ds, es);
|
|
|
|
pr_regs4(regs, ss, sp, fs, gs);
|
|
|
|
pr_regs4(regs, di, si, dx, cx);
|
|
|
|
pr_regs4(regs, ax, r8, r9, r10);
|
|
|
|
pr_regs4(regs, r11, r12, r13, r14);
|
|
|
|
pr_regs3(regs, r15, bp, bx);
|
|
|
|
pr_regs4(regs, orig_ax, flags, fs_base, gs_base);
|
|
|
|
pr_msg("\n");
|
2011-11-21 20:19:35 +04:00
|
|
|
}
|
|
|
|
|
2012-07-19 13:23:01 +04:00
|
|
|
void show_thread_info(ThreadInfoX86 *thread_info)
|
2012-04-09 18:02:00 +04:00
|
|
|
{
|
2012-07-20 14:13:14 +04:00
|
|
|
if (!thread_info)
|
|
|
|
return;
|
|
|
|
|
2012-07-19 13:23:01 +04:00
|
|
|
pr_msg("\t---[ Thread info ]---\n");
|
|
|
|
pr_msg("\tclear_tid_addr: 0x%lx\n", thread_info->clear_tid_addr);
|
|
|
|
pr_msg("\n");
|
|
|
|
|
|
|
|
show_core_regs(thread_info->gpregs);
|
2012-04-09 18:02:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
void show_core(int fd_core, struct cr_options *o)
|
2011-09-23 12:00:45 +04:00
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_vertical(fd_core, PB_CORE);
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|
|
|
|
|
2012-04-09 14:51:37 +04:00
|
|
|
void show_mm(int fd_mm, struct cr_options *o)
|
|
|
|
{
|
2012-08-07 02:51:34 +04:00
|
|
|
pb_show_vertical(fd_mm, PB_MM);
|
2012-04-09 14:51:37 +04:00
|
|
|
}
|
|
|
|
|
2012-08-08 15:03:15 +04:00
|
|
|
static struct {
|
|
|
|
u32 magic;
|
|
|
|
u32 mask;
|
|
|
|
char *hint;
|
|
|
|
} magic_hints[] = {
|
|
|
|
{ .magic = 0x45311224, .mask = 0xffffffff, .hint = "ip route dump", },
|
|
|
|
{ .magic = 0x47361222, .mask = 0xffffffff, .hint = "ip ifaddr dump", },
|
|
|
|
{ .magic = 0x00008b1f, .mask = 0x0000ffff, .hint = "gzip file", },
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static void try_hint_magic(u32 magic)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; magic_hints[i].hint != 0; i++)
|
|
|
|
if ((magic & magic_hints[i].mask) == magic_hints[i].magic)
|
|
|
|
pr_msg("This can be %s\n", magic_hints[i].hint);
|
|
|
|
}
|
|
|
|
|
2011-12-05 15:57:47 +04:00
|
|
|
static int cr_parse_file(struct cr_options *opts)
|
2011-09-23 12:00:45 +04:00
|
|
|
{
|
2011-12-05 15:57:47 +04:00
|
|
|
u32 magic;
|
2012-03-27 12:01:14 +04:00
|
|
|
int fd = -1, ret = -1, i;
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2011-12-05 15:57:47 +04:00
|
|
|
fd = open(opts->show_dump_file, O_RDONLY);
|
|
|
|
if (fd < 0) {
|
2012-01-31 15:13:05 +04:00
|
|
|
pr_perror("Can't open %s", opts->show_dump_file);
|
2011-12-05 15:57:47 +04:00
|
|
|
goto err;
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|
|
|
|
|
2012-01-22 20:20:40 +04:00
|
|
|
if (read_img(fd, &magic) < 0)
|
|
|
|
goto err;
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
for (i = 0; i < CR_FD_MAX; i++)
|
|
|
|
if (fdset_template[i].magic == magic)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (i == CR_FD_MAX) {
|
2012-04-24 15:20:24 +04:00
|
|
|
pr_err("Unknown magic %#x in %s\n",
|
2012-03-27 12:01:14 +04:00
|
|
|
magic, opts->show_dump_file);
|
2012-08-08 15:03:15 +04:00
|
|
|
try_hint_magic(magic);
|
2011-12-05 15:57:47 +04:00
|
|
|
goto err;
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
if (!fdset_template[i].show) {
|
2012-04-24 15:20:24 +04:00
|
|
|
pr_err("No handler for %#x/%s\n",
|
2012-03-27 12:01:14 +04:00
|
|
|
magic, opts->show_dump_file);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
fdset_template[i].show(fd, opts);
|
|
|
|
ret = 0;
|
2011-12-05 15:57:47 +04:00
|
|
|
err:
|
|
|
|
close_safe(&fd);
|
|
|
|
return ret;
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|
|
|
|
|
2012-03-27 11:04:23 +04:00
|
|
|
static int cr_show_all(struct cr_options *opts)
|
2011-09-23 12:00:45 +04:00
|
|
|
{
|
2012-05-31 14:50:00 +04:00
|
|
|
struct pstree_item *item = NULL, *tmp;
|
2012-03-27 11:04:23 +04:00
|
|
|
int i, ret = -1, fd, pid;
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-03-26 17:37:41 +04:00
|
|
|
fd = open_image_ro(CR_FD_PSTREE);
|
|
|
|
if (fd < 0)
|
2011-09-23 12:00:45 +04:00
|
|
|
goto out;
|
2012-07-28 09:07:27 +04:00
|
|
|
show_collect_pstree(fd, 1);
|
2012-03-26 17:37:41 +04:00
|
|
|
close(fd);
|
|
|
|
|
2012-03-26 17:38:59 +04:00
|
|
|
fd = open_image_ro(CR_FD_SK_QUEUES);
|
2012-03-26 17:37:41 +04:00
|
|
|
if (fd < 0)
|
2012-03-23 18:42:00 +04:00
|
|
|
goto out;
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
show_sk_queues(fd, opts);
|
2012-03-26 17:37:41 +04:00
|
|
|
close(fd);
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-06-22 00:38:00 +04:00
|
|
|
pid = list_first_entry(&pstree_list, struct pstree_item, list)->pid.virt;
|
2012-03-27 12:01:14 +04:00
|
|
|
ret = try_show_namespaces(pid, opts);
|
2012-01-26 15:27:00 +04:00
|
|
|
if (ret)
|
|
|
|
goto out;
|
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
list_for_each_entry(item, &pstree_list, list) {
|
2012-03-26 17:37:41 +04:00
|
|
|
struct cr_fdset *cr_fdset = NULL;
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-06-22 00:38:00 +04:00
|
|
|
cr_fdset = cr_task_fdset_open(item->pid.virt, O_SHOW);
|
2011-09-23 12:00:45 +04:00
|
|
|
if (!cr_fdset)
|
|
|
|
goto out;
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
show_core(fdset_fd(cr_fdset, CR_FD_CORE), opts);
|
2011-10-20 23:11:31 +04:00
|
|
|
|
|
|
|
if (item->nr_threads > 1) {
|
2012-03-27 12:01:14 +04:00
|
|
|
int fd_th;
|
2011-10-20 23:11:31 +04:00
|
|
|
|
|
|
|
for (i = 0; i < item->nr_threads; i++) {
|
|
|
|
|
2012-06-22 00:38:00 +04:00
|
|
|
if (item->threads[i].virt == item->pid.virt)
|
2011-10-20 23:11:31 +04:00
|
|
|
continue;
|
|
|
|
|
2012-03-26 17:42:28 +04:00
|
|
|
fd_th = open_image_ro(CR_FD_CORE, item->threads[i]);
|
|
|
|
if (fd_th < 0)
|
2011-10-20 23:11:31 +04:00
|
|
|
goto out;
|
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("\n");
|
2012-06-22 00:38:00 +04:00
|
|
|
pr_msg("Thread: %d\n", item->threads[i].virt);
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("----------------------------------------\n");
|
2011-10-20 23:11:31 +04:00
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
show_core(fd_th, opts);
|
2011-10-20 23:11:31 +04:00
|
|
|
|
2012-03-02 00:59:59 +04:00
|
|
|
pr_msg("----------------------------------------\n");
|
2011-10-20 23:11:31 +04:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-27 12:01:14 +04:00
|
|
|
for (i = _CR_FD_TASK_FROM + 1; i < _CR_FD_TASK_TO; i++)
|
|
|
|
if (i != CR_FD_CORE && fdset_template[i].show)
|
|
|
|
fdset_template[i].show(fdset_fd(cr_fdset, i), opts);
|
2012-01-27 21:43:32 +04:00
|
|
|
|
2012-01-12 21:25:19 +04:00
|
|
|
close_cr_fdset(&cr_fdset);
|
2011-09-23 12:00:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2012-05-31 14:50:00 +04:00
|
|
|
list_for_each_entry_safe(item, tmp, &pstree_list, list) {
|
|
|
|
list_del(&item->list);
|
|
|
|
xfree(item->threads);
|
|
|
|
xfree(item);
|
|
|
|
}
|
2011-09-23 12:00:45 +04:00
|
|
|
return ret;
|
|
|
|
}
|
2011-12-05 15:57:47 +04:00
|
|
|
|
2012-03-27 11:04:23 +04:00
|
|
|
int cr_show(struct cr_options *opts)
|
2011-12-05 15:57:47 +04:00
|
|
|
{
|
2011-12-28 20:38:00 +04:00
|
|
|
if (opts->show_dump_file)
|
2011-12-05 15:57:47 +04:00
|
|
|
return cr_parse_file(opts);
|
|
|
|
|
2012-03-27 11:04:23 +04:00
|
|
|
return cr_show_all(opts);
|
2011-12-05 15:57:47 +04:00
|
|
|
}
|