Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Apr 2019 15:24:39 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r346053 - head/sys/kern
Message-ID:  <201904091524.x39FOdPv023299@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Tue Apr  9 15:24:38 2019
New Revision: 346053
URL: https://svnweb.freebsd.org/changeset/base/346053

Log:
  Factor out section loading into a separate function.
  
  Reviewed by:	kib
  MFC after:	2 weeks
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D19846

Modified:
  head/sys/kern/imgact_elf.c

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Tue Apr  9 13:54:08 2019	(r346052)
+++ head/sys/kern/imgact_elf.c	Tue Apr  9 15:24:38 2019	(r346053)
@@ -649,6 +649,45 @@ __elfN(load_section)(struct image_params *imgp, vm_oof
 	return (0);
 }
 
+static int
+__elfN(load_sections)(struct image_params *imgp, const Elf_Ehdr *hdr,
+    const Elf_Phdr *phdr, u_long rbase, u_long *base_addrp)
+{
+	vm_prot_t prot;
+	u_long base_addr;
+	bool first;
+	int error, i;
+
+	base_addr = 0;
+	first = true;
+
+	for (i = 0; i < hdr->e_phnum; i++) {
+		if (phdr[i].p_type != PT_LOAD || phdr[i].p_memsz == 0)
+			continue;
+
+		/* Loadable segment */
+		prot = __elfN(trans_prot)(phdr[i].p_flags);
+		error = __elfN(load_section)(imgp, phdr[i].p_offset,
+		    (caddr_t)(uintptr_t)phdr[i].p_vaddr + rbase,
+		    phdr[i].p_memsz, phdr[i].p_filesz, prot);
+		if (error != 0)
+			return (error);
+
+		/*
+		 * Establish the base address if this is the first segment.
+		 */
+		if (first) {
+  			base_addr = trunc_page(phdr[i].p_vaddr + rbase);
+			first = false;
+		}
+	}
+
+	if (base_addrp != NULL)
+		*base_addrp = base_addr;
+
+	return (0);
+}
+
 /*
  * Load the file "file" into memory.  It may be either a shared object
  * or an executable.
@@ -675,10 +714,9 @@ __elfN(load_file)(struct proc *p, const char *file, u_
 	struct nameidata *nd;
 	struct vattr *attr;
 	struct image_params *imgp;
-	vm_prot_t prot;
 	u_long rbase;
 	u_long base_addr = 0;
-	int error, i, numsegs;
+	int error;
 
 #ifdef CAPABILITY_MODE
 	/*
@@ -756,25 +794,10 @@ __elfN(load_file)(struct proc *p, const char *file, u_
 		goto fail;
 	}
 
-	for (i = 0, numsegs = 0; i < hdr->e_phnum; i++) {
-		if (phdr[i].p_type == PT_LOAD && phdr[i].p_memsz != 0) {
-			/* Loadable segment */
-			prot = __elfN(trans_prot)(phdr[i].p_flags);
-			error = __elfN(load_section)(imgp, phdr[i].p_offset,
-			    (caddr_t)(uintptr_t)phdr[i].p_vaddr + rbase,
-			    phdr[i].p_memsz, phdr[i].p_filesz, prot);
-			if (error != 0)
-				goto fail;
-			/*
-			 * Establish the base address if this is the
-			 * first segment.
-			 */
-			if (numsegs == 0)
-  				base_addr = trunc_page(phdr[i].p_vaddr +
-				    rbase);
-			numsegs++;
-		}
-	}
+	error = __elfN(load_sections)(imgp, hdr, phdr, rbase, &base_addr);
+	if (error != 0)
+		goto fail;
+
 	*addr = base_addr;
 	*entry = (unsigned long)hdr->e_entry + rbase;
 
@@ -998,7 +1021,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i
 	char *interp;
 	Elf_Brandinfo *brand_info;
 	struct sysentvec *sv;
-	vm_prot_t prot;
 	u_long addr, baddr, et_dyn_addr, entry, proghdr;
 	u_long maxalign, mapsz, maxv, maxv1;
 	uint32_t fctl0;
@@ -1055,6 +1077,17 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i
 				maxalign = phdr[i].p_align;
 			mapsz += phdr[i].p_memsz;
 			n++;
+
+			/*
+			 * If this segment contains the program headers,
+			 * remember their virtual address for the AT_PHDR
+			 * aux entry. Static binaries don't usually include
+			 * a PT_PHDR entry.
+			 */
+			if (phdr[i].p_offset == 0 &&
+			    hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize
+				<= phdr[i].p_filesz)
+				proghdr = phdr[i].p_vaddr + hdr->e_phoff;
 			break;
 		case PT_INTERP:
 			/* Path to interpreter */
@@ -1074,6 +1107,9 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i
 				    __elfN(trans_prot)(phdr[i].p_flags);
 			imgp->stack_sz = phdr[i].p_memsz;
 			break;
+		case PT_PHDR: 	/* Program header table info */
+			proghdr = phdr[i].p_vaddr;
+			break;
 		}
 	}
 
@@ -1174,38 +1210,10 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i
 	if (error != 0)
 		goto ret;
 
-	for (i = 0; i < hdr->e_phnum; i++) {
-		switch (phdr[i].p_type) {
-		case PT_LOAD:	/* Loadable segment */
-			if (phdr[i].p_memsz == 0)
-				break;
-			prot = __elfN(trans_prot)(phdr[i].p_flags);
-			error = __elfN(load_section)(imgp, phdr[i].p_offset,
-			    (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr,
-			    phdr[i].p_memsz, phdr[i].p_filesz, prot);
-			if (error != 0)
-				goto ret;
+	error = __elfN(load_sections)(imgp, hdr, phdr, et_dyn_addr, NULL);
+	if (error != 0)
+		goto ret;
 
-			/*
-			 * If this segment contains the program headers,
-			 * remember their virtual address for the AT_PHDR
-			 * aux entry. Static binaries don't usually include
-			 * a PT_PHDR entry.
-			 */
-			if (phdr[i].p_offset == 0 &&
-			    hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize
-				<= phdr[i].p_filesz)
-				proghdr = phdr[i].p_vaddr + hdr->e_phoff +
-				    et_dyn_addr;
-			break;
-		case PT_PHDR: 	/* Program header table info */
-			proghdr = phdr[i].p_vaddr + et_dyn_addr;
-			break;
-		default:
-			break;
-		}
-	}
-
 	error = __elfN(enforce_limits)(imgp, hdr, phdr, et_dyn_addr);
 	if (error != 0)
 		goto ret;
@@ -1253,7 +1261,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *i
 	 */
 	elf_auxargs = malloc(sizeof(Elf_Auxargs), M_TEMP, M_WAITOK);
 	elf_auxargs->execfd = -1;
-	elf_auxargs->phdr = proghdr;
+	elf_auxargs->phdr = proghdr + et_dyn_addr;
 	elf_auxargs->phent = hdr->e_phentsize;
 	elf_auxargs->phnum = hdr->e_phnum;
 	elf_auxargs->pagesz = PAGE_SIZE;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904091524.x39FOdPv023299>