Author: kib
Date: Tue Oct 20 13:34:41 2009
New Revision: 198284
URL: http://svn.freebsd.org/changeset/base/198284

Log:
  MFC r197934:
  Map PIE binaries at non-zero base address.
  
  MFC r198202:
  Honour non-zero mapbase for PIE binaries. Inform interpreter-less PIE
  binary about its relocbase.
  
  Approved by:  re (kensmith)

Modified:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/kern/imgact_elf.c

Modified: stable/8/sys/kern/imgact_elf.c
==============================================================================
--- stable/8/sys/kern/imgact_elf.c      Tue Oct 20 13:32:28 2009        
(r198283)
+++ stable/8/sys/kern/imgact_elf.c      Tue Oct 20 13:34:41 2009        
(r198284)
@@ -685,9 +685,9 @@ __CONCAT(exec_, __elfN(imgact))(struct i
        u_long text_size = 0, data_size = 0, total_size = 0;
        u_long text_addr = 0, data_addr = 0;
        u_long seg_size, seg_addr;
-       u_long addr, entry = 0, proghdr = 0;
+       u_long addr, baddr, et_dyn_addr, entry = 0, proghdr = 0;
        int32_t osrel = 0;
-       int error = 0, i;
+       int error = 0, i, n;
        const char *interp = NULL, *newinterp = NULL;
        Elf_Brandinfo *brand_info;
        char *path;
@@ -716,14 +716,22 @@ __CONCAT(exec_, __elfN(imgact))(struct i
        phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
        if (!aligned(phdr, Elf_Addr))
                return (ENOEXEC);
+       n = 0;
+       baddr = 0;
        for (i = 0; i < hdr->e_phnum; i++) {
+               if (phdr[i].p_type == PT_LOAD) {
+                       if (n == 0)
+                               baddr = phdr[i].p_vaddr;
+                       n++;
+                       continue;
+               }
                if (phdr[i].p_type == PT_INTERP) {
                        /* Path to interpreter */
                        if (phdr[i].p_filesz > MAXPATHLEN ||
                            phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE)
                                return (ENOEXEC);
                        interp = imgp->image_header + phdr[i].p_offset;
-                       break;
+                       continue;
                }
        }
 
@@ -733,9 +741,19 @@ __CONCAT(exec_, __elfN(imgact))(struct i
                    hdr->e_ident[EI_OSABI]);
                return (ENOEXEC);
        }
-       if (hdr->e_type == ET_DYN &&
-           (brand_info->flags & BI_CAN_EXEC_DYN) == 0)
-               return (ENOEXEC);
+       if (hdr->e_type == ET_DYN) {
+               if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
+                       return (ENOEXEC);
+               /*
+                * Honour the base load address from the dso if it is
+                * non-zero for some reason.
+                */
+               if (baddr == 0)
+                       et_dyn_addr = ET_DYN_LOAD_ADDR;
+               else
+                       et_dyn_addr = 0;
+       } else
+               et_dyn_addr = 0;
        sv = brand_info->sysvec;
        if (interp != NULL && brand_info->interp_newpath != NULL)
                newinterp = brand_info->interp_newpath;
@@ -783,7 +801,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 
                        if ((error = __elfN(load_section)(vmspace,
                            imgp->object, phdr[i].p_offset,
-                           (caddr_t)(uintptr_t)phdr[i].p_vaddr,
+                           (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr,
                            phdr[i].p_memsz, phdr[i].p_filesz, prot,
                            sv->sv_pagesize)) != 0)
                                return (error);
@@ -797,11 +815,12 @@ __CONCAT(exec_, __elfN(imgact))(struct i
                        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;
+                               proghdr = phdr[i].p_vaddr + hdr->e_phoff +
+                                   et_dyn_addr;
 
-                       seg_addr = trunc_page(phdr[i].p_vaddr);
+                       seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr);
                        seg_size = round_page(phdr[i].p_memsz +
-                           phdr[i].p_vaddr - seg_addr);
+                           phdr[i].p_vaddr + et_dyn_addr - seg_addr);
 
                        /*
                         * Is this .text or .data?  We can't use
@@ -823,7 +842,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
                            phdr[i].p_memsz)) {
                                text_size = seg_size;
                                text_addr = seg_addr;
-                               entry = (u_long)hdr->e_entry;
+                               entry = (u_long)hdr->e_entry + et_dyn_addr;
                        } else {
                                data_size = seg_size;
                                data_addr = seg_addr;
@@ -831,7 +850,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
                        total_size += seg_size;
                        break;
                case PT_PHDR:   /* Program header table info */
-                       proghdr = phdr[i].p_vaddr;
+                       proghdr = phdr[i].p_vaddr + et_dyn_addr;
                        break;
                default:
                        break;
@@ -903,7 +922,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
                        return (error);
                }
        } else
-               addr = 0;
+               addr = et_dyn_addr;
 
        /*
         * Construct auxargs table (used by the fixup routine)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to