⬢ DragonFlyBSD Kernel Audit
DF-5535 / dumpchk.c
← back to finding ↓ download raw
/*
 * dumpchk.c - check whether physical pages made it into a DragonFly
 * amd64 minidump (as saved by savecore to vmcore.N).
 *
 * usage: dumpchk <vmcore-file> <pa> [<pa> ...]
 *
 * Prints SET (page in dump bitmap) or CLEAR (page missing) for each pa.
 */
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

struct mdhdr2 {
	char magic[24];
	uint32_t version;
	uint32_t unused01;
	uint64_t msgbufsize;
	uint64_t bitmapsize;
	uint64_t ptesize;
	uint64_t kernbase;
	uint64_t dmapbase;
	uint64_t dmapend;
};

int
main(int argc, char **argv)
{
	FILE *f;
	unsigned char hdr[512], page[4096];
	struct mdhdr2 *md;
	uint64_t bitmap_off;
	unsigned char *bm;
	long bmsz;
	int i;

	if (argc < 3) {
		fprintf(stderr, "usage: %s vmcore pa...\n", argv[0]);
		return (2);
	}
	f = fopen(argv[1], "rb");
	if (!f) { perror(argv[1]); return (2); }
	if (fread(page, 1, 4096, f) != 4096) { fprintf(stderr, "short mdhdr page\n"); return (2); }
	if (memcmp(page, "minidump DFlyBSD/x86-64", 24) != 0) {
		/* maybe the kerneldumpheader prefix was kept: skip it */
		if (fseek(f, 512, SEEK_SET) != 0 ||
		    fread(page, 1, 4096, f) != 4096 ||
		    memcmp(page, "minidump DFlyBSD/x86-64", 24) != 0) {
			fprintf(stderr, "bad minidump magic: %.24s\n", page);
			return (2);
		}
	}
	md = (struct mdhdr2 *)(void *)page;
	if (memcmp(md->magic, "minidump DFlyBSD/x86-64", 24) != 0) {
		fprintf(stderr, "bad minidump magic: %.24s\n", md->magic);
		return (2);
	}
	printf("minidump: version=%u msgbufsize=%" PRIu64 " bitmapsize=%" PRIu64
	    " ptesize=%" PRIu64 "\n", md->version, md->msgbufsize,
	    md->bitmapsize, md->ptesize);
	bmsz = (long)md->bitmapsize;
	bm = malloc(bmsz);
	if (!bm) { perror("malloc"); return (2); }
	/* file position now after kdh(512) + mdhdr page(4096) */
	bitmap_off = ftell(f);
	/* then msgbuf, rounded to page */
	if (fseek(f, (md->msgbufsize + 4095) & ~4095UL, SEEK_CUR) != 0) {
		perror("seek msgbuf"); return (2);
	}
	if (fread(bm, 1, bmsz, f) != (size_t)bmsz) {
		fprintf(stderr, "short bitmap read\n"); return (2);
	}
	printf("bitmap at file offset %" PRIu64 " (%ld bytes)\n",
	    (uint64_t)(bitmap_off + ((md->msgbufsize + 4095) & ~4095UL)), bmsz);

	for (i = 2; i < argc; i++) {
		uint64_t pa = strtoull(argv[i], NULL, 0);
		uint64_t pg = pa >> 12;
		uint64_t word = pg >> 6;
		int bit = (int)(pg & 63);
		/* little-endian: byte word*8 + bit/8, bit bit&7 */
		int set = (bm[word * 8 + (bit >> 3)] >> (bit & 7)) & 1;
		printf("pa 0x%09" PRIx64 " (page %" PRIu64 "): %s\n",
		    pa, pg, set ? "SET (in dump)" : "CLEAR (MISSING from dump)");
	}
	return (0);
}