diff --git a/Makefile.crtools b/Makefile.crtools index 4d81c36a6..aa3461165 100644 --- a/Makefile.crtools +++ b/Makefile.crtools @@ -45,6 +45,7 @@ obj-y += file-lock.o obj-y += page-pipe.o obj-y += page-xfer.o obj-y += page-read.o +obj-y += kerndat.o ifneq ($(MAKECMDGOALS),clean) incdeps := y diff --git a/cr-dump.c b/cr-dump.c index 31cc1122f..574355102 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -58,6 +58,7 @@ #include "elf.h" #include "file-lock.h" #include "page-xfer.h" +#include "kerndat.h" #include "asm/dump.h" @@ -1552,6 +1553,9 @@ int cr_dump_tasks(pid_t pid, const struct cr_options *opts) pr_info("Dumping processes (pid: %d)\n", pid); pr_info("========================================\n"); + if (kerndat_init()) + goto err; + if (cpu_init()) goto err; diff --git a/include/kerndat.h b/include/kerndat.h new file mode 100644 index 000000000..38b29391e --- /dev/null +++ b/include/kerndat.h @@ -0,0 +1,11 @@ +#ifndef __CR_KERNDAT_H__ +#define __CR_KERNDAT_H__ +/* + * kerndat stands for "kernel data" and is a collection + * of run-time information about current kernel + */ + +int kerndat_init(void); + +extern dev_t kerndat_shmem_dev; +#endif diff --git a/kerndat.c b/kerndat.c new file mode 100644 index 000000000..7ae49295e --- /dev/null +++ b/kerndat.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +#include "log.h" +#include "kerndat.h" +#include "asm/types.h" + +dev_t kerndat_shmem_dev; + +/* + * Anonymous shared mappings are backed by hidden tmpfs + * mount. Find out its dev to distinguish such mappings + * from real tmpfs files maps. + */ + +static int kerndat_get_shmemdev(void) +{ + void *map; + char maps[128]; + struct stat buf; + + map = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, 0, 0); + if (map == MAP_FAILED) { + pr_perror("Can't mmap piggie"); + return -1; + } + + sprintf(maps, "/proc/self/map_files/%lx-%lx", + (unsigned long)map, (unsigned long)map + PAGE_SIZE); + if (stat(maps, &buf) < 0) { + pr_perror("Can't stat piggie"); + return -1; + } + + munmap(map, PAGE_SIZE); + + kerndat_shmem_dev = buf.st_dev; + pr_info("Found anon-shmem piggie at %"PRIx64"\n", kerndat_shmem_dev); + return 0; +} + +int kerndat_init(void) +{ + int ret; + + ret = kerndat_get_shmemdev(); + + return ret; +} diff --git a/proc_parse.c b/proc_parse.c index e735e13dc..6920bd467 100644 --- a/proc_parse.c +++ b/proc_parse.c @@ -18,6 +18,7 @@ #include "file-lock.h" #include "pstree.h" #include "fsnotify.h" +#include "kerndat.h" #include "proc_parse.h" #include "protobuf.h" @@ -133,37 +134,9 @@ static int parse_vmflags(char *buf, struct vma_area *vma_area) return 0; } -static int is_anon_shmem_map(dev_t dev) +static inline int is_anon_shmem_map(dev_t dev) { - static dev_t shmem_dev = 0; - - if (!shmem_dev) { - void *map; - char maps[128]; - struct stat buf; - - map = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, 0, 0); - if (map == MAP_FAILED) { - pr_perror("Can't mmap piggie"); - return -1; - } - - sprintf(maps, "/proc/%d/map_files/%lx-%lx", - getpid(), (unsigned long)map, - (unsigned long)map + PAGE_SIZE); - if (stat(maps, &buf) < 0) { - pr_perror("Can't stat piggie"); - return -1; - } - - munmap(map, PAGE_SIZE); - - shmem_dev = buf.st_dev; - pr_info("Found anon-shmem piggie at %"PRIx64"\n", shmem_dev); - } - - return shmem_dev == dev; + return kerndat_shmem_dev == dev; } int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files)