Example #1
0
int
get_machdep_info_x86_64(void)
{
	int i, j, mfns[MAX_X86_64_FRAMES];
	unsigned long frame_mfn[MAX_X86_64_FRAMES];
	unsigned long buf[MFNS_PER_FRAME];

	info->section_size_bits = _SECTION_SIZE_BITS;

	if (!is_xen_memory())
		return TRUE;

	/*
	 * Get the information for translating domain-0's physical
	 * address into machine address.
	 */
	if (!readmem(MADDR_XEN, pfn_to_paddr(get_xen_p2m_mfn()),
					 &frame_mfn, PAGESIZE())) {
		ERRMSG("Can't get p2m_mfn.\n");
		return FALSE;
	}

	/*
	 * Count the number of p2m frame.
	 */
	for (i = 0; i < MAX_X86_64_FRAMES; i++) {
		mfns[i] = 0;
		if (!frame_mfn[i])
			break;

		if (!readmem(MADDR_XEN, pfn_to_paddr(frame_mfn[i]), &buf,
		    PAGESIZE())) {
			ERRMSG("Can't get frame_mfn[%d].\n", i);
			return FALSE;
		}
		for (j = 0; j < MFNS_PER_FRAME; j++) {
			if (!buf[j])
				break;

			mfns[i]++;
		}
		info->p2m_frames += mfns[i];
	}
	info->p2m_mfn_frame_list
	    = malloc(sizeof(unsigned long) * info->p2m_frames);
	if (info->p2m_mfn_frame_list == NULL) {
		ERRMSG("Can't allocate memory for p2m_mfn_frame_list. %s\n",
		    strerror(errno));
		return FALSE;
	}

	/*
	 * Get p2m_mfn_frame_list.
	 */
	for (i = 0; i < MAX_X86_64_FRAMES; i++) {
		if (!frame_mfn[i])
			break;

		if (!readmem(MADDR_XEN, pfn_to_paddr(frame_mfn[i]),
		    &info->p2m_mfn_frame_list[i * MFNS_PER_FRAME],
		    mfns[i] * sizeof(unsigned long))) {
			ERRMSG("Can't get p2m_mfn_frame_list.\n");
			return FALSE;
		}
		if (mfns[i] != MFNS_PER_FRAME)
			break;
	}
	return TRUE;
}
Example #2
0
/* 
 *  Just pass in an unused filename.
 */
void
cmd_snap(void)
{
        int c, fd, n;
	physaddr_t paddr;
	size_t offset;
	char *buf;
	char *filename;
	struct node_table *nt;
	int type;
	char *elf_header;
	Elf64_Phdr *load;
	int load_index;

	if (!supported)
		error(FATAL, "command not supported on the %s architecture\n",
			pc->machine_type);

	filename = NULL;
	buf = GETBUF(PAGESIZE()); 
	type = KDUMP_ELF64;

        while ((c = getopt(argcnt, args, "n")) != EOF) {
                switch(c)
                {
		case 'n':
			if (machine_type("X86_64"))
				option_not_supported('n');
			else
				type = NETDUMP_ELF64;
			break;
                default:
                        argerrs++;
                        break;
                }
        }

        if (argerrs || !args[optind])
                cmd_usage(pc->curcmd, SYNOPSIS);

	while (args[optind]) {
		if (filename)
                	cmd_usage(pc->curcmd, SYNOPSIS);

		if (file_exists(args[optind], NULL))
			error(FATAL, "%s: file already exists\n", args[optind]);
		else if ((fd = open(args[optind], O_RDWR|O_CREAT, 0644)) < 0)
			error(FATAL, args[optind]);

		filename = args[optind];
		optind++;
	}

	if (!filename)
                cmd_usage(pc->curcmd, SYNOPSIS);

	init_ram_segments();

	if (!(elf_header = generate_elf_header(type, fd, filename)))
		error(FATAL, "cannot generate ELF header\n");

	load = (Elf64_Phdr *)(elf_header + sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr));
	load_index = machine_type("X86_64") || machine_type("IA64") ? 1 : 0;

	for (n = 0; n < vt->numnodes; n++) {
		nt = &vt->node_table[n];
		paddr = nt->start_paddr;
		offset = load[load_index + n].p_offset;

		for (c = 0; c < nt->size; c++, paddr += PAGESIZE()) {
			if (!verify_paddr(paddr))
				continue;
			if (!readmem(paddr, PHYSADDR, &buf[0], PAGESIZE(), 
			    "memory page", QUIET|RETURN_ON_ERROR))
				continue;

			lseek(fd, (off_t)(paddr + offset - nt->start_paddr), SEEK_SET);
			if (write(fd, &buf[0], PAGESIZE()) != PAGESIZE())
				error(FATAL, "write to dumpfile failed\n");

			if (!print_progress(filename, BTOP(paddr)))
				return;
		}
	}

        fprintf(stderr, "\r%s: [100%%] ", filename);
	fprintf(fp, "\n");
	sprintf(buf, "/bin/ls -l %s\n", filename);
	system(buf);

	FREEBUF(elf_header);
	FREEBUF(buf);
}
Example #3
0
static void
init_ram_segments(void)
{
	int i, errflag;
        FILE *iomem; 
	char buf[BUFSIZE], *p1, *p2;
	physaddr_t start, end;

	if ((iomem = fopen("/proc/iomem", "r")) == NULL)
		goto fail_iomem;

	while (fgets(buf, BUFSIZE, iomem)) {
		if (strstr(buf, "System RAM")) {
			console(buf);
			nr_segments++;
		}
	}
	if (!nr_segments)
		goto fail_iomem;

	ram_segments = (struct ram_segments *)
		GETBUF(sizeof(struct ram_segments) * nr_segments);

	rewind(iomem);
	i = 0;
	while (fgets(buf, BUFSIZE, iomem)) {
		if (strstr(buf, "System RAM")) {
			if (!(p1 = strstr(buf, ":")))
				goto fail_iomem;
			*p1 = NULLCHAR;
			clean_line(buf);
			if (strstr(buf, " "))
				goto fail_iomem;
			p1 = buf;
			if (!(p2 = strstr(buf, "-")))
				goto fail_iomem;
			*p2 = NULLCHAR;
			p2++;
			errflag = 0;
			start = htoll(p1, RETURN_ON_ERROR|QUIET, &errflag);
			end = htoll(p2, RETURN_ON_ERROR|QUIET, &errflag);
			if (errflag)
				goto fail_iomem;
			ram_segments[i].start = PHYSPAGEBASE(start);
			if (PAGEOFFSET(start))
				ram_segments[i].start += PAGESIZE();
			ram_segments[i].end = PHYSPAGEBASE(end);
			if (PAGEOFFSET(end) == (PAGESIZE()-1))
				ram_segments[i].end += PAGESIZE();
			console("ram_segments[%d]: %016llx %016llx [%s-%s]\n", i,
				(ulonglong)ram_segments[i].start, 
				(ulonglong)ram_segments[i].end, p1, p2);
			i++;
		}
	}

	fclose(iomem);
	return;

fail_iomem:
	fclose(iomem);
	nr_segments = 0;
	if (ram_segments)
		FREEBUF(ram_segments);

	return; 
}
Example #4
0
char *
generate_elf_header(int type, int fd, char *filename)
{
	int i, n;
	char *buffer, *ptr;
	Elf64_Ehdr *elf;
	Elf64_Phdr *notes;
	Elf64_Phdr *load;
	size_t offset, len, l_offset;
	size_t data_offset;
	struct elf_prpsinfo_64 prpsinfo;
	union prstatus prstatus;
	int prstatus_len;
	ushort e_machine;
	int num_segments;
	struct node_table *nt;
	struct SNAP_info {
		ulonglong task_struct;
		ulonglong arch_data1;
		ulonglong arch_data2;
	} SNAP_info;

	num_segments = vt->numnodes;

	if (machine_type("X86_64")) {
		e_machine = EM_X86_64;
		prstatus_len = sizeof(prstatus.x86_64);
		num_segments += 1;  /* mapped kernel section for phys_base */
	} else if (machine_type("X86")) {
		e_machine = EM_386;
		prstatus_len = sizeof(prstatus.x86);
	} else if (machine_type("IA64")) {
		e_machine = EM_IA_64;
		prstatus_len = sizeof(prstatus.ia64);
		num_segments += 1;  /* mapped kernel section for phys_start */
	} else if (machine_type("PPC64")) {
		e_machine = EM_PPC64;
		prstatus_len = sizeof(prstatus.ppc64);
	} else if (machine_type("ARM64")) {
		e_machine = EM_AARCH64;
		prstatus_len = sizeof(prstatus.arm64);
	} else
		return NULL;

	/* should be enought for the notes + roundup + two blocks */
	buffer = (char *)GETBUF(sizeof(Elf64_Ehdr) +
		num_segments * sizeof(Elf64_Phdr) + PAGESIZE() * 2);
	offset = 0;
	ptr = buffer;

	/* Elf header */
	elf = (Elf64_Ehdr *)ptr;
	memcpy(elf->e_ident, ELFMAG, SELFMAG);
	elf->e_ident[EI_CLASS] = ELFCLASS64;
#if __BYTE_ORDER == __BIG_ENDIAN
	elf->e_ident[EI_DATA] = ELFDATA2MSB;
#else
	elf->e_ident[EI_DATA] = ELFDATA2LSB;
#endif
	elf->e_ident[EI_VERSION] = EV_CURRENT;
	elf->e_ident[EI_OSABI] = ELFOSABI_SYSV;
	elf->e_ident[EI_ABIVERSION] = 0;
	memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);

	elf->e_type = ET_CORE;
	elf->e_machine = e_machine;
	elf->e_version = EV_CURRENT;
	elf->e_entry = 0;
	elf->e_phoff = sizeof(Elf64_Ehdr);
	elf->e_shoff = 0;
	elf->e_flags = 0;
	elf->e_ehsize = sizeof(Elf64_Ehdr);
	elf->e_phentsize = sizeof(Elf64_Phdr);
	elf->e_phnum = 1 + num_segments;
	elf->e_shentsize = 0;
	elf->e_shnum = 0;
	elf->e_shstrndx = 0;

	offset += sizeof(Elf64_Ehdr);
	ptr += sizeof(Elf64_Ehdr);

	/* PT_NOTE */
	notes = (Elf64_Phdr *)ptr;
	notes->p_type = PT_NOTE;
	notes->p_offset = 0; /* TO BE FILLED IN */
	notes->p_vaddr = 0;
	notes->p_paddr = 0;
	notes->p_filesz = 0; /* TO BE FILLED IN */
	notes->p_memsz = 0;
	notes->p_flags = 0;
	notes->p_align = 0;

	offset += sizeof(Elf64_Phdr);
	ptr += sizeof(Elf64_Phdr);

	/* PT_LOAD */
	load = (Elf64_Phdr *)ptr;
	for (i = n = 0; i < num_segments; i++) {
		load[i].p_type = PT_LOAD;
		load[i].p_offset = 0; /* TO BE FILLED IN */

		switch (e_machine)
		{
		case EM_X86_64:
			nt = &vt->node_table[n];
			if (i == 0) {
#ifdef X86_64
				load[i].p_vaddr = __START_KERNEL_map;
				load[i].p_paddr = machdep->machspec->phys_base;
#endif
				load[i].p_filesz = 0;
				load[i].p_memsz = load[i].p_filesz;
			} else {
				load[i].p_vaddr = PTOV(nt->start_paddr);
				load[i].p_paddr = nt->start_paddr;
				load[i].p_filesz = nt->size * PAGESIZE();
				load[i].p_memsz = load[i].p_filesz;
				n++;
			}
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = 0;
			break;

		case EM_386:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = 0;
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_IA_64:
			nt = &vt->node_table[n];
			if (i == 0) {
#ifdef IA64
				load[i].p_vaddr = machdep->machspec->kernel_start;
				load[i].p_paddr = machdep->machspec->phys_start;
#endif
				load[i].p_filesz = 0;
				load[i].p_memsz = load[i].p_filesz;
			} else {
				load[i].p_vaddr = PTOV(nt->start_paddr);
				load[i].p_paddr = nt->start_paddr;
				load[i].p_filesz = nt->size * PAGESIZE();
 				load[i].p_memsz = load[i].p_filesz;
				n++;
			}
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_PPC64:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = PTOV(nt->start_paddr);
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;

		case EM_AARCH64:
			nt = &vt->node_table[n++];
			load[i].p_vaddr = PTOV(nt->start_paddr);
			load[i].p_paddr = nt->start_paddr;
			load[i].p_filesz = nt->size * PAGESIZE();
			load[i].p_memsz = load[i].p_filesz;
			load[i].p_flags = PF_R | PF_W | PF_X;
			load[i].p_align = (type == NETDUMP_ELF64) ? PAGESIZE() : 0;
			break;
		}

//		l_offset += load[i].p_filesz;
		offset += sizeof(Elf64_Phdr);
		ptr += sizeof(Elf64_Phdr);
	}
	notes->p_offset = offset;

	/* NT_PRSTATUS note */
	memset(&prstatus, 0, sizeof(prstatus));
	len = dump_elf_note(ptr, NT_PRSTATUS, "CORE",
		(char *)&prstatus, prstatus_len);
	offset += len;
	ptr += len;
	notes->p_filesz += len;

	/* NT_PRPSINFO note */
	memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo_64));
	prpsinfo.pr_state = 0;
	prpsinfo.pr_sname = 'R';
	prpsinfo.pr_zomb = 0;
	strcpy(prpsinfo.pr_fname, "vmlinux");

	len = dump_elf_note(ptr, NT_PRPSINFO, "CORE",
		(char *)&prpsinfo, sizeof(prpsinfo));

	offset += len;
	ptr += len;
	notes->p_filesz += len;

  	/* NT_TASKSTRUCT note */
	SNAP_info.task_struct = CURRENT_TASK();
#ifdef X86_64
	SNAP_info.arch_data1 = kt->relocate;
	SNAP_info.arch_data2 = 0;
#elif ARM64
	SNAP_info.arch_data1 = machdep->machspec->kimage_voffset;
	SNAP_info.arch_data2 = (machdep->machspec->VA_BITS_ACTUAL << 32) | 
				machdep->machspec->CONFIG_ARM64_VA_BITS;
#else
	SNAP_info.arch_data1 = 0;
	SNAP_info.arch_data2 = 0;
#endif
	len = dump_elf_note (ptr, NT_TASKSTRUCT, "SNAP",
		(char *)&SNAP_info, sizeof(struct SNAP_info));
	offset += len;
	ptr += len;
	notes->p_filesz += len;

	if (type == NETDUMP_ELF64)
		offset = roundup (offset, PAGESIZE());

	l_offset = offset;
	for (i = 0; i < num_segments; i++) {
		load[i].p_offset = l_offset;
		l_offset += load[i].p_filesz;
	}
	data_offset = offset;

	while (offset > 0) {
		len = write(fd, buffer + (data_offset - offset), offset);
		if (len < 0) {
			perror(filename);
			FREEBUF(buffer);
			return NULL;
		}

		offset -= len;
	}

	return buffer;
}