mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +00:00
show: Remove deprecated code
The 'show' action has been deprecated since 1.6, let's finally drop it. The print_data() routine is kept for yet another (to be deprecated too) feature called 'criu exec'. Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com> Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
This commit is contained in:
@@ -12,7 +12,6 @@ obj-y += cr-errno.o
|
||||
obj-y += cr-exec.o
|
||||
obj-y += cr-restore.o
|
||||
obj-y += cr-service.o
|
||||
obj-y += cr-show.o
|
||||
obj-y += crtools.o
|
||||
obj-y += eventfd.o
|
||||
obj-y += eventpoll.o
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "parasite-syscall.h"
|
||||
#include "vma.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
struct syscall_exec_desc {
|
||||
char *name;
|
||||
|
574
criu/cr-show.c
574
criu/cr-show.c
@@ -1,574 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "list.h"
|
||||
#include "imgset.h"
|
||||
#include "namespaces.h"
|
||||
#include "compiler.h"
|
||||
#include "cr_options.h"
|
||||
#include "util.h"
|
||||
#include "sockets.h"
|
||||
#include "image.h"
|
||||
#include "uts_ns.h"
|
||||
#include "ipc_ns.h"
|
||||
#include "pstree.h"
|
||||
#include "cr-show.h"
|
||||
#include "crtools.h"
|
||||
|
||||
#include "protobuf.h"
|
||||
#include "images/pstree.pb-c.h"
|
||||
#include "images/pipe-data.pb-c.h"
|
||||
#include "images/siginfo.pb-c.h"
|
||||
|
||||
#define DEF_PAGES_PER_LINE 6
|
||||
|
||||
|
||||
static LIST_HEAD(pstree_list);
|
||||
|
||||
static void pipe_data_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
PipeDataEntry *e = obj;
|
||||
print_image_data(img, e->bytes, opts.show_pages_content);
|
||||
}
|
||||
|
||||
static int nice_width_for(unsigned long addr)
|
||||
{
|
||||
int ret = 3;
|
||||
|
||||
while (addr) {
|
||||
addr >>= 4;
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void pr_xdigi(unsigned char *data, size_t len, int pos)
|
||||
{
|
||||
if (pos < len)
|
||||
pr_msg("%02x ", data[pos]);
|
||||
else
|
||||
pr_msg(" ");
|
||||
}
|
||||
|
||||
static inline void pr_xsym(unsigned char *data, size_t len, int pos)
|
||||
{
|
||||
char sym;
|
||||
|
||||
if (pos < len)
|
||||
sym = data[pos];
|
||||
else
|
||||
sym = ' ';
|
||||
|
||||
pr_msg("%c", isprint(sym) ? sym : '.');
|
||||
}
|
||||
|
||||
void print_data(unsigned long addr, unsigned char *data, size_t size)
|
||||
{
|
||||
int i, j, addr_len;
|
||||
unsigned zero_line = 0;
|
||||
|
||||
addr_len = nice_width_for(addr + size);
|
||||
|
||||
for (i = 0; i < size; i += 16) {
|
||||
if (*(u64 *)(data + i) == 0 && *(u64 *)(data + i + 8) == 0) {
|
||||
if (zero_line == 0)
|
||||
zero_line = 1;
|
||||
else {
|
||||
if (zero_line == 1) {
|
||||
pr_msg("*\n");
|
||||
zero_line = 2;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
zero_line = 0;
|
||||
|
||||
pr_msg("%#0*lx: ", addr_len, addr + i);
|
||||
for (j = 0; j < 8; j++)
|
||||
pr_xdigi(data, size, i + j);
|
||||
pr_msg(" ");
|
||||
for (j = 8; j < 16; j++)
|
||||
pr_xdigi(data, size, i + j);
|
||||
|
||||
pr_msg(" |");
|
||||
for (j = 0; j < 8; j++)
|
||||
pr_xsym(data, size, i + j);
|
||||
pr_msg(" ");
|
||||
for (j = 8; j < 16; j++)
|
||||
pr_xsym(data, size, i + j);
|
||||
|
||||
pr_msg("|\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_image_data(struct cr_img *img, unsigned int length, int show)
|
||||
{
|
||||
void *data;
|
||||
int ret;
|
||||
|
||||
if (!show) {
|
||||
lseek(img_raw_fd(img), length, SEEK_CUR);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_msg("\n");
|
||||
|
||||
data = xmalloc(length);
|
||||
if (!data)
|
||||
return;
|
||||
ret = read_img_buf(img, (unsigned char *)data, length);
|
||||
if (ret < 0) {
|
||||
xfree(data);
|
||||
return;
|
||||
}
|
||||
print_data(0, (unsigned char *)data, length);
|
||||
xfree(data);
|
||||
}
|
||||
|
||||
static void show_pagemaps(struct cr_img *img, void *obj)
|
||||
{
|
||||
pb_show_plain_pretty(img, PB_PAGEMAP, "nr_pages:%u");
|
||||
}
|
||||
|
||||
void show_siginfo(struct cr_img *img)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pr_img_head(CR_FD_SIGNAL);
|
||||
while (1) {
|
||||
SiginfoEntry *sie;
|
||||
siginfo_t *info;
|
||||
|
||||
ret = pb_read_one_eof(img, &sie, PB_SIGINFO);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
||||
info = (siginfo_t *) sie->siginfo.data;
|
||||
pr_msg("signal: si_signo=%d si_code=%x\n",
|
||||
info->si_signo, info->si_code);
|
||||
siginfo_entry__free_unpacked(sie, NULL);
|
||||
|
||||
}
|
||||
pr_img_tail(CR_FD_SIGNAL);
|
||||
}
|
||||
|
||||
static int pstree_item_from_pb(PstreeEntry *e, struct pstree_item *item)
|
||||
{
|
||||
int i;
|
||||
|
||||
item->pid.virt = e->pid;
|
||||
item->nr_threads = e->n_threads;
|
||||
item->threads = xzalloc(sizeof(struct pid) * e->n_threads);
|
||||
if (!item->threads)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < item->nr_threads; i++)
|
||||
item->threads[i].virt = e->threads[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pstree_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
PstreeEntry *e = obj;
|
||||
struct pstree_item *item = NULL;
|
||||
|
||||
item = xzalloc(sizeof(struct pstree_item));
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (pstree_item_from_pb(e, item)) {
|
||||
xfree(item);
|
||||
return;
|
||||
}
|
||||
|
||||
list_add_tail(&item->sibling, &pstree_list);
|
||||
}
|
||||
|
||||
static void show_collect_pstree(struct cr_img *img, int collect)
|
||||
{
|
||||
pb_show_plain_payload_pretty(img, PB_PSTREE,
|
||||
collect ? pstree_handler : NULL, "*:%d");
|
||||
}
|
||||
|
||||
static inline char *task_state_str(int state)
|
||||
{
|
||||
switch (state) {
|
||||
case TASK_ALIVE:
|
||||
return "running/sleeping";
|
||||
case TASK_DEAD:
|
||||
return "zombie";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static void show_core_regs(UserX86RegsEntry *regs)
|
||||
{
|
||||
#define pr_regs4(s, n1, n2, n3, n4) \
|
||||
pr_msg("\t%8s: 0x%-16"PRIx64" " \
|
||||
"%8s: 0x%-16"PRIx64" " \
|
||||
"%8s: 0x%-16"PRIx64" " \
|
||||
"%8s: 0x%-16"PRIx64"\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%-16"PRIx64" " \
|
||||
"%8s: 0x%-16"PRIx64" " \
|
||||
"%8s: 0x%-16"PRIx64"\n", \
|
||||
#n1, s->n1, \
|
||||
#n2, s->n2, \
|
||||
#n3, s->n3)
|
||||
|
||||
pr_msg("\t---[ GP registers set ]---\n");
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void show_thread_info(ThreadInfoX86 *thread_info)
|
||||
{
|
||||
if (!thread_info)
|
||||
return;
|
||||
|
||||
pr_msg("\t---[ Thread info ]---\n");
|
||||
pr_msg("\tclear_tid_addr: 0x%"PRIx64"\n", thread_info->clear_tid_addr);
|
||||
pr_msg("\n");
|
||||
|
||||
show_core_regs(thread_info->gpregs);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#define SHOW_PLAIN(name) { name##_MAGIC, PB_##name, false, NULL, NULL, }
|
||||
/* nothing special behind this -S, just to avoid heavy patching */
|
||||
#define SHOW_PLAINS(name) { name##S_MAGIC, PB_##name, false, NULL, NULL, }
|
||||
#define SHOW_VERT(name) { name##_MAGIC, PB_##name, true, NULL, NULL, }
|
||||
|
||||
static struct show_image_info show_infos[] = {
|
||||
SHOW_VERT(INVENTORY),
|
||||
SHOW_VERT(CORE),
|
||||
SHOW_VERT(IDS),
|
||||
SHOW_VERT(CREDS),
|
||||
SHOW_VERT(UTSNS),
|
||||
SHOW_VERT(IPC_VAR),
|
||||
SHOW_VERT(FS),
|
||||
SHOW_VERT(GHOST_FILE),
|
||||
SHOW_VERT(MM),
|
||||
SHOW_VERT(CGROUP),
|
||||
|
||||
SHOW_PLAINS(REG_FILE),
|
||||
SHOW_PLAINS(NS_FILE),
|
||||
SHOW_PLAIN(EVENTFD_FILE),
|
||||
SHOW_PLAIN(EVENTPOLL_FILE),
|
||||
SHOW_PLAIN(EVENTPOLL_TFD),
|
||||
SHOW_PLAIN(SIGNALFD),
|
||||
SHOW_PLAIN(TIMERFD),
|
||||
SHOW_PLAIN(INOTIFY_FILE),
|
||||
SHOW_PLAIN(INOTIFY_WD),
|
||||
SHOW_PLAIN(FANOTIFY_FILE),
|
||||
SHOW_PLAIN(FANOTIFY_MARK),
|
||||
SHOW_PLAINS(VMA),
|
||||
SHOW_PLAINS(PIPE),
|
||||
SHOW_PLAIN(FIFO),
|
||||
SHOW_PLAIN(SIGACT),
|
||||
SHOW_PLAIN(NETLINK_SK),
|
||||
SHOW_PLAIN(REMAP_FPATH),
|
||||
SHOW_PLAINS(MNT),
|
||||
SHOW_PLAINS(TTY_FILE),
|
||||
SHOW_PLAIN(TTY_INFO),
|
||||
SHOW_PLAIN(RLIMIT),
|
||||
SHOW_PLAIN(TUNFILE),
|
||||
SHOW_PLAINS(EXT_FILE),
|
||||
SHOW_PLAIN(IRMAP_CACHE),
|
||||
SHOW_PLAIN(CPUINFO),
|
||||
SHOW_PLAIN(USERNS),
|
||||
SHOW_PLAIN(NETNS),
|
||||
|
||||
{ FILE_LOCKS_MAGIC, PB_FILE_LOCK, false, NULL, "3:%u", },
|
||||
{ TCP_STREAM_MAGIC, PB_TCP_STREAM, true, show_tcp_stream, "1:%u 2:%u 3:%u 4:%u 12:%u", },
|
||||
{ STATS_MAGIC, PB_STATS, true, NULL, "1.1:%u 1.2:%u 1.3:%u 1.4:%u 1.5:%Lu 1.6:%Lu 1.7:%Lu 1.8:%u", },
|
||||
{ FDINFO_MAGIC, PB_FDINFO, false, NULL, "flags:%#o fd:%d", },
|
||||
{ UNIXSK_MAGIC, PB_UNIX_SK, false, NULL, "1:%#x 2:%#x 3:%d 4:%d 5:%d 6:%d 7:%d 8:%#x 11:S", },
|
||||
{ INETSK_MAGIC, PB_INET_SK, false, NULL, "1:%#x 2:%#x 3:%d 4:%d 5:%d 6:%d 7:%d 8:%d 9:%2x 11:A 12:A", },
|
||||
{ PACKETSK_MAGIC, PB_PACKET_SOCK, false, NULL, "5:%d", },
|
||||
{ ITIMERS_MAGIC, PB_ITIMER, false, NULL, "*:%Lu", },
|
||||
{ POSIX_TIMERS_MAGIC, PB_POSIX_TIMER, false, NULL, "*:%d 5:%Lu 7:%Lu 8:%lu 9:%Lu 10:%Lu", },
|
||||
{ NETDEV_MAGIC, PB_NETDEV, false, NULL, "2:%d", },
|
||||
|
||||
{ PAGEMAP_MAGIC, PB_PAGEMAP_HEAD, true, show_pagemaps, NULL, },
|
||||
{ PIPES_DATA_MAGIC, PB_PIPE_DATA, false, pipe_data_handler, NULL, },
|
||||
{ FIFO_DATA_MAGIC, PB_PIPE_DATA, false, pipe_data_handler, NULL, },
|
||||
{ SK_QUEUES_MAGIC, PB_SK_QUEUES, false, sk_queue_data_handler, NULL, },
|
||||
{ IPCNS_SHM_MAGIC, PB_IPC_SHM, false, ipc_shm_handler, NULL, },
|
||||
{ IPCNS_SEM_MAGIC, PB_IPC_SEM, false, ipc_sem_handler, NULL, },
|
||||
{ IPCNS_MSG_MAGIC, PB_IPCNS_MSG_ENT, false, ipc_msg_handler, NULL, },
|
||||
|
||||
{ }
|
||||
};
|
||||
|
||||
static int cr_parse_file(void)
|
||||
{
|
||||
u32 magic;
|
||||
int ret = -1, fd;
|
||||
struct cr_img *img = NULL;
|
||||
|
||||
fd = open(opts.show_dump_file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
pr_perror("Can't open %s", opts.show_dump_file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
img = img_from_fd(fd);
|
||||
if (!img)
|
||||
goto out;
|
||||
|
||||
if (read_img(img, &magic) < 0)
|
||||
goto out;
|
||||
|
||||
ret = cr_parse_fd(img, magic);
|
||||
out:
|
||||
if (img)
|
||||
close_image(img);
|
||||
else
|
||||
close_safe(&fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cr_parse_fd(struct cr_img *img, u32 magic)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
||||
if (magic == IMG_COMMON_MAGIC || magic == IMG_SERVICE_MAGIC) {
|
||||
if (read_img(img, &magic) < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (magic == PSTREE_MAGIC) {
|
||||
show_collect_pstree(img, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (magic == SIGNAL_MAGIC || magic == PSIGNAL_MAGIC) {
|
||||
show_siginfo(img);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; show_infos[i].magic; i++) {
|
||||
struct show_image_info *si;
|
||||
|
||||
si = &show_infos[i];
|
||||
if (si->magic != magic)
|
||||
continue;
|
||||
|
||||
do_pb_show_plain(img, si->pb_type, si->single,
|
||||
si->payload, si->fmt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
pr_err("Unknown magic %#x in %s\n",
|
||||
magic, opts.show_dump_file);
|
||||
try_hint_magic(magic);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cr_show_pstree_item(struct pstree_item *item)
|
||||
{
|
||||
int ret = -1, i;
|
||||
struct cr_img *img;
|
||||
struct cr_imgset *cr_imgset = NULL;
|
||||
TaskKobjIdsEntry *ids;
|
||||
|
||||
cr_imgset = cr_task_imgset_open(item->pid.virt, O_SHOW);
|
||||
if (!cr_imgset)
|
||||
goto out;
|
||||
|
||||
pr_msg("Task %d:\n", item->pid.virt);
|
||||
pr_msg("----------------------------------------\n");
|
||||
|
||||
cr_parse_fd(img_from_set(cr_imgset, CR_FD_CORE), CORE_MAGIC);
|
||||
|
||||
if (item->nr_threads > 1) {
|
||||
for (i = 0; i < item->nr_threads; i++) {
|
||||
|
||||
if (item->threads[i].virt == item->pid.virt)
|
||||
continue;
|
||||
|
||||
img = open_image(CR_FD_CORE, O_SHOW, item->threads[i].virt);
|
||||
if (!img)
|
||||
goto outc;
|
||||
|
||||
pr_msg("Thread %d.%d:\n", item->pid.virt, item->threads[i].virt);
|
||||
pr_msg("----------------------------------------\n");
|
||||
|
||||
cr_parse_fd(img, CORE_MAGIC);
|
||||
close_image(img);
|
||||
}
|
||||
}
|
||||
|
||||
pr_msg("Resources for %d:\n", item->pid.virt);
|
||||
pr_msg("----------------------------------------\n");
|
||||
for (i = _CR_FD_TASK_FROM + 1; i < _CR_FD_TASK_TO; i++)
|
||||
if ((i != CR_FD_CORE) && (i != CR_FD_IDS)) {
|
||||
pr_msg("* ");
|
||||
pr_msg(imgset_template[i].fmt, item->pid.virt);
|
||||
pr_msg(":\n");
|
||||
cr_parse_fd(img_from_set(cr_imgset, i), imgset_template[i].magic);
|
||||
}
|
||||
|
||||
img = open_image(CR_FD_RLIMIT, O_SHOW, item->pid.virt);
|
||||
if (img) {
|
||||
pr_msg("* ");
|
||||
pr_msg(imgset_template[CR_FD_RLIMIT].fmt, item->pid.virt);
|
||||
pr_msg(":\n");
|
||||
|
||||
cr_parse_fd(img, RLIMIT_MAGIC);
|
||||
close_image(img);
|
||||
}
|
||||
|
||||
if (pb_read_one(img_from_set(cr_imgset, CR_FD_IDS), &ids, PB_IDS) > 0) {
|
||||
img = open_image(CR_FD_FDINFO, O_SHOW, ids->files_id);
|
||||
if (img) {
|
||||
pr_msg("* ");
|
||||
pr_msg(imgset_template[CR_FD_FDINFO].fmt, ids->files_id);
|
||||
pr_msg(":\n");
|
||||
|
||||
cr_parse_fd(img, FDINFO_MAGIC);
|
||||
close_image(img);
|
||||
}
|
||||
|
||||
task_kobj_ids_entry__free_unpacked(ids, NULL);
|
||||
}
|
||||
|
||||
pr_msg("---[ end of task %d ]---\n", item->pid.virt);
|
||||
|
||||
ret = 0;
|
||||
outc:
|
||||
close_cr_imgset(&cr_imgset);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cr_show_pid(int pid)
|
||||
{
|
||||
int ret;
|
||||
struct cr_img *img;
|
||||
struct pstree_item item;
|
||||
|
||||
img = open_image(CR_FD_PSTREE, O_SHOW);
|
||||
if (!img)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
PstreeEntry *pe;
|
||||
|
||||
ret = pb_read_one_eof(img, &pe, PB_PSTREE);
|
||||
if (ret <= 0) {
|
||||
close_image(img);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pe->pid == pid) {
|
||||
pstree_item_from_pb(pe, &item);
|
||||
pstree_entry__free_unpacked(pe, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
pstree_entry__free_unpacked(pe, NULL);
|
||||
}
|
||||
|
||||
close_image(img);
|
||||
|
||||
return cr_show_pstree_item(&item);
|
||||
}
|
||||
|
||||
static int cr_show_all(void)
|
||||
{
|
||||
struct pstree_item *item = NULL, *tmp;
|
||||
int ret = -1, pid;
|
||||
struct cr_img *img;
|
||||
|
||||
img = open_image(CR_FD_PSTREE, O_SHOW);
|
||||
if (!img)
|
||||
goto out;
|
||||
show_collect_pstree(img, 1);
|
||||
close_image(img);
|
||||
|
||||
pid = list_first_entry(&pstree_list, struct pstree_item, sibling)->pid.virt;
|
||||
ret = try_show_namespaces(pid);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(item, &pstree_list, sibling)
|
||||
if (cr_show_pstree_item(item))
|
||||
break;
|
||||
|
||||
out:
|
||||
list_for_each_entry_safe(item, tmp, &pstree_list, sibling) {
|
||||
list_del(&item->sibling);
|
||||
xfree(item->threads);
|
||||
xfree(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cr_show(int pid)
|
||||
{
|
||||
if (isatty(STDOUT_FILENO)) {
|
||||
pr_msg("The \"show\" action is deprecated by the CRIT utility.\n");
|
||||
pr_msg("To view an image use the \"crit decode -i $name --pretty\" command.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opts.show_dump_file)
|
||||
return cr_parse_file();
|
||||
|
||||
if (pid)
|
||||
return cr_show_pid(pid);
|
||||
|
||||
return cr_show_all();
|
||||
}
|
@@ -661,8 +661,11 @@ int main(int argc, char *argv[], char *envp[])
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[optind], "show"))
|
||||
return cr_show(pid) != 0;
|
||||
if (!strcmp(argv[optind], "show")) {
|
||||
pr_msg("The \"show\" action is deprecated by the CRIT utility.\n");
|
||||
pr_msg("To view an image use the \"crit decode -i $name --pretty\" command.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[optind], "check"))
|
||||
return cr_check() != 0;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "image-desc.h"
|
||||
#include "cr-show.h"
|
||||
#include "magic.h"
|
||||
#include "image.h"
|
||||
|
||||
|
@@ -1,25 +0,0 @@
|
||||
#ifndef __CR_SHOW_H__
|
||||
#define __CR_SHOW_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "asm/types.h"
|
||||
|
||||
struct cr_img;
|
||||
|
||||
struct show_image_info {
|
||||
u32 magic;
|
||||
int pb_type;
|
||||
bool single;
|
||||
void (*payload)(struct cr_img *, void *);
|
||||
char *fmt;
|
||||
};
|
||||
|
||||
extern void show_siginfo(struct cr_img *);
|
||||
extern void sk_queue_data_handler(struct cr_img *, void *obj);
|
||||
extern void ipc_shm_handler(struct cr_img *, void *obj);
|
||||
extern void ipc_msg_handler(struct cr_img *, void *obj);
|
||||
extern void ipc_sem_handler(struct cr_img *, void *obj);
|
||||
extern int cr_parse_fd(struct cr_img *, u32 magic);
|
||||
extern void show_tcp_stream(struct cr_img *, void *obj);
|
||||
|
||||
#endif /* __CR_SHOW_H__ */
|
@@ -21,7 +21,6 @@ extern int prepare_inventory(InventoryEntry *he);
|
||||
extern int cr_dump_tasks(pid_t pid);
|
||||
extern int cr_pre_dump_tasks(pid_t pid);
|
||||
extern int cr_restore_tasks(void);
|
||||
extern int cr_show(int pid);
|
||||
extern int convert_to_elf(char *elf_path, int fd_core);
|
||||
extern int cr_check(void);
|
||||
extern int cr_exec(int pid, char **opts);
|
||||
|
@@ -75,7 +75,6 @@ extern int dump_mnt_namespaces(void);
|
||||
extern int dump_namespaces(struct pstree_item *item, unsigned int ns_flags);
|
||||
extern int prepare_namespace_before_tasks(void);
|
||||
extern int prepare_namespace(struct pstree_item *item, unsigned long clone_flags);
|
||||
extern int try_show_namespaces(int pid);
|
||||
|
||||
extern int switch_ns(int pid, struct ns_desc *nd, int *rst);
|
||||
extern int restore_ns(int rst, struct ns_desc *nd);
|
||||
|
@@ -27,20 +27,6 @@ extern int pb_write_one(struct cr_img *, void *obj, int type);
|
||||
|
||||
#include <google/protobuf-c/protobuf-c.h>
|
||||
|
||||
extern void do_pb_show_plain(struct cr_img *, int type, int single_entry,
|
||||
void (*payload_hadler)(struct cr_img *, void *obj),
|
||||
const char *pretty_fmt);
|
||||
|
||||
/* Don't have objects at hands to also do typechecking here */
|
||||
#define pb_show_plain_payload_pretty(__fd, __type, payload_hadler, pretty) \
|
||||
do_pb_show_plain(__fd, __type, 0, payload_hadler, pretty)
|
||||
|
||||
#define pb_show_plain_payload(__fd, __proto_message_name, payload_hadler) \
|
||||
pb_show_plain_payload_pretty(__fd, __proto_message_name, payload_hadler, NULL)
|
||||
|
||||
#define pb_show_plain_pretty(__fd, __proto_message_name, __pretty) \
|
||||
pb_show_plain_payload_pretty(__fd, __proto_message_name, NULL, __pretty)
|
||||
|
||||
struct collect_image_info {
|
||||
int fd_type;
|
||||
int pb_type;
|
||||
|
@@ -281,4 +281,6 @@ char *xstrcat(char *str, const char *fmt, ...)
|
||||
char *xsprintf(const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
void print_data(unsigned long addr, unsigned char *data, size_t size);
|
||||
|
||||
#endif /* __CR_UTIL_H__ */
|
||||
|
@@ -62,7 +62,6 @@ static void pr_ipc_sem_array(unsigned int loglevel, int nr, u16 *values)
|
||||
}
|
||||
|
||||
#define pr_info_ipc_sem_array(nr, values) pr_ipc_sem_array(LOG_INFO, nr, values)
|
||||
#define pr_msg_ipc_sem_array(nr, values) pr_ipc_sem_array(LOG_MSG, nr, values)
|
||||
|
||||
static void pr_info_ipc_sem_entry(const IpcSemEntry *sem)
|
||||
{
|
||||
@@ -473,48 +472,6 @@ err:
|
||||
return ret < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
void ipc_sem_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
IpcSemEntry *e = obj;
|
||||
u16 *values;
|
||||
int size;
|
||||
|
||||
pr_msg("\n");
|
||||
size = round_up(sizeof(u16) * e->nsems, sizeof(u64));
|
||||
values = xmalloc(size);
|
||||
if (values == NULL)
|
||||
return;
|
||||
if (read_img_buf(img, values, size) <= 0) {
|
||||
xfree(values);
|
||||
return;
|
||||
}
|
||||
pr_msg_ipc_sem_array(e->nsems, values);
|
||||
xfree(values);
|
||||
}
|
||||
|
||||
static void ipc_msg_data_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
IpcMsg *e = obj;
|
||||
print_image_data(img, round_up(e->msize, sizeof(u64)), opts.show_pages_content);
|
||||
}
|
||||
|
||||
void ipc_msg_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
IpcMsgEntry *e = obj;
|
||||
int msg_nr = 0;
|
||||
|
||||
pr_msg("\n");
|
||||
while (msg_nr++ < e->qnum)
|
||||
pb_show_plain_payload(img, PB_IPCNS_MSG, ipc_msg_data_handler);
|
||||
|
||||
}
|
||||
|
||||
void ipc_shm_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
IpcShmEntry *e = obj;
|
||||
print_image_data(img, round_up(e->size, sizeof(u32)), opts.show_pages_content);
|
||||
}
|
||||
|
||||
static int prepare_ipc_sem_values(struct cr_img *img, const IpcSemEntry *sem)
|
||||
{
|
||||
int ret, size;
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include "cr-show.h"
|
||||
#include "util.h"
|
||||
#include "imgset.h"
|
||||
#include "uts_ns.h"
|
||||
@@ -1338,66 +1337,5 @@ err_unds:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int try_show_namespaces(int ns_pid)
|
||||
{
|
||||
struct cr_imgset *imgset;
|
||||
int i, ret;
|
||||
struct cr_img *img;
|
||||
TaskKobjIdsEntry *ids;
|
||||
|
||||
pr_msg("Namespaces for %d:\n", ns_pid);
|
||||
|
||||
img = open_image(CR_FD_IDS, O_RSTR, ns_pid);
|
||||
if (!img)
|
||||
return -1;
|
||||
ret = pb_read_one(img, &ids, PB_IDS);
|
||||
close_image(img);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
imgset = cr_imgset_open(ids->net_ns_id, NETNS, O_SHOW);
|
||||
if (imgset) {
|
||||
pr_msg("-------------------NETNS---------------------\n");
|
||||
for (i = _CR_FD_NETNS_FROM + 1; i < _CR_FD_NETNS_TO; i++) {
|
||||
img = img_from_set(imgset, i);
|
||||
if (!img)
|
||||
continue;
|
||||
|
||||
cr_parse_fd(img, imgset_template[i].magic);
|
||||
}
|
||||
close_cr_imgset(&imgset);
|
||||
}
|
||||
|
||||
imgset = cr_imgset_open(ids->ipc_ns_id, IPCNS, O_SHOW);
|
||||
if (imgset) {
|
||||
pr_msg("-------------------IPCNS---------------------\n");
|
||||
for (i = _CR_FD_IPCNS_FROM + 1; i < _CR_FD_IPCNS_TO; i++) {
|
||||
img = img_from_set(imgset, i);
|
||||
if (!img)
|
||||
continue;
|
||||
|
||||
cr_parse_fd(img, imgset_template[i].magic);
|
||||
}
|
||||
close_cr_imgset(&imgset);
|
||||
}
|
||||
|
||||
img = open_image(CR_FD_UTSNS, O_SHOW, ids->uts_ns_id);
|
||||
if (img) {
|
||||
pr_msg("-------------------UTSNS---------------------\n");
|
||||
cr_parse_fd(img, imgset_template[CR_FD_UTSNS].magic);
|
||||
close_image(img);
|
||||
}
|
||||
|
||||
img = open_image(CR_FD_MNTS, O_SHOW, ids->mnt_ns_id);
|
||||
if (img) {
|
||||
pr_msg("-------------------MNTNS---------------------\n");
|
||||
cr_parse_fd(img, imgset_template[CR_FD_MNTS].magic);
|
||||
close_image(img);
|
||||
}
|
||||
|
||||
pr_msg("---[ end of %d namespaces ]---\n", ns_pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ns_desc pid_ns_desc = NS_DESC_ENTRY(CLONE_NEWPID, "pid");
|
||||
struct ns_desc user_ns_desc = NS_DESC_ENTRY(CLONE_NEWUSER, "user");
|
||||
|
465
criu/protobuf.c
465
criu/protobuf.c
@@ -27,471 +27,6 @@
|
||||
*/
|
||||
#define PB_PKOBJ_LOCAL_SIZE 1024
|
||||
|
||||
#define INET_ADDR_LEN 40
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
int number;
|
||||
int depth;
|
||||
int count;
|
||||
char fmt[32];
|
||||
} pb_pr_field_t;
|
||||
|
||||
typedef struct {
|
||||
void *arg;
|
||||
int single_entry;
|
||||
const char *pretty_fmt;
|
||||
pb_pr_field_t cur;
|
||||
} pb_pr_ctl_t;
|
||||
|
||||
typedef int (*pb_pr_show_t)(pb_pr_field_t *field);
|
||||
|
||||
/*
|
||||
* This one describes how fields should be shown
|
||||
* @fsize is the size of the field entry
|
||||
* @show is the callback to print the entry
|
||||
*/
|
||||
struct pb_shower {
|
||||
size_t fsize;
|
||||
pb_pr_show_t show;
|
||||
};
|
||||
|
||||
static int pb_msg_int32x(pb_pr_field_t *field)
|
||||
{
|
||||
pr_msg("%#x", *(int *)field->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_msg_int64x(pb_pr_field_t *field)
|
||||
{
|
||||
pr_msg("%#016lx", *(long *)field->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_msg_int64x_r(pb_pr_field_t *field)
|
||||
{
|
||||
long val = *(long *)field->data;
|
||||
if (val)
|
||||
pr_msg("%#016lx", val);
|
||||
else
|
||||
pr_msg("0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_msg_string(pb_pr_field_t *field)
|
||||
{
|
||||
pr_msg("\"%s\"", *(char **)field->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_msg_unk(pb_pr_field_t *field)
|
||||
{
|
||||
pr_msg("unknown object %p", field->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void print_tabs(pb_pr_ctl_t *ctl)
|
||||
{
|
||||
int counter = ctl->cur.depth;
|
||||
|
||||
if (!ctl->single_entry)
|
||||
return;
|
||||
|
||||
while (counter--)
|
||||
pr_msg("\t");
|
||||
}
|
||||
|
||||
static void print_nested_message_braces(pb_pr_ctl_t *ctl, int right_brace)
|
||||
{
|
||||
print_tabs(ctl);
|
||||
pr_msg("%s%s", (right_brace) ? "}" : "{", (ctl->single_entry) ? "\n" : " ");
|
||||
}
|
||||
|
||||
static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl);
|
||||
|
||||
static int show_nested_message(pb_pr_field_t *field)
|
||||
{
|
||||
pb_pr_ctl_t *ctl = container_of(field, pb_pr_ctl_t, cur);
|
||||
void *arg = ctl->arg;
|
||||
|
||||
print_nested_message_braces(ctl, 0);
|
||||
field->depth++;
|
||||
pb_show_msg(field->data, ctl);
|
||||
field->depth--;
|
||||
print_nested_message_braces(ctl, 1);
|
||||
ctl->arg = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_enum(pb_pr_field_t *field)
|
||||
{
|
||||
pb_pr_ctl_t *ctl = container_of(field, pb_pr_ctl_t, cur);
|
||||
ProtobufCEnumDescriptor *d = ctl->arg;
|
||||
const char *val_name = NULL;
|
||||
int val, i;
|
||||
|
||||
val = *(int *)field->data;
|
||||
for (i = 0; i < d->n_values; i++)
|
||||
if (d->values[i].value == val) {
|
||||
val_name = d->values[i].name;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val_name != NULL)
|
||||
pr_msg("%s", val_name);
|
||||
else
|
||||
pr_msg("%d", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_bool(pb_pr_field_t *field)
|
||||
{
|
||||
protobuf_c_boolean val = *(protobuf_c_boolean *)field->data;
|
||||
|
||||
if (val)
|
||||
pr_msg("True");
|
||||
else
|
||||
pr_msg("False");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_bytes(pb_pr_field_t *field)
|
||||
{
|
||||
ProtobufCBinaryData *bytes = (ProtobufCBinaryData *)field->data;
|
||||
int i = 0;
|
||||
|
||||
while (i < bytes->len)
|
||||
pr_msg("%02x ", bytes->data[i++]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pb_show_pretty(pb_pr_field_t *field)
|
||||
{
|
||||
switch (field->fmt[0]) {
|
||||
case '%':
|
||||
pr_msg(field->fmt, *(long *)field->data);
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
ProtobufCBinaryData *name = (ProtobufCBinaryData *)field->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < name->len; i++) {
|
||||
char c = (char)name->data[i];
|
||||
|
||||
if (isprint(c))
|
||||
pr_msg("%c", c);
|
||||
else if (c != 0)
|
||||
pr_msg(".");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'A':
|
||||
{
|
||||
char addr[INET_ADDR_LEN] = "<unknown>";
|
||||
int family = (field->count == 1) ? AF_INET : AF_INET6;
|
||||
|
||||
if (inet_ntop(family, (void *)field->data, addr,
|
||||
INET_ADDR_LEN) == NULL)
|
||||
pr_msg("failed to translate");
|
||||
else
|
||||
pr_msg("%s", addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pb_copy_fmt(const char *fmt, char *to)
|
||||
{
|
||||
while (*fmt != ' ' && *fmt != '\0') {
|
||||
*to = *fmt;
|
||||
to++;
|
||||
fmt++;
|
||||
}
|
||||
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
static const char *pb_next_pretty(const char *pfmt)
|
||||
{
|
||||
pfmt = strchr(pfmt, ' ');
|
||||
if (pfmt) {
|
||||
while (*pfmt == ' ')
|
||||
pfmt++;
|
||||
|
||||
if (*pfmt == '\0')
|
||||
pfmt = NULL;
|
||||
}
|
||||
|
||||
return pfmt;
|
||||
}
|
||||
|
||||
static int pb_find_fmt(char *what, pb_pr_ctl_t *ctl)
|
||||
{
|
||||
int len;
|
||||
const char *pretty = ctl->pretty_fmt;
|
||||
|
||||
len = strlen(what);
|
||||
while (1) {
|
||||
if (!strncmp(pretty, what, len)) {
|
||||
pb_copy_fmt(pretty + len, ctl->cur.fmt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pretty = pb_next_pretty(pretty + len);
|
||||
if (!pretty)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int pb_field_show_pretty(const ProtobufCFieldDescriptor *fd, pb_pr_ctl_t *ctl)
|
||||
{
|
||||
char cookie[32];
|
||||
|
||||
if (!ctl->pretty_fmt)
|
||||
return 0;
|
||||
|
||||
sprintf(cookie, "%s:", fd->name);
|
||||
if (pb_find_fmt(cookie, ctl))
|
||||
return 1;
|
||||
|
||||
if (!ctl->cur.depth)
|
||||
sprintf(cookie, "%d:", ctl->cur.number);
|
||||
else
|
||||
sprintf(cookie, "%d.%d:", ctl->cur.depth, ctl->cur.number);
|
||||
|
||||
if (pb_find_fmt(cookie, ctl))
|
||||
return 1;
|
||||
|
||||
sprintf(cookie, "*:");
|
||||
if (pb_find_fmt(cookie, ctl))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pb_prepare_shower(const ProtobufCFieldDescriptor *fd,
|
||||
pb_pr_ctl_t *ctl, struct pb_shower *sh)
|
||||
{
|
||||
sh->fsize = 0;
|
||||
sh->show = pb_msg_unk;
|
||||
|
||||
switch (fd->type) {
|
||||
case PROTOBUF_C_TYPE_INT32:
|
||||
case PROTOBUF_C_TYPE_SINT32:
|
||||
case PROTOBUF_C_TYPE_UINT32:
|
||||
case PROTOBUF_C_TYPE_SFIXED32:
|
||||
sh->fsize = 4;
|
||||
sh->show = pb_msg_int32x;
|
||||
break;
|
||||
|
||||
case PROTOBUF_C_TYPE_INT64:
|
||||
case PROTOBUF_C_TYPE_SINT64:
|
||||
case PROTOBUF_C_TYPE_SFIXED64:
|
||||
case PROTOBUF_C_TYPE_FIXED32:
|
||||
case PROTOBUF_C_TYPE_UINT64:
|
||||
case PROTOBUF_C_TYPE_FIXED64:
|
||||
sh->fsize = 8;
|
||||
sh->show = (fd->label == PROTOBUF_C_LABEL_REPEATED ?
|
||||
pb_msg_int64x_r : pb_msg_int64x);
|
||||
break;
|
||||
|
||||
case PROTOBUF_C_TYPE_STRING:
|
||||
sh->fsize = sizeof (void *);
|
||||
sh->show = pb_msg_string;
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_MESSAGE:
|
||||
sh->fsize = sizeof (void *);
|
||||
sh->show = show_nested_message;
|
||||
ctl->arg = (void *)fd->descriptor;
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_ENUM:
|
||||
sh->fsize = 4;
|
||||
sh->show = show_enum;
|
||||
ctl->arg = (void *)fd->descriptor;
|
||||
break;
|
||||
|
||||
case PROTOBUF_C_TYPE_BOOL:
|
||||
sh->fsize = sizeof (protobuf_c_boolean);
|
||||
sh->show = show_bool;
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_BYTES:
|
||||
sh->fsize = sizeof (ProtobufCBinaryData);
|
||||
sh->show = show_bytes;
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_FLOAT:
|
||||
sh->fsize = 4;
|
||||
break;
|
||||
case PROTOBUF_C_TYPE_DOUBLE:
|
||||
sh->fsize = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (pb_field_show_pretty(fd, ctl))
|
||||
sh->show = pb_show_pretty;
|
||||
}
|
||||
|
||||
static void pb_show_repeated(const ProtobufCFieldDescriptor *fd,
|
||||
pb_pr_ctl_t *ctl, struct pb_shower *sh)
|
||||
{
|
||||
pb_pr_field_t *field = &ctl->cur;
|
||||
unsigned long i, nr_fields = field->count;
|
||||
|
||||
if (nr_fields == 0) {
|
||||
pr_msg("<empty>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd->type == PROTOBUF_C_TYPE_MESSAGE) {
|
||||
void *p = field->data;
|
||||
|
||||
for (i = 0; i < nr_fields; i++) {
|
||||
field->data = (void *)(*(long *)p);
|
||||
sh->show(field);
|
||||
p += sh->fsize;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_fields; i++) {
|
||||
if (i)
|
||||
pr_msg(":");
|
||||
if (sh->show(field))
|
||||
break;
|
||||
field->data += sh->fsize;
|
||||
}
|
||||
}
|
||||
|
||||
static void pb_show_field(const ProtobufCFieldDescriptor *fd, pb_pr_ctl_t *ctl)
|
||||
{
|
||||
struct pb_shower sh;
|
||||
|
||||
print_tabs(ctl);
|
||||
pr_msg("%s: ", fd->name);
|
||||
|
||||
pb_prepare_shower(fd, ctl, &sh);
|
||||
pb_show_repeated(fd, ctl, &sh);
|
||||
|
||||
if (ctl->single_entry)
|
||||
pr_msg("\n");
|
||||
else
|
||||
pr_msg(" ");
|
||||
}
|
||||
|
||||
static int pb_optional_field_present(const ProtobufCFieldDescriptor *field,
|
||||
const void *msg)
|
||||
{
|
||||
if ((field->type == PROTOBUF_C_TYPE_MESSAGE) ||
|
||||
(field->type == PROTOBUF_C_TYPE_STRING)) {
|
||||
const void *opt_flag = * (const void * const *)(msg + field->offset);
|
||||
|
||||
if ((opt_flag == NULL) || (opt_flag == field->default_value))
|
||||
return 0;
|
||||
} else {
|
||||
const protobuf_c_boolean *has = msg + field->quantifier_offset;
|
||||
|
||||
if (!*has)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool should_show_field(const char *name)
|
||||
{
|
||||
char *s, *e;
|
||||
int len;
|
||||
|
||||
if (!opts.show_fmt)
|
||||
return true;
|
||||
|
||||
len = strlen(name);
|
||||
s = opts.show_fmt;
|
||||
|
||||
while (1) {
|
||||
e = strchrnul(s, ',');
|
||||
if (e - s == len) {
|
||||
if (!strncmp(name, s, len))
|
||||
return true;
|
||||
}
|
||||
if (*e == '\0')
|
||||
return false;
|
||||
s = e + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void pb_show_msg(const void *msg, pb_pr_ctl_t *ctl)
|
||||
{
|
||||
int i;
|
||||
const ProtobufCMessageDescriptor *md = ctl->arg;
|
||||
|
||||
BUG_ON(md == NULL);
|
||||
|
||||
for (i = 0; i < md->n_fields; i++) {
|
||||
const ProtobufCFieldDescriptor fd = md->fields[i];
|
||||
unsigned long *data;
|
||||
size_t nr_fields;
|
||||
|
||||
nr_fields = 1;
|
||||
data = (unsigned long *)(msg + fd.offset);
|
||||
|
||||
if (fd.label == PROTOBUF_C_LABEL_OPTIONAL) {
|
||||
if (!pb_optional_field_present(&fd, msg))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!should_show_field(fd.name))
|
||||
continue;
|
||||
|
||||
if (fd.label == PROTOBUF_C_LABEL_REPEATED) {
|
||||
nr_fields = *(size_t *)(msg + fd.quantifier_offset);
|
||||
data = (unsigned long *)*data;
|
||||
}
|
||||
|
||||
ctl->cur.data = data;
|
||||
ctl->cur.number = i + 1;
|
||||
ctl->cur.count = nr_fields;
|
||||
|
||||
pb_show_field(&fd, ctl);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pb_no_payload(struct cr_img *i, void *obj) { }
|
||||
|
||||
void do_pb_show_plain(struct cr_img *img, int type, int single_entry,
|
||||
void (*payload_hadler)(struct cr_img *, void *obj),
|
||||
const char *pretty_fmt)
|
||||
{
|
||||
pb_pr_ctl_t ctl = {NULL, single_entry, pretty_fmt};
|
||||
void (*handle_payload)(struct cr_img *, void *obj);
|
||||
|
||||
if (!cr_pb_descs[type].pb_desc) {
|
||||
pr_err("Wrong object requested %d\n", type);
|
||||
return;
|
||||
}
|
||||
|
||||
handle_payload = (payload_hadler) ? : pb_no_payload;
|
||||
|
||||
while (1) {
|
||||
void *obj;
|
||||
|
||||
if (pb_read_one_eof(img, &obj, type) <= 0)
|
||||
break;
|
||||
|
||||
ctl.arg = (void *)cr_pb_descs[type].pb_desc;
|
||||
pb_show_msg(obj, &ctl);
|
||||
handle_payload(img, obj);
|
||||
cr_pb_descs[type].free(obj, NULL);
|
||||
if (single_entry)
|
||||
break;
|
||||
pr_msg("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static char *image_name(struct cr_img *img)
|
||||
{
|
||||
int fd = img->_x.fd;
|
||||
|
@@ -179,12 +179,6 @@ err_brk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sk_queue_data_handler(struct cr_img *img, void *obj)
|
||||
{
|
||||
SkPacketEntry *e = obj;
|
||||
print_image_data(img, e->length, opts.show_pages_content);
|
||||
}
|
||||
|
||||
int restore_sk_queue(int fd, unsigned int peer_id)
|
||||
{
|
||||
struct sk_packet *pkt, *tmp;
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#include "namespaces.h"
|
||||
#include "xmalloc.h"
|
||||
#include "config.h"
|
||||
#include "cr-show.h"
|
||||
#include "kerndat.h"
|
||||
#include "rst-malloc.h"
|
||||
|
||||
@@ -758,14 +757,3 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void show_tcp_stream(struct cr_img *img, void *obj)
|
||||
{
|
||||
TcpStreamEntry *e = obj;
|
||||
if (opts.show_pages_content) {
|
||||
pr_msg("In-queue:");
|
||||
print_image_data(img, e->inq_len, 1);
|
||||
pr_msg("Out-queue:");
|
||||
print_image_data(img, e->outq_len, 1);
|
||||
}
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "cr_options.h"
|
||||
#include "imgset.h"
|
||||
#include "protobuf.h"
|
||||
#include "cr-show.h"
|
||||
#include "string.h"
|
||||
#include "files.h"
|
||||
#include "files-reg.h"
|
||||
|
74
criu/util.c
74
criu/util.c
@@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sched.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "asm/types.h"
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "vma.h"
|
||||
#include "mem.h"
|
||||
#include "namespaces.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "cr_options.h"
|
||||
#include "servicefd.h"
|
||||
@@ -1000,3 +1002,75 @@ void tcp_nodelay(int sk, bool on)
|
||||
int val = on ? 1 : 0;
|
||||
setsockopt(sk, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static inline void pr_xsym(unsigned char *data, size_t len, int pos)
|
||||
{
|
||||
char sym;
|
||||
|
||||
if (pos < len)
|
||||
sym = data[pos];
|
||||
else
|
||||
sym = ' ';
|
||||
|
||||
pr_msg("%c", isprint(sym) ? sym : '.');
|
||||
}
|
||||
|
||||
static inline void pr_xdigi(unsigned char *data, size_t len, int pos)
|
||||
{
|
||||
if (pos < len)
|
||||
pr_msg("%02x ", data[pos]);
|
||||
else
|
||||
pr_msg(" ");
|
||||
}
|
||||
|
||||
static int nice_width_for(unsigned long addr)
|
||||
{
|
||||
int ret = 3;
|
||||
|
||||
while (addr) {
|
||||
addr >>= 4;
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_data(unsigned long addr, unsigned char *data, size_t size)
|
||||
{
|
||||
int i, j, addr_len;
|
||||
unsigned zero_line = 0;
|
||||
|
||||
addr_len = nice_width_for(addr + size);
|
||||
|
||||
for (i = 0; i < size; i += 16) {
|
||||
if (*(u64 *)(data + i) == 0 && *(u64 *)(data + i + 8) == 0) {
|
||||
if (zero_line == 0)
|
||||
zero_line = 1;
|
||||
else {
|
||||
if (zero_line == 1) {
|
||||
pr_msg("*\n");
|
||||
zero_line = 2;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
} else
|
||||
zero_line = 0;
|
||||
|
||||
pr_msg("%#0*lx: ", addr_len, addr + i);
|
||||
for (j = 0; j < 8; j++)
|
||||
pr_xdigi(data, size, i + j);
|
||||
pr_msg(" ");
|
||||
for (j = 8; j < 16; j++)
|
||||
pr_xdigi(data, size, i + j);
|
||||
|
||||
pr_msg(" |");
|
||||
for (j = 0; j < 8; j++)
|
||||
pr_xsym(data, size, i + j);
|
||||
pr_msg(" ");
|
||||
for (j = 8; j < 16; j++)
|
||||
pr_xsym(data, size, i + j);
|
||||
|
||||
pr_msg("|\n");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user