Ejemplo n.º 1
0
Archivo: util.c Proyecto: OSLL/pmover
void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
{
	if (!vma_area)
		return;

	print_on_level(loglevel, "s: 0x%16"PRIx64" e: 0x%16"PRIx64" l: %8"PRIu64"K p: 0x%8x f: 0x%8x pg: 0x%8"PRIx64" "
		       "vf: %s st: %s spc: %-8s shmid: 0x%8"PRIx64"\n",
		       vma_area->vma.start, vma_area->vma.end,
		       KBYTES(vma_area_len(vma_area)),
		       vma_area->vma.prot,
		       vma_area->vma.flags,
		       vma_area->vma.pgoff,
		       vma_area->vm_file_fd < 0 ? "n" : "y",
		       !vma_area->vma.status ? "--" :
		       ((vma_area->vma.status & VMA_FILE_PRIVATE) ? "FP" :
			((vma_area->vma.status & VMA_FILE_SHARED) ? "FS" :
			 ((vma_area->vma.status & VMA_ANON_SHARED) ? "AS" :
			  ((vma_area->vma.status & VMA_ANON_PRIVATE) ? "AP" : "--")))),
		       !vma_area->vma.status ? "--" :
		       ((vma_area->vma.status & VMA_AREA_STACK) ? "stack" :
			((vma_area->vma.status & VMA_AREA_HEAP) ? "heap" :
			 ((vma_area->vma.status & VMA_AREA_VSYSCALL) ? "vsyscall" :
			  ((vma_area->vma.status & VMA_AREA_VDSO) ? "vdso" : "n")))),
			vma_area->vma.shmid);
}
Ejemplo n.º 2
0
static int vma_list_add(struct vma_area *vma_area,
			struct vm_area_list *vma_area_list,
			unsigned long *prev_end,
			struct vma_file_info *vfi, struct vma_file_info *prev_vfi)
{
	if (vma_area->e->status & VMA_UNSUPP) {
		pr_err("Unsupported mapping found %016"PRIx64"-%016"PRIx64"\n",
					vma_area->e->start, vma_area->e->end);
		return -1;
	}

	/* Add a guard page only if here is enough space for it */
	if ((vma_area->e->flags & MAP_GROWSDOWN) &&
	    *prev_end < vma_area->e->start)
		vma_area->e->start -= PAGE_SIZE; /* Guard page */
	*prev_end = vma_area->e->end;

	list_add_tail(&vma_area->list, &vma_area_list->h);
	vma_area_list->nr++;
	if (vma_area_is_private(vma_area, kdat.task_size)) {
		unsigned long pages;

		pages = vma_area_len(vma_area) / PAGE_SIZE;
		vma_area_list->priv_size += pages;
		vma_area_list->longest = max(vma_area_list->longest, pages);
	}

	*prev_vfi = *vfi;
	prev_vfi->vma = vma_area;

	return 0;
}
Ejemplo n.º 3
0
int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, bool use_map_files)
{
	struct vma_area *vma_area = NULL;
	unsigned long start, end, pgoff;
	unsigned long ino;
	char r, w, x, s;
	int dev_maj, dev_min;
	int ret = -1;

	DIR *map_files_dir = NULL;
	FILE *smaps = NULL;

	vma_area_list->nr = 0;
	vma_area_list->longest = 0;
	vma_area_list->priv_size = 0;
	INIT_LIST_HEAD(&vma_area_list->h);

	smaps = fopen_proc(pid, "smaps");
	if (!smaps)
		goto err;

	if (use_map_files) {
		map_files_dir = opendir_proc(pid, "map_files");
		if (!map_files_dir) /* old kernel? */
			goto err;
	}

	while (fgets(buf, BUF_SIZE, smaps)) {
		int num;
		char file_path[6];

		if (!is_vma_range_fmt(buf)) {
			if (!strncmp(buf, "Nonlinear", 9)) {
				BUG_ON(!vma_area);
				pr_err("Nonlinear mapping found %016"PRIx64"-%016"PRIx64"\n",
				       vma_area->vma.start, vma_area->vma.end);
				/*
				 * VMA is already on list and will be
				 * freed later as list get destroyed.
				 */
				vma_area = NULL;
				goto err;
			} else if (!strncmp(buf, "VmFlags: ", 9)) {
				BUG_ON(!vma_area);
				if (parse_vmflags(&buf[9], vma_area))
					goto err;
				continue;
			} else
				continue;
		}

		vma_area = alloc_vma_area();
		if (!vma_area)
			goto err;

		memset(file_path, 0, 6);
		num = sscanf(buf, "%lx-%lx %c%c%c%c %lx %02x:%02x %lu %5s",
			     &start, &end, &r, &w, &x, &s, &pgoff, &dev_maj,
			     &dev_min, &ino, file_path);
		if (num < 10) {
			pr_err("Can't parse: %s\n", buf);
			goto err;
		}

		if (map_files_dir) {
			char path[32];

			/* Figure out if it's file mapping */
			snprintf(path, sizeof(path), "%lx-%lx", start, end);

			/*
			 * Note that we "open" it in dumper process space
			 * so later we might refer to it via /proc/self/fd/vm_file_fd
			 * if needed.
			 */
			vma_area->vm_file_fd = openat(dirfd(map_files_dir), path, O_RDONLY);
			if (vma_area->vm_file_fd < 0) {
				if (errno == ENXIO) {
					struct stat buf;

					if (fstatat(dirfd(map_files_dir), path, &buf, 0))
						goto err_bogus_mapfile;

					if (!S_ISSOCK(buf.st_mode))
						goto err_bogus_mapfile;

					pr_info("Found socket %"PRIu64" mapping @%lx\n", buf.st_ino, start);
					vma_area->vma.status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
					vma_area->vm_socket_id = buf.st_ino;
				} else if (errno != ENOENT)
					goto err_bogus_mapfile;
			}
		}

		vma_area->vma.start	= start;
		vma_area->vma.end	= end;
		vma_area->vma.pgoff	= pgoff;
		vma_area->vma.prot	= PROT_NONE;

		if (r == 'r')
			vma_area->vma.prot |= PROT_READ;
		if (w == 'w')
			vma_area->vma.prot |= PROT_WRITE;
		if (x == 'x')
			vma_area->vma.prot |= PROT_EXEC;

		if (s == 's')
			vma_area->vma.flags = MAP_SHARED;
		else if (s == 'p')
			vma_area->vma.flags = MAP_PRIVATE;
		else {
			pr_err("Unexpected VMA met (%c)\n", s);
			goto err;
		}

		if (vma_area->vma.status != 0) {
			goto done;
		} else if (strstr(buf, "[vsyscall]")) {
			vma_area->vma.status |= VMA_AREA_VSYSCALL;
		} else if (strstr(buf, "[vdso]")) {
			vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
		} else if (strstr(buf, "[heap]")) {
			vma_area->vma.status |= VMA_AREA_REGULAR | VMA_AREA_HEAP;
		} else {
			vma_area->vma.status = VMA_AREA_REGULAR;
		}

		/*
		 * Some mapping hints for restore, we save this on
		 * disk and restore might need to analyze it.
		 */
		if (vma_area->vm_file_fd >= 0) {
			struct stat st_buf;

			if (fstat(vma_area->vm_file_fd, &st_buf) < 0) {
				pr_perror("Failed fstat on %d's map %lu", pid, start);
				goto err;
			}

			if (!S_ISREG(st_buf.st_mode) &&
			    !(S_ISCHR(st_buf.st_mode) && st_buf.st_rdev == DEVZERO)) {
				pr_err("Can't handle non-regular mapping on %d's map %lu\n", pid, start);
				goto err;
			}

			/*
			 * /dev/zero stands for anon-shared mapping
			 * otherwise it's some file mapping.
			 */
			if (is_anon_shmem_map(st_buf.st_dev)) {
				if (!(vma_area->vma.flags & MAP_SHARED))
					goto err_bogus_mapping;
				vma_area->vma.flags  |= MAP_ANONYMOUS;
				vma_area->vma.status |= VMA_ANON_SHARED;
				vma_area->vma.shmid = st_buf.st_ino;

				if (!strcmp(file_path, "/SYSV")) {
					pr_info("path: %s\n", file_path);
					vma_area->vma.status |= VMA_AREA_SYSVIPC;
				}
			} else {
				if (vma_area->vma.flags & MAP_PRIVATE)
					vma_area->vma.status |= VMA_FILE_PRIVATE;
				else
					vma_area->vma.status |= VMA_FILE_SHARED;
			}
		} else {
			/*
			 * No file but mapping -- anonymous one.
			 */
			if (vma_area->vma.flags & MAP_SHARED) {
				vma_area->vma.status |= VMA_ANON_SHARED;
				vma_area->vma.shmid = ino;
			} else {
				vma_area->vma.status |= VMA_ANON_PRIVATE;
			}
			vma_area->vma.flags  |= MAP_ANONYMOUS;
		}
done:
		list_add_tail(&vma_area->list, &vma_area_list->h);
		vma_area_list->nr++;
		if (privately_dump_vma(vma_area)) {
			unsigned long pages;

			pages = vma_area_len(vma_area) / PAGE_SIZE;
			vma_area_list->priv_size += pages;
			vma_area_list->longest = max(vma_area_list->longest, pages);
		}
	}

	vma_area = NULL;
	ret = 0;

err:
	if (smaps)
		fclose(smaps);

	if (map_files_dir)
		closedir(map_files_dir);

	xfree(vma_area);
	return ret;

err_bogus_mapping:
	pr_err("Bogus mapping 0x%"PRIx64"-0x%"PRIx64" (flags: %#x vm_file_fd: %d)\n",
	       vma_area->vma.start, vma_area->vma.end,
	       vma_area->vma.flags, vma_area->vm_file_fd);
	goto err;

err_bogus_mapfile:
	pr_perror("Can't open %d's mapfile link %lx", pid, start);
	goto err;
}