⬢ DragonFlyBSD Kernel Audit
DF-5833 / parse_core.c
← back to finding ↓ download raw
/*
 * parse_core.c -- DF-5833 rig: analyze a produced core file.
 * Prints: e_phnum, PT_NOTE size, NT_PRSTATUS count + list of pr_pid
 * (lwp_tid) values, and the derived counts the rig needs for tuning.
 */
#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct { uint32_t namesz, descsz, type; } Elf64_Nhdr_t;
#pragma pack(1)
typedef struct {
	unsigned char e_ident[16];
	uint16_t e_type, e_machine;
	uint32_t e_version;
	uint64_t e_entry, e_phoff, e_shoff;
	uint32_t e_flags;
	uint16_t e_ehsize, e_phentsize, e_phnum, e_shentsize,
	    e_shnum, e_shstrndx;
} Ehdr;
typedef struct {
	uint32_t p_type, p_flags;
	uint64_t p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_align;
} Phdr;
#pragma pack()

int
main(int argc, char **argv)
{
	if (argc < 2) {
		fprintf(stderr, "usage: %s core\n", argv[0]);
		return (1);
	}
	FILE *f = fopen(argv[1], "rb");
	if (!f) {
		perror(argv[1]);
		return (1);
	}
	Ehdr eh;
	if (fread(&eh, sizeof(eh), 1, f) != 1) {
		fprintf(stderr, "short read ehdr\n");
		return (1);
	}
	printf("e_phnum=%u e_phoff=%llu\n", eh.e_phnum,
	    (unsigned long long)eh.e_phoff);
	Phdr *ph = calloc(eh.e_phnum, sizeof(Phdr));
	fseek(f, eh.e_phoff, SEEK_SET);
	if (fread(ph, sizeof(Phdr), eh.e_phnum, f) != eh.e_phnum) {
		fprintf(stderr, "short read phdrs\n");
		return (1);
	}
	int count_prstatus = 0, count_fpreg = 0, count_psinfo = 0;
	int pids[4096];
	int npid = 0;
	uint64_t note_off = 0, note_sz = 0;

	for (int i = 0; i < eh.e_phnum; i++) {
		if (ph[i].p_type != 4)	/* PT_NOTE */
			continue;
		note_off = ph[i].p_offset;
		note_sz = ph[i].p_filesz;
		unsigned char *buf = malloc(note_sz);
		fseek(f, note_off, SEEK_SET);
		if (fread(buf, 1, note_sz, f) != note_sz) {
			fprintf(stderr, "short read notes\n");
			return (1);
		}
		uint64_t off = 0;
		while (off + sizeof(Elf64_Nhdr_t) <= note_sz) {
			Elf64_Nhdr_t n;
			memcpy(&n, buf + off, sizeof(n));
			uint64_t p = off + sizeof(n);
			uint64_t namepad = (n.namesz + 3) & ~3ULL;
			uint64_t descpad = (n.descsz + 3) & ~3ULL;
			if (p + namepad + n.descsz > note_sz)
				break;
			if (n.type == 1) {	/* NT_PRSTATUS */
				count_prstatus++;
				/* pr_pid at desc+40 */
				int pid;
				memcpy(&pid, buf + p + namepad + 40, 4);
				if (npid < 4096)
					pids[npid++] = pid;
			} else if (n.type == 2) {
				count_fpreg++;
			} else if (n.type == 3) {
				count_psinfo++;
			}
			off = p + namepad + descpad;
			off = (off + 3) & ~3ULL;
		}
	}
	printf("note_off=%llu note_sz=%llu\n",
	    (unsigned long long)note_off, (unsigned long long)note_sz);
	printf("NT_PRSTATUS=%d NT_FPREGSET=%d NT_PRPSINFO=%d\n",
	    count_prstatus, count_fpreg, count_psinfo);
	printf("PIDS:");
	for (int i = 0; i < npid; i++)
		printf(" %d", pids[i]);
	printf("\n");
	return (0);
}