xref: /dflybsd-src/test/nvmm/demo/toyvirt/elf.c (revision db3748d66cd4118cb8a910da198671ba63c8117f)
18368e25fSAaron LI /*
2e84206a6SAaron LI  * Copyright (c) 2018-2021 Maxime Villard, m00nbsd.net
38368e25fSAaron LI  * All rights reserved.
48368e25fSAaron LI  *
5e84206a6SAaron LI  * This code is part of the NVMM hypervisor.
68368e25fSAaron LI  *
78368e25fSAaron LI  * Redistribution and use in source and binary forms, with or without
88368e25fSAaron LI  * modification, are permitted provided that the following conditions
98368e25fSAaron LI  * are met:
108368e25fSAaron LI  * 1. Redistributions of source code must retain the above copyright
118368e25fSAaron LI  *    notice, this list of conditions and the following disclaimer.
128368e25fSAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
138368e25fSAaron LI  *    notice, this list of conditions and the following disclaimer in the
148368e25fSAaron LI  *    documentation and/or other materials provided with the distribution.
158368e25fSAaron LI  *
16e84206a6SAaron LI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17e84206a6SAaron LI  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18e84206a6SAaron LI  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19e84206a6SAaron LI  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20e84206a6SAaron LI  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21e84206a6SAaron LI  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22e84206a6SAaron LI  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23e84206a6SAaron LI  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24e84206a6SAaron LI  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25e84206a6SAaron LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26e84206a6SAaron LI  * SUCH DAMAGE.
278368e25fSAaron LI  */
288368e25fSAaron LI 
29*db3748d6SAaron LI #include <sys/types.h>
30*db3748d6SAaron LI #include <sys/stat.h>
31*db3748d6SAaron LI 
32*db3748d6SAaron LI #include <err.h>
33*db3748d6SAaron LI #include <fcntl.h>
34*db3748d6SAaron LI #include <stdint.h>
358368e25fSAaron LI #include <stdio.h>
368368e25fSAaron LI #include <stdlib.h>
378368e25fSAaron LI #include <unistd.h>
388368e25fSAaron LI 
398368e25fSAaron LI #include "common.h"
408368e25fSAaron LI 
414dec84dcSAaron LI #ifdef __NetBSD__
428368e25fSAaron LI #define ELFSIZE		64
438368e25fSAaron LI #include <sys/exec_elf.h>
444dec84dcSAaron LI #else /* DragonFly */
454dec84dcSAaron LI #include <sys/elf64.h>
464dec84dcSAaron LI #define Elf_Ehdr	Elf64_Ehdr
474dec84dcSAaron LI #define Elf_Phdr	Elf64_Phdr
484dec84dcSAaron LI #endif /* __NetBSD__ */
498368e25fSAaron LI 
508368e25fSAaron LI #define ELF_MAXPHNUM	128
518368e25fSAaron LI #define ELF_MAXSHNUM	32768
528368e25fSAaron LI 
538368e25fSAaron LI static int
elf_check_header(Elf_Ehdr * eh)548368e25fSAaron LI elf_check_header(Elf_Ehdr *eh)
558368e25fSAaron LI {
568368e25fSAaron LI 	if (eh->e_shnum > ELF_MAXSHNUM || eh->e_phnum > ELF_MAXPHNUM)
578368e25fSAaron LI 		return -1;
588368e25fSAaron LI 	return 0;
598368e25fSAaron LI }
608368e25fSAaron LI 
618368e25fSAaron LI static uint64_t
elf_parse(struct nvmm_machine * mach,char * base)628368e25fSAaron LI elf_parse(struct nvmm_machine *mach, char *base)
638368e25fSAaron LI {
648368e25fSAaron LI 	Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
658368e25fSAaron LI 	Elf_Phdr *phdr;
668368e25fSAaron LI 	uintptr_t hva;
678368e25fSAaron LI 	gpaddr_t lastgpa;
688368e25fSAaron LI 	size_t i;
698368e25fSAaron LI 
708368e25fSAaron LI 	if (elf_check_header(ehdr) == -1)
718368e25fSAaron LI 		errx(EXIT_FAILURE, "wrong ELF header");
728368e25fSAaron LI 	phdr = (Elf_Phdr *)((char *)ehdr + ehdr->e_phoff);
738368e25fSAaron LI 
748368e25fSAaron LI 	for (i = 0; i < ehdr->e_phnum; i++) {
75f2252fffSAaron LI 		if (phdr[i].p_type != PT_LOAD) {
76f2252fffSAaron LI 			if (phdr[i].p_filesz == 0) {
77f2252fffSAaron LI 				/* Ignore zero-sized GNU_STACK segment
78f2252fffSAaron LI 				 * (found on DragonFly) */
79f2252fffSAaron LI 				continue;
80f2252fffSAaron LI 			} else {
81f2252fffSAaron LI 				errx(EXIT_FAILURE, "unsupported ELF");
82f2252fffSAaron LI 			}
83f2252fffSAaron LI 		}
84f2252fffSAaron LI 
858368e25fSAaron LI 		hva = toyvirt_mem_add(mach, phdr[i].p_vaddr,
868368e25fSAaron LI 		    roundup(phdr[i].p_filesz, PAGE_SIZE));
878368e25fSAaron LI 		memcpy((void *)hva, base + phdr[i].p_offset, phdr[i].p_filesz);
888368e25fSAaron LI 
898368e25fSAaron LI 		lastgpa = phdr[i].p_vaddr +
908368e25fSAaron LI 		    roundup(phdr[i].p_filesz, PAGE_SIZE);
918368e25fSAaron LI 	}
928368e25fSAaron LI 
938368e25fSAaron LI 	/* Add 128 pages after the kernel image. */
948368e25fSAaron LI 	toyvirt_mem_add(mach, lastgpa, 128 * PAGE_SIZE);
958368e25fSAaron LI 
968368e25fSAaron LI 	return ehdr->e_entry;
978368e25fSAaron LI }
988368e25fSAaron LI 
998368e25fSAaron LI int
elf_map(struct nvmm_machine * mach,const char * path,uint64_t * rip)1008368e25fSAaron LI elf_map(struct nvmm_machine *mach, const char *path, uint64_t *rip)
1018368e25fSAaron LI {
1028368e25fSAaron LI 	struct stat st;
1038368e25fSAaron LI 	char *base = NULL;
1048368e25fSAaron LI 	int fd, ret = -1;
1058368e25fSAaron LI 
1068368e25fSAaron LI 	fd = open(path, O_RDONLY);
1078368e25fSAaron LI 	if (fstat(fd, &st) == -1)
1088368e25fSAaron LI 		goto out;
109ce7051aeSAaron LI 	if ((size_t)st.st_size < sizeof(Elf_Ehdr))
1108368e25fSAaron LI 		goto out;
1118368e25fSAaron LI 	base = malloc(st.st_size);
1128368e25fSAaron LI 	pread(fd, base, st.st_size, 0);
1138368e25fSAaron LI 
1148368e25fSAaron LI 	*rip = elf_parse(mach, base);
1158368e25fSAaron LI 	ret = 0;
1168368e25fSAaron LI 
1178368e25fSAaron LI out:
1188368e25fSAaron LI 	close(fd);
1198368e25fSAaron LI 	free(base);
1208368e25fSAaron LI 	return ret;
1218368e25fSAaron LI }
122