qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
@ 2010-03-31 22:12 ` Richard Henderson
  2010-04-04 18:38 ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-03-31 22:12 UTC (permalink / raw)
  To: qemu-devel

I caught padzero not properly initializing the .bss segment
on a statically linked Alpha program.  Rather than a minimal
patch, replace the gross code with a single mmap+memset.

Share more code between load_elf_interp and load_elf_binary.

Legally, an ELF program need not have just a single .bss;
and PT_LOAD segment can have memsz > filesz.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  150 ++++++++++++++++++--------------------------------
 1 files changed, 54 insertions(+), 96 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4d3dd89..238e574 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1015,60 +1015,47 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
     return p;
 }
 
-static void set_brk(abi_ulong start, abi_ulong end)
-{
-	/* page-align the start and end addresses... */
-        start = HOST_PAGE_ALIGN(start);
-        end = HOST_PAGE_ALIGN(end);
-        if (end <= start)
-                return;
-        if(target_mmap(start, end - start,
-                       PROT_READ | PROT_WRITE | PROT_EXEC,
-                       MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
-	    perror("cannot mmap brk");
-	    exit(-1);
-	}
-}
-
-
-/* We need to explicitly zero any fractional pages after the data
-   section (i.e. bss).  This would contain the junk from the file that
-   should not be in memory. */
-static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
-{
-        abi_ulong nbyte;
-
-	if (elf_bss >= last_bss)
-		return;
-
-        /* XXX: this is really a hack : if the real host page size is
-           smaller than the target page size, some pages after the end
-           of the file may not be mapped. A better fix would be to
-           patch target_mmap(), but it is more complicated as the file
-           size must be known */
-        if (qemu_real_host_page_size < qemu_host_page_size) {
-            abi_ulong end_addr, end_addr1;
-            end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
-                ~(qemu_real_host_page_size - 1);
-            end_addr = HOST_PAGE_ALIGN(elf_bss);
-            if (end_addr1 < end_addr) {
-                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
-                     PROT_READ|PROT_WRITE|PROT_EXEC,
-                     MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-            }
+/* Map and zero the bss.  We need to explicitly zero any fractional pages
+   after the data section (i.e. bss).  */
+static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
+{
+    uintptr_t host_start, host_map_start, host_end;
+
+    last_bss = TARGET_PAGE_ALIGN(last_bss);
+
+    /* ??? There is confusion between qemu_real_host_page_size and
+       qemu_host_page_size here and elsewhere in target_mmap, which
+       may lead to the end of the data section mapping from the file
+       not being mapped.  At least there was an explicit test and
+       comment for that here, suggesting that "the file size must
+       be known".  The comment probably pre-dates the introduction
+       of the fstat system call in target_mmap which does in fact
+       find out the size.  What isn't clear is if the workaround
+       here is still actually needed.  For now, continue with it,
+       but merge it with the "normal" mmap that would allocate the bss.  */
+
+    host_start = (uintptr_t) g2h(elf_bss);
+    host_end = (uintptr_t) g2h(last_bss);
+    host_map_start = (host_start + qemu_real_host_page_size - 1);
+    host_map_start &= -qemu_real_host_page_size;
+
+    if (host_map_start < host_end) {
+        void *p = mmap((void *)host_map_start, host_end - host_map_start,
+                       prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+        if (p == MAP_FAILED) {
+            perror("cannot mmap brk");
+            exit(-1);
         }
 
-        nbyte = elf_bss & (qemu_host_page_size-1);
-        if (nbyte) {
-	    nbyte = qemu_host_page_size - nbyte;
-	    do {
-                /* FIXME - what to do if put_user() fails? */
-		put_user_u8(0, elf_bss);
-                elf_bss++;
-	    } while (--nbyte);
-        }
-}
+        /* Since we didn't use target_mmap, make sure to record
+           the validity of the pages with qemu.  */
+        page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
+    }
 
+    if (host_start < host_map_start) {
+        memset((void *)host_start, 0, host_map_start - host_start);
+    }
+}
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
@@ -1160,12 +1147,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	abi_ulong load_addr = 0;
 	int load_addr_set = 0;
 	int retval;
-	abi_ulong last_bss, elf_bss;
 	abi_ulong error;
 	int i;
 
-	elf_bss = 0;
-	last_bss = 0;
 	error = 0;
 
 #ifdef BSWAP_NEEDED
@@ -1238,7 +1222,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
 	    abi_ulong vaddr = 0;
-	    abi_ulong k;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
@@ -1266,40 +1249,17 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	      load_addr_set = 1;
 	    }
 
-	    /*
-	     * Find the end of the file  mapping for this phdr, and keep
-	     * track of the largest address we see for this.
-	     */
-	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
-	    if (k > elf_bss) elf_bss = k;
-
-	    /*
-	     * Do the same thing for the memory mapping - between
-	     * elf_bss and last_bss is the bss section.
-	     */
-	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
-	    if (k > last_bss) last_bss = k;
+            /* If the load segment requests extra zeros (e.g. bss), map it.  */
+            if (eppnt->p_filesz < eppnt->p_memsz) {
+                abi_ulong base = load_addr + eppnt->p_vaddr;
+                zero_bss(base + eppnt->p_filesz,
+                         base + eppnt->p_memsz, elf_prot);
+            }
 	  }
 
 	/* Now use mmap to map the library into memory. */
 
 	close(interpreter_fd);
-
-	/*
-	 * Now fill out the bss section.  First pad the last page up
-	 * to the page boundary, and then perform a mmap to make sure
-	 * that there are zeromapped pages up to and including the last
-	 * bss page.
-	 */
-	padzero(elf_bss, last_bss);
-	elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
-
-	/* Map the last of the bss segment */
-	if (last_bss > elf_bss) {
-            target_mmap(elf_bss, last_bss-elf_bss,
-                        PROT_READ|PROT_WRITE|PROT_EXEC,
-                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-	}
 	free(elf_phdata);
 
 	*interp_load_addr = load_addr;
@@ -1453,7 +1413,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
-    abi_ulong elf_bss, k, elf_brk;
+    abi_ulong k, elf_brk;
     int retval;
     char * elf_interpreter;
     abi_ulong elf_entry, interp_load_addr = 0;
@@ -1512,10 +1472,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 #endif
     elf_ppnt = elf_phdata;
 
-    elf_bss = 0;
     elf_brk = 0;
 
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1758,18 +1716,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         if (start_data < k)
             start_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if (k > elf_bss)
-            elf_bss = k;
         if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
             end_code = k;
         if (end_data < k)
             end_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) elf_brk = k;
+        if (k > elf_brk) {
+            elf_brk = TARGET_PAGE_ALIGN(k);
+        }
+
+        /* If the load segment requests extra zeros (e.g. bss), map it.  */
+        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
+            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
+            zero_bss(base + elf_ppnt->p_filesz,
+                     base + elf_ppnt->p_memsz, elf_prot);
+        }
     }
 
     elf_entry += load_bias;
-    elf_bss += load_bias;
     elf_brk += load_bias;
     start_code += load_bias;
     end_code += load_bias;
@@ -1824,12 +1788,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->end_data = end_data;
     info->start_stack = bprm->p;
 
-    /* Calling set_brk effectively mmaps the pages that we need for the bss and break
-       sections */
-    set_brk(elf_bss, elf_brk);
-
-    padzero(elf_bss, elf_brk);
-
 #if 0
     printf("(start_brk) %x\n" , info->start_brk);
     printf("(end_code) %x\n" , info->end_code);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
  2010-03-31 22:12 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
@ 2010-04-04 18:38 ` Richard Henderson
  2010-04-04 19:07 ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 18:38 UTC (permalink / raw)
  To: qemu-devel

... Well, sortof.  The Makefile bits are broken.
Patch to load the vdso into the running program to follow.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 Makefile                  |    3 +-
 pc-bios/Makefile          |    5 ++
 pc-bios/vdso-linux-x64.S  |  102 +++++++++++++++++++++++++++++++++++++++++++++
 pc-bios/vdso-linux-x64.ld |   81 +++++++++++++++++++++++++++++++++++
 pc-bios/vdso-linux-x64.so |  Bin 0 -> 7515 bytes
 5 files changed, 190 insertions(+), 1 deletions(-)
 create mode 100644 pc-bios/vdso-linux-x64.S
 create mode 100644 pc-bios/vdso-linux-x64.ld
 create mode 100755 pc-bios/vdso-linux-x64.so

diff --git a/Makefile b/Makefile
index a404fda..8e903ff 100644
--- a/Makefile
+++ b/Makefile
@@ -178,7 +178,8 @@ pxe-e1000.bin \
 pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
 bamboo.dtb petalogix-s3adsp1800.dtb \
-multiboot.bin linuxboot.bin
+multiboot.bin linuxboot.bin \
+vdso-linux-x64.so
 else
 BLOBS=
 endif
diff --git a/pc-bios/Makefile b/pc-bios/Makefile
index 315288d..70e2485 100644
--- a/pc-bios/Makefile
+++ b/pc-bios/Makefile
@@ -15,5 +15,10 @@ all: $(TARGETS)
 %.dtb: %.dts
 	dtc -I dts -O dtb -o $@ $<
 
+vdso-linux-x64.so: vdso-linux-x64.o vdso-linux-x64.ld
+	$(CC) -nostdlib -shared -Wl,-T,vdso-linux-x64.ld \
+	  -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=both \
+	  vdso-linux-x64.o -o $@
+
 clean:
 	rm -f $(TARGETS) *.o *~
diff --git a/pc-bios/vdso-linux-x64.S b/pc-bios/vdso-linux-x64.S
new file mode 100644
index 0000000..e7784c9
--- /dev/null
+++ b/pc-bios/vdso-linux-x64.S
@@ -0,0 +1,102 @@
+/*
+ *  x86-64 linux replacement vdso.
+ *
+ *  Copyright (c) 2010 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/unistd.h>
+
+	.globl	__vdso_clock_gettime
+	.type	__vdso_clock_gettime, @function
+	.balign	16
+	.cfi_startproc
+__vdso_clock_gettime:
+	mov	$__NR_clock_gettime, %eax
+	syscall
+	ret
+	.cfi_endproc
+	.size	__vdso_clock_gettime, . - __vdso_clock_gettime
+
+clock_gettime = __vdso_clock_gettime
+	.weak	clock_gettime
+
+
+	.globl	__vdso_gettimeofday
+	.type	__vdso_gettimeofday, @function
+	.balign	16
+	.cfi_startproc
+__vdso_gettimeofday:
+	mov	$__NR_gettimeofday, %eax
+	syscall
+	ret
+	.cfi_endproc
+	.size	__vdso_gettimeofday, . - __vdso_gettimeofday
+
+gettimeofday = __vdso_gettimeofday
+	.weak	gettimeofday
+
+
+	.globl	__vdso_getcpu
+	.type	__vdso_getcpu, @function
+	.balign	16
+	.cfi_startproc
+__vdso_getcpu:
+	/* ??? There is no syscall number for this allocated on x64.
+	   We can handle this several ways:
+
+	   (1) Invent a syscall number for use within qemu.
+               It should be easy enough to pick a number that
+               is well out of the way of the kernel numbers.
+
+           (2) Force the emulated cpu to support the rdtscp insn,
+	       and initialize the TSC_AUX value the appropriate value.
+
+	   (3) Pretend that we're always running on cpu 0.
+
+	   This last is the one that's implemented here, with the
+	   tiny bit of extra code to support rdtscp in place.  */
+
+	xor	%ecx, %ecx		/* rdtscp w/ tsc_aux = 0 */
+
+	/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
+	test	%rdi, %rdi
+	jz	1f
+	mov	%ecx, %eax
+	and	$0xfff, %eax
+	mov	%eax, (%rdi)
+
+	/* if (node != NULL) *node = (ecx >> 12); */
+1:	test	%rsi, %rsi
+	jz	2f
+	shr	$12, %ecx
+	mov	%ecx, (%rsi)
+
+2:	xor	%eax, %eax
+	ret
+	.cfi_endproc
+	.size	__vdso_getcpu, . - __vdso_getcpu
+
+getcpu = __vdso_getcpu
+	.weak	getcpu
+
+/* ??? Perhaps add elf notes.  E.g.
+
+   #include <linux/elfnote.h>
+   ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+   ELFNOTE_END
+
+   but what version number would we set for QEMU?  */
diff --git a/pc-bios/vdso-linux-x64.ld b/pc-bios/vdso-linux-x64.ld
new file mode 100644
index 0000000..d57d0e7
--- /dev/null
+++ b/pc-bios/vdso-linux-x64.ld
@@ -0,0 +1,81 @@
+/*
+ * Linker script for linux x64 replacement vdso.
+ *
+ *  Copyright (c) 2010 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+	local: *;
+	};
+}
+
+PHDRS {
+	phdr		PT_PHDR		FLAGS(4) PHDRS;
+	data		PT_LOAD		FLAGS(6) FILEHDR PHDRS;
+	text		PT_LOAD		FLAGS(5);
+	dynamic		PT_DYNAMIC	FLAGS(4);
+	note		PT_NOTE		FLAGS(4);
+	/* ??? Various versions of ld don't know PT_GNU_EH_FRAME. */
+	eh_frame_hdr	0x6474e550;
+}
+
+SECTIONS {
+	/* ??? We can't really prelink to any address without knowing
+	   something about the virtual memory space of the host, since
+	   that leaks over into the available memory space of the guest.  */
+	. = SIZEOF_HEADERS;
+
+	/* The following, including the FILEHDRS and PHDRS, are modified
+	   when we relocate the binary.  We want them to be initially
+	   writable for the relocation; we'll force them read-only after.  */
+	.dynamic	: { *(.dynamic) }	:data :dynamic
+	.dynsym		: { *(.dynsym) }	:data
+	.data		: {
+		/* There ought not be any real read-write data.
+		   But since we manipulated the segment layout,
+		   we have to put these sections somewhere.  */
+		*(.data*)
+		*(.sdata*)
+		*(.got.plt) *(.got)
+		*(.gnu.linkonce.d.*)
+		*(.bss*)
+		*(.dynbss*)
+		*(.gnu.linkonce.b.*)
+	}
+
+	. += 4096;
+	.hash		: { *(.hash) }		:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+	.note		: { *(.note*) }		:text :note
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }	:text :eh_frame_hdr
+	.eh_frame	: { *(.eh_frame) }	:text
+	.rodata		: { *(.rodata) }
+
+	. = ALIGN(0x100);
+	.text		: { *(.text*) }		:text	=0x90909090
+}
diff --git a/pc-bios/vdso-linux-x64.so b/pc-bios/vdso-linux-x64.so
new file mode 100755
index 0000000000000000000000000000000000000000..5ebf5959f9dac5065428148e7625f58c722e1cca
GIT binary patch
literal 7515
zcmeHMO>Z1U5Uus%*iM{y6Cwl{#0nW7EEvfVLXjZIcKj8xI3d_l!ezYij=dJ%U9iWI
z%^?^OD>4#Nj&MZWI6#g*@TnkV@(Xf7Z~z1s6b@K90872;dYhfeh7%G(Oxr!L>s3`x
zcTM-~sQUG>!gyOIBP>~YRwC&>#|)Wb$7F~@a#Z%{H7ENOMed0>XrOb2c-p!qcA6eE
zeD78^vQ9%3$wvhI+O=-n8;N(|CvA==(hoGodBw()L^o+QFg?c!AJlga>!k(uIa-LY
zMLGRLSVH?_^GhP_iS#=Vd5cEa74n?#Z-3Tn&}`fM5et-CCNrj2EDn2}TFw~mGrZsM
z_qywE*2ejV$>uIMO@7Yw=Ju~ZR<csIb-@APIXx=fBDOyH+#nuOK9}GhHv1%x#}4~s
zKa<KIlwa!#u`-|%?DN(?`b8Pkit!|QuD8f2y`&LHBalWQjX)ZKGy-V^(g>sxNF$I&
zAdNs8fiwdDs|X;S(WMo63*>s3&(UU7n9pH82KF6Vf#8t0fXy3+^O=!AHo&0|a2IF3
zc~!3WUcG#B^T!9?KVE%n;H&=rtLKBt*~@kD{R^d)nm@Nxn|s+`2*Pl&5|A{pHeV{P
zH*s^Xtjf}2b#?6txO)0OD1{SKGiUuH-cx!%jHvk!Ove7+`|OwfNFhC>mANg9y-oGI
zs~={WUP8VF1+f5!c}`5t$n~E(zYGQjCO+st_x8J=e$+R<aq`<tZ}#cD*^Fvu&uDvE
zaaysYxTMH_Gq0VI%vvtf+uhNLTnu=O1p#Ev2qO3=wcgU2<O|B()XH3sHvjWw`+J>2
zPy4l=M=nKk*`AHdgI`Z>*2Au?oyY1uB3m7ko4aBA7e9Az9T@!lns_Vgm9ThTF<f?7
zW~;PbEmjui#M6daDHg+`cnj54uUuRyJ3d@?%!OciWwBO`34TeuYAp=J3(Efda<LNl
z<&xS{5-$wa!f4R{z@=CFz@EW+Lt(y-h;@R({m8YEb99vdMQ)Y*l=)ZU4YPwkZ0OHC
z?BmMe7Q8?6oJ88GNmS@h#Qwv+=lz*4CLVQe4L$v^&rptN-PK$#{h41T4#7wZ_4IeF
z+k1Q`fnz?J$ow<yEu0i(R9p3?`!nB6JY<%<e-d9%J#yFNXR(pB5IO&3{GFBBX#?+7
z`X}@KeKa&=+(^%B19PJP-SYjkPx@maH~W8Q<0sD2(J&eRi{{Vu$vigkSi+y{mh?ew
zaP5%;9<%)RrDjsw$>-NR_GZ(a2c49&!01avP&t0CYy1Yby8n&nB`xx%>!xu{-oK$}
z(a7p(8~eCPpVg<u{n<q8IPN@WfIh3gO59Iz`}W3pOq}1-*avaGL%6Qvd}m|5#`&(s
z`BR+V+c;l}^ZSJBCeGhJ-yn}TX7qd`86TV*f#>^&_IYizI&blmZ*@+Beb?$72EV1P
z&QD&l{*&i33&tnURjSqx*E!df_@n2hhMzxiT>Oc`sgdD=e`<XE#j$CBdU&KT=1cs$
X=k`~OeHQ)A7f?*40=|k`eoXxZDW(!W

literal 0
HcmV?d00001

-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
  2010-03-31 22:12 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
  2010-04-04 18:38 ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
@ 2010-04-04 19:07 ` Richard Henderson
  2010-04-04 19:34 ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 19:07 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  594 +++++++++++++++++++++++++-------------------------
 1 files changed, 301 insertions(+), 293 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ead22fc..ab741fd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -35,18 +35,17 @@
  * These occupy the top three bytes.
  */
 enum {
-	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
-	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
-						 * (signal handling)
-						 */
-	MMAP_PAGE_ZERO =	0x0100000,
-	ADDR_COMPAT_LAYOUT =	0x0200000,
-	READ_IMPLIES_EXEC =	0x0400000,
-	ADDR_LIMIT_32BIT =	0x0800000,
-	SHORT_INODE =		0x1000000,
-	WHOLE_SECONDS =		0x2000000,
-	STICKY_TIMEOUTS	=	0x4000000,
-	ADDR_LIMIT_3GB = 	0x8000000,
+    ADDR_NO_RANDOMIZE = 0x0040000,	/* disable randomization of VA space */
+    FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to
+                                           descriptors (signal handling) */
+    MMAP_PAGE_ZERO =	0x0100000,
+    ADDR_COMPAT_LAYOUT = 0x0200000,
+    READ_IMPLIES_EXEC =	0x0400000,
+    ADDR_LIMIT_32BIT =	0x0800000,
+    SHORT_INODE =	0x1000000,
+    WHOLE_SECONDS =	0x2000000,
+    STICKY_TIMEOUTS =	0x4000000,
+    ADDR_LIMIT_3GB = 	0x8000000,
 };
 
 /*
@@ -56,30 +55,29 @@ enum {
  * conflict with error returns.
  */
 enum {
-	PER_LINUX =		0x0000,
-	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
-	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
-	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
-					 WHOLE_SECONDS | SHORT_INODE,
-	PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
-	PER_WYSEV386 =		0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
-	PER_BSD =		0x0006,
-	PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
-	PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_LINUX32 =		0x0008,
-	PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
-	PER_IRIX32 =		0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
-	PER_IRIXN32 =		0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
-	PER_IRIX64 =		0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
-	PER_RISCOS =		0x000c,
-	PER_SOLARIS =		0x000d | STICKY_TIMEOUTS,
-	PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
-	PER_HPUX =		0x0010,
-	PER_MASK =		0x00ff,
+    PER_LINUX =		0x0000,
+    PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
+    PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
+    PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_SCOSVR3 =	0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
+    PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+    PER_WYSEV386 =	0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
+    PER_BSD =		0x0006,
+    PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
+    PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_LINUX32 =	0x0008,
+    PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
+    PER_IRIX32 =	0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+    PER_IRIXN32 =	0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+    PER_IRIX64 =	0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+    PER_RISCOS =	0x000c,
+    PER_SOLARIS =	0x000d | STICKY_TIMEOUTS,
+    PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
+    PER_HPUX =		0x0010,
+    PER_MASK =		0x00ff,
 };
 
 /*
@@ -126,7 +124,7 @@ static const char *get_elf_platform(void)
 
 static uint32_t get_elf_hwcap(void)
 {
-  return thread_env->cpuid_features;
+    return thread_env->cpuid_features;
 }
 
 #ifdef TARGET_X86_64
@@ -201,7 +199,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_386
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->esp = infop->start_stack;
     regs->eip = infop->entry;
@@ -267,13 +266,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #endif
 #define ELF_ARCH	EM_ARM
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     abi_long stack = infop->start_stack;
     memset(regs, 0, sizeof(*regs));
     regs->ARM_cpsr = 0x10;
     if (infop->entry & 1)
-      regs->ARM_cpsr |= CPSR_T;
+        regs->ARM_cpsr |= CPSR_T;
     regs->ARM_pc = infop->entry & 0xfffffffe;
     regs->ARM_sp = infop->start_stack;
     /* FIXME - what to for failure of get_user()? */
@@ -317,26 +317,26 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 
 enum
 {
-  ARM_HWCAP_ARM_SWP       = 1 << 0,
-  ARM_HWCAP_ARM_HALF      = 1 << 1,
-  ARM_HWCAP_ARM_THUMB     = 1 << 2,
-  ARM_HWCAP_ARM_26BIT     = 1 << 3,
-  ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
-  ARM_HWCAP_ARM_FPA       = 1 << 5,
-  ARM_HWCAP_ARM_VFP       = 1 << 6,
-  ARM_HWCAP_ARM_EDSP      = 1 << 7,
-  ARM_HWCAP_ARM_JAVA      = 1 << 8,
-  ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
-  ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
-  ARM_HWCAP_ARM_NEON      = 1 << 11,
-  ARM_HWCAP_ARM_VFPv3     = 1 << 12,
-  ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
+    ARM_HWCAP_ARM_SWP       = 1 << 0,
+    ARM_HWCAP_ARM_HALF      = 1 << 1,
+    ARM_HWCAP_ARM_THUMB     = 1 << 2,
+    ARM_HWCAP_ARM_26BIT     = 1 << 3,
+    ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
+    ARM_HWCAP_ARM_FPA       = 1 << 5,
+    ARM_HWCAP_ARM_VFP       = 1 << 6,
+    ARM_HWCAP_ARM_EDSP      = 1 << 7,
+    ARM_HWCAP_ARM_JAVA      = 1 << 8,
+    ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
+    ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
+    ARM_HWCAP_ARM_NEON      = 1 << 11,
+    ARM_HWCAP_ARM_VFPv3     = 1 << 12,
+    ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
 };
 
-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
-                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
-                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
-                    | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
+#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF               \
+                   | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT      \
+                   | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP              \
+                   | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
 
 #endif
 
@@ -357,7 +357,8 @@ enum
 
 #define STACK_BIAS		2047
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
 #ifndef TARGET_ABI32
     regs->tstate = 0;
@@ -384,7 +385,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARC
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->psr = 0;
     regs->pc = infop->entry;
@@ -464,7 +466,7 @@ static uint32_t get_elf_hwcap(void)
 
     /* We don't have to be terribly complete here; the high points are
        Altivec/FP/SPE support.  Anything else is just a bonus.  */
-#define GET_FEATURE(flag, feature)              \
+#define GET_FEATURE(flag, feature)                                      \
     do {if (e->insns_flags & flag) features |= feature; } while(0)
     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
@@ -489,17 +491,17 @@ static uint32_t get_elf_hwcap(void)
  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  */
 #define DLINFO_ARCH_ITEMS       5
-#define ARCH_DLINFO                                                     \
-do {                                                                    \
-        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
-        /*                                                              \
-         * Now handle glibc compatibility.                              \
-         */                                                             \
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
- } while (0)
+#define ARCH_DLINFO                                     \
+    do {                                                \
+        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
+        /*                                              \
+         * Now handle glibc compatibility.              \
+         */                                             \
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+    } while (0)
 
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
@@ -559,7 +561,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #endif
 #define ELF_ARCH    EM_MIPS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->cp0_status = 2 << CP0St_KSU;
     regs->cp0_epc = infop->entry;
@@ -626,7 +629,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA	ELFDATA2MSB
 #define ELF_ARCH    EM_XILINX_MICROBLAZE
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->r1 = infop->start_stack;
@@ -647,11 +651,12 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_SH
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  /* Check other registers XXXXX */
-  regs->pc = infop->entry;
-  regs->regs[15] = infop->start_stack;
+    /* Check other registers XXXXX */
+    regs->pc = infop->entry;
+    regs->regs[15] = infop->start_stack;
 }
 
 /* See linux kernel: arch/sh/include/asm/elf.h.  */
@@ -669,7 +674,8 @@ enum {
     TARGET_REG_SYSCALL = 22
 };
 
-static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
+                                      const CPUState *env)
 {
     int i;
 
@@ -701,9 +707,10 @@ static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_CRIS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  regs->erp = infop->entry;
+    regs->erp = infop->entry;
 }
 
 #define ELF_EXEC_PAGESIZE        8192
@@ -721,9 +728,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_ARCH	EM_68K
 
 /* ??? Does this need to do anything?
-#define ELF_PLAT_INIT(_r) */
+   #define ELF_PLAT_INIT(_r) */
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->usp = infop->start_stack;
     regs->sr = 0;
@@ -773,7 +781,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA       ELFDATA2MSB
 #define ELF_ARCH       EM_ALPHA
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->ps = 8;
@@ -803,14 +812,14 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 struct exec
 {
-  unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
-  unsigned int a_text;   /* length of text, in bytes */
-  unsigned int a_data;   /* length of data, in bytes */
-  unsigned int a_bss;    /* length of uninitialized data area, in bytes */
-  unsigned int a_syms;   /* length of symbol table data in file, in bytes */
-  unsigned int a_entry;  /* start address */
-  unsigned int a_trsize; /* length of relocation info for text, in bytes */
-  unsigned int a_drsize; /* length of relocation info for data, in bytes */
+    unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
+    unsigned int a_text;   /* length of text, in bytes */
+    unsigned int a_data;   /* length of data, in bytes */
+    unsigned int a_bss;    /* length of uninitialized data area, in bytes */
+    unsigned int a_syms;   /* length of symbol table data in file, in bytes */
+    unsigned int a_entry;  /* start address */
+    unsigned int a_trsize; /* length of relocation info for text, in bytes */
+    unsigned int a_drsize; /* length of relocation info for data, in bytes */
 };
 
 
@@ -839,7 +848,7 @@ struct exec
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
-	memcpy(to, from, n);
+    memcpy(to, from, n);
 }
 
 static int load_aout_interp(void * exptr, int interp_fd);
@@ -847,7 +856,7 @@ static int load_aout_interp(void * exptr, int interp_fd);
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
-    bswap16s(&ehdr->e_type);			/* Object file type */
+    bswap16s(&ehdr->e_type);		/* Object file type */
     bswap16s(&ehdr->e_machine);		/* Architecture */
     bswap32s(&ehdr->e_version);		/* Object file version */
     bswaptls(&ehdr->e_entry);		/* Entry point virtual address */
@@ -855,16 +864,16 @@ static void bswap_ehdr(struct elfhdr *ehdr)
     bswaptls(&ehdr->e_shoff);		/* Section header table file offset */
     bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
     bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
-    bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
+    bswap16s(&ehdr->e_phentsize);	/* Program header table entry size */
     bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
-    bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
+    bswap16s(&ehdr->e_shentsize);	/* Section header table entry size */
     bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
-    bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
+    bswap16s(&ehdr->e_shstrndx);	/* Section header string table index */
 }
 
 static void bswap_phdr(struct elf_phdr *phdr)
 {
-    bswap32s(&phdr->p_type);			/* Segment type */
+    bswap32s(&phdr->p_type);		/* Segment type */
     bswaptls(&phdr->p_offset);		/* Segment file offset */
     bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
     bswaptls(&phdr->p_paddr);		/* Segment physical address */
@@ -936,7 +945,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 	while (*tmp++);
 	len = tmp - tmp1;
 	if (p < len) {  /* this shouldn't happen - 128kB */
-		return 0;
+            return 0;
 	}
 	while (len) {
 	    --p; --tmp; --len;
@@ -955,12 +964,12 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 	        *(pag + offset) = *tmp;
 	    }
 	    else {
-	      int bytes_to_copy = (len > offset) ? offset : len;
-	      tmp -= bytes_to_copy;
-	      p -= bytes_to_copy;
-	      offset -= bytes_to_copy;
-	      len -= bytes_to_copy;
-	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
+                int bytes_to_copy = (len > offset) ? offset : len;
+                tmp -= bytes_to_copy;
+                p -= bytes_to_copy;
+                offset -= bytes_to_copy;
+                len -= bytes_to_copy;
+                memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
 	    }
 	}
     }
@@ -1055,77 +1064,77 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    abi_ulong interp_load_addr, int ibcs,
                                    struct image_info *info)
 {
-        abi_ulong sp;
-        int size;
-        abi_ulong u_platform;
-        const char *k_platform;
-        const int n = sizeof(elf_addr_t);
-
-        sp = p;
-        u_platform = 0;
-        k_platform = ELF_PLATFORM;
-        if (k_platform) {
-            size_t len = strlen(k_platform) + 1;
-            sp -= (len + n - 1) & ~(n - 1);
-            u_platform = sp;
-            /* FIXME - check return value of memcpy_to_target() for failure */
-            memcpy_to_target(sp, k_platform, len);
-        }
-	/*
-	 * Force 16 byte _final_ alignment here for generality.
-	 */
-        sp = sp &~ (abi_ulong)15;
-        size = (DLINFO_ITEMS + 1) * 2;
-        if (k_platform)
-          size += 2;
+    abi_ulong sp;
+    int size;
+    abi_ulong u_platform;
+    const char *k_platform;
+    const int n = sizeof(elf_addr_t);
+
+    sp = p;
+    u_platform = 0;
+    k_platform = ELF_PLATFORM;
+    if (k_platform) {
+        size_t len = strlen(k_platform) + 1;
+        sp -= (len + n - 1) & ~(n - 1);
+        u_platform = sp;
+        /* FIXME - check return value of memcpy_to_target() for failure */
+        memcpy_to_target(sp, k_platform, len);
+    }
+    /*
+     * Force 16 byte _final_ alignment here for generality.
+     */
+    sp = sp &~ (abi_ulong)15;
+    size = (DLINFO_ITEMS + 1) * 2;
+    if (k_platform)
+        size += 2;
 #ifdef DLINFO_ARCH_ITEMS
-	size += DLINFO_ARCH_ITEMS * 2;
+    size += DLINFO_ARCH_ITEMS * 2;
 #endif
-        size += envc + argc + 2;
-	size += (!ibcs ? 3 : 1);	/* argc itself */
-        size *= n;
-        if (size & 15)
-            sp -= 16 - (size & 15);
-
-        /* This is correct because Linux defines
-         * elf_addr_t as Elf32_Off / Elf64_Off
-         */
+    size += envc + argc + 2;
+    size += (!ibcs ? 3 : 1);	/* argc itself */
+    size *= n;
+    if (size & 15)
+        sp -= 16 - (size & 15);
+
+    /* This is correct because Linux defines
+     * elf_addr_t as Elf32_Off / Elf64_Off
+     */
 #define NEW_AUX_ENT(id, val) do {		\
-            sp -= n; put_user_ual(val, sp);	\
-            sp -= n; put_user_ual(id, sp);	\
-          } while(0)
-
-        NEW_AUX_ENT (AT_NULL, 0);
-
-        /* There must be exactly DLINFO_ITEMS entries here.  */
-        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
-        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
-        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
-        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
-        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
-        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
-        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
-        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
-        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
-        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
-        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
-        if (k_platform)
-            NEW_AUX_ENT(AT_PLATFORM, u_platform);
+        sp -= n; put_user_ual(val, sp);         \
+        sp -= n; put_user_ual(id, sp);          \
+    } while(0)
+
+    NEW_AUX_ENT (AT_NULL, 0);
+
+    /* There must be exactly DLINFO_ITEMS entries here.  */
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
+    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+    if (k_platform)
+        NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-	/*
-	 * ARCH_DLINFO must come last so platform specific code can enforce
-	 * special alignment requirements on the AUXV if necessary (eg. PPC).
-	 */
-        ARCH_DLINFO;
+    /*
+     * ARCH_DLINFO must come last so platform specific code can enforce
+     * special alignment requirements on the AUXV if necessary (eg. PPC).
+     */
+    ARCH_DLINFO;
 #endif
 #undef NEW_AUX_ENT
 
-        info->saved_auxv = sp;
+    info->saved_auxv = sp;
 
-        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
-        return sp;
+    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    return sp;
 }
 
 
@@ -1133,83 +1142,83 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
                                  abi_ulong *interp_load_addr)
 {
-	struct elf_phdr *elf_phdata  =  NULL;
-	struct elf_phdr *eppnt;
-	abi_ulong load_addr = 0;
-	int load_addr_set = 0;
-	int retval;
-	abi_ulong error;
-	int i;
+    struct elf_phdr *elf_phdata  =  NULL;
+    struct elf_phdr *eppnt;
+    abi_ulong load_addr = 0;
+    int load_addr_set = 0;
+    int retval;
+    abi_ulong error;
+    int i;
 
-	error = 0;
+    error = 0;
 
 #ifdef BSWAP_NEEDED
-        bswap_ehdr(interp_elf_ex);
+    bswap_ehdr(interp_elf_ex);
 #endif
-	/* First of all, some simple consistency checks */
-	if ((interp_elf_ex->e_type != ET_EXEC &&
-             interp_elf_ex->e_type != ET_DYN) ||
-	   !elf_check_arch(interp_elf_ex->e_machine)) {
-		return ~((abi_ulong)0UL);
-	}
+    /* First of all, some simple consistency checks */
+    if ((interp_elf_ex->e_type != ET_EXEC &&
+         interp_elf_ex->e_type != ET_DYN) ||
+        !elf_check_arch(interp_elf_ex->e_machine)) {
+        return ~((abi_ulong)0UL);
+    }
 
 
-	/* Now read in all of the header information */
+    /* Now read in all of the header information */
 
-	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-	    return ~(abi_ulong)0UL;
+    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
+        return ~(abi_ulong)0UL;
 
-	elf_phdata =  (struct elf_phdr *)
-		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    elf_phdata =  (struct elf_phdr *)
+        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-	if (!elf_phdata)
-	  return ~((abi_ulong)0UL);
+    if (!elf_phdata)
+        return ~((abi_ulong)0UL);
 
-	/*
-	 * If the size of this structure has changed, then punt, since
-	 * we will be doing the wrong thing.
-	 */
-	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-	    free(elf_phdata);
-	    return ~((abi_ulong)0UL);
-        }
+    /*
+     * If the size of this structure has changed, then punt, since
+     * we will be doing the wrong thing.
+     */
+    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
+        free(elf_phdata);
+        return ~((abi_ulong)0UL);
+    }
 
-	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-	if(retval >= 0) {
-	    retval = read(interpreter_fd,
-			   (char *) elf_phdata,
-			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-	}
-	if (retval < 0) {
-		perror("load_elf_interp");
-		exit(-1);
-		free (elf_phdata);
-		return retval;
- 	}
+    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
+    if(retval >= 0) {
+        retval = read(interpreter_fd,
+                      (char *) elf_phdata,
+                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    }
+    if (retval < 0) {
+        perror("load_elf_interp");
+        exit(-1);
+        free (elf_phdata);
+        return retval;
+    }
 #ifdef BSWAP_NEEDED
-	eppnt = elf_phdata;
-	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-            bswap_phdr(eppnt);
-        }
+    eppnt = elf_phdata;
+    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+        bswap_phdr(eppnt);
+    }
 #endif
 
-        if (interp_elf_ex->e_type == ET_DYN) {
-            /* in order to avoid hardcoding the interpreter load
-               address in qemu, we allocate a big enough memory zone */
-            error = target_mmap(0, INTERP_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
-            if (error == -1) {
-                perror("mmap");
-                exit(-1);
-            }
-            load_addr = error;
-            load_addr_set = 1;
+    if (interp_elf_ex->e_type == ET_DYN) {
+        /* in order to avoid hardcoding the interpreter load
+           address in qemu, we allocate a big enough memory zone */
+        error = target_mmap(0, INTERP_MAP_SIZE,
+                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
+                            -1, 0);
+        if (error == -1) {
+            perror("mmap");
+            exit(-1);
         }
+        load_addr = error;
+        load_addr_set = 1;
+    }
 
-	eppnt = elf_phdata;
-	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
-	  if (eppnt->p_type == PT_LOAD) {
+    eppnt = elf_phdata;
+    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+        if (eppnt->p_type == PT_LOAD) {
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
 	    abi_ulong vaddr = 0;
@@ -1222,22 +1231,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	    	vaddr = eppnt->p_vaddr;
 	    }
 	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-		 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-		 elf_prot,
-		 elf_type,
-		 interpreter_fd,
-		 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
+                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
+                                elf_prot,
+                                elf_type,
+                                interpreter_fd,
+                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
 
 	    if (error == -1) {
-	      /* Real error */
-	      close(interpreter_fd);
-	      free(elf_phdata);
-	      return ~((abi_ulong)0UL);
+                /* Real error */
+                close(interpreter_fd);
+                free(elf_phdata);
+                return ~((abi_ulong)0UL);
 	    }
 
 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-	      load_addr = error;
-	      load_addr_set = 1;
+                load_addr = error;
+                load_addr_set = 1;
 	    }
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
@@ -1246,15 +1255,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 zero_bss(base + eppnt->p_filesz,
                          base + eppnt->p_memsz, elf_prot);
             }
-	  }
+        }
 
-	/* Now use mmap to map the library into memory. */
+    /* Now use mmap to map the library into memory. */
 
-	close(interpreter_fd);
-	free(elf_phdata);
+    close(interpreter_fd);
+    free(elf_phdata);
 
-	*interp_load_addr = load_addr;
-	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    *interp_load_addr = load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1356,8 +1365,8 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 #endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
-                syms[i].st_shndx >= SHN_LORESERVE ||
-                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            syms[i].st_shndx >= SHN_LORESERVE ||
+            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
             nsyms--;
             if (i < nsyms) {
                 syms[i] = syms[nsyms];
@@ -1425,8 +1434,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-       				(! elf_check_arch(elf_ex.e_machine))) {
-	    return -ENOEXEC;
+        (! elf_check_arch(elf_ex.e_machine))) {
+        return -ENOEXEC;
     }
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
@@ -1445,7 +1454,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
     if(retval > 0) {
 	retval = read(bprm->fd, (char *) elf_phdata,
-				elf_ex.e_phentsize * elf_ex.e_phnum);
+                      elf_ex.e_phentsize * elf_ex.e_phnum);
     }
 
     if (retval < 0) {
@@ -1513,7 +1522,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
 	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
 		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-	      ibcs2_interpreter = 1;
+                ibcs2_interpreter = 1;
 	    }
 
 #if 0
@@ -1559,8 +1568,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
 	/* Now figure out which format our binary is */
 	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-	    	(N_MAGIC(interp_ex) != QMAGIC)) {
-	  interpreter_type = INTERPRETER_ELF;
+            (N_MAGIC(interp_ex) != QMAGIC)) {
+            interpreter_type = INTERPRETER_ELF;
 	}
 
 	if (interp_elf_ex.e_ident[0] != 0x7f ||
@@ -1620,7 +1629,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
          * in that case set guest_base to corresponding address.
          */
         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-            i++, elf_ppnt++) {
+             i++, elf_ppnt++) {
             if (elf_ppnt->p_type != PT_LOAD)
                 continue;
             if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
@@ -1737,7 +1746,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	}
 	else if (interpreter_type & 2) {
 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-					    &interp_load_addr);
+                                        &interp_load_addr);
 	}
         reloc_func_desc = interp_load_addr;
 
@@ -1764,13 +1773,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->start_stack = bprm->p = elf_stack - 4;
 #endif
     bprm->p = create_elf_tables(bprm->p,
-		    bprm->argc,
-		    bprm->envc,
-                    &elf_ex,
-                    load_addr, load_bias,
-		    interp_load_addr,
-		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
-		    info);
+                                bprm->argc,
+                                bprm->envc,
+                                &elf_ex,
+                                load_addr, load_bias,
+                                interp_load_addr,
+                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
+                                info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
     info->end_code = end_code;
@@ -1790,12 +1799,12 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     if ( info->personality == PER_SVR4 )
     {
-	    /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-	       and some applications "depend" upon this behavior.
-	       Since we do not have the power to recompile these, we
-	       emulate the SVr4 behavior.  Sigh.  */
-	    mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                      MAP_FIXED | MAP_PRIVATE, -1, 0);
+        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+           and some applications "depend" upon this behavior.
+           Since we do not have the power to recompile these, we
+           emulate the SVr4 behavior.  Sigh.  */
+        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
     }
 
     info->entry = elf_entry;
@@ -1808,7 +1817,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 }
 
 #ifdef USE_ELF_CORE_DUMP
-
 /*
  * Definitions to generate Intel SVR4-like core files.
  * These mostly have the same names as the SVR4 types with "target_elf_"
@@ -1945,17 +1953,17 @@ struct mm_struct {
 static struct mm_struct *vma_init(void);
 static void vma_delete(struct mm_struct *);
 static int vma_add_mapping(struct mm_struct *, abi_ulong,
-    abi_ulong, abi_ulong);
+                           abi_ulong, abi_ulong);
 static int vma_get_mapping_count(const struct mm_struct *);
 static struct vm_area_struct *vma_first(const struct mm_struct *);
 static struct vm_area_struct *vma_next(struct vm_area_struct *);
 static abi_ulong vma_dump_size(const struct vm_area_struct *);
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags);
+                      unsigned long flags);
 
 static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
 static void fill_note(struct memelfnote *, const char *, int,
-    unsigned int, void *);
+                      unsigned int, void *);
 static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
 static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
 static void fill_auxv_note(struct memelfnote *, const TaskState *);
@@ -2035,7 +2043,7 @@ static void vma_delete(struct mm_struct *mm)
 }
 
 static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
-    abi_ulong end, abi_ulong flags)
+                           abi_ulong end, abi_ulong flags)
 {
     struct vm_area_struct *vma;
 
@@ -2104,7 +2112,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
 }
 
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags)
+                      unsigned long flags)
 {
     struct mm_struct *mm = (struct mm_struct *)priv;
 
@@ -2119,7 +2127,7 @@ static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
 }
 
 static void fill_note(struct memelfnote *note, const char *name, int type,
-    unsigned int sz, void *data)
+                      unsigned int sz, void *data)
 {
     unsigned int namesz;
 
@@ -2140,7 +2148,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
 }
 
 static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
-    uint32_t flags)
+                            uint32_t flags)
 {
     (void) memset(elf, 0, sizeof(*elf));
 
@@ -2186,7 +2194,7 @@ static size_t note_size(const struct memelfnote *note)
 }
 
 static void fill_prstatus(struct target_elf_prstatus *prstatus,
-    const TaskState *ts, int signr)
+                          const TaskState *ts, int signr)
 {
     (void) memset(prstatus, 0, sizeof (*prstatus));
     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@@ -2227,7 +2235,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strncpy(psinfo->pr_fname, base_filename,
-        sizeof(psinfo->pr_fname));
+                   sizeof(psinfo->pr_fname));
     free(base_filename);
     free(filename);
 
@@ -2276,7 +2284,7 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
  * Returns 0 in case of success, -1 otherwise (errno is set).
  */
 static int core_dump_filename(const TaskState *ts, char *buf,
-    size_t bufsize)
+                              size_t bufsize)
 {
     char timestamp[64];
     char *filename = NULL;
@@ -2288,16 +2296,16 @@ static int core_dump_filename(const TaskState *ts, char *buf,
 
     if (gettimeofday(&tv, NULL) < 0) {
         (void) fprintf(stderr, "unable to get current timestamp: %s",
-            strerror(errno));
+                       strerror(errno));
         return (-1);
     }
 
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
-        localtime_r(&tv.tv_sec, &tm));
+                    localtime_r(&tv.tv_sec, &tm));
     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
-        base_filename, timestamp, (int)getpid());
+                    base_filename, timestamp, (int)getpid());
     free(base_filename);
     free(filename);
 
@@ -2382,7 +2390,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
     fill_prstatus(&ets->prstatus, ts, 0);
     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
-        &ets->prstatus);
+              &ets->prstatus);
 
     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
 
@@ -2390,7 +2398,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
 }
 
 static int fill_note_info(struct elf_note_info *info,
-    long signr, const CPUState *env)
+                          long signr, const CPUState *env)
 {
 #define NUMNOTES 3
     CPUState *cpu = NULL;
@@ -2418,10 +2426,10 @@ static int fill_note_info(struct elf_note_info *info,
     fill_prstatus(info->prstatus, ts, signr);
     elf_core_copy_regs(&info->prstatus->pr_reg, env);
     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
-        sizeof (*info->prstatus), info->prstatus);
+              sizeof (*info->prstatus), info->prstatus);
     fill_psinfo(info->psinfo, ts);
     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
-        sizeof (*info->psinfo), info->psinfo);
+              sizeof (*info->psinfo), info->psinfo);
     fill_auxv_note(&info->notes[2], ts);
     info->numnote = 3;
 
@@ -2468,7 +2476,7 @@ static int write_note_info(struct elf_note_info *info, int fd)
 
     /* write prstatus for each thread */
     for (ets = info->thread_list.tqh_first; ets != NULL;
-        ets = ets->ets_link.tqe_next) {
+         ets = ets->ets_link.tqe_next) {
         if ((error = write_note(&ets->notes[0], fd)) != 0)
             return (error);
     }
@@ -2536,13 +2544,13 @@ static int elf_core_dump(int signr, const CPUState *env)
     errno = 0;
     getrlimit(RLIMIT_CORE, &dumpsize);
     if (dumpsize.rlim_cur == 0)
-       return 0;
+        return 0;
 
     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
         return (-errno);
 
     if ((fd = open(corefile, O_WRONLY | O_CREAT,
-        S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
         return (-errno);
 
     /*
@@ -2631,7 +2639,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         end = vma->vma_start + vma_dump_size(vma);
 
         for (addr = vma->vma_start; addr < end;
-            addr += TARGET_PAGE_SIZE) {
+             addr += TARGET_PAGE_SIZE) {
             char page[TARGET_PAGE_SIZE];
             int error;
 
@@ -2642,7 +2650,7 @@ static int elf_core_dump(int signr, const CPUState *env)
             error = copy_from_user(page, addr, sizeof (page));
             if (error != 0) {
                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
-                    addr);
+                               addr);
                 errno = -error;
                 goto out;
             }
@@ -2651,7 +2659,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         }
     }
 
-out:
+ out:
     free_note_info(&info);
     if (mm != NULL)
         vma_delete(mm);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (2 preceding siblings ...)
  2010-04-04 19:07 ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
@ 2010-04-04 19:34 ` Richard Henderson
  2010-04-04 19:35 ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 19:34 UTC (permalink / raw)
  To: qemu-devel

Define BPRM_BUF_SIZE to 4k and read that amount initially.  If the
data we want from the binary is in this buffer, use it instead of
reading from the file again.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c   |  105 ++++++++++++++++++++---------------------------
 linux-user/linuxload.c |   17 +++-----
 linux-user/qemu.h      |    7 +++-
 3 files changed, 58 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ab741fd..962f9ba 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1140,7 +1140,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
-                                 abi_ulong *interp_load_addr)
+                                 abi_ulong *interp_load_addr,
+                                 char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
     struct elf_phdr *eppnt;
@@ -1183,17 +1184,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(interpreter_fd,
-                      (char *) elf_phdata,
-                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    }
-    if (retval < 0) {
-        perror("load_elf_interp");
-        exit(-1);
-        free (elf_phdata);
-        return retval;
+    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
+    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    } else {
+        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        if (retval != i) {
+            perror("load_elf_interp");
+            exit(-1);
+        }
     }
 #ifdef BSWAP_NEEDED
     eppnt = elf_phdata;
@@ -1451,17 +1450,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	return -ENOMEM;
     }
 
-    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
-    if(retval > 0) {
-	retval = read(bprm->fd, (char *) elf_phdata,
-                      elf_ex.e_phentsize * elf_ex.e_phnum);
-    }
-
-    if (retval < 0) {
-	perror("load_elf_binary");
-	exit(-1);
-	free (elf_phdata);
-	return -errno;
+    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
+    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
+    } else {
+	retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
+        if (retval != i) {
+            perror("load_elf_binary");
+            exit(-1);
+        }
     }
 
 #ifdef BSWAP_NEEDED
@@ -1505,13 +1502,16 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 		return -ENOMEM;
 	    }
 
-	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
-	    if(retval >= 0) {
-		retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
-	    }
-	    if(retval < 0) {
-	 	perror("load_elf_binary2");
-		exit(-1);
+            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
+                       elf_ppnt->p_filesz);
+            } else {
+		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
+                               elf_ppnt->p_offset);
+                if (retval != elf_ppnt->p_filesz) {
+                    perror("load_elf_binary2");
+                    exit(-1);
+                }
 	    }
 
 	    /* If the program interpreter is one of these two,
@@ -1525,39 +1525,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 ibcs2_interpreter = 1;
 	    }
 
-#if 0
-	    printf("Using ELF interpreter %s\n", path(elf_interpreter));
-#endif
-	    if (retval >= 0) {
-		retval = open(path(elf_interpreter), O_RDONLY);
-		if(retval >= 0) {
-		    interpreter_fd = retval;
-		}
-		else {
-		    perror(elf_interpreter);
-		    exit(-1);
-		    /* retval = -errno; */
-		}
-	    }
+            retval = open(path(elf_interpreter), O_RDONLY);
+            if (retval < 0) {
+                perror(elf_interpreter);
+                exit(-1);
+            }
+            interpreter_fd = retval;
 
-	    if (retval >= 0) {
-		retval = lseek(interpreter_fd, 0, SEEK_SET);
-		if(retval >= 0) {
-		    retval = read(interpreter_fd,bprm->buf,128);
-		}
-	    }
-	    if (retval >= 0) {
-		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-		interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
-	    }
-	    if (retval < 0) {
+            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
+            if (retval < 0) {
 		perror("load_elf_binary3");
 		exit(-1);
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return retval;
 	    }
+            if (retval < BPRM_BUF_SIZE) {
+                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
+            }
+
+            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
 	}
 	elf_ppnt++;
     }
@@ -1746,7 +1731,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	}
 	else if (interpreter_type & 2) {
 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr);
+                                        &interp_load_addr, bprm->buf);
 	}
         reloc_func_desc = interp_load_addr;
 
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 2d778a2..f67ace5 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
 	}
     }
 
-    retval = lseek(bprm->fd, 0L, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(bprm->fd, bprm->buf, 128);
-    }
-    if(retval < 0) {
+    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
 	perror("prepare_binprm");
 	exit(-1);
-	/* return(-errno); */
     }
-    else {
-	return(retval);
+    if (retval < BPRM_BUF_SIZE) {
+        /* Make sure the rest of the loader won't read garbage.  */
+        memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
+    return retval;
 }
 
 /* Construct the envp and argv tables on the target stack.  */
@@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
     int i;
 
     bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
-    for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-            bprm->page[i] = NULL;
+    memset(bprm->page, 0, sizeof(bprm->page));
     retval = open(filename, O_RDONLY);
     if (retval < 0)
         return retval;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 47fc686..bcf07bf 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -31,6 +31,7 @@
  * task_struct fields in the kernel
  */
 struct image_info {
+        abi_ulong       load_bias;
         abi_ulong       load_addr;
         abi_ulong       start_code;
         abi_ulong       end_code;
@@ -143,12 +144,16 @@ extern unsigned long mmap_min_addr;
  */
 #define MAX_ARG_PAGES 33
 
+/* Read a good amount of data initially, to hopefully get all the 
+   program headers loaded.  */
+#define BPRM_BUF_SIZE  4096
+
 /*
  * This structure is used to hold the arguments that are
  * used when loading binaries.
  */
 struct linux_binprm {
-        char buf[128];
+        char buf[BPRM_BUF_SIZE] __attribute__((aligned));
         void *page[MAX_ARG_PAGES];
         abi_ulong p;
 	int fd;
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (3 preceding siblings ...)
  2010-04-04 19:34 ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
@ 2010-04-04 19:35 ` Richard Henderson
  2010-04-04 19:54 ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 19:35 UTC (permalink / raw)
  To: qemu-devel

Alpha is little-endian on Linux.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 962f9ba..5814702 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -778,7 +778,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == ELF_ARCH )
 
 #define ELF_CLASS      ELFCLASS64
-#define ELF_DATA       ELFDATA2MSB
+#define ELF_DATA       ELFDATA2LSB
 #define ELF_ARCH       EM_ALPHA
 
 static inline void init_thread(struct target_pt_regs *regs,
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (4 preceding siblings ...)
  2010-04-04 19:35 ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
@ 2010-04-04 19:54 ` Richard Henderson
  2010-04-04 21:16 ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 19:54 UTC (permalink / raw)
  To: qemu-devel

Remove ifdefs from code by defining empty inline functions
when byte swapping isn't needed.  Push loops over swapping
arrays of structures into the swapping functions.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  119 ++++++++++++++++++++------------------------------
 1 files changed, 48 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5814702..9cf1eeb 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -871,30 +871,36 @@ static void bswap_ehdr(struct elfhdr *ehdr)
     bswap16s(&ehdr->e_shstrndx);	/* Section header string table index */
 }
 
-static void bswap_phdr(struct elf_phdr *phdr)
+static void bswap_phdr(struct elf_phdr *phdr, int phnum)
 {
-    bswap32s(&phdr->p_type);		/* Segment type */
-    bswaptls(&phdr->p_offset);		/* Segment file offset */
-    bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
-    bswaptls(&phdr->p_paddr);		/* Segment physical address */
-    bswaptls(&phdr->p_filesz);		/* Segment size in file */
-    bswaptls(&phdr->p_memsz);		/* Segment size in memory */
-    bswap32s(&phdr->p_flags);		/* Segment flags */
-    bswaptls(&phdr->p_align);		/* Segment alignment */
+    int i;
+    for (i = 0; i < phnum; ++i, ++phdr) {
+        bswap32s(&phdr->p_type);	/* Segment type */
+        bswap32s(&phdr->p_flags);	/* Segment flags */
+        bswaptls(&phdr->p_offset);	/* Segment file offset */
+        bswaptls(&phdr->p_vaddr);	/* Segment virtual address */
+        bswaptls(&phdr->p_paddr);	/* Segment physical address */
+        bswaptls(&phdr->p_filesz);	/* Segment size in file */
+        bswaptls(&phdr->p_memsz);	/* Segment size in memory */
+        bswaptls(&phdr->p_align);	/* Segment alignment */
+    }
 }
 
-static void bswap_shdr(struct elf_shdr *shdr)
+static void bswap_shdr(struct elf_shdr *shdr, int shnum)
 {
-    bswap32s(&shdr->sh_name);
-    bswap32s(&shdr->sh_type);
-    bswaptls(&shdr->sh_flags);
-    bswaptls(&shdr->sh_addr);
-    bswaptls(&shdr->sh_offset);
-    bswaptls(&shdr->sh_size);
-    bswap32s(&shdr->sh_link);
-    bswap32s(&shdr->sh_info);
-    bswaptls(&shdr->sh_addralign);
-    bswaptls(&shdr->sh_entsize);
+    int i;
+    for (i = 0; i < shnum; ++i, ++shdr) {
+        bswap32s(&shdr->sh_name);
+        bswap32s(&shdr->sh_type);
+        bswaptls(&shdr->sh_flags);
+        bswaptls(&shdr->sh_addr);
+        bswaptls(&shdr->sh_offset);
+        bswaptls(&shdr->sh_size);
+        bswap32s(&shdr->sh_link);
+        bswap32s(&shdr->sh_info);
+        bswaptls(&shdr->sh_addralign);
+        bswaptls(&shdr->sh_entsize);
+    }
 }
 
 static void bswap_sym(struct elf_sym *sym)
@@ -904,20 +910,15 @@ static void bswap_sym(struct elf_sym *sym)
     bswaptls(&sym->st_size);
     bswap16s(&sym->st_shndx);
 }
+#else
+static inline void bswap_ehdr(struct elfhdr *ehdr) { }
+static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
+static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
+static inline void bswap_sym(struct elf_sym *sym) { }
 #endif
 
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
-
-#ifdef BSWAP_NEEDED
-static void bswap_note(struct elf_note *en)
-{
-    bswap32s(&en->n_namesz);
-    bswap32s(&en->n_descsz);
-    bswap32s(&en->n_type);
-}
-#endif /* BSWAP_NEEDED */
-
 #endif /* USE_ELF_CORE_DUMP */
 
 /*
@@ -1153,9 +1154,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
     error = 0;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(interp_elf_ex);
-#endif
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
          interp_elf_ex->e_type != ET_DYN) ||
@@ -1194,12 +1193,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             exit(-1);
         }
     }
-#ifdef BSWAP_NEEDED
-    eppnt = elf_phdata;
-    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-        bswap_phdr(eppnt);
-    }
-#endif
+    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
     if (interp_elf_ex->e_type == ET_DYN) {
         /* in order to avoid hardcoding the interpreter load
@@ -1323,9 +1317,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
     for (i = 0; i < hdr->e_shnum; i++) {
         if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
             return;
-#ifdef BSWAP_NEEDED
-        bswap_shdr(&sechdr);
-#endif
+        bswap_shdr(&sechdr, 1);
         if (sechdr.sh_type == SHT_SYMTAB) {
             symtab = sechdr;
             lseek(fd, hdr->e_shoff
@@ -1333,9 +1325,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
             if (read(fd, &strtab, sizeof(strtab))
                 != sizeof(strtab))
                 return;
-#ifdef BSWAP_NEEDED
-            bswap_shdr(&strtab);
-#endif
+            bswap_shdr(&strtab, 1);
             goto found;
         }
     }
@@ -1359,9 +1349,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 
     i = 0;
     while (i < nsyms) {
-#ifdef BSWAP_NEEDED
         bswap_sym(syms + i);
-#endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
             syms[i].st_shndx >= SHN_LORESERVE ||
@@ -1427,9 +1415,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-#ifdef BSWAP_NEEDED
     bswap_ehdr(&elf_ex);
-#endif
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
@@ -1460,17 +1446,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             exit(-1);
         }
     }
-
-#ifdef BSWAP_NEEDED
-    elf_ppnt = elf_phdata;
-    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
-        bswap_phdr(elf_ppnt);
-    }
-#endif
-    elf_ppnt = elf_phdata;
+    bswap_phdr(elf_phdata, elf_ex.e_phnum);
 
     elf_brk = 0;
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1479,6 +1457,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data = 0;
     interp_ex.a_info = 0;
 
+    elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
 	if (elf_ppnt->p_type == PT_INTERP) {
 	    if ( elf_interpreter != NULL )
@@ -1964,9 +1943,6 @@ static int write_note(struct memelfnote *, int);
 static int write_note_info(struct elf_note_info *, int);
 
 #ifdef BSWAP_NEEDED
-static void bswap_prstatus(struct target_elf_prstatus *);
-static void bswap_psinfo(struct target_elf_prpsinfo *);
-
 static void bswap_prstatus(struct target_elf_prstatus *prstatus)
 {
     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
@@ -1994,6 +1970,17 @@ static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
     psinfo->pr_sid = tswap32(psinfo->pr_sid);
 }
+
+static void bswap_note(struct elf_note *en)
+{
+    bswap32s(&en->n_namesz);
+    bswap32s(&en->n_descsz);
+    bswap32s(&en->n_type);
+}
+#else
+static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
+static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
+static inline void bswap_note(struct elf_note *en) { }
 #endif /* BSWAP_NEEDED */
 
 /*
@@ -2152,9 +2139,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
     elf->e_phentsize = sizeof(struct elf_phdr);
     elf->e_phnum = segs;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(elf);
-#endif
 }
 
 static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
@@ -2168,9 +2153,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
     phdr->p_flags = 0;
     phdr->p_align = 0;
 
-#ifdef BSWAP_NEEDED
-    bswap_phdr(phdr);
-#endif
+    bswap_phdr(phdr, 1);
 }
 
 static size_t note_size(const struct memelfnote *note)
@@ -2188,9 +2171,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus,
     prstatus->pr_pgrp = getpgrp();
     prstatus->pr_sid = getsid(0);
 
-#ifdef BSWAP_NEEDED
     bswap_prstatus(prstatus);
-#endif
 }
 
 static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
@@ -2224,9 +2205,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     free(base_filename);
     free(filename);
 
-#ifdef BSWAP_NEEDED
     bswap_psinfo(psinfo);
-#endif
     return (0);
 }
 
@@ -2351,9 +2330,7 @@ static int write_note(struct memelfnote *men, int fd)
     en.n_type = men->type;
     en.n_descsz = men->datasz;
 
-#ifdef BSWAP_NEEDED
     bswap_note(&en);
-#endif
 
     if (dump_write(fd, &en, sizeof(en)) != 0)
         return (-1);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (5 preceding siblings ...)
  2010-04-04 19:54 ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
@ 2010-04-04 21:16 ` Richard Henderson
  2010-04-04 22:04 ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 21:16 UTC (permalink / raw)
  To: qemu-devel

First, adjust load_symbols to accept a load_bias parameter.  At the same
time, read the entire section header table in one go, use pread instead
f lseek+read for the symbol and string tables, and properly free
allocated structures on error exit paths.

Second, adjust load_elf_interp to compute load_bias.  This requires
finding out the built-in load addresses.  Which allows us to honor a
pre-linked interpreter image when possible, and eliminate the hard-coded
INTERP_MAP_SIZE value.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  189 +++++++++++++++++++++++++++-----------------------
 1 files changed, 101 insertions(+), 88 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9cf1eeb..7e94fe3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -829,9 +829,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss space allocated to elf interpreter */
-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
-
 /* max code+data+bss+brk space allocated to ET_DYN executables */
 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
 
@@ -920,6 +917,7 @@ static inline void bswap_sym(struct elf_sym *sym) { }
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
@@ -1145,15 +1143,11 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
-    struct elf_phdr *eppnt;
-    abi_ulong load_addr = 0;
-    int load_addr_set = 0;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr;
     int retval;
     abi_ulong error;
     int i;
 
-    error = 0;
-
     bswap_ehdr(interp_elf_ex);
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
@@ -1162,7 +1156,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-
     /* Now read in all of the header information */
 
     if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
@@ -1195,41 +1188,56 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
     bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
+    /* Find the maximum size of the image and allocate an appropriate
+       amount of memory to handle that.  */
+    loaddr = -1, hiaddr = 0;
+    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
+        if (elf_phdata[i].p_type == PT_LOAD) {
+            abi_ulong a = elf_phdata[i].p_vaddr;
+            if (a < loaddr) {
+                loaddr = a;
+            }
+            a += elf_phdata[i].p_memsz;
+            if (a > hiaddr) {
+                hiaddr = a;
+            }
+        }
+    }
+
+    load_addr = loaddr;
     if (interp_elf_ex->e_type == ET_DYN) {
-        /* in order to avoid hardcoding the interpreter load
-           address in qemu, we allocate a big enough memory zone */
-        error = target_mmap(0, INTERP_MAP_SIZE,
-                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                            -1, 0);
-        if (error == -1) {
+        /* The image indicates that it can be loaded anywhere.  Find a
+           location that can hold the memory space required.  If the
+           image is pre-linked, LOADDR will be non-zero.  Since we do
+           not supply MAP_FIXED here we'll use that address if and
+           only if it remains available.  */
+        load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
+                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                                -1, 0);
+        if (load_addr == -1) {
             perror("mmap");
             exit(-1);
         }
-        load_addr = error;
-        load_addr_set = 1;
     }
+    load_bias = load_addr - loaddr;
 
-    eppnt = elf_phdata;
-    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
+        struct elf_phdr *eppnt = elf_phdata + i;
         if (eppnt->p_type == PT_LOAD) {
-	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+	    abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 	    int elf_prot = 0;
-	    abi_ulong vaddr = 0;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
-	    	elf_type |= MAP_FIXED;
-	    	vaddr = eppnt->p_vaddr;
-	    }
-	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-                                elf_prot,
-                                elf_type,
-                                interpreter_fd,
-                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
 
+            vaddr = load_bias + eppnt->p_vaddr;
+            vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
+            vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
+
+	    error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+                                elf_prot, MAP_PRIVATE | MAP_FIXED,
+                                interpreter_fd, eppnt->p_offset - vaddr_po);
 	    if (error == -1) {
                 /* Real error */
                 close(interpreter_fd);
@@ -1237,26 +1245,25 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 return ~((abi_ulong)0UL);
 	    }
 
-	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-                load_addr = error;
-                load_addr_set = 1;
-	    }
+            vaddr_ef = vaddr + eppnt->p_filesz;
+            vaddr_em = vaddr + eppnt->p_memsz;
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
-            if (eppnt->p_filesz < eppnt->p_memsz) {
-                abi_ulong base = load_addr + eppnt->p_vaddr;
-                zero_bss(base + eppnt->p_filesz,
-                         base + eppnt->p_memsz, elf_prot);
+            if (vaddr_ef < vaddr_em) {
+                zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
         }
+    }
 
-    /* Now use mmap to map the library into memory. */
+    if (qemu_log_enabled()) {
+	load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+    }
 
     close(interpreter_fd);
     free(elf_phdata);
 
     *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1305,82 +1312,87 @@ static int symcmp(const void *s0, const void *s1)
 }
 
 /* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd)
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 {
-    unsigned int i, nsyms;
-    struct elf_shdr sechdr, symtab, strtab;
+    int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
+    struct elf_shdr *shdr;
     char *strings;
     struct syminfo *s;
     struct elf_sym *syms;
 
-    lseek(fd, hdr->e_shoff, SEEK_SET);
-    for (i = 0; i < hdr->e_shnum; i++) {
-        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
-            return;
-        bswap_shdr(&sechdr, 1);
-        if (sechdr.sh_type == SHT_SYMTAB) {
-            symtab = sechdr;
-            lseek(fd, hdr->e_shoff
-                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
-            if (read(fd, &strtab, sizeof(strtab))
-                != sizeof(strtab))
-                return;
-            bswap_shdr(&strtab, 1);
+    shnum = hdr->e_shnum;
+    i = shnum * sizeof(struct elf_shdr);
+    shdr = (struct elf_shdr *)alloca(i);
+    if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+        return;
+    }
+
+    bswap_shdr(shdr, shnum);
+    for (i = 0; i < shnum; ++i) {
+        if (shdr[i].sh_type == SHT_SYMTAB) {
+            sym_idx = i;
+            str_idx = shdr[i].sh_link;
             goto found;
         }
     }
-    return; /* Shouldn't happen... */
+
+    /* There will be no symbol table if the file was stripped.  */
+    return;
 
  found:
-    /* Now know where the strtab and symtab are.  Snarf them. */
+    /* Now know where the strtab and symtab are.  Snarf them.  */
     s = malloc(sizeof(*s));
-    syms = malloc(symtab.sh_size);
-    if (!syms)
-        return;
-    s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_strtab)
+    if (!s) {
         return;
+    }
 
-    lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+    i = shdr[str_idx].sh_size;
+    s->disas_strtab = strings = malloc(i);
+    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
         return;
+    }
 
-    nsyms = symtab.sh_size / sizeof(struct elf_sym);
+    i = shdr[sym_idx].sh_size;
+    syms = malloc(i);
+    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
+        free(syms);
+        return;
+    }
 
-    i = 0;
-    while (i < nsyms) {
+    nsyms = i / sizeof(struct elf_sym);
+    for (i = 0; i < nsyms; ) {
         bswap_sym(syms + i);
-        // Throw away entries which we do not need.
-        if (syms[i].st_shndx == SHN_UNDEF ||
-            syms[i].st_shndx >= SHN_LORESERVE ||
-            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
-            nsyms--;
-            if (i < nsyms) {
+        /* Throw away entries which we do not need.  */
+        if (syms[i].st_shndx == SHN_UNDEF
+            || syms[i].st_shndx >= SHN_LORESERVE
+            || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            if (i < --nsyms) {
                 syms[i] = syms[nsyms];
             }
-            continue;
-        }
+        } else {
 #if defined(TARGET_ARM) || defined (TARGET_MIPS)
-        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
-        syms[i].st_value &= ~(target_ulong)1;
+            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
+            syms[i].st_value &= ~(target_ulong)1;
 #endif
-        i++;
+            syms[i].st_value += load_bias;
+            i++;
+        }
     }
-    syms = realloc(syms, nsyms * sizeof(*syms));
 
+    syms = realloc(syms, nsyms * sizeof(*syms));
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
-    lseek(fd, strtab.sh_offset, SEEK_SET);
-    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
-        return;
     s->disas_num_syms = nsyms;
 #if ELF_CLASS == ELFCLASS32
     s->disas_symtab.elf32 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #else
     s->disas_symtab.elf64 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #endif
+    s->lookup_symbol = lookup_symbolxx;
     s->next = syminfos;
     syminfos = s;
 }
@@ -1727,8 +1739,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     free(elf_phdata);
 
-    if (qemu_log_enabled())
-	load_symbols(&elf_ex, bprm->fd);
+    if (qemu_log_enabled()) {
+	load_symbols(&elf_ex, bprm->fd, load_bias);
+    }
 
     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (6 preceding siblings ...)
  2010-04-04 21:16 ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
@ 2010-04-04 22:04 ` Richard Henderson
  2010-04-04 22:14 ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 22:04 UTC (permalink / raw)
  To: qemu-devel

Validate more fields of the elf header.  Extract those checks
into two common functions to be used in both load_elf_interp
and load_elf_binary.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   57 +++++++++++++++++++++++++++++---------------------
 1 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7e94fe3..5853a30 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -919,6 +919,30 @@ static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
 static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
+/* Verify the portions of EHDR within E_IDENT for the target.
+   This can be performed before bswapping the entire header.  */
+static _Bool elf_check_ident(struct elfhdr *ehdr)
+{
+    return (ehdr->e_ident[EI_MAG0] == ELFMAG0
+            && ehdr->e_ident[EI_MAG1] == ELFMAG1
+            && ehdr->e_ident[EI_MAG2] == ELFMAG2
+            && ehdr->e_ident[EI_MAG3] == ELFMAG3
+            && ehdr->e_ident[EI_CLASS] == ELF_CLASS
+            && ehdr->e_ident[EI_DATA] == ELF_DATA
+            && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
+}
+
+/* Verify the portions of EHDR outside of E_IDENT for the target.
+   This has to wait until after bswapping the header.  */
+static _Bool elf_check_ehdr(struct elfhdr *ehdr)
+{
+    return (elf_check_arch(ehdr->e_machine)
+            && ehdr->e_ehsize == sizeof(struct elfhdr)
+            && ehdr->e_phentsize == sizeof(struct elf_phdr)
+            && ehdr->e_shentsize == sizeof(struct elf_shdr)
+            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
+}
+
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
  * memory to free pages in kernel mem. These are in a format ready
@@ -1149,33 +1173,16 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     int i;
 
     bswap_ehdr(interp_elf_ex);
-    /* First of all, some simple consistency checks */
-    if ((interp_elf_ex->e_type != ET_EXEC &&
-         interp_elf_ex->e_type != ET_DYN) ||
-        !elf_check_arch(interp_elf_ex->e_machine)) {
+    if (!elf_check_ehdr(interp_elf_ex)) {
         return ~((abi_ulong)0UL);
     }
 
     /* Now read in all of the header information */
-
-    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-        return ~(abi_ulong)0UL;
-
     elf_phdata =  (struct elf_phdr *)
         malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-
     if (!elf_phdata)
         return ~((abi_ulong)0UL);
 
-    /*
-     * If the size of this structure has changed, then punt, since
-     * we will be doing the wrong thing.
-     */
-    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-        free(elf_phdata);
-        return ~((abi_ulong)0UL);
-    }
-
     i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
     if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
         memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
@@ -1427,11 +1434,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-    bswap_ehdr(&elf_ex);
 
     /* First of all, some simple consistency checks */
-    if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-        (! elf_check_arch(elf_ex.e_machine))) {
+    if (!elf_check_ident(&elf_ex)) {
+        return -ENOEXEC;
+    }
+    bswap_ehdr(&elf_ex);
+    if (!elf_check_ehdr(&elf_ex)) {
         return -ENOEXEC;
     }
 
@@ -1443,7 +1452,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
+    elf_phdata = (struct elf_phdr *)
+        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
     if (elf_phdata == NULL) {
 	return -ENOMEM;
     }
@@ -1548,8 +1558,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             interpreter_type = INTERPRETER_ELF;
 	}
 
-	if (interp_elf_ex.e_ident[0] != 0x7f ||
-            strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
+        if (!elf_check_ident(&interp_elf_ex)) {
 	    interpreter_type &= ~INTERPRETER_ELF;
 	}
 
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (7 preceding siblings ...)
  2010-04-04 22:04 ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
@ 2010-04-04 22:14 ` Richard Henderson
  2010-04-04 22:31 ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 22:14 UTC (permalink / raw)
  To: qemu-devel

There are no supported stack-grows-up targets.  We were putting
the guard page at the highest address, i.e. the bottom of the stack.
Use the maximum of host and guest page size for the guard size.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   29 ++++++++++++++++-------------
 1 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5853a30..464160a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1002,28 +1002,31 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
                                  struct image_info *info)
 {
-    abi_ulong stack_base, size, error;
+    abi_ulong stack_base, size, error, guard;
     int i;
 
     /* Create enough stack to hold everything.  If we don't use
-     * it for args, we'll use it for something else...
-     */
+       it for args, we'll use it for something else.  */
     size = guest_stack_size;
-    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
-    error = target_mmap(0,
-                        size + qemu_host_page_size,
-                        PROT_READ | PROT_WRITE,
-                        MAP_PRIVATE | MAP_ANONYMOUS,
-                        -1, 0);
+    }
+    guard = TARGET_PAGE_SIZE;
+    if (guard < qemu_real_host_page_size) {
+        guard = qemu_real_host_page_size;
+    }
+
+    error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (error == -1) {
-        perror("stk mmap");
+        perror("mmap stack");
         exit(-1);
     }
-    /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
 
-    stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+    /* We reserve one extra page at the top of the stack as guard.  */
+    target_mprotect(error, guard, PROT_NONE);
+
+    stack_base = error + guard + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
     p += stack_base;
 
     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (8 preceding siblings ...)
  2010-04-04 22:14 ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
@ 2010-04-04 22:31 ` Richard Henderson
  2010-04-05  0:46 ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-04 22:31 UTC (permalink / raw)
  To: qemu-devel

At the bottom of the a.out support was the unimplemented load_aout_interp
function.  There were other portions of the support that didn't look
right; when I went to look in the Linux kernel for clarification, I found
that the support for such interpreters has been removed from binfmt_elf.
There doesn't seem to be any reason to keep this broken support in qemu.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   80 +++++--------------------------------------------
 1 files changed, 9 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 464160a..2f15b9c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -837,10 +837,6 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define INTERPRETER_NONE 0
-#define INTERPRETER_AOUT 1
-#define INTERPRETER_ELF 2
-
 #define DLINFO_ITEMS 12
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
@@ -848,8 +844,6 @@ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
     memcpy(to, from, n);
 }
 
-static int load_aout_interp(void * exptr, int interp_fd);
-
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
@@ -1087,7 +1081,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
                                    abi_ulong load_addr,
                                    abi_ulong load_bias,
-                                   abi_ulong interp_load_addr, int ibcs,
+                                   abi_ulong interp_load_addr,
                                    struct image_info *info)
 {
     abi_ulong sp;
@@ -1117,7 +1111,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
     size += envc + argc + 2;
-    size += (!ibcs ? 3 : 1);	/* argc itself */
+    size += 1;	/* argc itself */
     size *= n;
     if (size & 15)
         sp -= 16 - (size & 15);
@@ -1159,7 +1153,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
     info->saved_auxv = sp;
 
-    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    sp = loader_build_argptr(envc, argc, sp, p, 0);
     return sp;
 }
 
@@ -1412,11 +1406,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct elfhdr elf_ex;
     struct elfhdr interp_elf_ex;
-    struct exec interp_ex;
     int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned int interpreter_type = INTERPRETER_NONE;
     unsigned char ibcs2_interpreter;
     int i;
     abi_ulong mapped_addr;
@@ -1430,7 +1422,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong start_code, end_code, start_data, end_data;
     abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
-    char passed_fileno[6];
 
     ibcs2_interpreter = 0;
     status = 0;
@@ -1480,7 +1471,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_code = 0;
     start_data = 0;
     end_data = 0;
-    interp_ex.a_info = 0;
 
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
@@ -1545,59 +1535,22 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
             }
 
-            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf);
 	}
 	elf_ppnt++;
     }
 
     /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter){
-	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
-
-	/* Now figure out which format our binary is */
-	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-            (N_MAGIC(interp_ex) != QMAGIC)) {
-            interpreter_type = INTERPRETER_ELF;
-	}
-
+    if (elf_interpreter) {
         if (!elf_check_ident(&interp_elf_ex)) {
-	    interpreter_type &= ~INTERPRETER_ELF;
-	}
-
-	if (!interpreter_type) {
 	    free(elf_interpreter);
 	    free(elf_phdata);
 	    close(bprm->fd);
+            close(interpreter_fd);
 	    return -ELIBBAD;
 	}
     }
 
-    /* OK, we are done with that, now set up the arg stuff,
-       and then start this sucker up */
-
-    {
-	char * passed_p;
-
-	if (interpreter_type == INTERPRETER_AOUT) {
-	    snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
-	    passed_p = passed_fileno;
-
-	    if (elf_interpreter) {
-		bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
-		bprm->argc++;
-	    }
-	}
-	if (!bprm->p) {
-	    if (elf_interpreter) {
-	        free(elf_interpreter);
-	    }
-	    free (elf_phdata);
-	    close(bprm->fd);
-	    return -E2BIG;
-	}
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1729,16 +1682,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data += load_bias;
 
     if (elf_interpreter) {
-	if (interpreter_type & 1) {
-	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
-	}
-	else if (interpreter_type & 2) {
-	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr, bprm->buf);
-	}
+        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
+                                    &interp_load_addr, bprm->buf);
         reloc_func_desc = interp_load_addr;
-
-	close(interpreter_fd);
 	free(elf_interpreter);
 
 	if (elf_entry == ~((abi_ulong)0UL)) {
@@ -1755,7 +1701,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	load_symbols(&elf_ex, bprm->fd, load_bias);
     }
 
-    if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
+    close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
 #ifdef LOW_ELF_STACK
@@ -1767,7 +1713,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                                 &elf_ex,
                                 load_addr, load_bias,
                                 interp_load_addr,
-                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
                                 info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
@@ -2656,15 +2601,8 @@ static int elf_core_dump(int signr, const CPUState *env)
         return (-errno);
     return (0);
 }
-
 #endif /* USE_ELF_CORE_DUMP */
 
-static int load_aout_interp(void * exptr, int interp_fd)
-{
-    printf("a.out interpreter not yet supported\n");
-    return(0);
-}
-
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
     init_thread(regs, infop);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (9 preceding siblings ...)
  2010-04-04 22:31 ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
@ 2010-04-05  0:46 ` Richard Henderson
  2010-04-05  2:13 ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-05  0:46 UTC (permalink / raw)
  To: qemu-devel

Moving toward a single copy of the elf binary loading code.
Fill in the details of the loaded image into a struct image_info.

Adjust create_elf_tables to read from such structures instead
of from a collection of passed arguments.  Don't return error
values from load_elf_interp; always exit(-1) with a message to
stderr.  Collect elf_interpreter handling in load_elf_binary
to a common spot.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  341 ++++++++++++++++++++++++-------------------------
 1 files changed, 167 insertions(+), 174 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2f15b9c..c58387a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1078,11 +1078,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 }
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
-                                   struct elfhdr * exec,
-                                   abi_ulong load_addr,
-                                   abi_ulong load_bias,
-                                   abi_ulong interp_load_addr,
-                                   struct image_info *info)
+                                   struct elfhdr *exec,
+                                   struct image_info *info,
+                                   struct image_info *interp_info)
 {
     abi_ulong sp;
     int size;
@@ -1127,13 +1125,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT (AT_NULL, 0);
 
     /* There must be exactly DLINFO_ITEMS entries here.  */
-    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
@@ -1157,51 +1155,60 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
+/* Load an ELF image into the address space.
 
-static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
-                                 int interpreter_fd,
-                                 abi_ulong *interp_load_addr,
-                                 char bprm_buf[BPRM_BUF_SIZE])
+   IMAGE_NAME is the filename of the image, to use in error messages.
+   IMAGE_FD is the open file descriptor for the image.
+
+   BUFPAGE is a copy of the first page of the file; this of course
+   contains the elf file header at offset 0.  It is assumed that this
+   buffer is sufficiently aligned to present no problems to the host
+   in accessing data at aligned offsets within the buffer.
+
+   On return: INFO values will be filled in, as necessary or available.  */
+
+static void load_elf_image(const char *image_name, int image_fd,
+                           struct image_info *info,
+                           char bprm_buf[BPRM_BUF_SIZE])
 {
-    struct elf_phdr *elf_phdata  =  NULL;
-    abi_ulong load_addr, load_bias, loaddr, hiaddr;
-    int retval;
-    abi_ulong error;
-    int i;
+    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+    struct elf_phdr *phdr;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+    int i, retval;
+    const char *errmsg;
 
-    bswap_ehdr(interp_elf_ex);
-    if (!elf_check_ehdr(interp_elf_ex)) {
-        return ~((abi_ulong)0UL);
+    /* First of all, some simple consistency checks */
+    errmsg = "Invalid ELF image for this architecture";
+    if (!elf_check_ident(ehdr)) {
+        goto exit_errmsg;
+    }
+    bswap_ehdr(ehdr);
+    if (!elf_check_ehdr(ehdr)) {
+        goto exit_errmsg;
     }
 
-    /* Now read in all of the header information */
-    elf_phdata =  (struct elf_phdr *)
-        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    if (!elf_phdata)
-        return ~((abi_ulong)0UL);
-
-    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
-    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    i = ehdr->e_phnum * sizeof(struct elf_phdr);
+    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
+        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
     } else {
-        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        phdr = (struct elf_phdr *) alloca(i);
+        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
         if (retval != i) {
-            perror("load_elf_interp");
-            exit(-1);
+            goto exit_read;
         }
     }
-    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
+    bswap_phdr(phdr, ehdr->e_phnum);
 
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
-    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
-        if (elf_phdata[i].p_type == PT_LOAD) {
-            abi_ulong a = elf_phdata[i].p_vaddr;
+    for (i = 0; i < ehdr->e_phnum; ++i) {
+        if (phdr[i].p_type == PT_LOAD) {
+            abi_ulong a = phdr[i].p_vaddr;
             if (a < loaddr) {
                 loaddr = a;
             }
-            a += elf_phdata[i].p_memsz;
+            a += phdr[i].p_memsz;
             if (a > hiaddr) {
                 hiaddr = a;
             }
@@ -1209,7 +1216,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
 
     load_addr = loaddr;
-    if (interp_elf_ex->e_type == ET_DYN) {
+    if (ehdr->e_type == ET_DYN) {
         /* The image indicates that it can be loaded anywhere.  Find a
            location that can hold the memory space required.  If the
            image is pre-linked, LOADDR will be non-zero.  Since we do
@@ -1219,14 +1226,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
                                 -1, 0);
         if (load_addr == -1) {
-            perror("mmap");
-            exit(-1);
+            goto exit_perror;
         }
     }
     load_bias = load_addr - loaddr;
 
-    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
-        struct elf_phdr *eppnt = elf_phdata + i;
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = ehdr->e_entry + load_bias;
+    info->start_code = -1;
+    info->end_code = 0;
+    info->start_data = -1;
+    info->end_data = 0;
+    info->brk = 0;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+        struct elf_phdr *eppnt = phdr + i;
         if (eppnt->p_type == PT_LOAD) {
 	    abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 	    int elf_prot = 0;
@@ -1241,12 +1256,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
 	    error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
                                 elf_prot, MAP_PRIVATE | MAP_FIXED,
-                                interpreter_fd, eppnt->p_offset - vaddr_po);
+                                image_fd, eppnt->p_offset - vaddr_po);
 	    if (error == -1) {
-                /* Real error */
-                close(interpreter_fd);
-                free(elf_phdata);
-                return ~((abi_ulong)0UL);
+                goto exit_perror;
 	    }
 
             vaddr_ef = vaddr + eppnt->p_filesz;
@@ -1256,18 +1268,79 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (vaddr_ef < vaddr_em) {
                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
+
+            /* Find the full program boundaries.  */
+            if (elf_prot & PROT_EXEC) {
+                if (vaddr < info->start_code) {
+                    info->start_code = vaddr;
+                }
+                if (vaddr_ef > info->end_code) {
+                    info->end_code = vaddr_ef;
+                }
+            }
+            if (elf_prot & PROT_WRITE) {
+                if (vaddr < info->start_data) {
+                    info->start_data = vaddr;
+                }
+                if (vaddr_ef > info->end_data) {
+                    info->end_data = vaddr_ef;
+                }
+                if (vaddr_em > info->brk) {
+                    info->brk = vaddr_em;
+                }
+            }
         }
     }
 
+    if (info->end_data == 0) {
+        info->start_data = info->end_code;
+        info->end_data = info->end_code;
+        info->brk = info->end_code;
+    }
+
     if (qemu_log_enabled()) {
-	load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+	load_symbols(ehdr, image_fd, load_bias);
     }
 
-    close(interpreter_fd);
-    free(elf_phdata);
+    close(image_fd);
+    return;
+
+ exit_read:
+    if (retval >= 0) {
+        errmsg = "Incomplete read of file header";
+        goto exit_errmsg;
+    }
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", image_name, errmsg);
+    exit(-1);
+}
+
+static void load_elf_interp(const char *filename, struct image_info *info,
+                            char bprm_buf[BPRM_BUF_SIZE])
+{
+    int fd, retval;
+
+    fd = open(path(filename), O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
 
-    *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(filename, fd, info, bprm_buf);
+    return;
+
+ exit_perror:
+    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+    exit(-1);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1404,26 +1477,21 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
+    struct image_info interp_info;
     struct elfhdr elf_ex;
-    struct elfhdr interp_elf_ex;
-    int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned char ibcs2_interpreter;
     int i;
-    abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
     abi_ulong k, elf_brk;
     int retval;
-    char * elf_interpreter;
-    abi_ulong elf_entry, interp_load_addr = 0;
+    char *elf_interpreter = NULL;
+    abi_ulong elf_entry;
     int status;
     abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
 
-    ibcs2_interpreter = 0;
     status = 0;
     load_addr = 0;
     load_bias = 0;
@@ -1466,7 +1534,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     elf_brk = 0;
     elf_stack = ~((abi_ulong)0UL);
-    elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
     end_code = 0;
     start_data = 0;
@@ -1475,82 +1542,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
 	if (elf_ppnt->p_type == PT_INTERP) {
-	    if ( elf_interpreter != NULL )
-	    {
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return -EINVAL;
-	    }
-
-	    /* This is the program interpreter used for
-	     * shared libraries - for now assume that this
-	     * is an a.out format binary
-	     */
-
-	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-	    if (elf_interpreter == NULL) {
-		free (elf_phdata);
-		close(bprm->fd);
-		return -ENOMEM;
-	    }
-
             if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
-                       elf_ppnt->p_filesz);
+                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
             } else {
+                elf_interpreter = alloca(elf_ppnt->p_filesz);
 		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
                                elf_ppnt->p_offset);
                 if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary2");
+                    perror("load_elf_binary");
                     exit(-1);
                 }
 	    }
-
-	    /* If the program interpreter is one of these two,
-	       then assume an iBCS2 image. Otherwise assume
-	       a native linux image. */
-
-	    /* JRP - Need to add X86 lib dir stuff here... */
-
-	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-                ibcs2_interpreter = 1;
-	    }
-
-            retval = open(path(elf_interpreter), O_RDONLY);
-            if (retval < 0) {
-                perror(elf_interpreter);
-                exit(-1);
-            }
-            interpreter_fd = retval;
-
-            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
-            if (retval < 0) {
-		perror("load_elf_binary3");
-		exit(-1);
-	    }
-            if (retval < BPRM_BUF_SIZE) {
-                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
-            }
-
-            interp_elf_ex = *((struct elfhdr *) bprm->buf);
 	}
 	elf_ppnt++;
     }
 
-    /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter) {
-        if (!elf_check_ident(&interp_elf_ex)) {
-	    free(elf_interpreter);
-	    free(elf_phdata);
-	    close(bprm->fd);
-            close(interpreter_fd);
-	    return -ELIBBAD;
-	}
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1648,7 +1654,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
-                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1681,19 +1686,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     start_data += load_bias;
     end_data += load_bias;
 
-    if (elf_interpreter) {
-        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                    &interp_load_addr, bprm->buf);
-        reloc_func_desc = interp_load_addr;
-	free(elf_interpreter);
-
-	if (elf_entry == ~((abi_ulong)0UL)) {
-	    printf("Unable to load interpreter\n");
-	    free(elf_phdata);
-	    exit(-1);
-	    return 0;
-	}
-    }
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = elf_entry;
+    info->start_brk = info->brk = elf_brk;
+    info->end_code = end_code;
+    info->start_code = start_code;
+    info->start_data = start_data;
+    info->end_data = end_data;
+    info->personality = PER_LINUX;
 
     free(elf_phdata);
 
@@ -1702,46 +1703,38 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     close(bprm->fd);
-    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
-#ifdef LOW_ELF_STACK
-    info->start_stack = bprm->p = elf_stack - 4;
-#endif
-    bprm->p = create_elf_tables(bprm->p,
-                                bprm->argc,
-                                bprm->envc,
-                                &elf_ex,
-                                load_addr, load_bias,
-                                interp_load_addr,
-                                info);
-    info->load_addr = reloc_func_desc;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->start_stack = bprm->p;
+    if (elf_interpreter) {
+        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
 
-#if 0
-    printf("(start_brk) %x\n" , info->start_brk);
-    printf("(end_code) %x\n" , info->end_code);
-    printf("(start_code) %x\n" , info->start_code);
-    printf("(end_data) %x\n" , info->end_data);
-    printf("(start_stack) %x\n" , info->start_stack);
-    printf("(brk) %x\n" , info->brk);
-#endif
+        /* If the program interpreter is one of these two, then assume
+           an iBCS2 image.  Otherwise assume a native linux image.  */
 
-    if ( info->personality == PER_SVR4 )
-    {
-        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-           and some applications "depend" upon this behavior.
-           Since we do not have the power to recompile these, we
-           emulate the SVr4 behavior.  Sigh.  */
-        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
+        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
+            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
+            info->personality = PER_SVR4;
+
+            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+               and some applications "depend" upon this behavior.  Since
+               we do not have the power to recompile these, we emulate
+               the SVr4 behavior.  Sigh.  */
+            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                        MAP_FIXED | MAP_PRIVATE, -1, 0);
+        }
     }
 
-    info->entry = elf_entry;
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+                                info, (elf_interpreter ? &interp_info : NULL));
+    info->start_stack = bprm->p;
+
+    /* If we have an interpreter, set that as the program's entry point.
+       Copy the load_addr as well, to help PPC64 interpret the entry
+       point as a function descriptor.  Do this after creating elf tables
+       so that we copy the original program entry point into the AUXV.  */
+    if (elf_interpreter) {
+        info->load_addr = interp_info.load_addr;
+        info->entry = interp_info.entry;
+    }
 
 #ifdef USE_ELF_CORE_DUMP
     bprm->core_dump = &elf_core_dump;
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (10 preceding siblings ...)
  2010-04-05  0:46 ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
@ 2010-04-05  2:13 ` Richard Henderson
  2010-04-05 16:26 ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-05  2:13 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  201 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 193 insertions(+), 8 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 100efdc..7b854e2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -183,6 +183,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
 }
 
+#define VDSO_BASENAME  "vdso-linux-x64.so"
+
 #else
 
 #define ELF_START_MMAP 0x80000000
@@ -801,6 +803,10 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define ELF_HWCAP 0
 #endif
 
+#ifndef VDSO_BASENAME
+#define VDSO_BASENAME NULL
+#endif
+
 #ifdef TARGET_ABI32
 #undef ELF_CLASS
 #define ELF_CLASS ELFCLASS32
@@ -1077,7 +1083,8 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr *exec,
                                    struct image_info *info,
-                                   struct image_info *interp_info)
+                                   struct image_info *interp_info,
+                                   struct image_info *vdso_info)
 {
     abi_ulong sp;
     int size;
@@ -1100,16 +1107,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
      */
     sp = sp &~ (abi_ulong)15;
     size = (DLINFO_ITEMS + 1) * 2;
-    if (k_platform)
+    if (k_platform) {
         size += 2;
+    }
+    if (vdso_info) {
+        size += 4;
+    }
 #ifdef DLINFO_ARCH_ITEMS
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
     size += envc + argc + 2;
     size += 1;	/* argc itself */
     size *= n;
-    if (size & 15)
+    if (size & 15) {
         sp -= 16 - (size & 15);
+    }
 
     /* This is correct because Linux defines
      * elf_addr_t as Elf32_Off / Elf64_Off
@@ -1126,7 +1138,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
+    if (interp_info) {
+        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
+    }
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
     NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
@@ -1135,8 +1149,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
-    if (k_platform)
+    if (k_platform) {
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
+    }
+    if (vdso_info) {
+        NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);
+        NEW_AUX_ENT(AT_SYSINFO_EHDR, vdso_info->load_addr);
+    }
 #ifdef ARCH_DLINFO
     /*
      * ARCH_DLINFO must come last so platform specific code can enforce
@@ -1378,6 +1397,165 @@ static void load_elf_interp(const char *filename, struct image_info *info,
     exit(-1);
 }
 
+static void load_elf_vdso(const char *basename, struct image_info *info,
+                          char bprm_buf[BPRM_BUF_SIZE])
+{
+    const char *errmsg;
+    char *filename;
+    int fd, retval, i;
+    abi_ulong load_bias;
+
+    /* ??? What we really need access to is qemu_find_file, but that is
+       only built for system targets at the moment.  */
+    filename = alloca(strlen(CONFIG_QEMU_SHAREDIR "/") + strlen(basename) + 1);
+    stpcpy(stpcpy(filename, CONFIG_QEMU_SHAREDIR "/"), basename);
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
+
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(basename, fd, info, NULL, bprm_buf);
+    load_bias = info->load_bias;
+
+    /* We most likely need to relocate the VDSO image.  The one built into
+       the kernel is built for a fixed address.  The one built for QEMU is
+       not, since that requires close control of the guest address space.  */
+    if (load_bias) {
+        struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+        struct elf_phdr *phdr;
+        abi_ulong dynamic_addr = -1;
+        abi_ulong dynsym_addr = -1;
+
+        /* ??? Assume QEMU's VDSO is built "properly", which arranges
+           for the PHDRs, and all the sections manipulated below, to
+           be included with a writable load segment.  */
+
+        /* ??? One might think that we'd need to relocate ehdr.e_entry,
+           but for some reason glibc does that one itself, though that
+           is also available via the AT_SYSINFO entry.  */
+
+        /* Relocate the program headers.  */
+        phdr = (struct elf_phdr *)g2h(info->load_addr + ehdr->e_phoff); 
+        bswap_phdr(phdr, ehdr->e_phnum);
+        for (i = 0; i < ehdr->e_phnum; ++i) {
+            phdr[i].p_vaddr += load_bias;
+            phdr[i].p_paddr += load_bias;
+            if (phdr[i].p_type == PT_DYNAMIC) {
+                dynamic_addr = phdr[i].p_vaddr;
+            }
+        }
+        bswap_phdr(phdr, ehdr->e_phnum);
+
+        /* Relocate the DYNAMIC entries.  */
+        if (dynamic_addr != -1) {
+            abi_ulong tag, val, *dyn = (abi_ulong *)g2h(dynamic_addr);
+            do {
+                tag = tswapl(dyn[0]);
+                val = tswapl(dyn[1]);
+                switch (tag) {
+                case DT_SYMTAB:
+                    dynsym_addr = load_bias + val;
+                    dyn[1] = tswapl(dynsym_addr);
+                    break;
+                case DT_SYMENT:
+                    if (val != sizeof(struct elf_sym)) {
+                        errmsg = "VDSO has an unexpected dynamic symbol size";
+                        goto exit_errmsg;
+                    }
+                    break;
+
+                case DT_HASH:
+                case DT_STRTAB:
+                case DT_VERDEF:
+                case DT_VERSYM:
+                case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+                    /* These entries store an address in the entry.  */
+                    dyn[1] = tswapl(load_bias + val);
+                    break;
+
+                case DT_NULL:
+                case DT_STRSZ:
+                case DT_SONAME:
+                case DT_DEBUG:
+                case DT_FLAGS:
+                case DT_FLAGS_1:
+                case DT_VERDEFNUM:
+                case DT_VALRNGLO ... DT_VALRNGHI:
+                    /* These entries store an integer in the entry.  */
+                    break;
+
+                case DT_REL:
+                case DT_RELA:
+                    /* These entries indicate that the VDSO was built
+                       incorrectly.  It should not have real relocations.  */
+                    errmsg = "VDSO has relocations";
+                    goto exit_errmsg;
+                case DT_NEEDED:
+                case DT_VERNEED:
+                    errmsg = "VDSO has external dependancies";
+                    goto exit_errmsg;
+
+                default:
+                    /* This is probably something target specific.  */
+                    errmsg = "VDSO has unknown DYNAMIC entry";
+                    goto exit_errmsg;
+                }
+                dyn += 2;
+            } while (tag != DT_NULL);
+        }
+
+        /* Relocate the dynamic symbol table.  */
+        if (dynsym_addr != -1) {
+            struct elf_shdr *shdr;
+            struct elf_sym *sym;
+            int dynsym_size = 0;
+
+            /* Read the section headers to find out the size of the
+               dynamic symbol table.  */
+            shdr = (struct elf_shdr *)g2h(info->load_addr + ehdr->e_shoff);
+            for (i = 0; i < ehdr->e_shnum; ++i) {
+                abi_ulong addr = tswapl(shdr[i].sh_addr) + load_bias;
+                if (addr == dynsym_addr) {
+                    dynsym_size = tswapl(shdr[i].sh_size);
+                    break;
+                }
+            }
+
+            sym = (struct elf_sym *)g2h(dynsym_addr);
+            for (i = 0; i < dynsym_size / sizeof(*sym); ++i) {
+                sym[i].st_value = tswapl(tswapl(sym[i].st_value) + load_bias);
+            }
+        }
+    }
+
+    /* Mark the VDSO writable segment read-only.  */
+    /* ??? This assumes that the VDSO implementation doesn't actually
+       have any truely writable data.  Perhaps we should instead use
+       the PT_GNU_RELRO header to indicate that we really want this.  */
+    retval = target_mprotect(info->start_data, info->brk - info->start_data,
+                             PROT_READ);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    return;
+
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", filename, errmsg);
+    exit(-1);
+}
+
+
 static int symfind(const void *s0, const void *s1)
 {
     struct elf_sym *key = (struct elf_sym *)s0;
@@ -1512,7 +1690,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
-    struct image_info interp_info;
+    struct image_info interp_info, vdso_info;
     struct elfhdr elf_ex;
     char *elf_interpreter = NULL;
 
@@ -1559,8 +1737,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         }
     }
 
-    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
-                                info, (elf_interpreter ? &interp_info : NULL));
+    /* If we've been given a VDSO to load, do so.  */
+    if (VDSO_BASENAME) {
+        load_elf_vdso(VDSO_BASENAME, &vdso_info, bprm->buf);
+    }
+
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc,
+                                &elf_ex, info,
+                                (elf_interpreter ? &interp_info : NULL),
+                                (VDSO_BASENAME ? &vdso_info : NULL));
     info->start_stack = bprm->p;
 
     /* If we have an interpreter, set that as the program's entry point.
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (11 preceding siblings ...)
  2010-04-05  2:13 ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
@ 2010-04-05 16:26 ` Richard Henderson
  2010-04-05 16:37 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-05 16:26 UTC (permalink / raw)
  To: qemu-devel

Moving some PPC AT_* constants from elfload.c at the same time.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 elf.h                |   44 ++++++++++++++++++++++++++++++++++++++++++++
 linux-user/elfload.c |    9 ---------
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/elf.h b/elf.h
index c84c8ab..012532c 100644
--- a/elf.h
+++ b/elf.h
@@ -146,8 +146,37 @@ typedef int64_t  Elf64_Sxword;
 #define DT_DEBUG	21
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
+#define DT_BINDNOW	24
+#define DT_INIT_ARRAY	25
+#define DT_FINI_ARRAY	26
+#define DT_INIT_ARRAYSZ	27
+#define DT_FINI_ARRAYSZ	28
+#define DT_RUNPATH	29
+#define DT_FLAGS	30
+#define DT_LOOS		0x6000000d
+#define DT_HIOS		0x6ffff000
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
+
+/* DT_ entries which fall between DT_VALRNGLO and DT_VALRNDHI use
+   the d_val field of the Elf*_Dyn structure.  I.e. they contain scalars.  */
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_VALRNGHI	0x6ffffdff
+
+/* DT_ entries which fall between DT_ADDRRNGLO and DT_ADDRRNGHI use
+   the d_ptr field of the Elf*_Dyn structure.  I.e. they contain pointers.  */
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_ADDRRNGHI	0x6ffffeff
+
+#define	DT_VERSYM	0x6ffffff0
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+#define DT_FLAGS_1	0x6ffffffb
+#define DT_VERDEF	0x6ffffffc
+#define DT_VERDEFNUM	0x6ffffffd
+#define DT_VERNEED	0x6ffffffe
+#define DT_VERNEEDNUM	0x6fffffff
+
 #define DT_MIPS_RLD_VERSION	0x70000001
 #define DT_MIPS_TIME_STAMP	0x70000002
 #define DT_MIPS_ICHECKSUM	0x70000003
@@ -206,6 +235,21 @@ typedef int64_t  Elf64_Sxword;
 #define AT_PLATFORM 15  /* string identifying CPU for optimizations */
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
+#define AT_FPUCW  18	/* info about fpu initialization by kernel */
+#define AT_DCACHEBSIZE	19	/* data cache block size */
+#define AT_ICACHEBSIZE	20	/* instruction cache block size */
+#define AT_UCACHEBSIZE	21	/* unified cache block size */
+#define AT_IGNOREPPC	22	/* ppc only; entry should be ignored */
+#define AT_SECURE	23	/* boolean, was exec suid-like? */
+#define AT_BASE_PLATFORM 24	/* string identifying real platforms */
+#define AT_RANDOM	25	/* address of 16 random bytes */
+#define AT_EXECFN	31	/* filename of the executable */
+#define AT_SYSINFO	32	/* address of kernel entry point */
+#define AT_SYSINFO_EHDR	33	/* address of kernel vdso */
+#define AT_L1I_CACHESHAPE 34	/* shapes of the caches: */
+#define AT_L1D_CACHESHAPE 35	/*   bits 0-3: cache associativity.  */
+#define AT_L2_CACHESHAPE  36	/*   bits 4-7: log2 of line size.  */
+#define AT_L3_CACHESHAPE  37	/*   val&~255: cache size.  */
 
 typedef struct dynamic{
   Elf32_Sword d_tag;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 238e574..ead22fc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -480,15 +480,6 @@ static uint32_t get_elf_hwcap(void)
 }
 
 /*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE          19
-#define AT_ICACHEBSIZE          20
-#define AT_UCACHEBSIZE          21
-/* A special ignored type value for PPC, for glibc compatibility.  */
-#define AT_IGNOREPPC            22
-/*
  * The requirements here are:
  * - keep the final alignment of sp (sp & 0xf)
  * - make sure the 32-bit value at the first 16 byte aligned position of
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (12 preceding siblings ...)
  2010-04-05 16:26 ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
@ 2010-04-05 16:37 ` Richard Henderson
  2010-04-05 18:14   ` malc
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 48+ messages in thread
From: Richard Henderson @ 2010-04-05 16:37 UTC (permalink / raw)
  To: qemu-devel

This requires moving the PT_INTERP extraction and GUEST_BASE
handling into load_elf_image.  Key this off a non-null pointer
argument to receive the interpreter name.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  269 ++++++++++----------------------------------------
 1 files changed, 53 insertions(+), 216 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index c58387a..100efdc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -829,9 +829,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss+brk space allocated to ET_DYN executables */
-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-
 /* Necessary parameters */
 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -1168,7 +1165,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
    On return: INFO values will be filled in, as necessary or available.  */
 
 static void load_elf_image(const char *image_name, int image_fd,
-                           struct image_info *info,
+                           struct image_info *info, char **pinterp_name,
                            char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
@@ -1228,6 +1225,20 @@ static void load_elf_image(const char *image_name, int image_fd,
         if (load_addr == -1) {
             goto exit_perror;
         }
+    } else if (pinterp_name != NULL) {
+        /* This is the main executable.  Make sure that the low
+           address does not conflict with MMAP_MIN_ADDR.  */
+        /* ??? Ideally, we'd check against more than just the
+           minimum mmap address, but also against the QEMU program
+           image itself.  I.e. find a range that does not conflict
+           with PAGE_RESERVED entries.  Except that we havn't read
+           those in yet, since that code uses the guest_base that
+           we set up here.  Blah.  */
+#if defined(CONFIG_USE_GUEST_BASE)
+        if (HOST_PAGE_ALIGN(loaddr) < mmap_min_addr) {
+            guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
+        }
+#endif
     }
     load_bias = load_addr - loaddr;
 
@@ -1289,6 +1300,30 @@ static void load_elf_image(const char *image_name, int image_fd,
                     info->brk = vaddr_em;
                 }
             }
+        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
+            char *interp_name;
+
+            if (*pinterp_name) {
+                errmsg = "Multiple PT_INTERP entries";
+                goto exit_errmsg;
+            }
+            interp_name = malloc(eppnt->p_filesz);
+
+            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(interp_name, bprm_buf + eppnt->p_offset,
+                       eppnt->p_filesz);
+            } else {
+		retval = pread(image_fd, interp_name, eppnt->p_filesz,
+                               eppnt->p_offset);
+                if (retval != eppnt->p_filesz) {
+                    goto exit_perror;
+                }
+            }
+            if (interp_name[eppnt->p_filesz - 1] != 0) {
+                errmsg = "Invalid PT_INTERP entry";
+                goto exit_errmsg;
+            }
+            *pinterp_name = interp_name;
         }
     }
 
@@ -1335,7 +1370,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
 
-    load_elf_image(filename, fd, info, bprm_buf);
+    load_elf_image(filename, fd, info, NULL, bprm_buf);
     return;
 
  exit_perror:
@@ -1479,230 +1514,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct image_info interp_info;
     struct elfhdr elf_ex;
-    abi_ulong load_addr, load_bias;
-    int load_addr_set = 0;
-    int i;
-    struct elf_phdr * elf_ppnt;
-    struct elf_phdr *elf_phdata;
-    abi_ulong k, elf_brk;
-    int retval;
     char *elf_interpreter = NULL;
-    abi_ulong elf_entry;
-    int status;
-    abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong elf_stack;
 
-    status = 0;
-    load_addr = 0;
-    load_bias = 0;
-    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
+    info->start_mmap = (abi_ulong)ELF_START_MMAP;
+    info->mmap = 0;
+    info->rss = 0;
+
+    load_elf_image(bprm->filename, bprm->fd, info,
+                   &elf_interpreter, bprm->buf);
 
-    /* First of all, some simple consistency checks */
-    if (!elf_check_ident(&elf_ex)) {
-        return -ENOEXEC;
-    }
-    bswap_ehdr(&elf_ex);
-    if (!elf_check_ehdr(&elf_ex)) {
-        return -ENOEXEC;
-    }
+    /* ??? We need a copy of the elf header for passing to create_elf_tables.
+       If we do nothing, we'll have overwritten this when we re-use bprm->buf
+       when we load the interpreter.  */
+    elf_ex = *(struct elfhdr *)bprm->buf;
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
     if (!bprm->p) {
-        retval = -E2BIG;
-    }
-
-    /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)
-        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
-    if (elf_phdata == NULL) {
-	return -ENOMEM;
-    }
-
-    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
-    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
-    } else {
-	retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
-        if (retval != i) {
-            perror("load_elf_binary");
-            exit(-1);
-        }
-    }
-    bswap_phdr(elf_phdata, elf_ex.e_phnum);
-
-    elf_brk = 0;
-    elf_stack = ~((abi_ulong)0UL);
-    start_code = ~((abi_ulong)0UL);
-    end_code = 0;
-    start_data = 0;
-    end_data = 0;
-
-    elf_ppnt = elf_phdata;
-    for(i=0;i < elf_ex.e_phnum; i++) {
-	if (elf_ppnt->p_type == PT_INTERP) {
-            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
-            } else {
-                elf_interpreter = alloca(elf_ppnt->p_filesz);
-		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
-                               elf_ppnt->p_offset);
-                if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary");
-                    exit(-1);
-                }
-	    }
-	}
-	elf_ppnt++;
-    }
-
-    /* OK, This is the point of no return */
-    info->end_data = 0;
-    info->end_code = 0;
-    info->start_mmap = (abi_ulong)ELF_START_MMAP;
-    info->mmap = 0;
-    elf_entry = (abi_ulong) elf_ex.e_entry;
-
-#if defined(CONFIG_USE_GUEST_BASE)
-    /*
-     * In case where user has not explicitly set the guest_base, we
-     * probe here that should we set it automatically.
-     */
-    if (!have_guest_base) {
-        /*
-         * Go through ELF program header table and find out whether
-	 * any of the segments drop below our current mmap_min_addr and
-         * in that case set guest_base to corresponding address.
-         */
-        for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-             i++, elf_ppnt++) {
-            if (elf_ppnt->p_type != PT_LOAD)
-                continue;
-            if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
-                guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
-                break;
-            }
-        }
+        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
+        exit(-1);
     }
-#endif /* CONFIG_USE_GUEST_BASE */
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
-    info->rss = 0;
     bprm->p = setup_arg_pages(bprm->p, bprm, info);
-    info->start_stack = bprm->p;
-
-    /* Now we do a little grungy work by mmaping the ELF image into
-     * the correct location in memory.  At this point, we assume that
-     * the image should be loaded at fixed address, not at a variable
-     * address.
-     */
-
-    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
-        int elf_prot = 0;
-        int elf_flags = 0;
-        abi_ulong error;
-
-	if (elf_ppnt->p_type != PT_LOAD)
-            continue;
-
-        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
-        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
-        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
-            elf_flags |= MAP_FIXED;
-        } else if (elf_ex.e_type == ET_DYN) {
-            /* Try and get dynamic programs out of the way of the default mmap
-               base, as well as whatever program they might try to exec.  This
-               is because the brk will follow the loader, and is not movable.  */
-            /* NOTE: for qemu, we do a big mmap to get enough space
-               without hardcoding any address */
-            error = target_mmap(0, ET_DYN_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
-            if (error == -1) {
-                perror("mmap");
-                exit(-1);
-            }
-            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
-        }
-
-        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
-                            (elf_ppnt->p_filesz +
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-                            elf_prot,
-                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
-                            bprm->fd,
-                            (elf_ppnt->p_offset -
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
-        if (error == -1) {
-            perror("mmap");
-            exit(-1);
-        }
-
-#ifdef LOW_ELF_STACK
-        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
-            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
-#endif
-
-        if (!load_addr_set) {
-            load_addr_set = 1;
-            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-            if (elf_ex.e_type == ET_DYN) {
-                load_bias += error -
-                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
-                load_addr += load_bias;
-            }
-        }
-        k = elf_ppnt->p_vaddr;
-        if (k < start_code)
-            start_code = k;
-        if (start_data < k)
-            start_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-            end_code = k;
-        if (end_data < k)
-            end_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) {
-            elf_brk = TARGET_PAGE_ALIGN(k);
-        }
-
-        /* If the load segment requests extra zeros (e.g. bss), map it.  */
-        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
-            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
-            zero_bss(base + elf_ppnt->p_filesz,
-                     base + elf_ppnt->p_memsz, elf_prot);
-        }
-    }
-
-    elf_entry += load_bias;
-    elf_brk += load_bias;
-    start_code += load_bias;
-    end_code += load_bias;
-    start_data += load_bias;
-    end_data += load_bias;
-
-    info->load_bias = load_bias;
-    info->load_addr = load_addr;
-    info->entry = elf_entry;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->personality = PER_LINUX;
-
-    free(elf_phdata);
-
-    if (qemu_log_enabled()) {
-	load_symbols(&elf_ex, bprm->fd, load_bias);
-    }
-
-    close(bprm->fd);
 
     if (elf_interpreter) {
         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
@@ -1734,6 +1570,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     if (elf_interpreter) {
         info->load_addr = interp_info.load_addr;
         info->entry = interp_info.entry;
+        free(elf_interpreter);
     }
 
 #ifdef USE_ELF_CORE_DUMP
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user
@ 2010-04-05 16:47 Richard Henderson
  2010-03-31 22:12 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
                   ` (27 more replies)
  0 siblings, 28 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-05 16:47 UTC (permalink / raw)
  To: qemu-devel

To do this in any clean sort of way, I rewrote a substantial
portion of elfload.c.  Doing otherwise would have wound up
with 3 entirely separate bits of code to load an elf image.

The first patch seems out of order, since I did this work on
a branch that already contained some previously submitted
fixes for Alpha.

The third patch is *only* white-space changes.  There were
too many functions that I was touching that were improperly
indented for qemu's style.  Fixing this once at the beginning
minimizes the irrelevant whitespace changes that emacs autoindent
would have introduced when moving code around later.

The patch sequence has been tested at each point with all of
the targets in linux-user-test-0.3.

Since that doesn't actually test gettimeofday, I also tested the
final result against a small program that simply reads and prints
the timeval with the system glibc, and examining the logs to verify
that we do in fact call the __vdso_getttimeofday in the loaded vdso.
I didn't test with the linux-user-test-0.3 image because I have no
way of properly linking with that library, and programs linked
against my system glibc crash when run vs the uClibc library.

I'll admit that the Makefiles aren't quite right for building the VDSO.
I couldn't quite figure out what needed to be done.  The binary image
included in patch 13 is exactly what you'd get with the link command
included in the pc-bios/Makefile, provided that you can get that link
command executed.  I'd appreciate some help with this point.

Finally, do be aware that I was not able to use qemu_find_file to 
load the vdso image, since that function is only built for system
builds, and I'd rather this patch sequence be independent of cleanups
involving vl.c.  ;-)  As a short-term hack, I always load the vdso image
from the install directory.  Which does mean that x86-64 emulation will
not currently work from the build directory alone.



r~



Richard Henderson (14):
  linux-user: Handle filesz < memsz for any PT_LOAD segment.
  Add more DT_* and AT_* constants to qemu's copy of elf.h.
  linux-user: Reindent elfload.c.
  linux-user: Reduce lseek+reads while loading elf files.
  linux-user: Fix ELF_DATA for Alpha.
  linux-user: Clean up byte-swapping in elfload.c.
  linux-user: Load symbols from the interpreter.
  linux-user: Improve consistency checking in elf headers.
  linux-user: Put the stack guard page at the top.
  linux-user: Remove partial support for a.out interpreters.
  linux-user: Extract load_elf_image from load_elf_interp.
  linux-user: Re-use load_elf_image for the main binary.
  linux-user: Build vdso for x64.
  linux-user: Load a VDSO for x86-64.

 Makefile                  |    3 +-
 elf.h                     |   44 ++
 linux-user/elfload.c      | 1683 +++++++++++++++++++++------------------------
 linux-user/linuxload.c    |   17 +-
 linux-user/qemu.h         |    7 +-
 pc-bios/Makefile          |    5 +
 pc-bios/vdso-linux-x64.S  |  102 +++
 pc-bios/vdso-linux-x64.ld |   81 +++
 pc-bios/vdso-linux-x64.so |  Bin 0 -> 7515 bytes
 9 files changed, 1037 insertions(+), 905 deletions(-)
 create mode 100644 pc-bios/vdso-linux-x64.S
 create mode 100644 pc-bios/vdso-linux-x64.ld
 create mode 100755 pc-bios/vdso-linux-x64.so

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary.
  2010-04-05 16:37 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
@ 2010-04-05 18:14   ` malc
  2010-04-05 18:38     ` Richard Henderson
  0 siblings, 1 reply; 48+ messages in thread
From: malc @ 2010-04-05 18:14 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

On Mon, 5 Apr 2010, Richard Henderson wrote:

> This requires moving the PT_INTERP extraction and GUEST_BASE
> handling into load_elf_image.  Key this off a non-null pointer
> argument to receive the interpreter name.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  linux-user/elfload.c |  269 ++++++++++----------------------------------------
>  1 files changed, 53 insertions(+), 216 deletions(-)
> 
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index c58387a..100efdc 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -829,9 +829,6 @@ struct exec
>  #define ZMAGIC 0413
>  #define QMAGIC 0314
>  
> -/* max code+data+bss+brk space allocated to ET_DYN executables */
> -#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
> -
>  /* Necessary parameters */
>  #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
>  #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
> @@ -1168,7 +1165,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>     On return: INFO values will be filled in, as necessary or available.  */
>  
>  static void load_elf_image(const char *image_name, int image_fd,
> -                           struct image_info *info,
> +                           struct image_info *info, char **pinterp_name,
>                             char bprm_buf[BPRM_BUF_SIZE])
>  {
>      struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
> @@ -1228,6 +1225,20 @@ static void load_elf_image(const char *image_name, int image_fd,
>          if (load_addr == -1) {
>              goto exit_perror;
>          }
> +    } else if (pinterp_name != NULL) {
> +        /* This is the main executable.  Make sure that the low
> +           address does not conflict with MMAP_MIN_ADDR.  */
> +        /* ??? Ideally, we'd check against more than just the
> +           minimum mmap address, but also against the QEMU program
> +           image itself.  I.e. find a range that does not conflict
> +           with PAGE_RESERVED entries.  Except that we havn't read
> +           those in yet, since that code uses the guest_base that
> +           we set up here.  Blah.  */
> +#if defined(CONFIG_USE_GUEST_BASE)
> +        if (HOST_PAGE_ALIGN(loaddr) < mmap_min_addr) {
> +            guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
> +        }
> +#endif
>      }
>      load_bias = load_addr - loaddr;
>  
> @@ -1289,6 +1300,30 @@ static void load_elf_image(const char *image_name, int image_fd,
>                      info->brk = vaddr_em;
>                  }
>              }
> +        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
> +            char *interp_name;
> +
> +            if (*pinterp_name) {
> +                errmsg = "Multiple PT_INTERP entries";
> +                goto exit_errmsg;
> +            }
> +            interp_name = malloc(eppnt->p_filesz);

malloc can fail

> +
> +            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
> +                memcpy(interp_name, bprm_buf + eppnt->p_offset,
> +                       eppnt->p_filesz);
> +            } else {
> +		retval = pread(image_fd, interp_name, eppnt->p_filesz,

Indentation seems off.
> +                               eppnt->p_offset);
> +                if (retval != eppnt->p_filesz) {
> +                    goto exit_perror;
> +                }
> +            }
> +            if (interp_name[eppnt->p_filesz - 1] != 0) {
> +                errmsg = "Invalid PT_INTERP entry";
> +                goto exit_errmsg;
> +            }
> +            *pinterp_name = interp_name;
>          }
>      }
>  
> @@ -1335,7 +1370,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
>          memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
>      }
>  
> -    load_elf_image(filename, fd, info, bprm_buf);
> +    load_elf_image(filename, fd, info, NULL, bprm_buf);
>      return;
>  
>   exit_perror:
> @@ -1479,230 +1514,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
>  {
>      struct image_info interp_info;
>      struct elfhdr elf_ex;
> -    abi_ulong load_addr, load_bias;
> -    int load_addr_set = 0;
> -    int i;
> -    struct elf_phdr * elf_ppnt;
> -    struct elf_phdr *elf_phdata;
> -    abi_ulong k, elf_brk;
> -    int retval;
>      char *elf_interpreter = NULL;
> -    abi_ulong elf_entry;
> -    int status;
> -    abi_ulong start_code, end_code, start_data, end_data;
> -    abi_ulong elf_stack;
>  
> -    status = 0;
> -    load_addr = 0;
> -    load_bias = 0;
> -    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
> +    info->start_mmap = (abi_ulong)ELF_START_MMAP;
> +    info->mmap = 0;
> +    info->rss = 0;
> +
> +    load_elf_image(bprm->filename, bprm->fd, info,
> +                   &elf_interpreter, bprm->buf);
>  
> -    /* First of all, some simple consistency checks */
> -    if (!elf_check_ident(&elf_ex)) {
> -        return -ENOEXEC;
> -    }
> -    bswap_ehdr(&elf_ex);
> -    if (!elf_check_ehdr(&elf_ex)) {
> -        return -ENOEXEC;
> -    }
> +    /* ??? We need a copy of the elf header for passing to create_elf_tables.
> +       If we do nothing, we'll have overwritten this when we re-use bprm->buf
> +       when we load the interpreter.  */
> +    elf_ex = *(struct elfhdr *)bprm->buf;
>  
>      bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
>      bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
>      bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
>      if (!bprm->p) {
> -        retval = -E2BIG;
> -    }
> -
> -    /* Now read in all of the header information */
> -    elf_phdata = (struct elf_phdr *)
> -        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
> -    if (elf_phdata == NULL) {
> -	return -ENOMEM;
> -    }
> -
> -    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
> -    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
> -        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
> -    } else {
> -	retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
> -        if (retval != i) {
> -            perror("load_elf_binary");
> -            exit(-1);
> -        }
> -    }
> -    bswap_phdr(elf_phdata, elf_ex.e_phnum);
> -
> -    elf_brk = 0;
> -    elf_stack = ~((abi_ulong)0UL);
> -    start_code = ~((abi_ulong)0UL);
> -    end_code = 0;
> -    start_data = 0;
> -    end_data = 0;
> -
> -    elf_ppnt = elf_phdata;
> -    for(i=0;i < elf_ex.e_phnum; i++) {
> -	if (elf_ppnt->p_type == PT_INTERP) {
> -            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
> -                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
> -            } else {
> -                elf_interpreter = alloca(elf_ppnt->p_filesz);
> -		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
> -                               elf_ppnt->p_offset);
> -                if (retval != elf_ppnt->p_filesz) {
> -                    perror("load_elf_binary");
> -                    exit(-1);
> -                }
> -	    }
> -	}
> -	elf_ppnt++;
> -    }
> -
> -    /* OK, This is the point of no return */
> -    info->end_data = 0;
> -    info->end_code = 0;
> -    info->start_mmap = (abi_ulong)ELF_START_MMAP;
> -    info->mmap = 0;
> -    elf_entry = (abi_ulong) elf_ex.e_entry;
> -
> -#if defined(CONFIG_USE_GUEST_BASE)
> -    /*
> -     * In case where user has not explicitly set the guest_base, we
> -     * probe here that should we set it automatically.
> -     */
> -    if (!have_guest_base) {
> -        /*
> -         * Go through ELF program header table and find out whether
> -	 * any of the segments drop below our current mmap_min_addr and
> -         * in that case set guest_base to corresponding address.
> -         */
> -        for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
> -             i++, elf_ppnt++) {
> -            if (elf_ppnt->p_type != PT_LOAD)
> -                continue;
> -            if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
> -                guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
> -                break;
> -            }
> -        }
> +        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
> +        exit(-1);
>      }
> -#endif /* CONFIG_USE_GUEST_BASE */
>  
>      /* Do this so that we can load the interpreter, if need be.  We will
>         change some of these later */
> -    info->rss = 0;
>      bprm->p = setup_arg_pages(bprm->p, bprm, info);
> -    info->start_stack = bprm->p;
> -
> -    /* Now we do a little grungy work by mmaping the ELF image into
> -     * the correct location in memory.  At this point, we assume that
> -     * the image should be loaded at fixed address, not at a variable
> -     * address.
> -     */
> -
> -    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
> -        int elf_prot = 0;
> -        int elf_flags = 0;
> -        abi_ulong error;
> -
> -	if (elf_ppnt->p_type != PT_LOAD)
> -            continue;
> -
> -        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
> -        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
> -        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
> -        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
> -        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
> -            elf_flags |= MAP_FIXED;
> -        } else if (elf_ex.e_type == ET_DYN) {
> -            /* Try and get dynamic programs out of the way of the default mmap
> -               base, as well as whatever program they might try to exec.  This
> -               is because the brk will follow the loader, and is not movable.  */
> -            /* NOTE: for qemu, we do a big mmap to get enough space
> -               without hardcoding any address */
> -            error = target_mmap(0, ET_DYN_MAP_SIZE,
> -                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
> -                                -1, 0);
> -            if (error == -1) {
> -                perror("mmap");
> -                exit(-1);
> -            }
> -            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
> -        }
> -
> -        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
> -                            (elf_ppnt->p_filesz +
> -                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
> -                            elf_prot,
> -                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
> -                            bprm->fd,
> -                            (elf_ppnt->p_offset -
> -                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
> -        if (error == -1) {
> -            perror("mmap");
> -            exit(-1);
> -        }
> -
> -#ifdef LOW_ELF_STACK
> -        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
> -            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
> -#endif
> -
> -        if (!load_addr_set) {
> -            load_addr_set = 1;
> -            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
> -            if (elf_ex.e_type == ET_DYN) {
> -                load_bias += error -
> -                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
> -                load_addr += load_bias;
> -            }
> -        }
> -        k = elf_ppnt->p_vaddr;
> -        if (k < start_code)
> -            start_code = k;
> -        if (start_data < k)
> -            start_data = k;
> -        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
> -        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
> -            end_code = k;
> -        if (end_data < k)
> -            end_data = k;
> -        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
> -        if (k > elf_brk) {
> -            elf_brk = TARGET_PAGE_ALIGN(k);
> -        }
> -
> -        /* If the load segment requests extra zeros (e.g. bss), map it.  */
> -        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
> -            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
> -            zero_bss(base + elf_ppnt->p_filesz,
> -                     base + elf_ppnt->p_memsz, elf_prot);
> -        }
> -    }
> -
> -    elf_entry += load_bias;
> -    elf_brk += load_bias;
> -    start_code += load_bias;
> -    end_code += load_bias;
> -    start_data += load_bias;
> -    end_data += load_bias;
> -
> -    info->load_bias = load_bias;
> -    info->load_addr = load_addr;
> -    info->entry = elf_entry;
> -    info->start_brk = info->brk = elf_brk;
> -    info->end_code = end_code;
> -    info->start_code = start_code;
> -    info->start_data = start_data;
> -    info->end_data = end_data;
> -    info->personality = PER_LINUX;
> -
> -    free(elf_phdata);
> -
> -    if (qemu_log_enabled()) {
> -	load_symbols(&elf_ex, bprm->fd, load_bias);
> -    }
> -
> -    close(bprm->fd);
>  
>      if (elf_interpreter) {
>          load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
> @@ -1734,6 +1570,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
>      if (elf_interpreter) {
>          info->load_addr = interp_info.load_addr;
>          info->entry = interp_info.entry;
> +        free(elf_interpreter);
>      }
>  
>  #ifdef USE_ELF_CORE_DUMP
> 

-- 
mailto:av1474@comtv.ru

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary.
  2010-04-05 18:14   ` malc
@ 2010-04-05 18:38     ` Richard Henderson
  0 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-05 18:38 UTC (permalink / raw)
  To: malc; +Cc: qemu-devel

On 04/05/2010 11:14 AM, malc wrote:
>> +            }
>> +            interp_name = malloc(eppnt->p_filesz);
> 
> malloc can fail
> 
>> +
>> +            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
>> +                memcpy(interp_name, bprm_buf + eppnt->p_offset,
>> +                       eppnt->p_filesz);
>> +            } else {
>> +		retval = pread(image_fd, interp_name, eppnt->p_filesz,
> 
> Indentation seems off.

Huh.  I suspect that the whitespace fixup patch should have also
eliminated tabs.  I don't know how else that could have crept in
there, since I have tab-expansion enabled in emacs.

I'll incorporate the following into the next version.


r~

---
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7b854e2..e8eca86 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1327,12 +1327,15 @@ static void load_elf_image(const char *image_name, int image_fd,
                 goto exit_errmsg;
             }
             interp_name = malloc(eppnt->p_filesz);
+            if (!interp_name) {
+                goto exit_perror;
+            }
 
             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
                 memcpy(interp_name, bprm_buf + eppnt->p_offset,
                        eppnt->p_filesz);
             } else {
-		retval = pread(image_fd, interp_name, eppnt->p_filesz,
+                retval = pread(image_fd, interp_name, eppnt->p_filesz,
                                eppnt->p_offset);
                 if (retval != eppnt->p_filesz) {
                     goto exit_perror;

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (13 preceding siblings ...)
  2010-04-05 16:37 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
@ 2010-04-28 19:36 ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
                     ` (13 more replies)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 00/12] Cleanup linux-user/elfload.c, v2 Richard Henderson
                   ` (12 subsequent siblings)
  27 siblings, 14 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:36 UTC (permalink / raw)
  To: qemu-devel

Changes v1->v2
  * Formatting bugs pointed out by malc.


r~



Richard Henderson (14):
  linux-user: Handle filesz < memsz for any PT_LOAD segment.
  Add more DT_* and AT_* constants to qemu's copy of elf.h.
  linux-user: Reindent elfload.c.
  linux-user: Reduce lseek+reads while loading elf files.
  linux-user: Fix ELF_DATA for Alpha.
  linux-user: Clean up byte-swapping in elfload.c.
  linux-user: Load symbols from the interpreter.
  linux-user: Improve consistency checking in elf headers.
  linux-user: Put the stack guard page at the top.
  linux-user: Remove partial support for a.out interpreters.
  linux-user: Extract load_elf_image from load_elf_interp.
  linux-user: Re-use load_elf_image for the main binary.
  linux-user: Build vdso for x64.
  linux-user: Load a VDSO for x86-64.

 Makefile                  |    3 +-
 elf.h                     |   44 ++
 linux-user/elfload.c      | 1686 +++++++++++++++++++++------------------------
 linux-user/linuxload.c    |   17 +-
 linux-user/qemu.h         |    7 +-
 pc-bios/Makefile          |    5 +
 pc-bios/vdso-linux-x64.S  |  102 +++
 pc-bios/vdso-linux-x64.ld |   81 +++
 pc-bios/vdso-linux-x64.so |  Bin 0 -> 7515 bytes
 9 files changed, 1040 insertions(+), 905 deletions(-)
 create mode 100644 pc-bios/vdso-linux-x64.S
 create mode 100644 pc-bios/vdso-linux-x64.ld
 create mode 100755 pc-bios/vdso-linux-x64.so

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
                     ` (12 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Define BPRM_BUF_SIZE to 4k and read that amount initially.  If the
data we want from the binary is in this buffer, use it instead of
reading from the file again.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c   |  105 ++++++++++++++++++++---------------------------
 linux-user/linuxload.c |   17 +++-----
 linux-user/qemu.h      |    7 +++-
 3 files changed, 58 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ab741fd..962f9ba 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1140,7 +1140,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
-                                 abi_ulong *interp_load_addr)
+                                 abi_ulong *interp_load_addr,
+                                 char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
     struct elf_phdr *eppnt;
@@ -1183,17 +1184,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(interpreter_fd,
-                      (char *) elf_phdata,
-                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    }
-    if (retval < 0) {
-        perror("load_elf_interp");
-        exit(-1);
-        free (elf_phdata);
-        return retval;
+    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
+    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    } else {
+        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        if (retval != i) {
+            perror("load_elf_interp");
+            exit(-1);
+        }
     }
 #ifdef BSWAP_NEEDED
     eppnt = elf_phdata;
@@ -1451,17 +1450,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	return -ENOMEM;
     }
 
-    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
-    if(retval > 0) {
-	retval = read(bprm->fd, (char *) elf_phdata,
-                      elf_ex.e_phentsize * elf_ex.e_phnum);
-    }
-
-    if (retval < 0) {
-	perror("load_elf_binary");
-	exit(-1);
-	free (elf_phdata);
-	return -errno;
+    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
+    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
+    } else {
+	retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
+        if (retval != i) {
+            perror("load_elf_binary");
+            exit(-1);
+        }
     }
 
 #ifdef BSWAP_NEEDED
@@ -1505,13 +1502,16 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 		return -ENOMEM;
 	    }
 
-	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
-	    if(retval >= 0) {
-		retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
-	    }
-	    if(retval < 0) {
-	 	perror("load_elf_binary2");
-		exit(-1);
+            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
+                       elf_ppnt->p_filesz);
+            } else {
+		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
+                               elf_ppnt->p_offset);
+                if (retval != elf_ppnt->p_filesz) {
+                    perror("load_elf_binary2");
+                    exit(-1);
+                }
 	    }
 
 	    /* If the program interpreter is one of these two,
@@ -1525,39 +1525,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 ibcs2_interpreter = 1;
 	    }
 
-#if 0
-	    printf("Using ELF interpreter %s\n", path(elf_interpreter));
-#endif
-	    if (retval >= 0) {
-		retval = open(path(elf_interpreter), O_RDONLY);
-		if(retval >= 0) {
-		    interpreter_fd = retval;
-		}
-		else {
-		    perror(elf_interpreter);
-		    exit(-1);
-		    /* retval = -errno; */
-		}
-	    }
+            retval = open(path(elf_interpreter), O_RDONLY);
+            if (retval < 0) {
+                perror(elf_interpreter);
+                exit(-1);
+            }
+            interpreter_fd = retval;
 
-	    if (retval >= 0) {
-		retval = lseek(interpreter_fd, 0, SEEK_SET);
-		if(retval >= 0) {
-		    retval = read(interpreter_fd,bprm->buf,128);
-		}
-	    }
-	    if (retval >= 0) {
-		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-		interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
-	    }
-	    if (retval < 0) {
+            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
+            if (retval < 0) {
 		perror("load_elf_binary3");
 		exit(-1);
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return retval;
 	    }
+            if (retval < BPRM_BUF_SIZE) {
+                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
+            }
+
+            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
 	}
 	elf_ppnt++;
     }
@@ -1746,7 +1731,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	}
 	else if (interpreter_type & 2) {
 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr);
+                                        &interp_load_addr, bprm->buf);
 	}
         reloc_func_desc = interp_load_addr;
 
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 13ad9aa..9ee27c3 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
 	}
     }
 
-    retval = lseek(bprm->fd, 0L, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(bprm->fd, bprm->buf, 128);
-    }
-    if(retval < 0) {
+    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
 	perror("prepare_binprm");
 	exit(-1);
-	/* return(-errno); */
     }
-    else {
-	return(retval);
+    if (retval < BPRM_BUF_SIZE) {
+        /* Make sure the rest of the loader won't read garbage.  */
+        memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
+    return retval;
 }
 
 /* Construct the envp and argv tables on the target stack.  */
@@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
     int i;
 
     bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
-    for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-            bprm->page[i] = NULL;
+    memset(bprm->page, 0, sizeof(bprm->page));
     retval = open(filename, O_RDONLY);
     if (retval < 0)
         return retval;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index dab3597..f7c8b65 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -31,6 +31,7 @@
  * task_struct fields in the kernel
  */
 struct image_info {
+        abi_ulong       load_bias;
         abi_ulong       load_addr;
         abi_ulong       start_code;
         abi_ulong       end_code;
@@ -143,12 +144,16 @@ extern unsigned long mmap_min_addr;
  */
 #define MAX_ARG_PAGES 33
 
+/* Read a good amount of data initially, to hopefully get all the 
+   program headers loaded.  */
+#define BPRM_BUF_SIZE  4096
+
 /*
  * This structure is used to hold the arguments that are
  * used when loading binaries.
  */
 struct linux_binprm {
-        char buf[128];
+        char buf[BPRM_BUF_SIZE] __attribute__((aligned));
         void *page[MAX_ARG_PAGES];
         abi_ulong p;
 	int fd;
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
                     ` (11 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

I caught padzero not properly initializing the .bss segment
on a statically linked Alpha program.  Rather than a minimal
patch, replace the gross code with a single mmap+memset.

Share more code between load_elf_interp and load_elf_binary.

Legally, an ELF program need not have just a single .bss;
and PT_LOAD segment can have memsz > filesz.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  150 ++++++++++++++++++--------------------------------
 1 files changed, 54 insertions(+), 96 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4d3dd89..238e574 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1015,60 +1015,47 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
     return p;
 }
 
-static void set_brk(abi_ulong start, abi_ulong end)
-{
-	/* page-align the start and end addresses... */
-        start = HOST_PAGE_ALIGN(start);
-        end = HOST_PAGE_ALIGN(end);
-        if (end <= start)
-                return;
-        if(target_mmap(start, end - start,
-                       PROT_READ | PROT_WRITE | PROT_EXEC,
-                       MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
-	    perror("cannot mmap brk");
-	    exit(-1);
-	}
-}
-
-
-/* We need to explicitly zero any fractional pages after the data
-   section (i.e. bss).  This would contain the junk from the file that
-   should not be in memory. */
-static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
-{
-        abi_ulong nbyte;
-
-	if (elf_bss >= last_bss)
-		return;
-
-        /* XXX: this is really a hack : if the real host page size is
-           smaller than the target page size, some pages after the end
-           of the file may not be mapped. A better fix would be to
-           patch target_mmap(), but it is more complicated as the file
-           size must be known */
-        if (qemu_real_host_page_size < qemu_host_page_size) {
-            abi_ulong end_addr, end_addr1;
-            end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
-                ~(qemu_real_host_page_size - 1);
-            end_addr = HOST_PAGE_ALIGN(elf_bss);
-            if (end_addr1 < end_addr) {
-                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
-                     PROT_READ|PROT_WRITE|PROT_EXEC,
-                     MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-            }
+/* Map and zero the bss.  We need to explicitly zero any fractional pages
+   after the data section (i.e. bss).  */
+static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
+{
+    uintptr_t host_start, host_map_start, host_end;
+
+    last_bss = TARGET_PAGE_ALIGN(last_bss);
+
+    /* ??? There is confusion between qemu_real_host_page_size and
+       qemu_host_page_size here and elsewhere in target_mmap, which
+       may lead to the end of the data section mapping from the file
+       not being mapped.  At least there was an explicit test and
+       comment for that here, suggesting that "the file size must
+       be known".  The comment probably pre-dates the introduction
+       of the fstat system call in target_mmap which does in fact
+       find out the size.  What isn't clear is if the workaround
+       here is still actually needed.  For now, continue with it,
+       but merge it with the "normal" mmap that would allocate the bss.  */
+
+    host_start = (uintptr_t) g2h(elf_bss);
+    host_end = (uintptr_t) g2h(last_bss);
+    host_map_start = (host_start + qemu_real_host_page_size - 1);
+    host_map_start &= -qemu_real_host_page_size;
+
+    if (host_map_start < host_end) {
+        void *p = mmap((void *)host_map_start, host_end - host_map_start,
+                       prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+        if (p == MAP_FAILED) {
+            perror("cannot mmap brk");
+            exit(-1);
         }
 
-        nbyte = elf_bss & (qemu_host_page_size-1);
-        if (nbyte) {
-	    nbyte = qemu_host_page_size - nbyte;
-	    do {
-                /* FIXME - what to do if put_user() fails? */
-		put_user_u8(0, elf_bss);
-                elf_bss++;
-	    } while (--nbyte);
-        }
-}
+        /* Since we didn't use target_mmap, make sure to record
+           the validity of the pages with qemu.  */
+        page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
+    }
 
+    if (host_start < host_map_start) {
+        memset((void *)host_start, 0, host_map_start - host_start);
+    }
+}
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
@@ -1160,12 +1147,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	abi_ulong load_addr = 0;
 	int load_addr_set = 0;
 	int retval;
-	abi_ulong last_bss, elf_bss;
 	abi_ulong error;
 	int i;
 
-	elf_bss = 0;
-	last_bss = 0;
 	error = 0;
 
 #ifdef BSWAP_NEEDED
@@ -1238,7 +1222,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
 	    abi_ulong vaddr = 0;
-	    abi_ulong k;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
@@ -1266,40 +1249,17 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	      load_addr_set = 1;
 	    }
 
-	    /*
-	     * Find the end of the file  mapping for this phdr, and keep
-	     * track of the largest address we see for this.
-	     */
-	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
-	    if (k > elf_bss) elf_bss = k;
-
-	    /*
-	     * Do the same thing for the memory mapping - between
-	     * elf_bss and last_bss is the bss section.
-	     */
-	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
-	    if (k > last_bss) last_bss = k;
+            /* If the load segment requests extra zeros (e.g. bss), map it.  */
+            if (eppnt->p_filesz < eppnt->p_memsz) {
+                abi_ulong base = load_addr + eppnt->p_vaddr;
+                zero_bss(base + eppnt->p_filesz,
+                         base + eppnt->p_memsz, elf_prot);
+            }
 	  }
 
 	/* Now use mmap to map the library into memory. */
 
 	close(interpreter_fd);
-
-	/*
-	 * Now fill out the bss section.  First pad the last page up
-	 * to the page boundary, and then perform a mmap to make sure
-	 * that there are zeromapped pages up to and including the last
-	 * bss page.
-	 */
-	padzero(elf_bss, last_bss);
-	elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
-
-	/* Map the last of the bss segment */
-	if (last_bss > elf_bss) {
-            target_mmap(elf_bss, last_bss-elf_bss,
-                        PROT_READ|PROT_WRITE|PROT_EXEC,
-                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-	}
 	free(elf_phdata);
 
 	*interp_load_addr = load_addr;
@@ -1453,7 +1413,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
-    abi_ulong elf_bss, k, elf_brk;
+    abi_ulong k, elf_brk;
     int retval;
     char * elf_interpreter;
     abi_ulong elf_entry, interp_load_addr = 0;
@@ -1512,10 +1472,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 #endif
     elf_ppnt = elf_phdata;
 
-    elf_bss = 0;
     elf_brk = 0;
 
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1758,18 +1716,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         if (start_data < k)
             start_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if (k > elf_bss)
-            elf_bss = k;
         if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
             end_code = k;
         if (end_data < k)
             end_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) elf_brk = k;
+        if (k > elf_brk) {
+            elf_brk = TARGET_PAGE_ALIGN(k);
+        }
+
+        /* If the load segment requests extra zeros (e.g. bss), map it.  */
+        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
+            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
+            zero_bss(base + elf_ppnt->p_filesz,
+                     base + elf_ppnt->p_memsz, elf_prot);
+        }
     }
 
     elf_entry += load_bias;
-    elf_bss += load_bias;
     elf_brk += load_bias;
     start_code += load_bias;
     end_code += load_bias;
@@ -1824,12 +1788,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->end_data = end_data;
     info->start_stack = bprm->p;
 
-    /* Calling set_brk effectively mmaps the pages that we need for the bss and break
-       sections */
-    set_brk(elf_bss, elf_brk);
-
-    padzero(elf_bss, elf_brk);
-
 #if 0
     printf("(start_brk) %x\n" , info->start_brk);
     printf("(end_code) %x\n" , info->end_code);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
                     ` (10 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Moving some PPC AT_* constants from elfload.c at the same time.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 elf.h                |   44 ++++++++++++++++++++++++++++++++++++++++++++
 linux-user/elfload.c |    9 ---------
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/elf.h b/elf.h
index c84c8ab..012532c 100644
--- a/elf.h
+++ b/elf.h
@@ -146,8 +146,37 @@ typedef int64_t  Elf64_Sxword;
 #define DT_DEBUG	21
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
+#define DT_BINDNOW	24
+#define DT_INIT_ARRAY	25
+#define DT_FINI_ARRAY	26
+#define DT_INIT_ARRAYSZ	27
+#define DT_FINI_ARRAYSZ	28
+#define DT_RUNPATH	29
+#define DT_FLAGS	30
+#define DT_LOOS		0x6000000d
+#define DT_HIOS		0x6ffff000
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
+
+/* DT_ entries which fall between DT_VALRNGLO and DT_VALRNDHI use
+   the d_val field of the Elf*_Dyn structure.  I.e. they contain scalars.  */
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_VALRNGHI	0x6ffffdff
+
+/* DT_ entries which fall between DT_ADDRRNGLO and DT_ADDRRNGHI use
+   the d_ptr field of the Elf*_Dyn structure.  I.e. they contain pointers.  */
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_ADDRRNGHI	0x6ffffeff
+
+#define	DT_VERSYM	0x6ffffff0
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+#define DT_FLAGS_1	0x6ffffffb
+#define DT_VERDEF	0x6ffffffc
+#define DT_VERDEFNUM	0x6ffffffd
+#define DT_VERNEED	0x6ffffffe
+#define DT_VERNEEDNUM	0x6fffffff
+
 #define DT_MIPS_RLD_VERSION	0x70000001
 #define DT_MIPS_TIME_STAMP	0x70000002
 #define DT_MIPS_ICHECKSUM	0x70000003
@@ -206,6 +235,21 @@ typedef int64_t  Elf64_Sxword;
 #define AT_PLATFORM 15  /* string identifying CPU for optimizations */
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
+#define AT_FPUCW  18	/* info about fpu initialization by kernel */
+#define AT_DCACHEBSIZE	19	/* data cache block size */
+#define AT_ICACHEBSIZE	20	/* instruction cache block size */
+#define AT_UCACHEBSIZE	21	/* unified cache block size */
+#define AT_IGNOREPPC	22	/* ppc only; entry should be ignored */
+#define AT_SECURE	23	/* boolean, was exec suid-like? */
+#define AT_BASE_PLATFORM 24	/* string identifying real platforms */
+#define AT_RANDOM	25	/* address of 16 random bytes */
+#define AT_EXECFN	31	/* filename of the executable */
+#define AT_SYSINFO	32	/* address of kernel entry point */
+#define AT_SYSINFO_EHDR	33	/* address of kernel vdso */
+#define AT_L1I_CACHESHAPE 34	/* shapes of the caches: */
+#define AT_L1D_CACHESHAPE 35	/*   bits 0-3: cache associativity.  */
+#define AT_L2_CACHESHAPE  36	/*   bits 4-7: log2 of line size.  */
+#define AT_L3_CACHESHAPE  37	/*   val&~255: cache size.  */
 
 typedef struct dynamic{
   Elf32_Sword d_tag;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 238e574..ead22fc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -480,15 +480,6 @@ static uint32_t get_elf_hwcap(void)
 }
 
 /*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE          19
-#define AT_ICACHEBSIZE          20
-#define AT_UCACHEBSIZE          21
-/* A special ignored type value for PPC, for glibc compatibility.  */
-#define AT_IGNOREPPC            22
-/*
  * The requirements here are:
  * - keep the final alignment of sp (sp & 0xf)
  * - make sure the 32-bit value at the first 16 byte aligned position of
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (2 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
                     ` (9 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

There are no supported stack-grows-up targets.  We were putting
the guard page at the highest address, i.e. the bottom of the stack.
Use the maximum of host and guest page size for the guard size.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   29 ++++++++++++++++-------------
 1 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5853a30..464160a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1002,28 +1002,31 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
                                  struct image_info *info)
 {
-    abi_ulong stack_base, size, error;
+    abi_ulong stack_base, size, error, guard;
     int i;
 
     /* Create enough stack to hold everything.  If we don't use
-     * it for args, we'll use it for something else...
-     */
+       it for args, we'll use it for something else.  */
     size = guest_stack_size;
-    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
-    error = target_mmap(0,
-                        size + qemu_host_page_size,
-                        PROT_READ | PROT_WRITE,
-                        MAP_PRIVATE | MAP_ANONYMOUS,
-                        -1, 0);
+    }
+    guard = TARGET_PAGE_SIZE;
+    if (guard < qemu_real_host_page_size) {
+        guard = qemu_real_host_page_size;
+    }
+
+    error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (error == -1) {
-        perror("stk mmap");
+        perror("mmap stack");
         exit(-1);
     }
-    /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
 
-    stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+    /* We reserve one extra page at the top of the stack as guard.  */
+    target_mprotect(error, guard, PROT_NONE);
+
+    stack_base = error + guard + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
     p += stack_base;
 
     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (4 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
                     ` (7 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Alpha is little-endian on Linux.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 962f9ba..5814702 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -778,7 +778,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == ELF_ARCH )
 
 #define ELF_CLASS      ELFCLASS64
-#define ELF_DATA       ELFDATA2MSB
+#define ELF_DATA       ELFDATA2LSB
 #define ELF_ARCH       EM_ALPHA
 
 static inline void init_thread(struct target_pt_regs *regs,
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (5 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
                     ` (6 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Remove ifdefs from code by defining empty inline functions
when byte swapping isn't needed.  Push loops over swapping
arrays of structures into the swapping functions.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  119 ++++++++++++++++++++------------------------------
 1 files changed, 48 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5814702..9cf1eeb 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -871,30 +871,36 @@ static void bswap_ehdr(struct elfhdr *ehdr)
     bswap16s(&ehdr->e_shstrndx);	/* Section header string table index */
 }
 
-static void bswap_phdr(struct elf_phdr *phdr)
+static void bswap_phdr(struct elf_phdr *phdr, int phnum)
 {
-    bswap32s(&phdr->p_type);		/* Segment type */
-    bswaptls(&phdr->p_offset);		/* Segment file offset */
-    bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
-    bswaptls(&phdr->p_paddr);		/* Segment physical address */
-    bswaptls(&phdr->p_filesz);		/* Segment size in file */
-    bswaptls(&phdr->p_memsz);		/* Segment size in memory */
-    bswap32s(&phdr->p_flags);		/* Segment flags */
-    bswaptls(&phdr->p_align);		/* Segment alignment */
+    int i;
+    for (i = 0; i < phnum; ++i, ++phdr) {
+        bswap32s(&phdr->p_type);	/* Segment type */
+        bswap32s(&phdr->p_flags);	/* Segment flags */
+        bswaptls(&phdr->p_offset);	/* Segment file offset */
+        bswaptls(&phdr->p_vaddr);	/* Segment virtual address */
+        bswaptls(&phdr->p_paddr);	/* Segment physical address */
+        bswaptls(&phdr->p_filesz);	/* Segment size in file */
+        bswaptls(&phdr->p_memsz);	/* Segment size in memory */
+        bswaptls(&phdr->p_align);	/* Segment alignment */
+    }
 }
 
-static void bswap_shdr(struct elf_shdr *shdr)
+static void bswap_shdr(struct elf_shdr *shdr, int shnum)
 {
-    bswap32s(&shdr->sh_name);
-    bswap32s(&shdr->sh_type);
-    bswaptls(&shdr->sh_flags);
-    bswaptls(&shdr->sh_addr);
-    bswaptls(&shdr->sh_offset);
-    bswaptls(&shdr->sh_size);
-    bswap32s(&shdr->sh_link);
-    bswap32s(&shdr->sh_info);
-    bswaptls(&shdr->sh_addralign);
-    bswaptls(&shdr->sh_entsize);
+    int i;
+    for (i = 0; i < shnum; ++i, ++shdr) {
+        bswap32s(&shdr->sh_name);
+        bswap32s(&shdr->sh_type);
+        bswaptls(&shdr->sh_flags);
+        bswaptls(&shdr->sh_addr);
+        bswaptls(&shdr->sh_offset);
+        bswaptls(&shdr->sh_size);
+        bswap32s(&shdr->sh_link);
+        bswap32s(&shdr->sh_info);
+        bswaptls(&shdr->sh_addralign);
+        bswaptls(&shdr->sh_entsize);
+    }
 }
 
 static void bswap_sym(struct elf_sym *sym)
@@ -904,20 +910,15 @@ static void bswap_sym(struct elf_sym *sym)
     bswaptls(&sym->st_size);
     bswap16s(&sym->st_shndx);
 }
+#else
+static inline void bswap_ehdr(struct elfhdr *ehdr) { }
+static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
+static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
+static inline void bswap_sym(struct elf_sym *sym) { }
 #endif
 
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
-
-#ifdef BSWAP_NEEDED
-static void bswap_note(struct elf_note *en)
-{
-    bswap32s(&en->n_namesz);
-    bswap32s(&en->n_descsz);
-    bswap32s(&en->n_type);
-}
-#endif /* BSWAP_NEEDED */
-
 #endif /* USE_ELF_CORE_DUMP */
 
 /*
@@ -1153,9 +1154,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
     error = 0;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(interp_elf_ex);
-#endif
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
          interp_elf_ex->e_type != ET_DYN) ||
@@ -1194,12 +1193,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             exit(-1);
         }
     }
-#ifdef BSWAP_NEEDED
-    eppnt = elf_phdata;
-    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-        bswap_phdr(eppnt);
-    }
-#endif
+    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
     if (interp_elf_ex->e_type == ET_DYN) {
         /* in order to avoid hardcoding the interpreter load
@@ -1323,9 +1317,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
     for (i = 0; i < hdr->e_shnum; i++) {
         if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
             return;
-#ifdef BSWAP_NEEDED
-        bswap_shdr(&sechdr);
-#endif
+        bswap_shdr(&sechdr, 1);
         if (sechdr.sh_type == SHT_SYMTAB) {
             symtab = sechdr;
             lseek(fd, hdr->e_shoff
@@ -1333,9 +1325,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
             if (read(fd, &strtab, sizeof(strtab))
                 != sizeof(strtab))
                 return;
-#ifdef BSWAP_NEEDED
-            bswap_shdr(&strtab);
-#endif
+            bswap_shdr(&strtab, 1);
             goto found;
         }
     }
@@ -1359,9 +1349,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 
     i = 0;
     while (i < nsyms) {
-#ifdef BSWAP_NEEDED
         bswap_sym(syms + i);
-#endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
             syms[i].st_shndx >= SHN_LORESERVE ||
@@ -1427,9 +1415,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-#ifdef BSWAP_NEEDED
     bswap_ehdr(&elf_ex);
-#endif
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
@@ -1460,17 +1446,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             exit(-1);
         }
     }
-
-#ifdef BSWAP_NEEDED
-    elf_ppnt = elf_phdata;
-    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
-        bswap_phdr(elf_ppnt);
-    }
-#endif
-    elf_ppnt = elf_phdata;
+    bswap_phdr(elf_phdata, elf_ex.e_phnum);
 
     elf_brk = 0;
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1479,6 +1457,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data = 0;
     interp_ex.a_info = 0;
 
+    elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
 	if (elf_ppnt->p_type == PT_INTERP) {
 	    if ( elf_interpreter != NULL )
@@ -1964,9 +1943,6 @@ static int write_note(struct memelfnote *, int);
 static int write_note_info(struct elf_note_info *, int);
 
 #ifdef BSWAP_NEEDED
-static void bswap_prstatus(struct target_elf_prstatus *);
-static void bswap_psinfo(struct target_elf_prpsinfo *);
-
 static void bswap_prstatus(struct target_elf_prstatus *prstatus)
 {
     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
@@ -1994,6 +1970,17 @@ static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
     psinfo->pr_sid = tswap32(psinfo->pr_sid);
 }
+
+static void bswap_note(struct elf_note *en)
+{
+    bswap32s(&en->n_namesz);
+    bswap32s(&en->n_descsz);
+    bswap32s(&en->n_type);
+}
+#else
+static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
+static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
+static inline void bswap_note(struct elf_note *en) { }
 #endif /* BSWAP_NEEDED */
 
 /*
@@ -2152,9 +2139,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
     elf->e_phentsize = sizeof(struct elf_phdr);
     elf->e_phnum = segs;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(elf);
-#endif
 }
 
 static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
@@ -2168,9 +2153,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
     phdr->p_flags = 0;
     phdr->p_align = 0;
 
-#ifdef BSWAP_NEEDED
-    bswap_phdr(phdr);
-#endif
+    bswap_phdr(phdr, 1);
 }
 
 static size_t note_size(const struct memelfnote *note)
@@ -2188,9 +2171,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus,
     prstatus->pr_pgrp = getpgrp();
     prstatus->pr_sid = getsid(0);
 
-#ifdef BSWAP_NEEDED
     bswap_prstatus(prstatus);
-#endif
 }
 
 static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
@@ -2224,9 +2205,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     free(base_filename);
     free(filename);
 
-#ifdef BSWAP_NEEDED
     bswap_psinfo(psinfo);
-#endif
     return (0);
 }
 
@@ -2351,9 +2330,7 @@ static int write_note(struct memelfnote *men, int fd)
     en.n_type = men->type;
     en.n_descsz = men->datasz;
 
-#ifdef BSWAP_NEEDED
     bswap_note(&en);
-#endif
 
     if (dump_write(fd, &en, sizeof(en)) != 0)
         return (-1);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (3 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
                     ` (8 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

At the bottom of the a.out support was the unimplemented load_aout_interp
function.  There were other portions of the support that didn't look
right; when I went to look in the Linux kernel for clarification, I found
that the support for such interpreters has been removed from binfmt_elf.
There doesn't seem to be any reason to keep this broken support in qemu.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   80 +++++--------------------------------------------
 1 files changed, 9 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 464160a..2f15b9c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -837,10 +837,6 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define INTERPRETER_NONE 0
-#define INTERPRETER_AOUT 1
-#define INTERPRETER_ELF 2
-
 #define DLINFO_ITEMS 12
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
@@ -848,8 +844,6 @@ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
     memcpy(to, from, n);
 }
 
-static int load_aout_interp(void * exptr, int interp_fd);
-
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
@@ -1087,7 +1081,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
                                    abi_ulong load_addr,
                                    abi_ulong load_bias,
-                                   abi_ulong interp_load_addr, int ibcs,
+                                   abi_ulong interp_load_addr,
                                    struct image_info *info)
 {
     abi_ulong sp;
@@ -1117,7 +1111,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
     size += envc + argc + 2;
-    size += (!ibcs ? 3 : 1);	/* argc itself */
+    size += 1;	/* argc itself */
     size *= n;
     if (size & 15)
         sp -= 16 - (size & 15);
@@ -1159,7 +1153,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
     info->saved_auxv = sp;
 
-    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    sp = loader_build_argptr(envc, argc, sp, p, 0);
     return sp;
 }
 
@@ -1412,11 +1406,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct elfhdr elf_ex;
     struct elfhdr interp_elf_ex;
-    struct exec interp_ex;
     int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned int interpreter_type = INTERPRETER_NONE;
     unsigned char ibcs2_interpreter;
     int i;
     abi_ulong mapped_addr;
@@ -1430,7 +1422,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong start_code, end_code, start_data, end_data;
     abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
-    char passed_fileno[6];
 
     ibcs2_interpreter = 0;
     status = 0;
@@ -1480,7 +1471,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_code = 0;
     start_data = 0;
     end_data = 0;
-    interp_ex.a_info = 0;
 
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
@@ -1545,59 +1535,22 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
             }
 
-            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf);
 	}
 	elf_ppnt++;
     }
 
     /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter){
-	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
-
-	/* Now figure out which format our binary is */
-	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-            (N_MAGIC(interp_ex) != QMAGIC)) {
-            interpreter_type = INTERPRETER_ELF;
-	}
-
+    if (elf_interpreter) {
         if (!elf_check_ident(&interp_elf_ex)) {
-	    interpreter_type &= ~INTERPRETER_ELF;
-	}
-
-	if (!interpreter_type) {
 	    free(elf_interpreter);
 	    free(elf_phdata);
 	    close(bprm->fd);
+            close(interpreter_fd);
 	    return -ELIBBAD;
 	}
     }
 
-    /* OK, we are done with that, now set up the arg stuff,
-       and then start this sucker up */
-
-    {
-	char * passed_p;
-
-	if (interpreter_type == INTERPRETER_AOUT) {
-	    snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
-	    passed_p = passed_fileno;
-
-	    if (elf_interpreter) {
-		bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
-		bprm->argc++;
-	    }
-	}
-	if (!bprm->p) {
-	    if (elf_interpreter) {
-	        free(elf_interpreter);
-	    }
-	    free (elf_phdata);
-	    close(bprm->fd);
-	    return -E2BIG;
-	}
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1729,16 +1682,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data += load_bias;
 
     if (elf_interpreter) {
-	if (interpreter_type & 1) {
-	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
-	}
-	else if (interpreter_type & 2) {
-	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr, bprm->buf);
-	}
+        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
+                                    &interp_load_addr, bprm->buf);
         reloc_func_desc = interp_load_addr;
-
-	close(interpreter_fd);
 	free(elf_interpreter);
 
 	if (elf_entry == ~((abi_ulong)0UL)) {
@@ -1755,7 +1701,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	load_symbols(&elf_ex, bprm->fd, load_bias);
     }
 
-    if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
+    close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
 #ifdef LOW_ELF_STACK
@@ -1767,7 +1713,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                                 &elf_ex,
                                 load_addr, load_bias,
                                 interp_load_addr,
-                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
                                 info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
@@ -2656,15 +2601,8 @@ static int elf_core_dump(int signr, const CPUState *env)
         return (-errno);
     return (0);
 }
-
 #endif /* USE_ELF_CORE_DUMP */
 
-static int load_aout_interp(void * exptr, int interp_fd)
-{
-    printf("a.out interpreter not yet supported\n");
-    return(0);
-}
-
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
     init_thread(regs, infop);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (6 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
                     ` (5 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Validate more fields of the elf header.  Extract those checks
into two common functions to be used in both load_elf_interp
and load_elf_binary.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   57 +++++++++++++++++++++++++++++---------------------
 1 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 7e94fe3..5853a30 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -919,6 +919,30 @@ static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
 static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
+/* Verify the portions of EHDR within E_IDENT for the target.
+   This can be performed before bswapping the entire header.  */
+static _Bool elf_check_ident(struct elfhdr *ehdr)
+{
+    return (ehdr->e_ident[EI_MAG0] == ELFMAG0
+            && ehdr->e_ident[EI_MAG1] == ELFMAG1
+            && ehdr->e_ident[EI_MAG2] == ELFMAG2
+            && ehdr->e_ident[EI_MAG3] == ELFMAG3
+            && ehdr->e_ident[EI_CLASS] == ELF_CLASS
+            && ehdr->e_ident[EI_DATA] == ELF_DATA
+            && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
+}
+
+/* Verify the portions of EHDR outside of E_IDENT for the target.
+   This has to wait until after bswapping the header.  */
+static _Bool elf_check_ehdr(struct elfhdr *ehdr)
+{
+    return (elf_check_arch(ehdr->e_machine)
+            && ehdr->e_ehsize == sizeof(struct elfhdr)
+            && ehdr->e_phentsize == sizeof(struct elf_phdr)
+            && ehdr->e_shentsize == sizeof(struct elf_shdr)
+            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
+}
+
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
  * memory to free pages in kernel mem. These are in a format ready
@@ -1149,33 +1173,16 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     int i;
 
     bswap_ehdr(interp_elf_ex);
-    /* First of all, some simple consistency checks */
-    if ((interp_elf_ex->e_type != ET_EXEC &&
-         interp_elf_ex->e_type != ET_DYN) ||
-        !elf_check_arch(interp_elf_ex->e_machine)) {
+    if (!elf_check_ehdr(interp_elf_ex)) {
         return ~((abi_ulong)0UL);
     }
 
     /* Now read in all of the header information */
-
-    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-        return ~(abi_ulong)0UL;
-
     elf_phdata =  (struct elf_phdr *)
         malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-
     if (!elf_phdata)
         return ~((abi_ulong)0UL);
 
-    /*
-     * If the size of this structure has changed, then punt, since
-     * we will be doing the wrong thing.
-     */
-    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-        free(elf_phdata);
-        return ~((abi_ulong)0UL);
-    }
-
     i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
     if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
         memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
@@ -1427,11 +1434,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-    bswap_ehdr(&elf_ex);
 
     /* First of all, some simple consistency checks */
-    if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-        (! elf_check_arch(elf_ex.e_machine))) {
+    if (!elf_check_ident(&elf_ex)) {
+        return -ENOEXEC;
+    }
+    bswap_ehdr(&elf_ex);
+    if (!elf_check_ehdr(&elf_ex)) {
         return -ENOEXEC;
     }
 
@@ -1443,7 +1452,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
+    elf_phdata = (struct elf_phdr *)
+        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
     if (elf_phdata == NULL) {
 	return -ENOMEM;
     }
@@ -1548,8 +1558,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             interpreter_type = INTERPRETER_ELF;
 	}
 
-	if (interp_elf_ex.e_ident[0] != 0x7f ||
-            strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
+        if (!elf_check_ident(&interp_elf_ex)) {
 	    interpreter_type &= ~INTERPRETER_ELF;
 	}
 
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (7 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
                     ` (4 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Moving toward a single copy of the elf binary loading code.
Fill in the details of the loaded image into a struct image_info.

Adjust create_elf_tables to read from such structures instead
of from a collection of passed arguments.  Don't return error
values from load_elf_interp; always exit(-1) with a message to
stderr.  Collect elf_interpreter handling in load_elf_binary
to a common spot.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  341 ++++++++++++++++++++++++-------------------------
 1 files changed, 167 insertions(+), 174 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2f15b9c..c58387a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1078,11 +1078,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 }
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
-                                   struct elfhdr * exec,
-                                   abi_ulong load_addr,
-                                   abi_ulong load_bias,
-                                   abi_ulong interp_load_addr,
-                                   struct image_info *info)
+                                   struct elfhdr *exec,
+                                   struct image_info *info,
+                                   struct image_info *interp_info)
 {
     abi_ulong sp;
     int size;
@@ -1127,13 +1125,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT (AT_NULL, 0);
 
     /* There must be exactly DLINFO_ITEMS entries here.  */
-    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
@@ -1157,51 +1155,60 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
+/* Load an ELF image into the address space.
 
-static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
-                                 int interpreter_fd,
-                                 abi_ulong *interp_load_addr,
-                                 char bprm_buf[BPRM_BUF_SIZE])
+   IMAGE_NAME is the filename of the image, to use in error messages.
+   IMAGE_FD is the open file descriptor for the image.
+
+   BUFPAGE is a copy of the first page of the file; this of course
+   contains the elf file header at offset 0.  It is assumed that this
+   buffer is sufficiently aligned to present no problems to the host
+   in accessing data at aligned offsets within the buffer.
+
+   On return: INFO values will be filled in, as necessary or available.  */
+
+static void load_elf_image(const char *image_name, int image_fd,
+                           struct image_info *info,
+                           char bprm_buf[BPRM_BUF_SIZE])
 {
-    struct elf_phdr *elf_phdata  =  NULL;
-    abi_ulong load_addr, load_bias, loaddr, hiaddr;
-    int retval;
-    abi_ulong error;
-    int i;
+    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+    struct elf_phdr *phdr;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+    int i, retval;
+    const char *errmsg;
 
-    bswap_ehdr(interp_elf_ex);
-    if (!elf_check_ehdr(interp_elf_ex)) {
-        return ~((abi_ulong)0UL);
+    /* First of all, some simple consistency checks */
+    errmsg = "Invalid ELF image for this architecture";
+    if (!elf_check_ident(ehdr)) {
+        goto exit_errmsg;
+    }
+    bswap_ehdr(ehdr);
+    if (!elf_check_ehdr(ehdr)) {
+        goto exit_errmsg;
     }
 
-    /* Now read in all of the header information */
-    elf_phdata =  (struct elf_phdr *)
-        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    if (!elf_phdata)
-        return ~((abi_ulong)0UL);
-
-    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
-    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    i = ehdr->e_phnum * sizeof(struct elf_phdr);
+    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
+        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
     } else {
-        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        phdr = (struct elf_phdr *) alloca(i);
+        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
         if (retval != i) {
-            perror("load_elf_interp");
-            exit(-1);
+            goto exit_read;
         }
     }
-    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
+    bswap_phdr(phdr, ehdr->e_phnum);
 
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
-    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
-        if (elf_phdata[i].p_type == PT_LOAD) {
-            abi_ulong a = elf_phdata[i].p_vaddr;
+    for (i = 0; i < ehdr->e_phnum; ++i) {
+        if (phdr[i].p_type == PT_LOAD) {
+            abi_ulong a = phdr[i].p_vaddr;
             if (a < loaddr) {
                 loaddr = a;
             }
-            a += elf_phdata[i].p_memsz;
+            a += phdr[i].p_memsz;
             if (a > hiaddr) {
                 hiaddr = a;
             }
@@ -1209,7 +1216,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
 
     load_addr = loaddr;
-    if (interp_elf_ex->e_type == ET_DYN) {
+    if (ehdr->e_type == ET_DYN) {
         /* The image indicates that it can be loaded anywhere.  Find a
            location that can hold the memory space required.  If the
            image is pre-linked, LOADDR will be non-zero.  Since we do
@@ -1219,14 +1226,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
                                 -1, 0);
         if (load_addr == -1) {
-            perror("mmap");
-            exit(-1);
+            goto exit_perror;
         }
     }
     load_bias = load_addr - loaddr;
 
-    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
-        struct elf_phdr *eppnt = elf_phdata + i;
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = ehdr->e_entry + load_bias;
+    info->start_code = -1;
+    info->end_code = 0;
+    info->start_data = -1;
+    info->end_data = 0;
+    info->brk = 0;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+        struct elf_phdr *eppnt = phdr + i;
         if (eppnt->p_type == PT_LOAD) {
 	    abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 	    int elf_prot = 0;
@@ -1241,12 +1256,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
 	    error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
                                 elf_prot, MAP_PRIVATE | MAP_FIXED,
-                                interpreter_fd, eppnt->p_offset - vaddr_po);
+                                image_fd, eppnt->p_offset - vaddr_po);
 	    if (error == -1) {
-                /* Real error */
-                close(interpreter_fd);
-                free(elf_phdata);
-                return ~((abi_ulong)0UL);
+                goto exit_perror;
 	    }
 
             vaddr_ef = vaddr + eppnt->p_filesz;
@@ -1256,18 +1268,79 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (vaddr_ef < vaddr_em) {
                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
+
+            /* Find the full program boundaries.  */
+            if (elf_prot & PROT_EXEC) {
+                if (vaddr < info->start_code) {
+                    info->start_code = vaddr;
+                }
+                if (vaddr_ef > info->end_code) {
+                    info->end_code = vaddr_ef;
+                }
+            }
+            if (elf_prot & PROT_WRITE) {
+                if (vaddr < info->start_data) {
+                    info->start_data = vaddr;
+                }
+                if (vaddr_ef > info->end_data) {
+                    info->end_data = vaddr_ef;
+                }
+                if (vaddr_em > info->brk) {
+                    info->brk = vaddr_em;
+                }
+            }
         }
     }
 
+    if (info->end_data == 0) {
+        info->start_data = info->end_code;
+        info->end_data = info->end_code;
+        info->brk = info->end_code;
+    }
+
     if (qemu_log_enabled()) {
-	load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+	load_symbols(ehdr, image_fd, load_bias);
     }
 
-    close(interpreter_fd);
-    free(elf_phdata);
+    close(image_fd);
+    return;
+
+ exit_read:
+    if (retval >= 0) {
+        errmsg = "Incomplete read of file header";
+        goto exit_errmsg;
+    }
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", image_name, errmsg);
+    exit(-1);
+}
+
+static void load_elf_interp(const char *filename, struct image_info *info,
+                            char bprm_buf[BPRM_BUF_SIZE])
+{
+    int fd, retval;
+
+    fd = open(path(filename), O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
 
-    *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(filename, fd, info, bprm_buf);
+    return;
+
+ exit_perror:
+    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+    exit(-1);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1404,26 +1477,21 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
+    struct image_info interp_info;
     struct elfhdr elf_ex;
-    struct elfhdr interp_elf_ex;
-    int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned char ibcs2_interpreter;
     int i;
-    abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
     abi_ulong k, elf_brk;
     int retval;
-    char * elf_interpreter;
-    abi_ulong elf_entry, interp_load_addr = 0;
+    char *elf_interpreter = NULL;
+    abi_ulong elf_entry;
     int status;
     abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
 
-    ibcs2_interpreter = 0;
     status = 0;
     load_addr = 0;
     load_bias = 0;
@@ -1466,7 +1534,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     elf_brk = 0;
     elf_stack = ~((abi_ulong)0UL);
-    elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
     end_code = 0;
     start_data = 0;
@@ -1475,82 +1542,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
 	if (elf_ppnt->p_type == PT_INTERP) {
-	    if ( elf_interpreter != NULL )
-	    {
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return -EINVAL;
-	    }
-
-	    /* This is the program interpreter used for
-	     * shared libraries - for now assume that this
-	     * is an a.out format binary
-	     */
-
-	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-	    if (elf_interpreter == NULL) {
-		free (elf_phdata);
-		close(bprm->fd);
-		return -ENOMEM;
-	    }
-
             if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
-                       elf_ppnt->p_filesz);
+                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
             } else {
+                elf_interpreter = alloca(elf_ppnt->p_filesz);
 		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
                                elf_ppnt->p_offset);
                 if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary2");
+                    perror("load_elf_binary");
                     exit(-1);
                 }
 	    }
-
-	    /* If the program interpreter is one of these two,
-	       then assume an iBCS2 image. Otherwise assume
-	       a native linux image. */
-
-	    /* JRP - Need to add X86 lib dir stuff here... */
-
-	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-                ibcs2_interpreter = 1;
-	    }
-
-            retval = open(path(elf_interpreter), O_RDONLY);
-            if (retval < 0) {
-                perror(elf_interpreter);
-                exit(-1);
-            }
-            interpreter_fd = retval;
-
-            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
-            if (retval < 0) {
-		perror("load_elf_binary3");
-		exit(-1);
-	    }
-            if (retval < BPRM_BUF_SIZE) {
-                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
-            }
-
-            interp_elf_ex = *((struct elfhdr *) bprm->buf);
 	}
 	elf_ppnt++;
     }
 
-    /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter) {
-        if (!elf_check_ident(&interp_elf_ex)) {
-	    free(elf_interpreter);
-	    free(elf_phdata);
-	    close(bprm->fd);
-            close(interpreter_fd);
-	    return -ELIBBAD;
-	}
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1648,7 +1654,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
-                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1681,19 +1686,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     start_data += load_bias;
     end_data += load_bias;
 
-    if (elf_interpreter) {
-        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                    &interp_load_addr, bprm->buf);
-        reloc_func_desc = interp_load_addr;
-	free(elf_interpreter);
-
-	if (elf_entry == ~((abi_ulong)0UL)) {
-	    printf("Unable to load interpreter\n");
-	    free(elf_phdata);
-	    exit(-1);
-	    return 0;
-	}
-    }
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = elf_entry;
+    info->start_brk = info->brk = elf_brk;
+    info->end_code = end_code;
+    info->start_code = start_code;
+    info->start_data = start_data;
+    info->end_data = end_data;
+    info->personality = PER_LINUX;
 
     free(elf_phdata);
 
@@ -1702,46 +1703,38 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     close(bprm->fd);
-    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
-#ifdef LOW_ELF_STACK
-    info->start_stack = bprm->p = elf_stack - 4;
-#endif
-    bprm->p = create_elf_tables(bprm->p,
-                                bprm->argc,
-                                bprm->envc,
-                                &elf_ex,
-                                load_addr, load_bias,
-                                interp_load_addr,
-                                info);
-    info->load_addr = reloc_func_desc;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->start_stack = bprm->p;
+    if (elf_interpreter) {
+        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
 
-#if 0
-    printf("(start_brk) %x\n" , info->start_brk);
-    printf("(end_code) %x\n" , info->end_code);
-    printf("(start_code) %x\n" , info->start_code);
-    printf("(end_data) %x\n" , info->end_data);
-    printf("(start_stack) %x\n" , info->start_stack);
-    printf("(brk) %x\n" , info->brk);
-#endif
+        /* If the program interpreter is one of these two, then assume
+           an iBCS2 image.  Otherwise assume a native linux image.  */
 
-    if ( info->personality == PER_SVR4 )
-    {
-        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-           and some applications "depend" upon this behavior.
-           Since we do not have the power to recompile these, we
-           emulate the SVr4 behavior.  Sigh.  */
-        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
+        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
+            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
+            info->personality = PER_SVR4;
+
+            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+               and some applications "depend" upon this behavior.  Since
+               we do not have the power to recompile these, we emulate
+               the SVr4 behavior.  Sigh.  */
+            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                        MAP_FIXED | MAP_PRIVATE, -1, 0);
+        }
     }
 
-    info->entry = elf_entry;
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+                                info, (elf_interpreter ? &interp_info : NULL));
+    info->start_stack = bprm->p;
+
+    /* If we have an interpreter, set that as the program's entry point.
+       Copy the load_addr as well, to help PPC64 interpret the entry
+       point as a function descriptor.  Do this after creating elf tables
+       so that we copy the original program entry point into the AUXV.  */
+    if (elf_interpreter) {
+        info->load_addr = interp_info.load_addr;
+        info->entry = interp_info.entry;
+    }
 
 #ifdef USE_ELF_CORE_DUMP
     bprm->core_dump = &elf_core_dump;
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (9 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
                     ` (2 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

... Well, sortof.  The Makefile bits are broken.
Patch to load the vdso into the running program to follow.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 Makefile                  |    3 +-
 pc-bios/Makefile          |    5 ++
 pc-bios/vdso-linux-x64.S  |  102 +++++++++++++++++++++++++++++++++++++++++++++
 pc-bios/vdso-linux-x64.ld |   81 +++++++++++++++++++++++++++++++++++
 pc-bios/vdso-linux-x64.so |  Bin 0 -> 7515 bytes
 5 files changed, 190 insertions(+), 1 deletions(-)
 create mode 100644 pc-bios/vdso-linux-x64.S
 create mode 100644 pc-bios/vdso-linux-x64.ld
 create mode 100755 pc-bios/vdso-linux-x64.so

diff --git a/Makefile b/Makefile
index 18e7368..c6d1de5 100644
--- a/Makefile
+++ b/Makefile
@@ -180,7 +180,8 @@ pxe-e1000.bin \
 pxe-ne2k_pci.bin pxe-pcnet.bin \
 pxe-rtl8139.bin pxe-virtio.bin \
 bamboo.dtb petalogix-s3adsp1800.dtb \
-multiboot.bin linuxboot.bin
+multiboot.bin linuxboot.bin \
+vdso-linux-x64.so
 else
 BLOBS=
 endif
diff --git a/pc-bios/Makefile b/pc-bios/Makefile
index 315288d..70e2485 100644
--- a/pc-bios/Makefile
+++ b/pc-bios/Makefile
@@ -15,5 +15,10 @@ all: $(TARGETS)
 %.dtb: %.dts
 	dtc -I dts -O dtb -o $@ $<
 
+vdso-linux-x64.so: vdso-linux-x64.o vdso-linux-x64.ld
+	$(CC) -nostdlib -shared -Wl,-T,vdso-linux-x64.ld \
+	  -Wl,-h,linux-vdso.so.1 -Wl,--hash-style=both \
+	  vdso-linux-x64.o -o $@
+
 clean:
 	rm -f $(TARGETS) *.o *~
diff --git a/pc-bios/vdso-linux-x64.S b/pc-bios/vdso-linux-x64.S
new file mode 100644
index 0000000..e7784c9
--- /dev/null
+++ b/pc-bios/vdso-linux-x64.S
@@ -0,0 +1,102 @@
+/*
+ *  x86-64 linux replacement vdso.
+ *
+ *  Copyright (c) 2010 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/unistd.h>
+
+	.globl	__vdso_clock_gettime
+	.type	__vdso_clock_gettime, @function
+	.balign	16
+	.cfi_startproc
+__vdso_clock_gettime:
+	mov	$__NR_clock_gettime, %eax
+	syscall
+	ret
+	.cfi_endproc
+	.size	__vdso_clock_gettime, . - __vdso_clock_gettime
+
+clock_gettime = __vdso_clock_gettime
+	.weak	clock_gettime
+
+
+	.globl	__vdso_gettimeofday
+	.type	__vdso_gettimeofday, @function
+	.balign	16
+	.cfi_startproc
+__vdso_gettimeofday:
+	mov	$__NR_gettimeofday, %eax
+	syscall
+	ret
+	.cfi_endproc
+	.size	__vdso_gettimeofday, . - __vdso_gettimeofday
+
+gettimeofday = __vdso_gettimeofday
+	.weak	gettimeofday
+
+
+	.globl	__vdso_getcpu
+	.type	__vdso_getcpu, @function
+	.balign	16
+	.cfi_startproc
+__vdso_getcpu:
+	/* ??? There is no syscall number for this allocated on x64.
+	   We can handle this several ways:
+
+	   (1) Invent a syscall number for use within qemu.
+               It should be easy enough to pick a number that
+               is well out of the way of the kernel numbers.
+
+           (2) Force the emulated cpu to support the rdtscp insn,
+	       and initialize the TSC_AUX value the appropriate value.
+
+	   (3) Pretend that we're always running on cpu 0.
+
+	   This last is the one that's implemented here, with the
+	   tiny bit of extra code to support rdtscp in place.  */
+
+	xor	%ecx, %ecx		/* rdtscp w/ tsc_aux = 0 */
+
+	/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
+	test	%rdi, %rdi
+	jz	1f
+	mov	%ecx, %eax
+	and	$0xfff, %eax
+	mov	%eax, (%rdi)
+
+	/* if (node != NULL) *node = (ecx >> 12); */
+1:	test	%rsi, %rsi
+	jz	2f
+	shr	$12, %ecx
+	mov	%ecx, (%rsi)
+
+2:	xor	%eax, %eax
+	ret
+	.cfi_endproc
+	.size	__vdso_getcpu, . - __vdso_getcpu
+
+getcpu = __vdso_getcpu
+	.weak	getcpu
+
+/* ??? Perhaps add elf notes.  E.g.
+
+   #include <linux/elfnote.h>
+   ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+   ELFNOTE_END
+
+   but what version number would we set for QEMU?  */
diff --git a/pc-bios/vdso-linux-x64.ld b/pc-bios/vdso-linux-x64.ld
new file mode 100644
index 0000000..d57d0e7
--- /dev/null
+++ b/pc-bios/vdso-linux-x64.ld
@@ -0,0 +1,81 @@
+/*
+ * Linker script for linux x64 replacement vdso.
+ *
+ *  Copyright (c) 2010 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+VERSION {
+	LINUX_2.6 {
+	global:
+		clock_gettime;
+		__vdso_clock_gettime;
+		gettimeofday;
+		__vdso_gettimeofday;
+		getcpu;
+		__vdso_getcpu;
+	local: *;
+	};
+}
+
+PHDRS {
+	phdr		PT_PHDR		FLAGS(4) PHDRS;
+	data		PT_LOAD		FLAGS(6) FILEHDR PHDRS;
+	text		PT_LOAD		FLAGS(5);
+	dynamic		PT_DYNAMIC	FLAGS(4);
+	note		PT_NOTE		FLAGS(4);
+	/* ??? Various versions of ld don't know PT_GNU_EH_FRAME. */
+	eh_frame_hdr	0x6474e550;
+}
+
+SECTIONS {
+	/* ??? We can't really prelink to any address without knowing
+	   something about the virtual memory space of the host, since
+	   that leaks over into the available memory space of the guest.  */
+	. = SIZEOF_HEADERS;
+
+	/* The following, including the FILEHDRS and PHDRS, are modified
+	   when we relocate the binary.  We want them to be initially
+	   writable for the relocation; we'll force them read-only after.  */
+	.dynamic	: { *(.dynamic) }	:data :dynamic
+	.dynsym		: { *(.dynsym) }	:data
+	.data		: {
+		/* There ought not be any real read-write data.
+		   But since we manipulated the segment layout,
+		   we have to put these sections somewhere.  */
+		*(.data*)
+		*(.sdata*)
+		*(.got.plt) *(.got)
+		*(.gnu.linkonce.d.*)
+		*(.bss*)
+		*(.dynbss*)
+		*(.gnu.linkonce.b.*)
+	}
+
+	. += 4096;
+	.hash		: { *(.hash) }		:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+	.note		: { *(.note*) }		:text :note
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }	:text :eh_frame_hdr
+	.eh_frame	: { *(.eh_frame) }	:text
+	.rodata		: { *(.rodata) }
+
+	. = ALIGN(0x100);
+	.text		: { *(.text*) }		:text	=0x90909090
+}
diff --git a/pc-bios/vdso-linux-x64.so b/pc-bios/vdso-linux-x64.so
new file mode 100755
index 0000000000000000000000000000000000000000..5ebf5959f9dac5065428148e7625f58c722e1cca
GIT binary patch
literal 7515
zcmeHMO>Z1U5Uus%*iM{y6Cwl{#0nW7EEvfVLXjZIcKj8xI3d_l!ezYij=dJ%U9iWI
z%^?^OD>4#Nj&MZWI6#g*@TnkV@(Xf7Z~z1s6b@K90872;dYhfeh7%G(Oxr!L>s3`x
zcTM-~sQUG>!gyOIBP>~YRwC&>#|)Wb$7F~@a#Z%{H7ENOMed0>XrOb2c-p!qcA6eE
zeD78^vQ9%3$wvhI+O=-n8;N(|CvA==(hoGodBw()L^o+QFg?c!AJlga>!k(uIa-LY
zMLGRLSVH?_^GhP_iS#=Vd5cEa74n?#Z-3Tn&}`fM5et-CCNrj2EDn2}TFw~mGrZsM
z_qywE*2ejV$>uIMO@7Yw=Ju~ZR<csIb-@APIXx=fBDOyH+#nuOK9}GhHv1%x#}4~s
zKa<KIlwa!#u`-|%?DN(?`b8Pkit!|QuD8f2y`&LHBalWQjX)ZKGy-V^(g>sxNF$I&
zAdNs8fiwdDs|X;S(WMo63*>s3&(UU7n9pH82KF6Vf#8t0fXy3+^O=!AHo&0|a2IF3
zc~!3WUcG#B^T!9?KVE%n;H&=rtLKBt*~@kD{R^d)nm@Nxn|s+`2*Pl&5|A{pHeV{P
zH*s^Xtjf}2b#?6txO)0OD1{SKGiUuH-cx!%jHvk!Ove7+`|OwfNFhC>mANg9y-oGI
zs~={WUP8VF1+f5!c}`5t$n~E(zYGQjCO+st_x8J=e$+R<aq`<tZ}#cD*^Fvu&uDvE
zaaysYxTMH_Gq0VI%vvtf+uhNLTnu=O1p#Ev2qO3=wcgU2<O|B()XH3sHvjWw`+J>2
zPy4l=M=nKk*`AHdgI`Z>*2Au?oyY1uB3m7ko4aBA7e9Az9T@!lns_Vgm9ThTF<f?7
zW~;PbEmjui#M6daDHg+`cnj54uUuRyJ3d@?%!OciWwBO`34TeuYAp=J3(Efda<LNl
z<&xS{5-$wa!f4R{z@=CFz@EW+Lt(y-h;@R({m8YEb99vdMQ)Y*l=)ZU4YPwkZ0OHC
z?BmMe7Q8?6oJ88GNmS@h#Qwv+=lz*4CLVQe4L$v^&rptN-PK$#{h41T4#7wZ_4IeF
z+k1Q`fnz?J$ow<yEu0i(R9p3?`!nB6JY<%<e-d9%J#yFNXR(pB5IO&3{GFBBX#?+7
z`X}@KeKa&=+(^%B19PJP-SYjkPx@maH~W8Q<0sD2(J&eRi{{Vu$vigkSi+y{mh?ew
zaP5%;9<%)RrDjsw$>-NR_GZ(a2c49&!01avP&t0CYy1Yby8n&nB`xx%>!xu{-oK$}
z(a7p(8~eCPpVg<u{n<q8IPN@WfIh3gO59Iz`}W3pOq}1-*avaGL%6Qvd}m|5#`&(s
z`BR+V+c;l}^ZSJBCeGhJ-yn}TX7qd`86TV*f#>^&_IYizI&blmZ*@+Beb?$72EV1P
z&QD&l{*&i33&tnURjSqx*E!df_@n2hhMzxiT>Oc`sgdD=e`<XE#j$CBdU&KT=1cs$
X=k`~OeHQ)A7f?*40=|k`eoXxZDW(!W

literal 0
HcmV?d00001

-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (8 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
                     ` (3 subsequent siblings)
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  201 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 193 insertions(+), 8 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5771344..e8eca86 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -183,6 +183,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
 }
 
+#define VDSO_BASENAME  "vdso-linux-x64.so"
+
 #else
 
 #define ELF_START_MMAP 0x80000000
@@ -801,6 +803,10 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define ELF_HWCAP 0
 #endif
 
+#ifndef VDSO_BASENAME
+#define VDSO_BASENAME NULL
+#endif
+
 #ifdef TARGET_ABI32
 #undef ELF_CLASS
 #define ELF_CLASS ELFCLASS32
@@ -1077,7 +1083,8 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr *exec,
                                    struct image_info *info,
-                                   struct image_info *interp_info)
+                                   struct image_info *interp_info,
+                                   struct image_info *vdso_info)
 {
     abi_ulong sp;
     int size;
@@ -1100,16 +1107,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
      */
     sp = sp &~ (abi_ulong)15;
     size = (DLINFO_ITEMS + 1) * 2;
-    if (k_platform)
+    if (k_platform) {
         size += 2;
+    }
+    if (vdso_info) {
+        size += 4;
+    }
 #ifdef DLINFO_ARCH_ITEMS
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
     size += envc + argc + 2;
     size += 1;	/* argc itself */
     size *= n;
-    if (size & 15)
+    if (size & 15) {
         sp -= 16 - (size & 15);
+    }
 
     /* This is correct because Linux defines
      * elf_addr_t as Elf32_Off / Elf64_Off
@@ -1126,7 +1138,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
+    if (interp_info) {
+        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
+    }
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
     NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
@@ -1135,8 +1149,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
-    if (k_platform)
+    if (k_platform) {
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
+    }
+    if (vdso_info) {
+        NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry);
+        NEW_AUX_ENT(AT_SYSINFO_EHDR, vdso_info->load_addr);
+    }
 #ifdef ARCH_DLINFO
     /*
      * ARCH_DLINFO must come last so platform specific code can enforce
@@ -1381,6 +1400,165 @@ static void load_elf_interp(const char *filename, struct image_info *info,
     exit(-1);
 }
 
+static void load_elf_vdso(const char *basename, struct image_info *info,
+                          char bprm_buf[BPRM_BUF_SIZE])
+{
+    const char *errmsg;
+    char *filename;
+    int fd, retval, i;
+    abi_ulong load_bias;
+
+    /* ??? What we really need access to is qemu_find_file, but that is
+       only built for system targets at the moment.  */
+    filename = alloca(strlen(CONFIG_QEMU_SHAREDIR "/") + strlen(basename) + 1);
+    stpcpy(stpcpy(filename, CONFIG_QEMU_SHAREDIR "/"), basename);
+
+    fd = open(filename, O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
+
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(basename, fd, info, NULL, bprm_buf);
+    load_bias = info->load_bias;
+
+    /* We most likely need to relocate the VDSO image.  The one built into
+       the kernel is built for a fixed address.  The one built for QEMU is
+       not, since that requires close control of the guest address space.  */
+    if (load_bias) {
+        struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+        struct elf_phdr *phdr;
+        abi_ulong dynamic_addr = -1;
+        abi_ulong dynsym_addr = -1;
+
+        /* ??? Assume QEMU's VDSO is built "properly", which arranges
+           for the PHDRs, and all the sections manipulated below, to
+           be included with a writable load segment.  */
+
+        /* ??? One might think that we'd need to relocate ehdr.e_entry,
+           but for some reason glibc does that one itself, though that
+           is also available via the AT_SYSINFO entry.  */
+
+        /* Relocate the program headers.  */
+        phdr = (struct elf_phdr *)g2h(info->load_addr + ehdr->e_phoff); 
+        bswap_phdr(phdr, ehdr->e_phnum);
+        for (i = 0; i < ehdr->e_phnum; ++i) {
+            phdr[i].p_vaddr += load_bias;
+            phdr[i].p_paddr += load_bias;
+            if (phdr[i].p_type == PT_DYNAMIC) {
+                dynamic_addr = phdr[i].p_vaddr;
+            }
+        }
+        bswap_phdr(phdr, ehdr->e_phnum);
+
+        /* Relocate the DYNAMIC entries.  */
+        if (dynamic_addr != -1) {
+            abi_ulong tag, val, *dyn = (abi_ulong *)g2h(dynamic_addr);
+            do {
+                tag = tswapl(dyn[0]);
+                val = tswapl(dyn[1]);
+                switch (tag) {
+                case DT_SYMTAB:
+                    dynsym_addr = load_bias + val;
+                    dyn[1] = tswapl(dynsym_addr);
+                    break;
+                case DT_SYMENT:
+                    if (val != sizeof(struct elf_sym)) {
+                        errmsg = "VDSO has an unexpected dynamic symbol size";
+                        goto exit_errmsg;
+                    }
+                    break;
+
+                case DT_HASH:
+                case DT_STRTAB:
+                case DT_VERDEF:
+                case DT_VERSYM:
+                case DT_ADDRRNGLO ... DT_ADDRRNGHI:
+                    /* These entries store an address in the entry.  */
+                    dyn[1] = tswapl(load_bias + val);
+                    break;
+
+                case DT_NULL:
+                case DT_STRSZ:
+                case DT_SONAME:
+                case DT_DEBUG:
+                case DT_FLAGS:
+                case DT_FLAGS_1:
+                case DT_VERDEFNUM:
+                case DT_VALRNGLO ... DT_VALRNGHI:
+                    /* These entries store an integer in the entry.  */
+                    break;
+
+                case DT_REL:
+                case DT_RELA:
+                    /* These entries indicate that the VDSO was built
+                       incorrectly.  It should not have real relocations.  */
+                    errmsg = "VDSO has relocations";
+                    goto exit_errmsg;
+                case DT_NEEDED:
+                case DT_VERNEED:
+                    errmsg = "VDSO has external dependancies";
+                    goto exit_errmsg;
+
+                default:
+                    /* This is probably something target specific.  */
+                    errmsg = "VDSO has unknown DYNAMIC entry";
+                    goto exit_errmsg;
+                }
+                dyn += 2;
+            } while (tag != DT_NULL);
+        }
+
+        /* Relocate the dynamic symbol table.  */
+        if (dynsym_addr != -1) {
+            struct elf_shdr *shdr;
+            struct elf_sym *sym;
+            int dynsym_size = 0;
+
+            /* Read the section headers to find out the size of the
+               dynamic symbol table.  */
+            shdr = (struct elf_shdr *)g2h(info->load_addr + ehdr->e_shoff);
+            for (i = 0; i < ehdr->e_shnum; ++i) {
+                abi_ulong addr = tswapl(shdr[i].sh_addr) + load_bias;
+                if (addr == dynsym_addr) {
+                    dynsym_size = tswapl(shdr[i].sh_size);
+                    break;
+                }
+            }
+
+            sym = (struct elf_sym *)g2h(dynsym_addr);
+            for (i = 0; i < dynsym_size / sizeof(*sym); ++i) {
+                sym[i].st_value = tswapl(tswapl(sym[i].st_value) + load_bias);
+            }
+        }
+    }
+
+    /* Mark the VDSO writable segment read-only.  */
+    /* ??? This assumes that the VDSO implementation doesn't actually
+       have any truely writable data.  Perhaps we should instead use
+       the PT_GNU_RELRO header to indicate that we really want this.  */
+    retval = target_mprotect(info->start_data, info->brk - info->start_data,
+                             PROT_READ);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    return;
+
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", filename, errmsg);
+    exit(-1);
+}
+
+
 static int symfind(const void *s0, const void *s1)
 {
     struct elf_sym *key = (struct elf_sym *)s0;
@@ -1515,7 +1693,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
-    struct image_info interp_info;
+    struct image_info interp_info, vdso_info;
     struct elfhdr elf_ex;
     char *elf_interpreter = NULL;
 
@@ -1562,8 +1740,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         }
     }
 
-    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
-                                info, (elf_interpreter ? &interp_info : NULL));
+    /* If we've been given a VDSO to load, do so.  */
+    if (VDSO_BASENAME) {
+        load_elf_vdso(VDSO_BASENAME, &vdso_info, bprm->buf);
+    }
+
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc,
+                                &elf_ex, info,
+                                (elf_interpreter ? &interp_info : NULL),
+                                (VDSO_BASENAME ? &vdso_info : NULL));
     info->start_stack = bprm->p;
 
     /* If we have an interpreter, set that as the program's entry point.
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (10 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

This requires moving the PT_INTERP extraction and GUEST_BASE
handling into load_elf_image.  Key this off a non-null pointer
argument to receive the interpreter name.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  272 ++++++++++---------------------------------------
 1 files changed, 56 insertions(+), 216 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index c58387a..5771344 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -829,9 +829,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss+brk space allocated to ET_DYN executables */
-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-
 /* Necessary parameters */
 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -1168,7 +1165,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
    On return: INFO values will be filled in, as necessary or available.  */
 
 static void load_elf_image(const char *image_name, int image_fd,
-                           struct image_info *info,
+                           struct image_info *info, char **pinterp_name,
                            char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
@@ -1228,6 +1225,20 @@ static void load_elf_image(const char *image_name, int image_fd,
         if (load_addr == -1) {
             goto exit_perror;
         }
+    } else if (pinterp_name != NULL) {
+        /* This is the main executable.  Make sure that the low
+           address does not conflict with MMAP_MIN_ADDR.  */
+        /* ??? Ideally, we'd check against more than just the
+           minimum mmap address, but also against the QEMU program
+           image itself.  I.e. find a range that does not conflict
+           with PAGE_RESERVED entries.  Except that we havn't read
+           those in yet, since that code uses the guest_base that
+           we set up here.  Blah.  */
+#if defined(CONFIG_USE_GUEST_BASE)
+        if (HOST_PAGE_ALIGN(loaddr) < mmap_min_addr) {
+            guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
+        }
+#endif
     }
     load_bias = load_addr - loaddr;
 
@@ -1289,6 +1300,33 @@ static void load_elf_image(const char *image_name, int image_fd,
                     info->brk = vaddr_em;
                 }
             }
+        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
+            char *interp_name;
+
+            if (*pinterp_name) {
+                errmsg = "Multiple PT_INTERP entries";
+                goto exit_errmsg;
+            }
+            interp_name = malloc(eppnt->p_filesz);
+            if (!interp_name) {
+                goto exit_perror;
+            }
+
+            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(interp_name, bprm_buf + eppnt->p_offset,
+                       eppnt->p_filesz);
+            } else {
+                retval = pread(image_fd, interp_name, eppnt->p_filesz,
+                               eppnt->p_offset);
+                if (retval != eppnt->p_filesz) {
+                    goto exit_perror;
+                }
+            }
+            if (interp_name[eppnt->p_filesz - 1] != 0) {
+                errmsg = "Invalid PT_INTERP entry";
+                goto exit_errmsg;
+            }
+            *pinterp_name = interp_name;
         }
     }
 
@@ -1335,7 +1373,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
 
-    load_elf_image(filename, fd, info, bprm_buf);
+    load_elf_image(filename, fd, info, NULL, bprm_buf);
     return;
 
  exit_perror:
@@ -1479,230 +1517,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct image_info interp_info;
     struct elfhdr elf_ex;
-    abi_ulong load_addr, load_bias;
-    int load_addr_set = 0;
-    int i;
-    struct elf_phdr * elf_ppnt;
-    struct elf_phdr *elf_phdata;
-    abi_ulong k, elf_brk;
-    int retval;
     char *elf_interpreter = NULL;
-    abi_ulong elf_entry;
-    int status;
-    abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong elf_stack;
 
-    status = 0;
-    load_addr = 0;
-    load_bias = 0;
-    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
+    info->start_mmap = (abi_ulong)ELF_START_MMAP;
+    info->mmap = 0;
+    info->rss = 0;
 
-    /* First of all, some simple consistency checks */
-    if (!elf_check_ident(&elf_ex)) {
-        return -ENOEXEC;
-    }
-    bswap_ehdr(&elf_ex);
-    if (!elf_check_ehdr(&elf_ex)) {
-        return -ENOEXEC;
-    }
+    load_elf_image(bprm->filename, bprm->fd, info,
+                   &elf_interpreter, bprm->buf);
+
+    /* ??? We need a copy of the elf header for passing to create_elf_tables.
+       If we do nothing, we'll have overwritten this when we re-use bprm->buf
+       when we load the interpreter.  */
+    elf_ex = *(struct elfhdr *)bprm->buf;
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
     if (!bprm->p) {
-        retval = -E2BIG;
-    }
-
-    /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)
-        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
-    if (elf_phdata == NULL) {
-	return -ENOMEM;
-    }
-
-    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
-    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
-    } else {
-	retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
-        if (retval != i) {
-            perror("load_elf_binary");
-            exit(-1);
-        }
-    }
-    bswap_phdr(elf_phdata, elf_ex.e_phnum);
-
-    elf_brk = 0;
-    elf_stack = ~((abi_ulong)0UL);
-    start_code = ~((abi_ulong)0UL);
-    end_code = 0;
-    start_data = 0;
-    end_data = 0;
-
-    elf_ppnt = elf_phdata;
-    for(i=0;i < elf_ex.e_phnum; i++) {
-	if (elf_ppnt->p_type == PT_INTERP) {
-            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
-            } else {
-                elf_interpreter = alloca(elf_ppnt->p_filesz);
-		retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
-                               elf_ppnt->p_offset);
-                if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary");
-                    exit(-1);
-                }
-	    }
-	}
-	elf_ppnt++;
-    }
-
-    /* OK, This is the point of no return */
-    info->end_data = 0;
-    info->end_code = 0;
-    info->start_mmap = (abi_ulong)ELF_START_MMAP;
-    info->mmap = 0;
-    elf_entry = (abi_ulong) elf_ex.e_entry;
-
-#if defined(CONFIG_USE_GUEST_BASE)
-    /*
-     * In case where user has not explicitly set the guest_base, we
-     * probe here that should we set it automatically.
-     */
-    if (!have_guest_base) {
-        /*
-         * Go through ELF program header table and find out whether
-	 * any of the segments drop below our current mmap_min_addr and
-         * in that case set guest_base to corresponding address.
-         */
-        for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-             i++, elf_ppnt++) {
-            if (elf_ppnt->p_type != PT_LOAD)
-                continue;
-            if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
-                guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
-                break;
-            }
-        }
+        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
+        exit(-1);
     }
-#endif /* CONFIG_USE_GUEST_BASE */
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
-    info->rss = 0;
     bprm->p = setup_arg_pages(bprm->p, bprm, info);
-    info->start_stack = bprm->p;
-
-    /* Now we do a little grungy work by mmaping the ELF image into
-     * the correct location in memory.  At this point, we assume that
-     * the image should be loaded at fixed address, not at a variable
-     * address.
-     */
-
-    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
-        int elf_prot = 0;
-        int elf_flags = 0;
-        abi_ulong error;
-
-	if (elf_ppnt->p_type != PT_LOAD)
-            continue;
-
-        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
-        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
-        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
-            elf_flags |= MAP_FIXED;
-        } else if (elf_ex.e_type == ET_DYN) {
-            /* Try and get dynamic programs out of the way of the default mmap
-               base, as well as whatever program they might try to exec.  This
-               is because the brk will follow the loader, and is not movable.  */
-            /* NOTE: for qemu, we do a big mmap to get enough space
-               without hardcoding any address */
-            error = target_mmap(0, ET_DYN_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
-            if (error == -1) {
-                perror("mmap");
-                exit(-1);
-            }
-            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
-        }
-
-        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
-                            (elf_ppnt->p_filesz +
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-                            elf_prot,
-                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
-                            bprm->fd,
-                            (elf_ppnt->p_offset -
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
-        if (error == -1) {
-            perror("mmap");
-            exit(-1);
-        }
-
-#ifdef LOW_ELF_STACK
-        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
-            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
-#endif
-
-        if (!load_addr_set) {
-            load_addr_set = 1;
-            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-            if (elf_ex.e_type == ET_DYN) {
-                load_bias += error -
-                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
-                load_addr += load_bias;
-            }
-        }
-        k = elf_ppnt->p_vaddr;
-        if (k < start_code)
-            start_code = k;
-        if (start_data < k)
-            start_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-            end_code = k;
-        if (end_data < k)
-            end_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) {
-            elf_brk = TARGET_PAGE_ALIGN(k);
-        }
-
-        /* If the load segment requests extra zeros (e.g. bss), map it.  */
-        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
-            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
-            zero_bss(base + elf_ppnt->p_filesz,
-                     base + elf_ppnt->p_memsz, elf_prot);
-        }
-    }
-
-    elf_entry += load_bias;
-    elf_brk += load_bias;
-    start_code += load_bias;
-    end_code += load_bias;
-    start_data += load_bias;
-    end_data += load_bias;
-
-    info->load_bias = load_bias;
-    info->load_addr = load_addr;
-    info->entry = elf_entry;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->personality = PER_LINUX;
-
-    free(elf_phdata);
-
-    if (qemu_log_enabled()) {
-	load_symbols(&elf_ex, bprm->fd, load_bias);
-    }
-
-    close(bprm->fd);
 
     if (elf_interpreter) {
         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
@@ -1734,6 +1573,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     if (elf_interpreter) {
         info->load_addr = interp_info.load_addr;
         info->entry = interp_info.entry;
+        free(elf_interpreter);
     }
 
 #ifdef USE_ELF_CORE_DUMP
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (12 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  594 +++++++++++++++++++++++++-------------------------
 1 files changed, 301 insertions(+), 293 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ead22fc..ab741fd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -35,18 +35,17 @@
  * These occupy the top three bytes.
  */
 enum {
-	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
-	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
-						 * (signal handling)
-						 */
-	MMAP_PAGE_ZERO =	0x0100000,
-	ADDR_COMPAT_LAYOUT =	0x0200000,
-	READ_IMPLIES_EXEC =	0x0400000,
-	ADDR_LIMIT_32BIT =	0x0800000,
-	SHORT_INODE =		0x1000000,
-	WHOLE_SECONDS =		0x2000000,
-	STICKY_TIMEOUTS	=	0x4000000,
-	ADDR_LIMIT_3GB = 	0x8000000,
+    ADDR_NO_RANDOMIZE = 0x0040000,	/* disable randomization of VA space */
+    FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to
+                                           descriptors (signal handling) */
+    MMAP_PAGE_ZERO =	0x0100000,
+    ADDR_COMPAT_LAYOUT = 0x0200000,
+    READ_IMPLIES_EXEC =	0x0400000,
+    ADDR_LIMIT_32BIT =	0x0800000,
+    SHORT_INODE =	0x1000000,
+    WHOLE_SECONDS =	0x2000000,
+    STICKY_TIMEOUTS =	0x4000000,
+    ADDR_LIMIT_3GB = 	0x8000000,
 };
 
 /*
@@ -56,30 +55,29 @@ enum {
  * conflict with error returns.
  */
 enum {
-	PER_LINUX =		0x0000,
-	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
-	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
-	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
-					 WHOLE_SECONDS | SHORT_INODE,
-	PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
-	PER_WYSEV386 =		0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
-	PER_BSD =		0x0006,
-	PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
-	PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_LINUX32 =		0x0008,
-	PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
-	PER_IRIX32 =		0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
-	PER_IRIXN32 =		0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
-	PER_IRIX64 =		0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
-	PER_RISCOS =		0x000c,
-	PER_SOLARIS =		0x000d | STICKY_TIMEOUTS,
-	PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
-	PER_HPUX =		0x0010,
-	PER_MASK =		0x00ff,
+    PER_LINUX =		0x0000,
+    PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
+    PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
+    PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_SCOSVR3 =	0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
+    PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+    PER_WYSEV386 =	0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
+    PER_BSD =		0x0006,
+    PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
+    PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_LINUX32 =	0x0008,
+    PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
+    PER_IRIX32 =	0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+    PER_IRIXN32 =	0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+    PER_IRIX64 =	0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+    PER_RISCOS =	0x000c,
+    PER_SOLARIS =	0x000d | STICKY_TIMEOUTS,
+    PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
+    PER_HPUX =		0x0010,
+    PER_MASK =		0x00ff,
 };
 
 /*
@@ -126,7 +124,7 @@ static const char *get_elf_platform(void)
 
 static uint32_t get_elf_hwcap(void)
 {
-  return thread_env->cpuid_features;
+    return thread_env->cpuid_features;
 }
 
 #ifdef TARGET_X86_64
@@ -201,7 +199,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_386
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->esp = infop->start_stack;
     regs->eip = infop->entry;
@@ -267,13 +266,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #endif
 #define ELF_ARCH	EM_ARM
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     abi_long stack = infop->start_stack;
     memset(regs, 0, sizeof(*regs));
     regs->ARM_cpsr = 0x10;
     if (infop->entry & 1)
-      regs->ARM_cpsr |= CPSR_T;
+        regs->ARM_cpsr |= CPSR_T;
     regs->ARM_pc = infop->entry & 0xfffffffe;
     regs->ARM_sp = infop->start_stack;
     /* FIXME - what to for failure of get_user()? */
@@ -317,26 +317,26 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 
 enum
 {
-  ARM_HWCAP_ARM_SWP       = 1 << 0,
-  ARM_HWCAP_ARM_HALF      = 1 << 1,
-  ARM_HWCAP_ARM_THUMB     = 1 << 2,
-  ARM_HWCAP_ARM_26BIT     = 1 << 3,
-  ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
-  ARM_HWCAP_ARM_FPA       = 1 << 5,
-  ARM_HWCAP_ARM_VFP       = 1 << 6,
-  ARM_HWCAP_ARM_EDSP      = 1 << 7,
-  ARM_HWCAP_ARM_JAVA      = 1 << 8,
-  ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
-  ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
-  ARM_HWCAP_ARM_NEON      = 1 << 11,
-  ARM_HWCAP_ARM_VFPv3     = 1 << 12,
-  ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
+    ARM_HWCAP_ARM_SWP       = 1 << 0,
+    ARM_HWCAP_ARM_HALF      = 1 << 1,
+    ARM_HWCAP_ARM_THUMB     = 1 << 2,
+    ARM_HWCAP_ARM_26BIT     = 1 << 3,
+    ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
+    ARM_HWCAP_ARM_FPA       = 1 << 5,
+    ARM_HWCAP_ARM_VFP       = 1 << 6,
+    ARM_HWCAP_ARM_EDSP      = 1 << 7,
+    ARM_HWCAP_ARM_JAVA      = 1 << 8,
+    ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
+    ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
+    ARM_HWCAP_ARM_NEON      = 1 << 11,
+    ARM_HWCAP_ARM_VFPv3     = 1 << 12,
+    ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
 };
 
-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
-                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
-                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
-                    | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
+#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF               \
+                   | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT      \
+                   | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP              \
+                   | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
 
 #endif
 
@@ -357,7 +357,8 @@ enum
 
 #define STACK_BIAS		2047
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
 #ifndef TARGET_ABI32
     regs->tstate = 0;
@@ -384,7 +385,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARC
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->psr = 0;
     regs->pc = infop->entry;
@@ -464,7 +466,7 @@ static uint32_t get_elf_hwcap(void)
 
     /* We don't have to be terribly complete here; the high points are
        Altivec/FP/SPE support.  Anything else is just a bonus.  */
-#define GET_FEATURE(flag, feature)              \
+#define GET_FEATURE(flag, feature)                                      \
     do {if (e->insns_flags & flag) features |= feature; } while(0)
     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
@@ -489,17 +491,17 @@ static uint32_t get_elf_hwcap(void)
  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  */
 #define DLINFO_ARCH_ITEMS       5
-#define ARCH_DLINFO                                                     \
-do {                                                                    \
-        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
-        /*                                                              \
-         * Now handle glibc compatibility.                              \
-         */                                                             \
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
- } while (0)
+#define ARCH_DLINFO                                     \
+    do {                                                \
+        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
+        /*                                              \
+         * Now handle glibc compatibility.              \
+         */                                             \
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+    } while (0)
 
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
@@ -559,7 +561,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #endif
 #define ELF_ARCH    EM_MIPS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->cp0_status = 2 << CP0St_KSU;
     regs->cp0_epc = infop->entry;
@@ -626,7 +629,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA	ELFDATA2MSB
 #define ELF_ARCH    EM_XILINX_MICROBLAZE
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->r1 = infop->start_stack;
@@ -647,11 +651,12 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_SH
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  /* Check other registers XXXXX */
-  regs->pc = infop->entry;
-  regs->regs[15] = infop->start_stack;
+    /* Check other registers XXXXX */
+    regs->pc = infop->entry;
+    regs->regs[15] = infop->start_stack;
 }
 
 /* See linux kernel: arch/sh/include/asm/elf.h.  */
@@ -669,7 +674,8 @@ enum {
     TARGET_REG_SYSCALL = 22
 };
 
-static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
+                                      const CPUState *env)
 {
     int i;
 
@@ -701,9 +707,10 @@ static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_CRIS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  regs->erp = infop->entry;
+    regs->erp = infop->entry;
 }
 
 #define ELF_EXEC_PAGESIZE        8192
@@ -721,9 +728,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_ARCH	EM_68K
 
 /* ??? Does this need to do anything?
-#define ELF_PLAT_INIT(_r) */
+   #define ELF_PLAT_INIT(_r) */
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->usp = infop->start_stack;
     regs->sr = 0;
@@ -773,7 +781,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA       ELFDATA2MSB
 #define ELF_ARCH       EM_ALPHA
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->ps = 8;
@@ -803,14 +812,14 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 struct exec
 {
-  unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
-  unsigned int a_text;   /* length of text, in bytes */
-  unsigned int a_data;   /* length of data, in bytes */
-  unsigned int a_bss;    /* length of uninitialized data area, in bytes */
-  unsigned int a_syms;   /* length of symbol table data in file, in bytes */
-  unsigned int a_entry;  /* start address */
-  unsigned int a_trsize; /* length of relocation info for text, in bytes */
-  unsigned int a_drsize; /* length of relocation info for data, in bytes */
+    unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
+    unsigned int a_text;   /* length of text, in bytes */
+    unsigned int a_data;   /* length of data, in bytes */
+    unsigned int a_bss;    /* length of uninitialized data area, in bytes */
+    unsigned int a_syms;   /* length of symbol table data in file, in bytes */
+    unsigned int a_entry;  /* start address */
+    unsigned int a_trsize; /* length of relocation info for text, in bytes */
+    unsigned int a_drsize; /* length of relocation info for data, in bytes */
 };
 
 
@@ -839,7 +848,7 @@ struct exec
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
-	memcpy(to, from, n);
+    memcpy(to, from, n);
 }
 
 static int load_aout_interp(void * exptr, int interp_fd);
@@ -847,7 +856,7 @@ static int load_aout_interp(void * exptr, int interp_fd);
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
-    bswap16s(&ehdr->e_type);			/* Object file type */
+    bswap16s(&ehdr->e_type);		/* Object file type */
     bswap16s(&ehdr->e_machine);		/* Architecture */
     bswap32s(&ehdr->e_version);		/* Object file version */
     bswaptls(&ehdr->e_entry);		/* Entry point virtual address */
@@ -855,16 +864,16 @@ static void bswap_ehdr(struct elfhdr *ehdr)
     bswaptls(&ehdr->e_shoff);		/* Section header table file offset */
     bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
     bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
-    bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
+    bswap16s(&ehdr->e_phentsize);	/* Program header table entry size */
     bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
-    bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
+    bswap16s(&ehdr->e_shentsize);	/* Section header table entry size */
     bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
-    bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
+    bswap16s(&ehdr->e_shstrndx);	/* Section header string table index */
 }
 
 static void bswap_phdr(struct elf_phdr *phdr)
 {
-    bswap32s(&phdr->p_type);			/* Segment type */
+    bswap32s(&phdr->p_type);		/* Segment type */
     bswaptls(&phdr->p_offset);		/* Segment file offset */
     bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
     bswaptls(&phdr->p_paddr);		/* Segment physical address */
@@ -936,7 +945,7 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 	while (*tmp++);
 	len = tmp - tmp1;
 	if (p < len) {  /* this shouldn't happen - 128kB */
-		return 0;
+            return 0;
 	}
 	while (len) {
 	    --p; --tmp; --len;
@@ -955,12 +964,12 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 	        *(pag + offset) = *tmp;
 	    }
 	    else {
-	      int bytes_to_copy = (len > offset) ? offset : len;
-	      tmp -= bytes_to_copy;
-	      p -= bytes_to_copy;
-	      offset -= bytes_to_copy;
-	      len -= bytes_to_copy;
-	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
+                int bytes_to_copy = (len > offset) ? offset : len;
+                tmp -= bytes_to_copy;
+                p -= bytes_to_copy;
+                offset -= bytes_to_copy;
+                len -= bytes_to_copy;
+                memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
 	    }
 	}
     }
@@ -1055,77 +1064,77 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    abi_ulong interp_load_addr, int ibcs,
                                    struct image_info *info)
 {
-        abi_ulong sp;
-        int size;
-        abi_ulong u_platform;
-        const char *k_platform;
-        const int n = sizeof(elf_addr_t);
-
-        sp = p;
-        u_platform = 0;
-        k_platform = ELF_PLATFORM;
-        if (k_platform) {
-            size_t len = strlen(k_platform) + 1;
-            sp -= (len + n - 1) & ~(n - 1);
-            u_platform = sp;
-            /* FIXME - check return value of memcpy_to_target() for failure */
-            memcpy_to_target(sp, k_platform, len);
-        }
-	/*
-	 * Force 16 byte _final_ alignment here for generality.
-	 */
-        sp = sp &~ (abi_ulong)15;
-        size = (DLINFO_ITEMS + 1) * 2;
-        if (k_platform)
-          size += 2;
+    abi_ulong sp;
+    int size;
+    abi_ulong u_platform;
+    const char *k_platform;
+    const int n = sizeof(elf_addr_t);
+
+    sp = p;
+    u_platform = 0;
+    k_platform = ELF_PLATFORM;
+    if (k_platform) {
+        size_t len = strlen(k_platform) + 1;
+        sp -= (len + n - 1) & ~(n - 1);
+        u_platform = sp;
+        /* FIXME - check return value of memcpy_to_target() for failure */
+        memcpy_to_target(sp, k_platform, len);
+    }
+    /*
+     * Force 16 byte _final_ alignment here for generality.
+     */
+    sp = sp &~ (abi_ulong)15;
+    size = (DLINFO_ITEMS + 1) * 2;
+    if (k_platform)
+        size += 2;
 #ifdef DLINFO_ARCH_ITEMS
-	size += DLINFO_ARCH_ITEMS * 2;
+    size += DLINFO_ARCH_ITEMS * 2;
 #endif
-        size += envc + argc + 2;
-	size += (!ibcs ? 3 : 1);	/* argc itself */
-        size *= n;
-        if (size & 15)
-            sp -= 16 - (size & 15);
-
-        /* This is correct because Linux defines
-         * elf_addr_t as Elf32_Off / Elf64_Off
-         */
+    size += envc + argc + 2;
+    size += (!ibcs ? 3 : 1);	/* argc itself */
+    size *= n;
+    if (size & 15)
+        sp -= 16 - (size & 15);
+
+    /* This is correct because Linux defines
+     * elf_addr_t as Elf32_Off / Elf64_Off
+     */
 #define NEW_AUX_ENT(id, val) do {		\
-            sp -= n; put_user_ual(val, sp);	\
-            sp -= n; put_user_ual(id, sp);	\
-          } while(0)
-
-        NEW_AUX_ENT (AT_NULL, 0);
-
-        /* There must be exactly DLINFO_ITEMS entries here.  */
-        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
-        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
-        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
-        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
-        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
-        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
-        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
-        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
-        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
-        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
-        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
-        if (k_platform)
-            NEW_AUX_ENT(AT_PLATFORM, u_platform);
+        sp -= n; put_user_ual(val, sp);         \
+        sp -= n; put_user_ual(id, sp);          \
+    } while(0)
+
+    NEW_AUX_ENT (AT_NULL, 0);
+
+    /* There must be exactly DLINFO_ITEMS entries here.  */
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
+    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+    if (k_platform)
+        NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-	/*
-	 * ARCH_DLINFO must come last so platform specific code can enforce
-	 * special alignment requirements on the AUXV if necessary (eg. PPC).
-	 */
-        ARCH_DLINFO;
+    /*
+     * ARCH_DLINFO must come last so platform specific code can enforce
+     * special alignment requirements on the AUXV if necessary (eg. PPC).
+     */
+    ARCH_DLINFO;
 #endif
 #undef NEW_AUX_ENT
 
-        info->saved_auxv = sp;
+    info->saved_auxv = sp;
 
-        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
-        return sp;
+    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    return sp;
 }
 
 
@@ -1133,83 +1142,83 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
                                  abi_ulong *interp_load_addr)
 {
-	struct elf_phdr *elf_phdata  =  NULL;
-	struct elf_phdr *eppnt;
-	abi_ulong load_addr = 0;
-	int load_addr_set = 0;
-	int retval;
-	abi_ulong error;
-	int i;
+    struct elf_phdr *elf_phdata  =  NULL;
+    struct elf_phdr *eppnt;
+    abi_ulong load_addr = 0;
+    int load_addr_set = 0;
+    int retval;
+    abi_ulong error;
+    int i;
 
-	error = 0;
+    error = 0;
 
 #ifdef BSWAP_NEEDED
-        bswap_ehdr(interp_elf_ex);
+    bswap_ehdr(interp_elf_ex);
 #endif
-	/* First of all, some simple consistency checks */
-	if ((interp_elf_ex->e_type != ET_EXEC &&
-             interp_elf_ex->e_type != ET_DYN) ||
-	   !elf_check_arch(interp_elf_ex->e_machine)) {
-		return ~((abi_ulong)0UL);
-	}
+    /* First of all, some simple consistency checks */
+    if ((interp_elf_ex->e_type != ET_EXEC &&
+         interp_elf_ex->e_type != ET_DYN) ||
+        !elf_check_arch(interp_elf_ex->e_machine)) {
+        return ~((abi_ulong)0UL);
+    }
 
 
-	/* Now read in all of the header information */
+    /* Now read in all of the header information */
 
-	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-	    return ~(abi_ulong)0UL;
+    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
+        return ~(abi_ulong)0UL;
 
-	elf_phdata =  (struct elf_phdr *)
-		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    elf_phdata =  (struct elf_phdr *)
+        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-	if (!elf_phdata)
-	  return ~((abi_ulong)0UL);
+    if (!elf_phdata)
+        return ~((abi_ulong)0UL);
 
-	/*
-	 * If the size of this structure has changed, then punt, since
-	 * we will be doing the wrong thing.
-	 */
-	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-	    free(elf_phdata);
-	    return ~((abi_ulong)0UL);
-        }
+    /*
+     * If the size of this structure has changed, then punt, since
+     * we will be doing the wrong thing.
+     */
+    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
+        free(elf_phdata);
+        return ~((abi_ulong)0UL);
+    }
 
-	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-	if(retval >= 0) {
-	    retval = read(interpreter_fd,
-			   (char *) elf_phdata,
-			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-	}
-	if (retval < 0) {
-		perror("load_elf_interp");
-		exit(-1);
-		free (elf_phdata);
-		return retval;
- 	}
+    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
+    if(retval >= 0) {
+        retval = read(interpreter_fd,
+                      (char *) elf_phdata,
+                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    }
+    if (retval < 0) {
+        perror("load_elf_interp");
+        exit(-1);
+        free (elf_phdata);
+        return retval;
+    }
 #ifdef BSWAP_NEEDED
-	eppnt = elf_phdata;
-	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-            bswap_phdr(eppnt);
-        }
+    eppnt = elf_phdata;
+    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+        bswap_phdr(eppnt);
+    }
 #endif
 
-        if (interp_elf_ex->e_type == ET_DYN) {
-            /* in order to avoid hardcoding the interpreter load
-               address in qemu, we allocate a big enough memory zone */
-            error = target_mmap(0, INTERP_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
-            if (error == -1) {
-                perror("mmap");
-                exit(-1);
-            }
-            load_addr = error;
-            load_addr_set = 1;
+    if (interp_elf_ex->e_type == ET_DYN) {
+        /* in order to avoid hardcoding the interpreter load
+           address in qemu, we allocate a big enough memory zone */
+        error = target_mmap(0, INTERP_MAP_SIZE,
+                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
+                            -1, 0);
+        if (error == -1) {
+            perror("mmap");
+            exit(-1);
         }
+        load_addr = error;
+        load_addr_set = 1;
+    }
 
-	eppnt = elf_phdata;
-	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
-	  if (eppnt->p_type == PT_LOAD) {
+    eppnt = elf_phdata;
+    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+        if (eppnt->p_type == PT_LOAD) {
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
 	    abi_ulong vaddr = 0;
@@ -1222,22 +1231,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	    	vaddr = eppnt->p_vaddr;
 	    }
 	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-		 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-		 elf_prot,
-		 elf_type,
-		 interpreter_fd,
-		 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
+                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
+                                elf_prot,
+                                elf_type,
+                                interpreter_fd,
+                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
 
 	    if (error == -1) {
-	      /* Real error */
-	      close(interpreter_fd);
-	      free(elf_phdata);
-	      return ~((abi_ulong)0UL);
+                /* Real error */
+                close(interpreter_fd);
+                free(elf_phdata);
+                return ~((abi_ulong)0UL);
 	    }
 
 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-	      load_addr = error;
-	      load_addr_set = 1;
+                load_addr = error;
+                load_addr_set = 1;
 	    }
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
@@ -1246,15 +1255,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 zero_bss(base + eppnt->p_filesz,
                          base + eppnt->p_memsz, elf_prot);
             }
-	  }
+        }
 
-	/* Now use mmap to map the library into memory. */
+    /* Now use mmap to map the library into memory. */
 
-	close(interpreter_fd);
-	free(elf_phdata);
+    close(interpreter_fd);
+    free(elf_phdata);
 
-	*interp_load_addr = load_addr;
-	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    *interp_load_addr = load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1356,8 +1365,8 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 #endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
-                syms[i].st_shndx >= SHN_LORESERVE ||
-                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            syms[i].st_shndx >= SHN_LORESERVE ||
+            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
             nsyms--;
             if (i < nsyms) {
                 syms[i] = syms[nsyms];
@@ -1425,8 +1434,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-       				(! elf_check_arch(elf_ex.e_machine))) {
-	    return -ENOEXEC;
+        (! elf_check_arch(elf_ex.e_machine))) {
+        return -ENOEXEC;
     }
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
@@ -1445,7 +1454,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
     if(retval > 0) {
 	retval = read(bprm->fd, (char *) elf_phdata,
-				elf_ex.e_phentsize * elf_ex.e_phnum);
+                      elf_ex.e_phentsize * elf_ex.e_phnum);
     }
 
     if (retval < 0) {
@@ -1513,7 +1522,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
 	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
 		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-	      ibcs2_interpreter = 1;
+                ibcs2_interpreter = 1;
 	    }
 
 #if 0
@@ -1559,8 +1568,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
 	/* Now figure out which format our binary is */
 	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-	    	(N_MAGIC(interp_ex) != QMAGIC)) {
-	  interpreter_type = INTERPRETER_ELF;
+            (N_MAGIC(interp_ex) != QMAGIC)) {
+            interpreter_type = INTERPRETER_ELF;
 	}
 
 	if (interp_elf_ex.e_ident[0] != 0x7f ||
@@ -1620,7 +1629,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
          * in that case set guest_base to corresponding address.
          */
         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-            i++, elf_ppnt++) {
+             i++, elf_ppnt++) {
             if (elf_ppnt->p_type != PT_LOAD)
                 continue;
             if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
@@ -1737,7 +1746,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 	}
 	else if (interpreter_type & 2) {
 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-					    &interp_load_addr);
+                                        &interp_load_addr);
 	}
         reloc_func_desc = interp_load_addr;
 
@@ -1764,13 +1773,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->start_stack = bprm->p = elf_stack - 4;
 #endif
     bprm->p = create_elf_tables(bprm->p,
-		    bprm->argc,
-		    bprm->envc,
-                    &elf_ex,
-                    load_addr, load_bias,
-		    interp_load_addr,
-		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
-		    info);
+                                bprm->argc,
+                                bprm->envc,
+                                &elf_ex,
+                                load_addr, load_bias,
+                                interp_load_addr,
+                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
+                                info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
     info->end_code = end_code;
@@ -1790,12 +1799,12 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     if ( info->personality == PER_SVR4 )
     {
-	    /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-	       and some applications "depend" upon this behavior.
-	       Since we do not have the power to recompile these, we
-	       emulate the SVr4 behavior.  Sigh.  */
-	    mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                      MAP_FIXED | MAP_PRIVATE, -1, 0);
+        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+           and some applications "depend" upon this behavior.
+           Since we do not have the power to recompile these, we
+           emulate the SVr4 behavior.  Sigh.  */
+        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
     }
 
     info->entry = elf_entry;
@@ -1808,7 +1817,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 }
 
 #ifdef USE_ELF_CORE_DUMP
-
 /*
  * Definitions to generate Intel SVR4-like core files.
  * These mostly have the same names as the SVR4 types with "target_elf_"
@@ -1945,17 +1953,17 @@ struct mm_struct {
 static struct mm_struct *vma_init(void);
 static void vma_delete(struct mm_struct *);
 static int vma_add_mapping(struct mm_struct *, abi_ulong,
-    abi_ulong, abi_ulong);
+                           abi_ulong, abi_ulong);
 static int vma_get_mapping_count(const struct mm_struct *);
 static struct vm_area_struct *vma_first(const struct mm_struct *);
 static struct vm_area_struct *vma_next(struct vm_area_struct *);
 static abi_ulong vma_dump_size(const struct vm_area_struct *);
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags);
+                      unsigned long flags);
 
 static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
 static void fill_note(struct memelfnote *, const char *, int,
-    unsigned int, void *);
+                      unsigned int, void *);
 static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
 static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
 static void fill_auxv_note(struct memelfnote *, const TaskState *);
@@ -2035,7 +2043,7 @@ static void vma_delete(struct mm_struct *mm)
 }
 
 static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
-    abi_ulong end, abi_ulong flags)
+                           abi_ulong end, abi_ulong flags)
 {
     struct vm_area_struct *vma;
 
@@ -2104,7 +2112,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
 }
 
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags)
+                      unsigned long flags)
 {
     struct mm_struct *mm = (struct mm_struct *)priv;
 
@@ -2119,7 +2127,7 @@ static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
 }
 
 static void fill_note(struct memelfnote *note, const char *name, int type,
-    unsigned int sz, void *data)
+                      unsigned int sz, void *data)
 {
     unsigned int namesz;
 
@@ -2140,7 +2148,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
 }
 
 static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
-    uint32_t flags)
+                            uint32_t flags)
 {
     (void) memset(elf, 0, sizeof(*elf));
 
@@ -2186,7 +2194,7 @@ static size_t note_size(const struct memelfnote *note)
 }
 
 static void fill_prstatus(struct target_elf_prstatus *prstatus,
-    const TaskState *ts, int signr)
+                          const TaskState *ts, int signr)
 {
     (void) memset(prstatus, 0, sizeof (*prstatus));
     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@@ -2227,7 +2235,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strncpy(psinfo->pr_fname, base_filename,
-        sizeof(psinfo->pr_fname));
+                   sizeof(psinfo->pr_fname));
     free(base_filename);
     free(filename);
 
@@ -2276,7 +2284,7 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
  * Returns 0 in case of success, -1 otherwise (errno is set).
  */
 static int core_dump_filename(const TaskState *ts, char *buf,
-    size_t bufsize)
+                              size_t bufsize)
 {
     char timestamp[64];
     char *filename = NULL;
@@ -2288,16 +2296,16 @@ static int core_dump_filename(const TaskState *ts, char *buf,
 
     if (gettimeofday(&tv, NULL) < 0) {
         (void) fprintf(stderr, "unable to get current timestamp: %s",
-            strerror(errno));
+                       strerror(errno));
         return (-1);
     }
 
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
-        localtime_r(&tv.tv_sec, &tm));
+                    localtime_r(&tv.tv_sec, &tm));
     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
-        base_filename, timestamp, (int)getpid());
+                    base_filename, timestamp, (int)getpid());
     free(base_filename);
     free(filename);
 
@@ -2382,7 +2390,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
     fill_prstatus(&ets->prstatus, ts, 0);
     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
-        &ets->prstatus);
+              &ets->prstatus);
 
     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
 
@@ -2390,7 +2398,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
 }
 
 static int fill_note_info(struct elf_note_info *info,
-    long signr, const CPUState *env)
+                          long signr, const CPUState *env)
 {
 #define NUMNOTES 3
     CPUState *cpu = NULL;
@@ -2418,10 +2426,10 @@ static int fill_note_info(struct elf_note_info *info,
     fill_prstatus(info->prstatus, ts, signr);
     elf_core_copy_regs(&info->prstatus->pr_reg, env);
     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
-        sizeof (*info->prstatus), info->prstatus);
+              sizeof (*info->prstatus), info->prstatus);
     fill_psinfo(info->psinfo, ts);
     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
-        sizeof (*info->psinfo), info->psinfo);
+              sizeof (*info->psinfo), info->psinfo);
     fill_auxv_note(&info->notes[2], ts);
     info->numnote = 3;
 
@@ -2468,7 +2476,7 @@ static int write_note_info(struct elf_note_info *info, int fd)
 
     /* write prstatus for each thread */
     for (ets = info->thread_list.tqh_first; ets != NULL;
-        ets = ets->ets_link.tqe_next) {
+         ets = ets->ets_link.tqe_next) {
         if ((error = write_note(&ets->notes[0], fd)) != 0)
             return (error);
     }
@@ -2536,13 +2544,13 @@ static int elf_core_dump(int signr, const CPUState *env)
     errno = 0;
     getrlimit(RLIMIT_CORE, &dumpsize);
     if (dumpsize.rlim_cur == 0)
-       return 0;
+        return 0;
 
     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
         return (-errno);
 
     if ((fd = open(corefile, O_WRONLY | O_CREAT,
-        S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
         return (-errno);
 
     /*
@@ -2631,7 +2639,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         end = vma->vma_start + vma_dump_size(vma);
 
         for (addr = vma->vma_start; addr < end;
-            addr += TARGET_PAGE_SIZE) {
+             addr += TARGET_PAGE_SIZE) {
             char page[TARGET_PAGE_SIZE];
             int error;
 
@@ -2642,7 +2650,7 @@ static int elf_core_dump(int signr, const CPUState *env)
             error = copy_from_user(page, addr, sizeof (page));
             if (error != 0) {
                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
-                    addr);
+                               addr);
                 errno = -error;
                 goto out;
             }
@@ -2651,7 +2659,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         }
     }
 
-out:
+ out:
     free_note_info(&info);
     if (mm != NULL)
         vma_delete(mm);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter.
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
                     ` (11 preceding siblings ...)
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
@ 2010-04-28 19:39   ` Richard Henderson
  2010-04-28 19:39   ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
  13 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-04-28 19:39 UTC (permalink / raw)
  To: qemu-devel

First, adjust load_symbols to accept a load_bias parameter.  At the same
time, read the entire section header table in one go, use pread instead
f lseek+read for the symbol and string tables, and properly free
allocated structures on error exit paths.

Second, adjust load_elf_interp to compute load_bias.  This requires
finding out the built-in load addresses.  Which allows us to honor a
pre-linked interpreter image when possible, and eliminate the hard-coded
INTERP_MAP_SIZE value.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  189 +++++++++++++++++++++++++++-----------------------
 1 files changed, 101 insertions(+), 88 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9cf1eeb..7e94fe3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -829,9 +829,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss space allocated to elf interpreter */
-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
-
 /* max code+data+bss+brk space allocated to ET_DYN executables */
 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
 
@@ -920,6 +917,7 @@ static inline void bswap_sym(struct elf_sym *sym) { }
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
@@ -1145,15 +1143,11 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
-    struct elf_phdr *eppnt;
-    abi_ulong load_addr = 0;
-    int load_addr_set = 0;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr;
     int retval;
     abi_ulong error;
     int i;
 
-    error = 0;
-
     bswap_ehdr(interp_elf_ex);
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
@@ -1162,7 +1156,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-
     /* Now read in all of the header information */
 
     if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
@@ -1195,41 +1188,56 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
     bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
+    /* Find the maximum size of the image and allocate an appropriate
+       amount of memory to handle that.  */
+    loaddr = -1, hiaddr = 0;
+    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
+        if (elf_phdata[i].p_type == PT_LOAD) {
+            abi_ulong a = elf_phdata[i].p_vaddr;
+            if (a < loaddr) {
+                loaddr = a;
+            }
+            a += elf_phdata[i].p_memsz;
+            if (a > hiaddr) {
+                hiaddr = a;
+            }
+        }
+    }
+
+    load_addr = loaddr;
     if (interp_elf_ex->e_type == ET_DYN) {
-        /* in order to avoid hardcoding the interpreter load
-           address in qemu, we allocate a big enough memory zone */
-        error = target_mmap(0, INTERP_MAP_SIZE,
-                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                            -1, 0);
-        if (error == -1) {
+        /* The image indicates that it can be loaded anywhere.  Find a
+           location that can hold the memory space required.  If the
+           image is pre-linked, LOADDR will be non-zero.  Since we do
+           not supply MAP_FIXED here we'll use that address if and
+           only if it remains available.  */
+        load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
+                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                                -1, 0);
+        if (load_addr == -1) {
             perror("mmap");
             exit(-1);
         }
-        load_addr = error;
-        load_addr_set = 1;
     }
+    load_bias = load_addr - loaddr;
 
-    eppnt = elf_phdata;
-    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
+        struct elf_phdr *eppnt = elf_phdata + i;
         if (eppnt->p_type == PT_LOAD) {
-	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+	    abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
 	    int elf_prot = 0;
-	    abi_ulong vaddr = 0;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
-	    	elf_type |= MAP_FIXED;
-	    	vaddr = eppnt->p_vaddr;
-	    }
-	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-                                elf_prot,
-                                elf_type,
-                                interpreter_fd,
-                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
 
+            vaddr = load_bias + eppnt->p_vaddr;
+            vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
+            vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
+
+	    error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+                                elf_prot, MAP_PRIVATE | MAP_FIXED,
+                                interpreter_fd, eppnt->p_offset - vaddr_po);
 	    if (error == -1) {
                 /* Real error */
                 close(interpreter_fd);
@@ -1237,26 +1245,25 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 return ~((abi_ulong)0UL);
 	    }
 
-	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-                load_addr = error;
-                load_addr_set = 1;
-	    }
+            vaddr_ef = vaddr + eppnt->p_filesz;
+            vaddr_em = vaddr + eppnt->p_memsz;
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
-            if (eppnt->p_filesz < eppnt->p_memsz) {
-                abi_ulong base = load_addr + eppnt->p_vaddr;
-                zero_bss(base + eppnt->p_filesz,
-                         base + eppnt->p_memsz, elf_prot);
+            if (vaddr_ef < vaddr_em) {
+                zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
         }
+    }
 
-    /* Now use mmap to map the library into memory. */
+    if (qemu_log_enabled()) {
+	load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+    }
 
     close(interpreter_fd);
     free(elf_phdata);
 
     *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1305,82 +1312,87 @@ static int symcmp(const void *s0, const void *s1)
 }
 
 /* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd)
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 {
-    unsigned int i, nsyms;
-    struct elf_shdr sechdr, symtab, strtab;
+    int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
+    struct elf_shdr *shdr;
     char *strings;
     struct syminfo *s;
     struct elf_sym *syms;
 
-    lseek(fd, hdr->e_shoff, SEEK_SET);
-    for (i = 0; i < hdr->e_shnum; i++) {
-        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
-            return;
-        bswap_shdr(&sechdr, 1);
-        if (sechdr.sh_type == SHT_SYMTAB) {
-            symtab = sechdr;
-            lseek(fd, hdr->e_shoff
-                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
-            if (read(fd, &strtab, sizeof(strtab))
-                != sizeof(strtab))
-                return;
-            bswap_shdr(&strtab, 1);
+    shnum = hdr->e_shnum;
+    i = shnum * sizeof(struct elf_shdr);
+    shdr = (struct elf_shdr *)alloca(i);
+    if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+        return;
+    }
+
+    bswap_shdr(shdr, shnum);
+    for (i = 0; i < shnum; ++i) {
+        if (shdr[i].sh_type == SHT_SYMTAB) {
+            sym_idx = i;
+            str_idx = shdr[i].sh_link;
             goto found;
         }
     }
-    return; /* Shouldn't happen... */
+
+    /* There will be no symbol table if the file was stripped.  */
+    return;
 
  found:
-    /* Now know where the strtab and symtab are.  Snarf them. */
+    /* Now know where the strtab and symtab are.  Snarf them.  */
     s = malloc(sizeof(*s));
-    syms = malloc(symtab.sh_size);
-    if (!syms)
-        return;
-    s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_strtab)
+    if (!s) {
         return;
+    }
 
-    lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+    i = shdr[str_idx].sh_size;
+    s->disas_strtab = strings = malloc(i);
+    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
         return;
+    }
 
-    nsyms = symtab.sh_size / sizeof(struct elf_sym);
+    i = shdr[sym_idx].sh_size;
+    syms = malloc(i);
+    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
+        free(syms);
+        return;
+    }
 
-    i = 0;
-    while (i < nsyms) {
+    nsyms = i / sizeof(struct elf_sym);
+    for (i = 0; i < nsyms; ) {
         bswap_sym(syms + i);
-        // Throw away entries which we do not need.
-        if (syms[i].st_shndx == SHN_UNDEF ||
-            syms[i].st_shndx >= SHN_LORESERVE ||
-            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
-            nsyms--;
-            if (i < nsyms) {
+        /* Throw away entries which we do not need.  */
+        if (syms[i].st_shndx == SHN_UNDEF
+            || syms[i].st_shndx >= SHN_LORESERVE
+            || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            if (i < --nsyms) {
                 syms[i] = syms[nsyms];
             }
-            continue;
-        }
+        } else {
 #if defined(TARGET_ARM) || defined (TARGET_MIPS)
-        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
-        syms[i].st_value &= ~(target_ulong)1;
+            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
+            syms[i].st_value &= ~(target_ulong)1;
 #endif
-        i++;
+            syms[i].st_value += load_bias;
+            i++;
+        }
     }
-    syms = realloc(syms, nsyms * sizeof(*syms));
 
+    syms = realloc(syms, nsyms * sizeof(*syms));
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
-    lseek(fd, strtab.sh_offset, SEEK_SET);
-    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
-        return;
     s->disas_num_syms = nsyms;
 #if ELF_CLASS == ELFCLASS32
     s->disas_symtab.elf32 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #else
     s->disas_symtab.elf64 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #endif
+    s->lookup_symbol = lookup_symbolxx;
     s->next = syminfos;
     syminfos = s;
 }
@@ -1727,8 +1739,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     free(elf_phdata);
 
-    if (qemu_log_enabled())
-	load_symbols(&elf_ex, bprm->fd);
+    if (qemu_log_enabled()) {
+	load_symbols(&elf_ex, bprm->fd, load_bias);
+    }
 
     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 00/12] Cleanup linux-user/elfload.c, v2
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (14 preceding siblings ...)
  2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Changes v1->v2:
  * Drop VDSO loading for the moment; let's concentrate on getting the
    basic elf loading in shape first.
  * Fix SH4-EB ELF_DATA definition
  * Re-base after pbrook's guest_base changes for the main executable.


r~



Richard Henderson (12):
  linux-user: Handle filesz < memsz for any PT_LOAD segment.
  Add more DT_* and AT_* constants to qemu's copy of elf.h.
  linux-user: Reindent elfload.c.
  linux-user: Reduce lseek+reads while loading elf files.
  linux-user: Define ELF_DATA generically.
  linux-user: Clean up byte-swapping in elfload.c.
  linux-user: Load symbols from the interpreter.
  linux-user: Improve consistency checking in elf headers.
  linux-user: Put the stack guard page at the top.
  linux-user: Remove partial support for a.out interpreters.
  linux-user: Extract load_elf_image from load_elf_interp.
  linux-user: Re-use load_elf_image for the main binary.

 elf.h                  |   44 ++
 linux-user/elfload.c   | 1789 ++++++++++++++++++++----------------------------
 linux-user/linuxload.c |   17 +-
 linux-user/qemu.h      |    7 +-
 4 files changed, 793 insertions(+), 1064 deletions(-)

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (15 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 00/12] Cleanup linux-user/elfload.c, v2 Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

I caught padzero not properly initializing the .bss segment
on a statically linked Alpha program.  Rather than a minimal
patch, replace the gross code with a single mmap+memset.

Share more code between load_elf_interp and load_elf_binary.

Legally, an ELF program need not have just a single .bss;
and PT_LOAD segment can have memsz > filesz.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  150 ++++++++++++++++++--------------------------------
 1 files changed, 54 insertions(+), 96 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4ef77bc..58728ff 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1015,60 +1015,47 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
     return p;
 }
 
-static void set_brk(abi_ulong start, abi_ulong end)
-{
-	/* page-align the start and end addresses... */
-        start = HOST_PAGE_ALIGN(start);
-        end = HOST_PAGE_ALIGN(end);
-        if (end <= start)
-                return;
-        if(target_mmap(start, end - start,
-                       PROT_READ | PROT_WRITE | PROT_EXEC,
-                       MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
-	    perror("cannot mmap brk");
-	    exit(-1);
-	}
-}
-
-
-/* We need to explicitly zero any fractional pages after the data
-   section (i.e. bss).  This would contain the junk from the file that
-   should not be in memory. */
-static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
-{
-        abi_ulong nbyte;
-
-	if (elf_bss >= last_bss)
-		return;
-
-        /* XXX: this is really a hack : if the real host page size is
-           smaller than the target page size, some pages after the end
-           of the file may not be mapped. A better fix would be to
-           patch target_mmap(), but it is more complicated as the file
-           size must be known */
-        if (qemu_real_host_page_size < qemu_host_page_size) {
-            abi_ulong end_addr, end_addr1;
-            end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
-                ~(qemu_real_host_page_size - 1);
-            end_addr = HOST_PAGE_ALIGN(elf_bss);
-            if (end_addr1 < end_addr) {
-                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
-                     PROT_READ|PROT_WRITE|PROT_EXEC,
-                     MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-            }
+/* Map and zero the bss.  We need to explicitly zero any fractional pages
+   after the data section (i.e. bss).  */
+static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
+{
+    uintptr_t host_start, host_map_start, host_end;
+
+    last_bss = TARGET_PAGE_ALIGN(last_bss);
+
+    /* ??? There is confusion between qemu_real_host_page_size and
+       qemu_host_page_size here and elsewhere in target_mmap, which
+       may lead to the end of the data section mapping from the file
+       not being mapped.  At least there was an explicit test and
+       comment for that here, suggesting that "the file size must
+       be known".  The comment probably pre-dates the introduction
+       of the fstat system call in target_mmap which does in fact
+       find out the size.  What isn't clear is if the workaround
+       here is still actually needed.  For now, continue with it,
+       but merge it with the "normal" mmap that would allocate the bss.  */
+
+    host_start = (uintptr_t) g2h(elf_bss);
+    host_end = (uintptr_t) g2h(last_bss);
+    host_map_start = (host_start + qemu_real_host_page_size - 1);
+    host_map_start &= -qemu_real_host_page_size;
+
+    if (host_map_start < host_end) {
+        void *p = mmap((void *)host_map_start, host_end - host_map_start,
+                       prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+        if (p == MAP_FAILED) {
+            perror("cannot mmap brk");
+            exit(-1);
         }
 
-        nbyte = elf_bss & (qemu_host_page_size-1);
-        if (nbyte) {
-	    nbyte = qemu_host_page_size - nbyte;
-	    do {
-                /* FIXME - what to do if put_user() fails? */
-		put_user_u8(0, elf_bss);
-                elf_bss++;
-	    } while (--nbyte);
-        }
-}
+        /* Since we didn't use target_mmap, make sure to record
+           the validity of the pages with qemu.  */
+        page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
+    }
 
+    if (host_start < host_map_start) {
+        memset((void *)host_start, 0, host_map_start - host_start);
+    }
+}
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
@@ -1160,12 +1147,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	abi_ulong load_addr = 0;
 	int load_addr_set = 0;
 	int retval;
-	abi_ulong last_bss, elf_bss;
 	abi_ulong error;
 	int i;
 
-	elf_bss = 0;
-	last_bss = 0;
 	error = 0;
 
 #ifdef BSWAP_NEEDED
@@ -1238,7 +1222,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 	    int elf_prot = 0;
 	    abi_ulong vaddr = 0;
-	    abi_ulong k;
 
 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
@@ -1266,40 +1249,17 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 	      load_addr_set = 1;
 	    }
 
-	    /*
-	     * Find the end of the file  mapping for this phdr, and keep
-	     * track of the largest address we see for this.
-	     */
-	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
-	    if (k > elf_bss) elf_bss = k;
-
-	    /*
-	     * Do the same thing for the memory mapping - between
-	     * elf_bss and last_bss is the bss section.
-	     */
-	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
-	    if (k > last_bss) last_bss = k;
+            /* If the load segment requests extra zeros (e.g. bss), map it.  */
+            if (eppnt->p_filesz < eppnt->p_memsz) {
+                abi_ulong base = load_addr + eppnt->p_vaddr;
+                zero_bss(base + eppnt->p_filesz,
+                         base + eppnt->p_memsz, elf_prot);
+            }
 	  }
 
 	/* Now use mmap to map the library into memory. */
 
 	close(interpreter_fd);
-
-	/*
-	 * Now fill out the bss section.  First pad the last page up
-	 * to the page boundary, and then perform a mmap to make sure
-	 * that there are zeromapped pages up to and including the last
-	 * bss page.
-	 */
-	padzero(elf_bss, last_bss);
-	elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
-
-	/* Map the last of the bss segment */
-	if (last_bss > elf_bss) {
-            target_mmap(elf_bss, last_bss-elf_bss,
-                        PROT_READ|PROT_WRITE|PROT_EXEC,
-                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-	}
 	free(elf_phdata);
 
 	*interp_load_addr = load_addr;
@@ -1453,7 +1413,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
-    abi_ulong elf_bss, k, elf_brk;
+    abi_ulong k, elf_brk;
     int retval;
     char * elf_interpreter;
     abi_ulong elf_entry, interp_load_addr = 0;
@@ -1512,10 +1472,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 #endif
     elf_ppnt = elf_phdata;
 
-    elf_bss = 0;
     elf_brk = 0;
 
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1819,18 +1777,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         if (start_data < k)
             start_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if (k > elf_bss)
-            elf_bss = k;
         if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
             end_code = k;
         if (end_data < k)
             end_data = k;
         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) elf_brk = k;
+        if (k > elf_brk) {
+            elf_brk = TARGET_PAGE_ALIGN(k);
+        }
+
+        /* If the load segment requests extra zeros (e.g. bss), map it.  */
+        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
+            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
+            zero_bss(base + elf_ppnt->p_filesz,
+                     base + elf_ppnt->p_memsz, elf_prot);
+        }
     }
 
     elf_entry += load_bias;
-    elf_bss += load_bias;
     elf_brk += load_bias;
     start_code += load_bias;
     end_code += load_bias;
@@ -1885,12 +1849,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->end_data = end_data;
     info->start_stack = bprm->p;
 
-    /* Calling set_brk effectively mmaps the pages that we need for the bss and break
-       sections */
-    set_brk(elf_bss, elf_brk);
-
-    padzero(elf_bss, elf_brk);
-
 #if 0
     printf("(start_brk) %x\n" , info->start_brk);
     printf("(end_code) %x\n" , info->end_code);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (16 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Moving some PPC AT_* constants from elfload.c at the same time.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 elf.h                |   44 ++++++++++++++++++++++++++++++++++++++++++++
 linux-user/elfload.c |    9 ---------
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/elf.h b/elf.h
index c84c8ab..012532c 100644
--- a/elf.h
+++ b/elf.h
@@ -146,8 +146,37 @@ typedef int64_t  Elf64_Sxword;
 #define DT_DEBUG	21
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
+#define DT_BINDNOW	24
+#define DT_INIT_ARRAY	25
+#define DT_FINI_ARRAY	26
+#define DT_INIT_ARRAYSZ	27
+#define DT_FINI_ARRAYSZ	28
+#define DT_RUNPATH	29
+#define DT_FLAGS	30
+#define DT_LOOS		0x6000000d
+#define DT_HIOS		0x6ffff000
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
+
+/* DT_ entries which fall between DT_VALRNGLO and DT_VALRNDHI use
+   the d_val field of the Elf*_Dyn structure.  I.e. they contain scalars.  */
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_VALRNGHI	0x6ffffdff
+
+/* DT_ entries which fall between DT_ADDRRNGLO and DT_ADDRRNGHI use
+   the d_ptr field of the Elf*_Dyn structure.  I.e. they contain pointers.  */
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_ADDRRNGHI	0x6ffffeff
+
+#define	DT_VERSYM	0x6ffffff0
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+#define DT_FLAGS_1	0x6ffffffb
+#define DT_VERDEF	0x6ffffffc
+#define DT_VERDEFNUM	0x6ffffffd
+#define DT_VERNEED	0x6ffffffe
+#define DT_VERNEEDNUM	0x6fffffff
+
 #define DT_MIPS_RLD_VERSION	0x70000001
 #define DT_MIPS_TIME_STAMP	0x70000002
 #define DT_MIPS_ICHECKSUM	0x70000003
@@ -206,6 +235,21 @@ typedef int64_t  Elf64_Sxword;
 #define AT_PLATFORM 15  /* string identifying CPU for optimizations */
 #define AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
 #define AT_CLKTCK 17	/* frequency at which times() increments */
+#define AT_FPUCW  18	/* info about fpu initialization by kernel */
+#define AT_DCACHEBSIZE	19	/* data cache block size */
+#define AT_ICACHEBSIZE	20	/* instruction cache block size */
+#define AT_UCACHEBSIZE	21	/* unified cache block size */
+#define AT_IGNOREPPC	22	/* ppc only; entry should be ignored */
+#define AT_SECURE	23	/* boolean, was exec suid-like? */
+#define AT_BASE_PLATFORM 24	/* string identifying real platforms */
+#define AT_RANDOM	25	/* address of 16 random bytes */
+#define AT_EXECFN	31	/* filename of the executable */
+#define AT_SYSINFO	32	/* address of kernel entry point */
+#define AT_SYSINFO_EHDR	33	/* address of kernel vdso */
+#define AT_L1I_CACHESHAPE 34	/* shapes of the caches: */
+#define AT_L1D_CACHESHAPE 35	/*   bits 0-3: cache associativity.  */
+#define AT_L2_CACHESHAPE  36	/*   bits 4-7: log2 of line size.  */
+#define AT_L3_CACHESHAPE  37	/*   val&~255: cache size.  */
 
 typedef struct dynamic{
   Elf32_Sword d_tag;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 58728ff..edd852f 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -480,15 +480,6 @@ static uint32_t get_elf_hwcap(void)
 }
 
 /*
- * We need to put in some extra aux table entries to tell glibc what
- * the cache block size is, so it can use the dcbz instruction safely.
- */
-#define AT_DCACHEBSIZE          19
-#define AT_ICACHEBSIZE          20
-#define AT_UCACHEBSIZE          21
-/* A special ignored type value for PPC, for glibc compatibility.  */
-#define AT_IGNOREPPC            22
-/*
  * The requirements here are:
  * - keep the final alignment of sp (sp & 0xf)
  * - make sure the 32-bit value at the first 16 byte aligned position of
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (17 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Nothing excepting whitespace changes here.  This reduces the number
of changes elsewhere in the patch series.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c | 1028 +++++++++++++++++++++++++-------------------------
 1 files changed, 518 insertions(+), 510 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index edd852f..ac118f2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -35,18 +35,17 @@
  * These occupy the top three bytes.
  */
 enum {
-	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
-	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
-						 * (signal handling)
-						 */
-	MMAP_PAGE_ZERO =	0x0100000,
-	ADDR_COMPAT_LAYOUT =	0x0200000,
-	READ_IMPLIES_EXEC =	0x0400000,
-	ADDR_LIMIT_32BIT =	0x0800000,
-	SHORT_INODE =		0x1000000,
-	WHOLE_SECONDS =		0x2000000,
-	STICKY_TIMEOUTS	=	0x4000000,
-	ADDR_LIMIT_3GB = 	0x8000000,
+    ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */
+    FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
+                                           descriptors (signal handling) */
+    MMAP_PAGE_ZERO =    0x0100000,
+    ADDR_COMPAT_LAYOUT = 0x0200000,
+    READ_IMPLIES_EXEC = 0x0400000,
+    ADDR_LIMIT_32BIT =  0x0800000,
+    SHORT_INODE =       0x1000000,
+    WHOLE_SECONDS =     0x2000000,
+    STICKY_TIMEOUTS =   0x4000000,
+    ADDR_LIMIT_3GB =    0x8000000,
 };
 
 /*
@@ -56,36 +55,35 @@ enum {
  * conflict with error returns.
  */
 enum {
-	PER_LINUX =		0x0000,
-	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
-	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
-	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
-					 WHOLE_SECONDS | SHORT_INODE,
-	PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
-	PER_WYSEV386 =		0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
-	PER_BSD =		0x0006,
-	PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
-	PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
-	PER_LINUX32 =		0x0008,
-	PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
-	PER_IRIX32 =		0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
-	PER_IRIXN32 =		0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
-	PER_IRIX64 =		0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
-	PER_RISCOS =		0x000c,
-	PER_SOLARIS =		0x000d | STICKY_TIMEOUTS,
-	PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
-	PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
-	PER_HPUX =		0x0010,
-	PER_MASK =		0x00ff,
+    PER_LINUX =         0x0000,
+    PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
+    PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
+    PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
+    PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+    PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
+    PER_BSD =           0x0006,
+    PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
+    PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+    PER_LINUX32 =       0x0008,
+    PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
+    PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+    PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+    PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+    PER_RISCOS =        0x000c,
+    PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
+    PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+    PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
+    PER_HPUX =          0x0010,
+    PER_MASK =          0x00ff,
 };
 
 /*
  * Return the base personality without flags.
  */
-#define personality(pers)	(pers & PER_MASK)
+#define personality(pers)       (pers & PER_MASK)
 
 /* this flag is uneffective under linux too, should be deleted */
 #ifndef MAP_DENYWRITE
@@ -97,15 +95,15 @@ enum {
 #define ELIBBAD 80
 #endif
 
-typedef target_ulong	target_elf_greg_t;
+typedef target_ulong    target_elf_greg_t;
 #ifdef USE_UID16
-typedef uint16_t	target_uid_t;
-typedef uint16_t	target_gid_t;
+typedef uint16_t        target_uid_t;
+typedef uint16_t        target_gid_t;
 #else
-typedef uint32_t	target_uid_t;
-typedef uint32_t	target_gid_t;
+typedef uint32_t        target_uid_t;
+typedef uint32_t        target_gid_t;
 #endif
-typedef int32_t		target_pid_t;
+typedef int32_t         target_pid_t;
 
 #ifdef TARGET_I386
 
@@ -126,7 +124,7 @@ static const char *get_elf_platform(void)
 
 static uint32_t get_elf_hwcap(void)
 {
-  return thread_env->cpuid_features;
+    return thread_env->cpuid_features;
 }
 
 #ifdef TARGET_X86_64
@@ -197,11 +195,12 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 /*
  * These are used to set parameters in the core dumps.
  */
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2LSB
-#define ELF_ARCH	EM_386
+#define ELF_CLASS       ELFCLASS32
+#define ELF_DATA        ELFDATA2LSB
+#define ELF_ARCH        EM_386
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->esp = infop->start_stack;
     regs->eip = infop->entry;
@@ -249,7 +248,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #endif
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	4096
+#define ELF_EXEC_PAGESIZE       4096
 
 #endif
 
@@ -259,21 +258,22 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 
 #define elf_check_arch(x) ( (x) == EM_ARM )
 
-#define ELF_CLASS	ELFCLASS32
+#define ELF_CLASS       ELFCLASS32
 #ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA	ELFDATA2MSB
+#define ELF_DATA        ELFDATA2MSB
 #else
-#define ELF_DATA	ELFDATA2LSB
+#define ELF_DATA        ELFDATA2LSB
 #endif
-#define ELF_ARCH	EM_ARM
+#define ELF_ARCH        EM_ARM
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     abi_long stack = infop->start_stack;
     memset(regs, 0, sizeof(*regs));
     regs->ARM_cpsr = 0x10;
     if (infop->entry & 1)
-      regs->ARM_cpsr |= CPSR_T;
+        regs->ARM_cpsr |= CPSR_T;
     regs->ARM_pc = infop->entry & 0xfffffffe;
     regs->ARM_sp = infop->start_stack;
     /* FIXME - what to for failure of get_user()? */
@@ -313,30 +313,30 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 }
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	4096
+#define ELF_EXEC_PAGESIZE       4096
 
 enum
 {
-  ARM_HWCAP_ARM_SWP       = 1 << 0,
-  ARM_HWCAP_ARM_HALF      = 1 << 1,
-  ARM_HWCAP_ARM_THUMB     = 1 << 2,
-  ARM_HWCAP_ARM_26BIT     = 1 << 3,
-  ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
-  ARM_HWCAP_ARM_FPA       = 1 << 5,
-  ARM_HWCAP_ARM_VFP       = 1 << 6,
-  ARM_HWCAP_ARM_EDSP      = 1 << 7,
-  ARM_HWCAP_ARM_JAVA      = 1 << 8,
-  ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
-  ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
-  ARM_HWCAP_ARM_NEON      = 1 << 11,
-  ARM_HWCAP_ARM_VFPv3     = 1 << 12,
-  ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
+    ARM_HWCAP_ARM_SWP       = 1 << 0,
+    ARM_HWCAP_ARM_HALF      = 1 << 1,
+    ARM_HWCAP_ARM_THUMB     = 1 << 2,
+    ARM_HWCAP_ARM_26BIT     = 1 << 3,
+    ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
+    ARM_HWCAP_ARM_FPA       = 1 << 5,
+    ARM_HWCAP_ARM_VFP       = 1 << 6,
+    ARM_HWCAP_ARM_EDSP      = 1 << 7,
+    ARM_HWCAP_ARM_JAVA      = 1 << 8,
+    ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
+    ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
+    ARM_HWCAP_ARM_NEON      = 1 << 11,
+    ARM_HWCAP_ARM_VFPv3     = 1 << 12,
+    ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
 };
 
-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
-                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
-                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
-                    | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
+#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF               \
+                   | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT      \
+                   | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP              \
+                   | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
 
 #endif
 
@@ -355,9 +355,10 @@ enum
 #define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARCV9
 
-#define STACK_BIAS		2047
+#define STACK_BIAS              2047
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
 #ifndef TARGET_ABI32
     regs->tstate = 0;
@@ -384,7 +385,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARC
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->psr = 0;
     regs->pc = infop->entry;
@@ -404,22 +406,22 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #define elf_check_arch(x) ( (x) == EM_PPC64 )
 
-#define ELF_CLASS	ELFCLASS64
+#define ELF_CLASS       ELFCLASS64
 
 #else
 
 #define elf_check_arch(x) ( (x) == EM_PPC )
 
-#define ELF_CLASS	ELFCLASS32
+#define ELF_CLASS       ELFCLASS32
 
 #endif
 
 #ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA	ELFDATA2MSB
+#define ELF_DATA        ELFDATA2MSB
 #else
-#define ELF_DATA	ELFDATA2LSB
+#define ELF_DATA        ELFDATA2LSB
 #endif
-#define ELF_ARCH	EM_PPC
+#define ELF_ARCH        EM_PPC
 
 /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
    See arch/powerpc/include/asm/cputable.h.  */
@@ -464,7 +466,7 @@ static uint32_t get_elf_hwcap(void)
 
     /* We don't have to be terribly complete here; the high points are
        Altivec/FP/SPE support.  Anything else is just a bonus.  */
-#define GET_FEATURE(flag, feature)              \
+#define GET_FEATURE(flag, feature)                                      \
     do {if (e->insns_flags & flag) features |= feature; } while(0)
     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
@@ -489,17 +491,17 @@ static uint32_t get_elf_hwcap(void)
  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
  */
 #define DLINFO_ARCH_ITEMS       5
-#define ARCH_DLINFO                                                     \
-do {                                                                    \
-        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
-        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
-        /*                                                              \
-         * Now handle glibc compatibility.                              \
-         */                                                             \
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
-	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
- } while (0)
+#define ARCH_DLINFO                                     \
+    do {                                                \
+        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);              \
+        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
+        /*                                              \
+         * Now handle glibc compatibility.              \
+         */                                             \
+        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
+    } while (0)
 
 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
 {
@@ -537,7 +539,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 }
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	4096
+#define ELF_EXEC_PAGESIZE       4096
 
 #endif
 
@@ -553,13 +555,14 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_CLASS   ELFCLASS32
 #endif
 #ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA	ELFDATA2MSB
+#define ELF_DATA        ELFDATA2MSB
 #else
-#define ELF_DATA	ELFDATA2LSB
+#define ELF_DATA        ELFDATA2LSB
 #endif
 #define ELF_ARCH    EM_MIPS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->cp0_status = 2 << CP0St_KSU;
     regs->cp0_epc = infop->entry;
@@ -623,10 +626,11 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE )
 
 #define ELF_CLASS   ELFCLASS32
-#define ELF_DATA	ELFDATA2MSB
+#define ELF_DATA        ELFDATA2MSB
 #define ELF_ARCH    EM_XILINX_MICROBLAZE
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->r1 = infop->start_stack;
@@ -647,11 +651,12 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_SH
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  /* Check other registers XXXXX */
-  regs->pc = infop->entry;
-  regs->regs[15] = infop->start_stack;
+    /* Check other registers XXXXX */
+    regs->pc = infop->entry;
+    regs->regs[15] = infop->start_stack;
 }
 
 /* See linux kernel: arch/sh/include/asm/elf.h.  */
@@ -669,7 +674,8 @@ enum {
     TARGET_REG_SYSCALL = 22
 };
 
-static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
+                                      const CPUState *env)
 {
     int i;
 
@@ -701,9 +707,10 @@ static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState
 #define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_CRIS
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
-  regs->erp = infop->entry;
+    regs->erp = infop->entry;
 }
 
 #define ELF_EXEC_PAGESIZE        8192
@@ -716,14 +723,15 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 #define elf_check_arch(x) ( (x) == EM_68K )
 
-#define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2MSB
-#define ELF_ARCH	EM_68K
+#define ELF_CLASS       ELFCLASS32
+#define ELF_DATA        ELFDATA2MSB
+#define ELF_ARCH        EM_68K
 
 /* ??? Does this need to do anything?
-#define ELF_PLAT_INIT(_r) */
+   #define ELF_PLAT_INIT(_r) */
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->usp = infop->start_stack;
     regs->sr = 0;
@@ -759,7 +767,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 }
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	8192
+#define ELF_EXEC_PAGESIZE       8192
 
 #endif
 
@@ -773,7 +781,8 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define ELF_DATA       ELFDATA2MSB
 #define ELF_ARCH       EM_ALPHA
 
-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+static inline void init_thread(struct target_pt_regs *regs,
+                               struct image_info *infop)
 {
     regs->pc = infop->entry;
     regs->ps = 8;
@@ -803,14 +812,14 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
 
 struct exec
 {
-  unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
-  unsigned int a_text;   /* length of text, in bytes */
-  unsigned int a_data;   /* length of data, in bytes */
-  unsigned int a_bss;    /* length of uninitialized data area, in bytes */
-  unsigned int a_syms;   /* length of symbol table data in file, in bytes */
-  unsigned int a_entry;  /* start address */
-  unsigned int a_trsize; /* length of relocation info for text, in bytes */
-  unsigned int a_drsize; /* length of relocation info for data, in bytes */
+    unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
+    unsigned int a_text;   /* length of text, in bytes */
+    unsigned int a_data;   /* length of data, in bytes */
+    unsigned int a_bss;    /* length of uninitialized data area, in bytes */
+    unsigned int a_syms;   /* length of symbol table data in file, in bytes */
+    unsigned int a_entry;  /* start address */
+    unsigned int a_trsize; /* length of relocation info for text, in bytes */
+    unsigned int a_drsize; /* length of relocation info for data, in bytes */
 };
 
 
@@ -839,7 +848,7 @@ struct exec
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
-	memcpy(to, from, n);
+    memcpy(to, from, n);
 }
 
 static int load_aout_interp(void * exptr, int interp_fd);
@@ -847,31 +856,31 @@ static int load_aout_interp(void * exptr, int interp_fd);
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
-    bswap16s(&ehdr->e_type);			/* Object file type */
-    bswap16s(&ehdr->e_machine);		/* Architecture */
-    bswap32s(&ehdr->e_version);		/* Object file version */
-    bswaptls(&ehdr->e_entry);		/* Entry point virtual address */
-    bswaptls(&ehdr->e_phoff);		/* Program header table file offset */
-    bswaptls(&ehdr->e_shoff);		/* Section header table file offset */
-    bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
-    bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
-    bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
-    bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
-    bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
-    bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
-    bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
+    bswap16s(&ehdr->e_type);            /* Object file type */
+    bswap16s(&ehdr->e_machine);         /* Architecture */
+    bswap32s(&ehdr->e_version);         /* Object file version */
+    bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
+    bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
+    bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
+    bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
+    bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
+    bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
+    bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
+    bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
+    bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
+    bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
 }
 
 static void bswap_phdr(struct elf_phdr *phdr)
 {
-    bswap32s(&phdr->p_type);			/* Segment type */
-    bswaptls(&phdr->p_offset);		/* Segment file offset */
-    bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
-    bswaptls(&phdr->p_paddr);		/* Segment physical address */
-    bswaptls(&phdr->p_filesz);		/* Segment size in file */
-    bswaptls(&phdr->p_memsz);		/* Segment size in memory */
-    bswap32s(&phdr->p_flags);		/* Segment flags */
-    bswaptls(&phdr->p_align);		/* Segment alignment */
+    bswap32s(&phdr->p_type);            /* Segment type */
+    bswaptls(&phdr->p_offset);          /* Segment file offset */
+    bswaptls(&phdr->p_vaddr);           /* Segment virtual address */
+    bswaptls(&phdr->p_paddr);           /* Segment physical address */
+    bswaptls(&phdr->p_filesz);          /* Segment size in file */
+    bswaptls(&phdr->p_memsz);           /* Segment size in memory */
+    bswap32s(&phdr->p_flags);           /* Segment flags */
+    bswaptls(&phdr->p_align);           /* Segment alignment */
 }
 
 static void bswap_shdr(struct elf_shdr *shdr)
@@ -924,24 +933,24 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
     int len, offset = 0;
 
     if (!p) {
-	return 0;       /* bullet-proofing */
+        return 0;       /* bullet-proofing */
     }
     while (argc-- > 0) {
         tmp = argv[argc];
         if (!tmp) {
-	    fprintf(stderr, "VFS: argc is wrong");
-	    exit(-1);
-	}
+            fprintf(stderr, "VFS: argc is wrong");
+            exit(-1);
+        }
         tmp1 = tmp;
-	while (*tmp++);
-	len = tmp - tmp1;
-	if (p < len) {  /* this shouldn't happen - 128kB */
-		return 0;
-	}
-	while (len) {
-	    --p; --tmp; --len;
-	    if (--offset < 0) {
-		offset = p % TARGET_PAGE_SIZE;
+        while (*tmp++);
+        len = tmp - tmp1;
+        if (p < len) {  /* this shouldn't happen - 128kB */
+            return 0;
+        }
+        while (len) {
+            --p; --tmp; --len;
+            if (--offset < 0) {
+                offset = p % TARGET_PAGE_SIZE;
                 pag = (char *)page[p/TARGET_PAGE_SIZE];
                 if (!pag) {
                     pag = (char *)malloc(TARGET_PAGE_SIZE);
@@ -949,20 +958,20 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
                     page[p/TARGET_PAGE_SIZE] = pag;
                     if (!pag)
                         return 0;
-		}
-	    }
-	    if (len == 0 || offset == 0) {
-	        *(pag + offset) = *tmp;
-	    }
-	    else {
-	      int bytes_to_copy = (len > offset) ? offset : len;
-	      tmp -= bytes_to_copy;
-	      p -= bytes_to_copy;
-	      offset -= bytes_to_copy;
-	      len -= bytes_to_copy;
-	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
-	    }
-	}
+                }
+            }
+            if (len == 0 || offset == 0) {
+                *(pag + offset) = *tmp;
+            }
+            else {
+                int bytes_to_copy = (len > offset) ? offset : len;
+                tmp -= bytes_to_copy;
+                p -= bytes_to_copy;
+                offset -= bytes_to_copy;
+                len -= bytes_to_copy;
+                memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
+            }
+        }
     }
     return p;
 }
@@ -995,12 +1004,12 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
     p += stack_base;
 
     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-	if (bprm->page[i]) {
-	    info->rss++;
+        if (bprm->page[i]) {
+            info->rss++;
             /* FIXME - check return value of memcpy_to_target() for failure */
-	    memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
-	    free(bprm->page[i]);
-	}
+            memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
+            free(bprm->page[i]);
+        }
         stack_base += TARGET_PAGE_SIZE;
     }
     return p;
@@ -1055,77 +1064,77 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    abi_ulong interp_load_addr, int ibcs,
                                    struct image_info *info)
 {
-        abi_ulong sp;
-        int size;
-        abi_ulong u_platform;
-        const char *k_platform;
-        const int n = sizeof(elf_addr_t);
-
-        sp = p;
-        u_platform = 0;
-        k_platform = ELF_PLATFORM;
-        if (k_platform) {
-            size_t len = strlen(k_platform) + 1;
-            sp -= (len + n - 1) & ~(n - 1);
-            u_platform = sp;
-            /* FIXME - check return value of memcpy_to_target() for failure */
-            memcpy_to_target(sp, k_platform, len);
-        }
-	/*
-	 * Force 16 byte _final_ alignment here for generality.
-	 */
-        sp = sp &~ (abi_ulong)15;
-        size = (DLINFO_ITEMS + 1) * 2;
-        if (k_platform)
-          size += 2;
+    abi_ulong sp;
+    int size;
+    abi_ulong u_platform;
+    const char *k_platform;
+    const int n = sizeof(elf_addr_t);
+
+    sp = p;
+    u_platform = 0;
+    k_platform = ELF_PLATFORM;
+    if (k_platform) {
+        size_t len = strlen(k_platform) + 1;
+        sp -= (len + n - 1) & ~(n - 1);
+        u_platform = sp;
+        /* FIXME - check return value of memcpy_to_target() for failure */
+        memcpy_to_target(sp, k_platform, len);
+    }
+    /*
+     * Force 16 byte _final_ alignment here for generality.
+     */
+    sp = sp &~ (abi_ulong)15;
+    size = (DLINFO_ITEMS + 1) * 2;
+    if (k_platform)
+        size += 2;
 #ifdef DLINFO_ARCH_ITEMS
-	size += DLINFO_ARCH_ITEMS * 2;
+    size += DLINFO_ARCH_ITEMS * 2;
 #endif
-        size += envc + argc + 2;
-	size += (!ibcs ? 3 : 1);	/* argc itself */
-        size *= n;
-        if (size & 15)
-            sp -= 16 - (size & 15);
-
-        /* This is correct because Linux defines
-         * elf_addr_t as Elf32_Off / Elf64_Off
-         */
-#define NEW_AUX_ENT(id, val) do {		\
-            sp -= n; put_user_ual(val, sp);	\
-            sp -= n; put_user_ual(id, sp);	\
-          } while(0)
-
-        NEW_AUX_ENT (AT_NULL, 0);
-
-        /* There must be exactly DLINFO_ITEMS entries here.  */
-        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
-        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
-        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
-        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
-        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
-        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
-        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
-        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
-        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
-        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
-        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
-        if (k_platform)
-            NEW_AUX_ENT(AT_PLATFORM, u_platform);
+    size += envc + argc + 2;
+    size += (!ibcs ? 3 : 1);    /* argc itself */
+    size *= n;
+    if (size & 15)
+        sp -= 16 - (size & 15);
+
+    /* This is correct because Linux defines
+     * elf_addr_t as Elf32_Off / Elf64_Off
+     */
+#define NEW_AUX_ENT(id, val) do {               \
+        sp -= n; put_user_ual(val, sp);         \
+        sp -= n; put_user_ual(id, sp);          \
+    } while(0)
+
+    NEW_AUX_ENT (AT_NULL, 0);
+
+    /* There must be exactly DLINFO_ITEMS entries here.  */
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
+    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
+    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
+    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+    if (k_platform)
+        NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-	/*
-	 * ARCH_DLINFO must come last so platform specific code can enforce
-	 * special alignment requirements on the AUXV if necessary (eg. PPC).
-	 */
-        ARCH_DLINFO;
+    /*
+     * ARCH_DLINFO must come last so platform specific code can enforce
+     * special alignment requirements on the AUXV if necessary (eg. PPC).
+     */
+    ARCH_DLINFO;
 #endif
 #undef NEW_AUX_ENT
 
-        info->saved_auxv = sp;
+    info->saved_auxv = sp;
 
-        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
-        return sp;
+    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    return sp;
 }
 
 
@@ -1133,112 +1142,112 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
                                  abi_ulong *interp_load_addr)
 {
-	struct elf_phdr *elf_phdata  =  NULL;
-	struct elf_phdr *eppnt;
-	abi_ulong load_addr = 0;
-	int load_addr_set = 0;
-	int retval;
-	abi_ulong error;
-	int i;
+    struct elf_phdr *elf_phdata  =  NULL;
+    struct elf_phdr *eppnt;
+    abi_ulong load_addr = 0;
+    int load_addr_set = 0;
+    int retval;
+    abi_ulong error;
+    int i;
 
-	error = 0;
+    error = 0;
 
 #ifdef BSWAP_NEEDED
-        bswap_ehdr(interp_elf_ex);
+    bswap_ehdr(interp_elf_ex);
 #endif
-	/* First of all, some simple consistency checks */
-	if ((interp_elf_ex->e_type != ET_EXEC &&
-             interp_elf_ex->e_type != ET_DYN) ||
-	   !elf_check_arch(interp_elf_ex->e_machine)) {
-		return ~((abi_ulong)0UL);
-	}
+    /* First of all, some simple consistency checks */
+    if ((interp_elf_ex->e_type != ET_EXEC &&
+         interp_elf_ex->e_type != ET_DYN) ||
+        !elf_check_arch(interp_elf_ex->e_machine)) {
+        return ~((abi_ulong)0UL);
+    }
 
 
-	/* Now read in all of the header information */
+    /* Now read in all of the header information */
 
-	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-	    return ~(abi_ulong)0UL;
+    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
+        return ~(abi_ulong)0UL;
 
-	elf_phdata =  (struct elf_phdr *)
-		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    elf_phdata =  (struct elf_phdr *)
+        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-	if (!elf_phdata)
-	  return ~((abi_ulong)0UL);
+    if (!elf_phdata)
+        return ~((abi_ulong)0UL);
 
-	/*
-	 * If the size of this structure has changed, then punt, since
-	 * we will be doing the wrong thing.
-	 */
-	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-	    free(elf_phdata);
-	    return ~((abi_ulong)0UL);
-        }
+    /*
+     * If the size of this structure has changed, then punt, since
+     * we will be doing the wrong thing.
+     */
+    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
+        free(elf_phdata);
+        return ~((abi_ulong)0UL);
+    }
 
-	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-	if(retval >= 0) {
-	    retval = read(interpreter_fd,
-			   (char *) elf_phdata,
-			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-	}
-	if (retval < 0) {
-		perror("load_elf_interp");
-		exit(-1);
-		free (elf_phdata);
-		return retval;
- 	}
+    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
+    if(retval >= 0) {
+        retval = read(interpreter_fd,
+                      (char *) elf_phdata,
+                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
+    }
+    if (retval < 0) {
+        perror("load_elf_interp");
+        exit(-1);
+        free (elf_phdata);
+        return retval;
+    }
 #ifdef BSWAP_NEEDED
-	eppnt = elf_phdata;
-	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-            bswap_phdr(eppnt);
-        }
+    eppnt = elf_phdata;
+    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
+        bswap_phdr(eppnt);
+    }
 #endif
 
-        if (interp_elf_ex->e_type == ET_DYN) {
-            /* in order to avoid hardcoding the interpreter load
-               address in qemu, we allocate a big enough memory zone */
-            error = target_mmap(0, INTERP_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
+    if (interp_elf_ex->e_type == ET_DYN) {
+        /* in order to avoid hardcoding the interpreter load
+           address in qemu, we allocate a big enough memory zone */
+        error = target_mmap(0, INTERP_MAP_SIZE,
+                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
+                            -1, 0);
+        if (error == -1) {
+            perror("mmap");
+            exit(-1);
+        }
+        load_addr = error;
+        load_addr_set = 1;
+    }
+
+    eppnt = elf_phdata;
+    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+        if (eppnt->p_type == PT_LOAD) {
+            int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+            int elf_prot = 0;
+            abi_ulong vaddr = 0;
+
+            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
+            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+            if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
+                elf_type |= MAP_FIXED;
+                vaddr = eppnt->p_vaddr;
+            }
+            error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
+                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
+                                elf_prot,
+                                elf_type,
+                                interpreter_fd,
+                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
+
             if (error == -1) {
-                perror("mmap");
-                exit(-1);
+                /* Real error */
+                close(interpreter_fd);
+                free(elf_phdata);
+                return ~((abi_ulong)0UL);
             }
-            load_addr = error;
-            load_addr_set = 1;
-        }
 
-	eppnt = elf_phdata;
-	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
-	  if (eppnt->p_type == PT_LOAD) {
-	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
-	    int elf_prot = 0;
-	    abi_ulong vaddr = 0;
-
-	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
-	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
-	    	elf_type |= MAP_FIXED;
-	    	vaddr = eppnt->p_vaddr;
-	    }
-	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-		 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-		 elf_prot,
-		 elf_type,
-		 interpreter_fd,
-		 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
-
-	    if (error == -1) {
-	      /* Real error */
-	      close(interpreter_fd);
-	      free(elf_phdata);
-	      return ~((abi_ulong)0UL);
-	    }
-
-	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-	      load_addr = error;
-	      load_addr_set = 1;
-	    }
+            if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
+                load_addr = error;
+                load_addr_set = 1;
+            }
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
             if (eppnt->p_filesz < eppnt->p_memsz) {
@@ -1246,15 +1255,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 zero_bss(base + eppnt->p_filesz,
                          base + eppnt->p_memsz, elf_prot);
             }
-	  }
+        }
 
-	/* Now use mmap to map the library into memory. */
+    /* Now use mmap to map the library into memory. */
 
-	close(interpreter_fd);
-	free(elf_phdata);
+    close(interpreter_fd);
+    free(elf_phdata);
 
-	*interp_load_addr = load_addr;
-	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    *interp_load_addr = load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1356,8 +1365,8 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 #endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
-                syms[i].st_shndx >= SHN_LORESERVE ||
-                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            syms[i].st_shndx >= SHN_LORESERVE ||
+            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
             nsyms--;
             if (i < nsyms) {
                 syms[i] = syms[nsyms];
@@ -1425,8 +1434,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-       				(! elf_check_arch(elf_ex.e_machine))) {
-	    return -ENOEXEC;
+        (! elf_check_arch(elf_ex.e_machine))) {
+        return -ENOEXEC;
     }
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
@@ -1439,20 +1448,20 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     /* Now read in all of the header information */
     elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
     if (elf_phdata == NULL) {
-	return -ENOMEM;
+        return -ENOMEM;
     }
 
     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
     if(retval > 0) {
-	retval = read(bprm->fd, (char *) elf_phdata,
-				elf_ex.e_phentsize * elf_ex.e_phnum);
+        retval = read(bprm->fd, (char *) elf_phdata,
+                      elf_ex.e_phentsize * elf_ex.e_phnum);
     }
 
     if (retval < 0) {
-	perror("load_elf_binary");
-	exit(-1);
-	free (elf_phdata);
-	return -errno;
+        perror("load_elf_binary");
+        exit(-1);
+        free (elf_phdata);
+        return -errno;
     }
 
 #ifdef BSWAP_NEEDED
@@ -1474,131 +1483,131 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     interp_ex.a_info = 0;
 
     for(i=0;i < elf_ex.e_phnum; i++) {
-	if (elf_ppnt->p_type == PT_INTERP) {
-	    if ( elf_interpreter != NULL )
-	    {
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return -EINVAL;
-	    }
-
-	    /* This is the program interpreter used for
-	     * shared libraries - for now assume that this
-	     * is an a.out format binary
-	     */
-
-	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-	    if (elf_interpreter == NULL) {
-		free (elf_phdata);
-		close(bprm->fd);
-		return -ENOMEM;
-	    }
-
-	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
-	    if(retval >= 0) {
-		retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
-	    }
-	    if(retval < 0) {
-	 	perror("load_elf_binary2");
-		exit(-1);
-	    }
-
-	    /* If the program interpreter is one of these two,
-	       then assume an iBCS2 image. Otherwise assume
-	       a native linux image. */
-
-	    /* JRP - Need to add X86 lib dir stuff here... */
-
-	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-	      ibcs2_interpreter = 1;
-	    }
+        if (elf_ppnt->p_type == PT_INTERP) {
+            if ( elf_interpreter != NULL )
+            {
+                free (elf_phdata);
+                free(elf_interpreter);
+                close(bprm->fd);
+                return -EINVAL;
+            }
+
+            /* This is the program interpreter used for
+             * shared libraries - for now assume that this
+             * is an a.out format binary
+             */
+
+            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
+
+            if (elf_interpreter == NULL) {
+                free (elf_phdata);
+                close(bprm->fd);
+                return -ENOMEM;
+            }
+
+            retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
+            if(retval >= 0) {
+                retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
+            }
+            if(retval < 0) {
+                perror("load_elf_binary2");
+                exit(-1);
+            }
+
+            /* If the program interpreter is one of these two,
+               then assume an iBCS2 image. Otherwise assume
+               a native linux image. */
+
+            /* JRP - Need to add X86 lib dir stuff here... */
+
+            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
+                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
+                ibcs2_interpreter = 1;
+            }
 
 #if 0
-	    printf("Using ELF interpreter %s\n", path(elf_interpreter));
+            printf("Using ELF interpreter %s\n", path(elf_interpreter));
 #endif
-	    if (retval >= 0) {
-		retval = open(path(elf_interpreter), O_RDONLY);
-		if(retval >= 0) {
-		    interpreter_fd = retval;
-		}
-		else {
-		    perror(elf_interpreter);
-		    exit(-1);
-		    /* retval = -errno; */
-		}
-	    }
-
-	    if (retval >= 0) {
-		retval = lseek(interpreter_fd, 0, SEEK_SET);
-		if(retval >= 0) {
-		    retval = read(interpreter_fd,bprm->buf,128);
-		}
-	    }
-	    if (retval >= 0) {
-		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-		interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
-	    }
-	    if (retval < 0) {
-		perror("load_elf_binary3");
-		exit(-1);
-		free (elf_phdata);
-		free(elf_interpreter);
-		close(bprm->fd);
-		return retval;
-	    }
-	}
-	elf_ppnt++;
+            if (retval >= 0) {
+                retval = open(path(elf_interpreter), O_RDONLY);
+                if(retval >= 0) {
+                    interpreter_fd = retval;
+                }
+                else {
+                    perror(elf_interpreter);
+                    exit(-1);
+                    /* retval = -errno; */
+                }
+            }
+
+            if (retval >= 0) {
+                retval = lseek(interpreter_fd, 0, SEEK_SET);
+                if(retval >= 0) {
+                    retval = read(interpreter_fd,bprm->buf,128);
+                }
+            }
+            if (retval >= 0) {
+                interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
+                interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
+            }
+            if (retval < 0) {
+                perror("load_elf_binary3");
+                exit(-1);
+                free (elf_phdata);
+                free(elf_interpreter);
+                close(bprm->fd);
+                return retval;
+            }
+        }
+        elf_ppnt++;
     }
 
     /* Some simple consistency checks for the interpreter */
     if (elf_interpreter){
-	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
+        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
 
-	/* Now figure out which format our binary is */
-	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-	    	(N_MAGIC(interp_ex) != QMAGIC)) {
-	  interpreter_type = INTERPRETER_ELF;
-	}
+        /* Now figure out which format our binary is */
+        if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
+            (N_MAGIC(interp_ex) != QMAGIC)) {
+            interpreter_type = INTERPRETER_ELF;
+        }
 
-	if (interp_elf_ex.e_ident[0] != 0x7f ||
+        if (interp_elf_ex.e_ident[0] != 0x7f ||
             strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
-	    interpreter_type &= ~INTERPRETER_ELF;
-	}
-
-	if (!interpreter_type) {
-	    free(elf_interpreter);
-	    free(elf_phdata);
-	    close(bprm->fd);
-	    return -ELIBBAD;
-	}
+            interpreter_type &= ~INTERPRETER_ELF;
+        }
+
+        if (!interpreter_type) {
+            free(elf_interpreter);
+            free(elf_phdata);
+            close(bprm->fd);
+            return -ELIBBAD;
+        }
     }
 
     /* OK, we are done with that, now set up the arg stuff,
        and then start this sucker up */
 
     {
-	char * passed_p;
-
-	if (interpreter_type == INTERPRETER_AOUT) {
-	    snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
-	    passed_p = passed_fileno;
-
-	    if (elf_interpreter) {
-		bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
-		bprm->argc++;
-	    }
-	}
-	if (!bprm->p) {
-	    if (elf_interpreter) {
-	        free(elf_interpreter);
-	    }
-	    free (elf_phdata);
-	    close(bprm->fd);
-	    return -E2BIG;
-	}
+        char * passed_p;
+
+        if (interpreter_type == INTERPRETER_AOUT) {
+            snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
+            passed_p = passed_fileno;
+
+            if (elf_interpreter) {
+                bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
+                bprm->argc++;
+            }
+        }
+        if (!bprm->p) {
+            if (elf_interpreter) {
+                free(elf_interpreter);
+            }
+            free (elf_phdata);
+            close(bprm->fd);
+            return -E2BIG;
+        }
     }
 
     /* OK, This is the point of no return */
@@ -1625,7 +1634,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         unsigned long real_start;
         unsigned long host_size;
         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-            i++, elf_ppnt++) {
+             i++, elf_ppnt++) {
             if (elf_ppnt->p_type != PT_LOAD)
                 continue;
             addr = elf_ppnt->p_vaddr;
@@ -1709,7 +1718,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         int elf_flags = 0;
         abi_ulong error;
 
-	if (elf_ppnt->p_type != PT_LOAD)
+        if (elf_ppnt->p_type != PT_LOAD)
             continue;
 
         if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
@@ -1793,30 +1802,30 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data += load_bias;
 
     if (elf_interpreter) {
-	if (interpreter_type & 1) {
-	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
-	}
-	else if (interpreter_type & 2) {
-	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-					    &interp_load_addr);
-	}
+        if (interpreter_type & 1) {
+            elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
+        }
+        else if (interpreter_type & 2) {
+            elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
+                                        &interp_load_addr);
+        }
         reloc_func_desc = interp_load_addr;
 
-	close(interpreter_fd);
-	free(elf_interpreter);
+        close(interpreter_fd);
+        free(elf_interpreter);
 
-	if (elf_entry == ~((abi_ulong)0UL)) {
-	    printf("Unable to load interpreter\n");
-	    free(elf_phdata);
-	    exit(-1);
-	    return 0;
-	}
+        if (elf_entry == ~((abi_ulong)0UL)) {
+            printf("Unable to load interpreter\n");
+            free(elf_phdata);
+            exit(-1);
+            return 0;
+        }
     }
 
     free(elf_phdata);
 
     if (qemu_log_enabled())
-	load_symbols(&elf_ex, bprm->fd);
+        load_symbols(&elf_ex, bprm->fd);
 
     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
@@ -1825,13 +1834,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     info->start_stack = bprm->p = elf_stack - 4;
 #endif
     bprm->p = create_elf_tables(bprm->p,
-		    bprm->argc,
-		    bprm->envc,
-                    &elf_ex,
-                    load_addr, load_bias,
-		    interp_load_addr,
-		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
-		    info);
+                                bprm->argc,
+                                bprm->envc,
+                                &elf_ex,
+                                load_addr, load_bias,
+                                interp_load_addr,
+                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
+                                info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
     info->end_code = end_code;
@@ -1851,12 +1860,12 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     if ( info->personality == PER_SVR4 )
     {
-	    /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-	       and some applications "depend" upon this behavior.
-	       Since we do not have the power to recompile these, we
-	       emulate the SVr4 behavior.  Sigh.  */
-	    mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                      MAP_FIXED | MAP_PRIVATE, -1, 0);
+        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+           and some applications "depend" upon this behavior.
+           Since we do not have the power to recompile these, we
+           emulate the SVr4 behavior.  Sigh.  */
+        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
     }
 
     info->entry = elf_entry;
@@ -1869,7 +1878,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 }
 
 #ifdef USE_ELF_CORE_DUMP
-
 /*
  * Definitions to generate Intel SVR4-like core files.
  * These mostly have the same names as the SVR4 types with "target_elf_"
@@ -2006,17 +2014,17 @@ struct mm_struct {
 static struct mm_struct *vma_init(void);
 static void vma_delete(struct mm_struct *);
 static int vma_add_mapping(struct mm_struct *, abi_ulong,
-    abi_ulong, abi_ulong);
+                           abi_ulong, abi_ulong);
 static int vma_get_mapping_count(const struct mm_struct *);
 static struct vm_area_struct *vma_first(const struct mm_struct *);
 static struct vm_area_struct *vma_next(struct vm_area_struct *);
 static abi_ulong vma_dump_size(const struct vm_area_struct *);
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags);
+                      unsigned long flags);
 
 static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
 static void fill_note(struct memelfnote *, const char *, int,
-    unsigned int, void *);
+                      unsigned int, void *);
 static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
 static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
 static void fill_auxv_note(struct memelfnote *, const TaskState *);
@@ -2096,7 +2104,7 @@ static void vma_delete(struct mm_struct *mm)
 }
 
 static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
-    abi_ulong end, abi_ulong flags)
+                           abi_ulong end, abi_ulong flags)
 {
     struct vm_area_struct *vma;
 
@@ -2165,7 +2173,7 @@ static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
 }
 
 static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
-    unsigned long flags)
+                      unsigned long flags)
 {
     struct mm_struct *mm = (struct mm_struct *)priv;
 
@@ -2174,7 +2182,7 @@ static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
 }
 
 static void fill_note(struct memelfnote *note, const char *name, int type,
-    unsigned int sz, void *data)
+                      unsigned int sz, void *data)
 {
     unsigned int namesz;
 
@@ -2195,7 +2203,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
 }
 
 static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
-    uint32_t flags)
+                            uint32_t flags)
 {
     (void) memset(elf, 0, sizeof(*elf));
 
@@ -2241,7 +2249,7 @@ static size_t note_size(const struct memelfnote *note)
 }
 
 static void fill_prstatus(struct target_elf_prstatus *prstatus,
-    const TaskState *ts, int signr)
+                          const TaskState *ts, int signr)
 {
     (void) memset(prstatus, 0, sizeof (*prstatus));
     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
@@ -2282,7 +2290,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strncpy(psinfo->pr_fname, base_filename,
-        sizeof(psinfo->pr_fname));
+                   sizeof(psinfo->pr_fname));
     free(base_filename);
     free(filename);
 
@@ -2331,7 +2339,7 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
  * Returns 0 in case of success, -1 otherwise (errno is set).
  */
 static int core_dump_filename(const TaskState *ts, char *buf,
-    size_t bufsize)
+                              size_t bufsize)
 {
     char timestamp[64];
     char *filename = NULL;
@@ -2343,16 +2351,16 @@ static int core_dump_filename(const TaskState *ts, char *buf,
 
     if (gettimeofday(&tv, NULL) < 0) {
         (void) fprintf(stderr, "unable to get current timestamp: %s",
-            strerror(errno));
+                       strerror(errno));
         return (-1);
     }
 
     filename = strdup(ts->bprm->filename);
     base_filename = strdup(basename(filename));
     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
-        localtime_r(&tv.tv_sec, &tm));
+                    localtime_r(&tv.tv_sec, &tm));
     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
-        base_filename, timestamp, (int)getpid());
+                    base_filename, timestamp, (int)getpid());
     free(base_filename);
     free(filename);
 
@@ -2437,7 +2445,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
     fill_prstatus(&ets->prstatus, ts, 0);
     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
-        &ets->prstatus);
+              &ets->prstatus);
 
     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
 
@@ -2445,7 +2453,7 @@ static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
 }
 
 static int fill_note_info(struct elf_note_info *info,
-    long signr, const CPUState *env)
+                          long signr, const CPUState *env)
 {
 #define NUMNOTES 3
     CPUState *cpu = NULL;
@@ -2473,10 +2481,10 @@ static int fill_note_info(struct elf_note_info *info,
     fill_prstatus(info->prstatus, ts, signr);
     elf_core_copy_regs(&info->prstatus->pr_reg, env);
     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
-        sizeof (*info->prstatus), info->prstatus);
+              sizeof (*info->prstatus), info->prstatus);
     fill_psinfo(info->psinfo, ts);
     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
-        sizeof (*info->psinfo), info->psinfo);
+              sizeof (*info->psinfo), info->psinfo);
     fill_auxv_note(&info->notes[2], ts);
     info->numnote = 3;
 
@@ -2523,7 +2531,7 @@ static int write_note_info(struct elf_note_info *info, int fd)
 
     /* write prstatus for each thread */
     for (ets = info->thread_list.tqh_first; ets != NULL;
-        ets = ets->ets_link.tqe_next) {
+         ets = ets->ets_link.tqe_next) {
         if ((error = write_note(&ets->notes[0], fd)) != 0)
             return (error);
     }
@@ -2591,13 +2599,13 @@ static int elf_core_dump(int signr, const CPUState *env)
     errno = 0;
     getrlimit(RLIMIT_CORE, &dumpsize);
     if (dumpsize.rlim_cur == 0)
-       return 0;
+        return 0;
 
     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
         return (-errno);
 
     if ((fd = open(corefile, O_WRONLY | O_CREAT,
-        S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
+                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
         return (-errno);
 
     /*
@@ -2686,7 +2694,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         end = vma->vma_start + vma_dump_size(vma);
 
         for (addr = vma->vma_start; addr < end;
-            addr += TARGET_PAGE_SIZE) {
+             addr += TARGET_PAGE_SIZE) {
             char page[TARGET_PAGE_SIZE];
             int error;
 
@@ -2697,7 +2705,7 @@ static int elf_core_dump(int signr, const CPUState *env)
             error = copy_from_user(page, addr, sizeof (page));
             if (error != 0) {
                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
-                    addr);
+                               addr);
                 errno = -error;
                 goto out;
             }
@@ -2706,7 +2714,7 @@ static int elf_core_dump(int signr, const CPUState *env)
         }
     }
 
-out:
+ out:
     free_note_info(&info);
     if (mm != NULL)
         vma_delete(mm);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (18 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Define BPRM_BUF_SIZE to 1k and read that amount initially.  If the
data we want from the binary is in this buffer, use it instead of
reading from the file again.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c   |  104 ++++++++++++++++++++---------------------------
 linux-user/linuxload.c |   17 +++-----
 linux-user/qemu.h      |    7 +++-
 3 files changed, 57 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index ac118f2..dec86d6 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1140,7 +1140,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  int interpreter_fd,
-                                 abi_ulong *interp_load_addr)
+                                 abi_ulong *interp_load_addr,
+                                 char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
     struct elf_phdr *eppnt;
@@ -1183,17 +1184,15 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-    retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(interpreter_fd,
-                      (char *) elf_phdata,
-                      sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    }
-    if (retval < 0) {
-        perror("load_elf_interp");
-        exit(-1);
-        free (elf_phdata);
-        return retval;
+    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
+    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    } else {
+        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        if (retval != i) {
+            perror("load_elf_interp");
+            exit(-1);
+        }
     }
 #ifdef BSWAP_NEEDED
     eppnt = elf_phdata;
@@ -1451,17 +1450,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         return -ENOMEM;
     }
 
-    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
-    if(retval > 0) {
-        retval = read(bprm->fd, (char *) elf_phdata,
-                      elf_ex.e_phentsize * elf_ex.e_phnum);
-    }
-
-    if (retval < 0) {
-        perror("load_elf_binary");
-        exit(-1);
-        free (elf_phdata);
-        return -errno;
+    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
+    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
+        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
+    } else {
+        retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
+        if (retval != i) {
+            perror("load_elf_binary");
+            exit(-1);
+        }
     }
 
 #ifdef BSWAP_NEEDED
@@ -1505,13 +1502,16 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 return -ENOMEM;
             }
 
-            retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
-            if(retval >= 0) {
-                retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
-            }
-            if(retval < 0) {
-                perror("load_elf_binary2");
-                exit(-1);
+            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
+                       elf_ppnt->p_filesz);
+            } else {
+                retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
+                               elf_ppnt->p_offset);
+                if (retval != elf_ppnt->p_filesz) {
+                    perror("load_elf_binary2");
+                    exit(-1);
+                }
             }
 
             /* If the program interpreter is one of these two,
@@ -1525,39 +1525,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 ibcs2_interpreter = 1;
             }
 
-#if 0
-            printf("Using ELF interpreter %s\n", path(elf_interpreter));
-#endif
-            if (retval >= 0) {
-                retval = open(path(elf_interpreter), O_RDONLY);
-                if(retval >= 0) {
-                    interpreter_fd = retval;
-                }
-                else {
-                    perror(elf_interpreter);
-                    exit(-1);
-                    /* retval = -errno; */
-                }
+            retval = open(path(elf_interpreter), O_RDONLY);
+            if (retval < 0) {
+                perror(elf_interpreter);
+                exit(-1);
             }
+            interpreter_fd = retval;
 
-            if (retval >= 0) {
-                retval = lseek(interpreter_fd, 0, SEEK_SET);
-                if(retval >= 0) {
-                    retval = read(interpreter_fd,bprm->buf,128);
-                }
-            }
-            if (retval >= 0) {
-                interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-                interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
-            }
+            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
             if (retval < 0) {
                 perror("load_elf_binary3");
                 exit(-1);
-                free (elf_phdata);
-                free(elf_interpreter);
-                close(bprm->fd);
-                return retval;
             }
+            if (retval < BPRM_BUF_SIZE) {
+                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
+            }
+
+            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
         }
         elf_ppnt++;
     }
@@ -1804,10 +1789,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     if (elf_interpreter) {
         if (interpreter_type & 1) {
             elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
-        }
-        else if (interpreter_type & 2) {
+        } else if (interpreter_type & 2) {
             elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr);
+                                        &interp_load_addr, bprm->buf);
         }
         reloc_func_desc = interp_load_addr;
 
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 13ad9aa..9ee27c3 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -96,18 +96,16 @@ static int prepare_binprm(struct linux_binprm *bprm)
 	}
     }
 
-    retval = lseek(bprm->fd, 0L, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(bprm->fd, bprm->buf, 128);
-    }
-    if(retval < 0) {
+    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
 	perror("prepare_binprm");
 	exit(-1);
-	/* return(-errno); */
     }
-    else {
-	return(retval);
+    if (retval < BPRM_BUF_SIZE) {
+        /* Make sure the rest of the loader won't read garbage.  */
+        memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
+    return retval;
 }
 
 /* Construct the envp and argv tables on the target stack.  */
@@ -163,8 +161,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
     int i;
 
     bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
-    for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
-            bprm->page[i] = NULL;
+    memset(bprm->page, 0, sizeof(bprm->page));
     retval = open(filename, O_RDONLY);
     if (retval < 0)
         return retval;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index dab3597..a60fcdd 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -31,6 +31,7 @@
  * task_struct fields in the kernel
  */
 struct image_info {
+        abi_ulong       load_bias;
         abi_ulong       load_addr;
         abi_ulong       start_code;
         abi_ulong       end_code;
@@ -143,12 +144,16 @@ extern unsigned long mmap_min_addr;
  */
 #define MAX_ARG_PAGES 33
 
+/* Read a good amount of data initially, to hopefully get all the 
+   program headers loaded.  */
+#define BPRM_BUF_SIZE  1024
+
 /*
  * This structure is used to hold the arguments that are
  * used when loading binaries.
  */
 struct linux_binprm {
-        char buf[128];
+        char buf[BPRM_BUF_SIZE] __attribute__((aligned));
         void *page[MAX_ARG_PAGES];
         abi_ulong p;
 	int fd;
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (19 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

The only consideration on this value is the target endianness.
The existing defines were incorrect for alpha and sh4eb.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   30 ++++++------------------------
 1 files changed, 6 insertions(+), 24 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dec86d6..8732bc0 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -95,6 +95,12 @@ enum {
 #define ELIBBAD 80
 #endif
 
+#ifdef TARGET_WORDS_BIGENDIAN
+#define ELF_DATA        ELFDATA2MSB
+#else
+#define ELF_DATA        ELFDATA2LSB
+#endif
+
 typedef target_ulong    target_elf_greg_t;
 #ifdef USE_UID16
 typedef uint16_t        target_uid_t;
@@ -132,7 +138,6 @@ static uint32_t get_elf_hwcap(void)
 #define elf_check_arch(x) ( ((x) == ELF_ARCH) )
 
 #define ELF_CLASS      ELFCLASS64
-#define ELF_DATA       ELFDATA2LSB
 #define ELF_ARCH       EM_X86_64
 
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
@@ -196,7 +201,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS       ELFCLASS32
-#define ELF_DATA        ELFDATA2LSB
 #define ELF_ARCH        EM_386
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -259,11 +263,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == EM_ARM )
 
 #define ELF_CLASS       ELFCLASS32
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA        ELFDATA2MSB
-#else
-#define ELF_DATA        ELFDATA2LSB
-#endif
 #define ELF_ARCH        EM_ARM
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -352,7 +351,6 @@ enum
 #endif
 
 #define ELF_CLASS   ELFCLASS64
-#define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARCV9
 
 #define STACK_BIAS              2047
@@ -382,7 +380,6 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define elf_check_arch(x) ( (x) == EM_SPARC )
 
 #define ELF_CLASS   ELFCLASS32
-#define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARC
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -416,11 +413,6 @@ static inline void init_thread(struct target_pt_regs *regs,
 
 #endif
 
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA        ELFDATA2MSB
-#else
-#define ELF_DATA        ELFDATA2LSB
-#endif
 #define ELF_ARCH        EM_PPC
 
 /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
@@ -554,11 +546,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #else
 #define ELF_CLASS   ELFCLASS32
 #endif
-#ifdef TARGET_WORDS_BIGENDIAN
-#define ELF_DATA        ELFDATA2MSB
-#else
-#define ELF_DATA        ELFDATA2LSB
-#endif
 #define ELF_ARCH    EM_MIPS
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -626,7 +613,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE )
 
 #define ELF_CLASS   ELFCLASS32
-#define ELF_DATA        ELFDATA2MSB
 #define ELF_ARCH    EM_XILINX_MICROBLAZE
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -648,7 +634,6 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define elf_check_arch(x) ( (x) == EM_SH )
 
 #define ELF_CLASS ELFCLASS32
-#define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_SH
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -704,7 +689,6 @@ static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
 #define elf_check_arch(x) ( (x) == EM_CRIS )
 
 #define ELF_CLASS ELFCLASS32
-#define ELF_DATA  ELFDATA2LSB
 #define ELF_ARCH  EM_CRIS
 
 static inline void init_thread(struct target_pt_regs *regs,
@@ -724,7 +708,6 @@ static inline void init_thread(struct target_pt_regs *regs,
 #define elf_check_arch(x) ( (x) == EM_68K )
 
 #define ELF_CLASS       ELFCLASS32
-#define ELF_DATA        ELFDATA2MSB
 #define ELF_ARCH        EM_68K
 
 /* ??? Does this need to do anything?
@@ -778,7 +761,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
 #define elf_check_arch(x) ( (x) == ELF_ARCH )
 
 #define ELF_CLASS      ELFCLASS64
-#define ELF_DATA       ELFDATA2MSB
 #define ELF_ARCH       EM_ALPHA
 
 static inline void init_thread(struct target_pt_regs *regs,
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (20 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Remove ifdefs from code by defining empty inline functions
when byte swapping isn't needed.  Push loops over swapping
arrays of structures into the swapping functions.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  119 ++++++++++++++++++++------------------------------
 1 files changed, 48 insertions(+), 71 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8732bc0..f12161c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -853,30 +853,36 @@ static void bswap_ehdr(struct elfhdr *ehdr)
     bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
 }
 
-static void bswap_phdr(struct elf_phdr *phdr)
+static void bswap_phdr(struct elf_phdr *phdr, int phnum)
 {
-    bswap32s(&phdr->p_type);            /* Segment type */
-    bswaptls(&phdr->p_offset);          /* Segment file offset */
-    bswaptls(&phdr->p_vaddr);           /* Segment virtual address */
-    bswaptls(&phdr->p_paddr);           /* Segment physical address */
-    bswaptls(&phdr->p_filesz);          /* Segment size in file */
-    bswaptls(&phdr->p_memsz);           /* Segment size in memory */
-    bswap32s(&phdr->p_flags);           /* Segment flags */
-    bswaptls(&phdr->p_align);           /* Segment alignment */
+    int i;
+    for (i = 0; i < phnum; ++i, ++phdr) {
+        bswap32s(&phdr->p_type);        /* Segment type */
+        bswap32s(&phdr->p_flags);       /* Segment flags */
+        bswaptls(&phdr->p_offset);      /* Segment file offset */
+        bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
+        bswaptls(&phdr->p_paddr);       /* Segment physical address */
+        bswaptls(&phdr->p_filesz);      /* Segment size in file */
+        bswaptls(&phdr->p_memsz);       /* Segment size in memory */
+        bswaptls(&phdr->p_align);       /* Segment alignment */
+    }
 }
 
-static void bswap_shdr(struct elf_shdr *shdr)
+static void bswap_shdr(struct elf_shdr *shdr, int shnum)
 {
-    bswap32s(&shdr->sh_name);
-    bswap32s(&shdr->sh_type);
-    bswaptls(&shdr->sh_flags);
-    bswaptls(&shdr->sh_addr);
-    bswaptls(&shdr->sh_offset);
-    bswaptls(&shdr->sh_size);
-    bswap32s(&shdr->sh_link);
-    bswap32s(&shdr->sh_info);
-    bswaptls(&shdr->sh_addralign);
-    bswaptls(&shdr->sh_entsize);
+    int i;
+    for (i = 0; i < shnum; ++i, ++shdr) {
+        bswap32s(&shdr->sh_name);
+        bswap32s(&shdr->sh_type);
+        bswaptls(&shdr->sh_flags);
+        bswaptls(&shdr->sh_addr);
+        bswaptls(&shdr->sh_offset);
+        bswaptls(&shdr->sh_size);
+        bswap32s(&shdr->sh_link);
+        bswap32s(&shdr->sh_info);
+        bswaptls(&shdr->sh_addralign);
+        bswaptls(&shdr->sh_entsize);
+    }
 }
 
 static void bswap_sym(struct elf_sym *sym)
@@ -886,20 +892,15 @@ static void bswap_sym(struct elf_sym *sym)
     bswaptls(&sym->st_size);
     bswap16s(&sym->st_shndx);
 }
+#else
+static inline void bswap_ehdr(struct elfhdr *ehdr) { }
+static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
+static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
+static inline void bswap_sym(struct elf_sym *sym) { }
 #endif
 
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
-
-#ifdef BSWAP_NEEDED
-static void bswap_note(struct elf_note *en)
-{
-    bswap32s(&en->n_namesz);
-    bswap32s(&en->n_descsz);
-    bswap32s(&en->n_type);
-}
-#endif /* BSWAP_NEEDED */
-
 #endif /* USE_ELF_CORE_DUMP */
 
 /*
@@ -1135,9 +1136,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
     error = 0;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(interp_elf_ex);
-#endif
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
          interp_elf_ex->e_type != ET_DYN) ||
@@ -1176,12 +1175,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             exit(-1);
         }
     }
-#ifdef BSWAP_NEEDED
-    eppnt = elf_phdata;
-    for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-        bswap_phdr(eppnt);
-    }
-#endif
+    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
     if (interp_elf_ex->e_type == ET_DYN) {
         /* in order to avoid hardcoding the interpreter load
@@ -1305,9 +1299,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
     for (i = 0; i < hdr->e_shnum; i++) {
         if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
             return;
-#ifdef BSWAP_NEEDED
-        bswap_shdr(&sechdr);
-#endif
+        bswap_shdr(&sechdr, 1);
         if (sechdr.sh_type == SHT_SYMTAB) {
             symtab = sechdr;
             lseek(fd, hdr->e_shoff
@@ -1315,9 +1307,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
             if (read(fd, &strtab, sizeof(strtab))
                 != sizeof(strtab))
                 return;
-#ifdef BSWAP_NEEDED
-            bswap_shdr(&strtab);
-#endif
+            bswap_shdr(&strtab, 1);
             goto found;
         }
     }
@@ -1341,9 +1331,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
 
     i = 0;
     while (i < nsyms) {
-#ifdef BSWAP_NEEDED
         bswap_sym(syms + i);
-#endif
         // Throw away entries which we do not need.
         if (syms[i].st_shndx == SHN_UNDEF ||
             syms[i].st_shndx >= SHN_LORESERVE ||
@@ -1409,9 +1397,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-#ifdef BSWAP_NEEDED
     bswap_ehdr(&elf_ex);
-#endif
 
     /* First of all, some simple consistency checks */
     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
@@ -1442,17 +1428,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             exit(-1);
         }
     }
-
-#ifdef BSWAP_NEEDED
-    elf_ppnt = elf_phdata;
-    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
-        bswap_phdr(elf_ppnt);
-    }
-#endif
-    elf_ppnt = elf_phdata;
+    bswap_phdr(elf_phdata, elf_ex.e_phnum);
 
     elf_brk = 0;
-
     elf_stack = ~((abi_ulong)0UL);
     elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
@@ -1461,6 +1439,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data = 0;
     interp_ex.a_info = 0;
 
+    elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
         if (elf_ppnt->p_type == PT_INTERP) {
             if ( elf_interpreter != NULL )
@@ -2006,9 +1985,6 @@ static int write_note(struct memelfnote *, int);
 static int write_note_info(struct elf_note_info *, int);
 
 #ifdef BSWAP_NEEDED
-static void bswap_prstatus(struct target_elf_prstatus *);
-static void bswap_psinfo(struct target_elf_prpsinfo *);
-
 static void bswap_prstatus(struct target_elf_prstatus *prstatus)
 {
     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
@@ -2036,6 +2012,17 @@ static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
     psinfo->pr_sid = tswap32(psinfo->pr_sid);
 }
+
+static void bswap_note(struct elf_note *en)
+{
+    bswap32s(&en->n_namesz);
+    bswap32s(&en->n_descsz);
+    bswap32s(&en->n_type);
+}
+#else
+static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
+static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
+static inline void bswap_note(struct elf_note *en) { }
 #endif /* BSWAP_NEEDED */
 
 /*
@@ -2188,9 +2175,7 @@ static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
     elf->e_phentsize = sizeof(struct elf_phdr);
     elf->e_phnum = segs;
 
-#ifdef BSWAP_NEEDED
     bswap_ehdr(elf);
-#endif
 }
 
 static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
@@ -2204,9 +2189,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
     phdr->p_flags = 0;
     phdr->p_align = 0;
 
-#ifdef BSWAP_NEEDED
-    bswap_phdr(phdr);
-#endif
+    bswap_phdr(phdr, 1);
 }
 
 static size_t note_size(const struct memelfnote *note)
@@ -2224,9 +2207,7 @@ static void fill_prstatus(struct target_elf_prstatus *prstatus,
     prstatus->pr_pgrp = getpgrp();
     prstatus->pr_sid = getsid(0);
 
-#ifdef BSWAP_NEEDED
     bswap_prstatus(prstatus);
-#endif
 }
 
 static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
@@ -2260,9 +2241,7 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
     free(base_filename);
     free(filename);
 
-#ifdef BSWAP_NEEDED
     bswap_psinfo(psinfo);
-#endif
     return (0);
 }
 
@@ -2387,9 +2366,7 @@ static int write_note(struct memelfnote *men, int fd)
     en.n_type = men->type;
     en.n_descsz = men->datasz;
 
-#ifdef BSWAP_NEEDED
     bswap_note(&en);
-#endif
 
     if (dump_write(fd, &en, sizeof(en)) != 0)
         return (-1);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (21 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

First, adjust load_symbols to accept a load_bias parameter.  At the same
time, read the entire section header table in one go, use pread instead
f lseek+read for the symbol and string tables, and properly free
allocated structures on error exit paths.

Second, adjust load_elf_interp to compute load_bias.  This requires
finding out the built-in load addresses.  Which allows us to honor a
pre-linked interpreter image when possible, and eliminate the hard-coded
INTERP_MAP_SIZE value.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  189 +++++++++++++++++++++++++++-----------------------
 1 files changed, 101 insertions(+), 88 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f12161c..723e956 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -811,9 +811,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss space allocated to elf interpreter */
-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
-
 /* max code+data+bss+brk space allocated to ET_DYN executables */
 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
 
@@ -902,6 +899,7 @@ static inline void bswap_sym(struct elf_sym *sym) { }
 #ifdef USE_ELF_CORE_DUMP
 static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
@@ -1127,15 +1125,11 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                  char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elf_phdr *elf_phdata  =  NULL;
-    struct elf_phdr *eppnt;
-    abi_ulong load_addr = 0;
-    int load_addr_set = 0;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr;
     int retval;
     abi_ulong error;
     int i;
 
-    error = 0;
-
     bswap_ehdr(interp_elf_ex);
     /* First of all, some simple consistency checks */
     if ((interp_elf_ex->e_type != ET_EXEC &&
@@ -1144,7 +1138,6 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
         return ~((abi_ulong)0UL);
     }
 
-
     /* Now read in all of the header information */
 
     if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
@@ -1177,41 +1170,56 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
     bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
 
+    /* Find the maximum size of the image and allocate an appropriate
+       amount of memory to handle that.  */
+    loaddr = -1, hiaddr = 0;
+    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
+        if (elf_phdata[i].p_type == PT_LOAD) {
+            abi_ulong a = elf_phdata[i].p_vaddr;
+            if (a < loaddr) {
+                loaddr = a;
+            }
+            a += elf_phdata[i].p_memsz;
+            if (a > hiaddr) {
+                hiaddr = a;
+            }
+        }
+    }
+
+    load_addr = loaddr;
     if (interp_elf_ex->e_type == ET_DYN) {
-        /* in order to avoid hardcoding the interpreter load
-           address in qemu, we allocate a big enough memory zone */
-        error = target_mmap(0, INTERP_MAP_SIZE,
-                            PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                            -1, 0);
-        if (error == -1) {
+        /* The image indicates that it can be loaded anywhere.  Find a
+           location that can hold the memory space required.  If the
+           image is pre-linked, LOADDR will be non-zero.  Since we do
+           not supply MAP_FIXED here we'll use that address if and
+           only if it remains available.  */
+        load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
+                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+                                -1, 0);
+        if (load_addr == -1) {
             perror("mmap");
             exit(-1);
         }
-        load_addr = error;
-        load_addr_set = 1;
     }
+    load_bias = load_addr - loaddr;
 
-    eppnt = elf_phdata;
-    for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
+        struct elf_phdr *eppnt = elf_phdata + i;
         if (eppnt->p_type == PT_LOAD) {
-            int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+            abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
             int elf_prot = 0;
-            abi_ulong vaddr = 0;
 
             if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
             if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
             if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-            if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
-                elf_type |= MAP_FIXED;
-                vaddr = eppnt->p_vaddr;
-            }
-            error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
-                                eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
-                                elf_prot,
-                                elf_type,
-                                interpreter_fd,
-                                eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
 
+            vaddr = load_bias + eppnt->p_vaddr;
+            vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
+            vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
+
+            error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+                                elf_prot, MAP_PRIVATE | MAP_FIXED,
+                                interpreter_fd, eppnt->p_offset - vaddr_po);
             if (error == -1) {
                 /* Real error */
                 close(interpreter_fd);
@@ -1219,26 +1227,25 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                 return ~((abi_ulong)0UL);
             }
 
-            if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-                load_addr = error;
-                load_addr_set = 1;
-            }
+            vaddr_ef = vaddr + eppnt->p_filesz;
+            vaddr_em = vaddr + eppnt->p_memsz;
 
             /* If the load segment requests extra zeros (e.g. bss), map it.  */
-            if (eppnt->p_filesz < eppnt->p_memsz) {
-                abi_ulong base = load_addr + eppnt->p_vaddr;
-                zero_bss(base + eppnt->p_filesz,
-                         base + eppnt->p_memsz, elf_prot);
+            if (vaddr_ef < vaddr_em) {
+                zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
         }
+    }
 
-    /* Now use mmap to map the library into memory. */
+    if (qemu_log_enabled()) {
+        load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+    }
 
     close(interpreter_fd);
     free(elf_phdata);
 
     *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
+    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1287,82 +1294,87 @@ static int symcmp(const void *s0, const void *s1)
 }
 
 /* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd)
+static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 {
-    unsigned int i, nsyms;
-    struct elf_shdr sechdr, symtab, strtab;
+    int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
+    struct elf_shdr *shdr;
     char *strings;
     struct syminfo *s;
     struct elf_sym *syms;
 
-    lseek(fd, hdr->e_shoff, SEEK_SET);
-    for (i = 0; i < hdr->e_shnum; i++) {
-        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
-            return;
-        bswap_shdr(&sechdr, 1);
-        if (sechdr.sh_type == SHT_SYMTAB) {
-            symtab = sechdr;
-            lseek(fd, hdr->e_shoff
-                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
-            if (read(fd, &strtab, sizeof(strtab))
-                != sizeof(strtab))
-                return;
-            bswap_shdr(&strtab, 1);
+    shnum = hdr->e_shnum;
+    i = shnum * sizeof(struct elf_shdr);
+    shdr = (struct elf_shdr *)alloca(i);
+    if (pread(fd, shdr, i, hdr->e_shoff) != i) {
+        return;
+    }
+
+    bswap_shdr(shdr, shnum);
+    for (i = 0; i < shnum; ++i) {
+        if (shdr[i].sh_type == SHT_SYMTAB) {
+            sym_idx = i;
+            str_idx = shdr[i].sh_link;
             goto found;
         }
     }
-    return; /* Shouldn't happen... */
+
+    /* There will be no symbol table if the file was stripped.  */
+    return;
 
  found:
-    /* Now know where the strtab and symtab are.  Snarf them. */
+    /* Now know where the strtab and symtab are.  Snarf them.  */
     s = malloc(sizeof(*s));
-    syms = malloc(symtab.sh_size);
-    if (!syms)
-        return;
-    s->disas_strtab = strings = malloc(strtab.sh_size);
-    if (!s->disas_strtab)
+    if (!s) {
         return;
+    }
 
-    lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+    i = shdr[str_idx].sh_size;
+    s->disas_strtab = strings = malloc(i);
+    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
         return;
+    }
 
-    nsyms = symtab.sh_size / sizeof(struct elf_sym);
+    i = shdr[sym_idx].sh_size;
+    syms = malloc(i);
+    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
+        free(s);
+        free(strings);
+        free(syms);
+        return;
+    }
 
-    i = 0;
-    while (i < nsyms) {
+    nsyms = i / sizeof(struct elf_sym);
+    for (i = 0; i < nsyms; ) {
         bswap_sym(syms + i);
-        // Throw away entries which we do not need.
-        if (syms[i].st_shndx == SHN_UNDEF ||
-            syms[i].st_shndx >= SHN_LORESERVE ||
-            ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
-            nsyms--;
-            if (i < nsyms) {
+        /* Throw away entries which we do not need.  */
+        if (syms[i].st_shndx == SHN_UNDEF
+            || syms[i].st_shndx >= SHN_LORESERVE
+            || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
+            if (i < --nsyms) {
                 syms[i] = syms[nsyms];
             }
-            continue;
-        }
+        } else {
 #if defined(TARGET_ARM) || defined (TARGET_MIPS)
-        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
-        syms[i].st_value &= ~(target_ulong)1;
+            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
+            syms[i].st_value &= ~(target_ulong)1;
 #endif
-        i++;
+            syms[i].st_value += load_bias;
+            i++;
+        }
     }
-    syms = realloc(syms, nsyms * sizeof(*syms));
 
+    syms = realloc(syms, nsyms * sizeof(*syms));
     qsort(syms, nsyms, sizeof(*syms), symcmp);
 
-    lseek(fd, strtab.sh_offset, SEEK_SET);
-    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
-        return;
     s->disas_num_syms = nsyms;
 #if ELF_CLASS == ELFCLASS32
     s->disas_symtab.elf32 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #else
     s->disas_symtab.elf64 = syms;
-    s->lookup_symbol = lookup_symbolxx;
 #endif
+    s->lookup_symbol = lookup_symbolxx;
     s->next = syminfos;
     syminfos = s;
 }
@@ -1769,8 +1781,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     free(elf_phdata);
 
-    if (qemu_log_enabled())
-        load_symbols(&elf_ex, bprm->fd);
+    if (qemu_log_enabled()) {
+        load_symbols(&elf_ex, bprm->fd, load_bias);
+    }
 
     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (22 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Validate more fields of the elf header.  Extract those checks
into two common functions to be used in both load_elf_interp
and load_elf_binary.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   57 +++++++++++++++++++++++++++++---------------------
 1 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 723e956..fb03687 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -901,6 +901,30 @@ static int elf_core_dump(int, const CPUState *);
 #endif /* USE_ELF_CORE_DUMP */
 static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
 
+/* Verify the portions of EHDR within E_IDENT for the target.
+   This can be performed before bswapping the entire header.  */
+static _Bool elf_check_ident(struct elfhdr *ehdr)
+{
+    return (ehdr->e_ident[EI_MAG0] == ELFMAG0
+            && ehdr->e_ident[EI_MAG1] == ELFMAG1
+            && ehdr->e_ident[EI_MAG2] == ELFMAG2
+            && ehdr->e_ident[EI_MAG3] == ELFMAG3
+            && ehdr->e_ident[EI_CLASS] == ELF_CLASS
+            && ehdr->e_ident[EI_DATA] == ELF_DATA
+            && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
+}
+
+/* Verify the portions of EHDR outside of E_IDENT for the target.
+   This has to wait until after bswapping the header.  */
+static _Bool elf_check_ehdr(struct elfhdr *ehdr)
+{
+    return (elf_check_arch(ehdr->e_machine)
+            && ehdr->e_ehsize == sizeof(struct elfhdr)
+            && ehdr->e_phentsize == sizeof(struct elf_phdr)
+            && ehdr->e_shentsize == sizeof(struct elf_shdr)
+            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
+}
+
 /*
  * 'copy_elf_strings()' copies argument/envelope strings from user
  * memory to free pages in kernel mem. These are in a format ready
@@ -1131,33 +1155,16 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     int i;
 
     bswap_ehdr(interp_elf_ex);
-    /* First of all, some simple consistency checks */
-    if ((interp_elf_ex->e_type != ET_EXEC &&
-         interp_elf_ex->e_type != ET_DYN) ||
-        !elf_check_arch(interp_elf_ex->e_machine)) {
+    if (!elf_check_ehdr(interp_elf_ex)) {
         return ~((abi_ulong)0UL);
     }
 
     /* Now read in all of the header information */
-
-    if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
-        return ~(abi_ulong)0UL;
-
     elf_phdata =  (struct elf_phdr *)
         malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-
     if (!elf_phdata)
         return ~((abi_ulong)0UL);
 
-    /*
-     * If the size of this structure has changed, then punt, since
-     * we will be doing the wrong thing.
-     */
-    if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
-        free(elf_phdata);
-        return ~((abi_ulong)0UL);
-    }
-
     i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
     if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
         memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
@@ -1409,11 +1416,13 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     load_addr = 0;
     load_bias = 0;
     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-    bswap_ehdr(&elf_ex);
 
     /* First of all, some simple consistency checks */
-    if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
-        (! elf_check_arch(elf_ex.e_machine))) {
+    if (!elf_check_ident(&elf_ex)) {
+        return -ENOEXEC;
+    }
+    bswap_ehdr(&elf_ex);
+    if (!elf_check_ehdr(&elf_ex)) {
         return -ENOEXEC;
     }
 
@@ -1425,7 +1434,8 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
+    elf_phdata = (struct elf_phdr *)
+        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
     if (elf_phdata == NULL) {
         return -ENOMEM;
     }
@@ -1530,8 +1540,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
             interpreter_type = INTERPRETER_ELF;
         }
 
-        if (interp_elf_ex.e_ident[0] != 0x7f ||
-            strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
+        if (!elf_check_ident(&interp_elf_ex)) {
             interpreter_type &= ~INTERPRETER_ELF;
         }
 
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (23 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

There are no supported stack-grows-up targets.  We were putting
the guard page at the highest address, i.e. the bottom of the stack.
Use the maximum of host and guest page size for the guard size.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   29 ++++++++++++++++-------------
 1 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index fb03687..bd4b8fc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -984,28 +984,31 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
                                  struct image_info *info)
 {
-    abi_ulong stack_base, size, error;
+    abi_ulong stack_base, size, error, guard;
     int i;
 
     /* Create enough stack to hold everything.  If we don't use
-     * it for args, we'll use it for something else...
-     */
+       it for args, we'll use it for something else.  */
     size = guest_stack_size;
-    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
-    error = target_mmap(0,
-                        size + qemu_host_page_size,
-                        PROT_READ | PROT_WRITE,
-                        MAP_PRIVATE | MAP_ANONYMOUS,
-                        -1, 0);
+    }
+    guard = TARGET_PAGE_SIZE;
+    if (guard < qemu_real_host_page_size) {
+        guard = qemu_real_host_page_size;
+    }
+
+    error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
+                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (error == -1) {
-        perror("stk mmap");
+        perror("mmap stack");
         exit(-1);
     }
-    /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
 
-    stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+    /* We reserve one extra page at the top of the stack as guard.  */
+    target_mprotect(error, guard, PROT_NONE);
+
+    stack_base = error + guard + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
     p += stack_base;
 
     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (24 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

At the bottom of the a.out support was the unimplemented load_aout_interp
function.  There were other portions of the support that didn't look
right; when I went to look in the Linux kernel for clarification, I found
that the support for such interpreters has been removed from binfmt_elf.
There doesn't seem to be any reason to keep this broken support in qemu.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |   79 ++++++--------------------------------------------
 1 files changed, 9 insertions(+), 70 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index bd4b8fc..77267a4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -819,10 +819,6 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define INTERPRETER_NONE 0
-#define INTERPRETER_AOUT 1
-#define INTERPRETER_ELF 2
-
 #define DLINFO_ITEMS 12
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
@@ -830,8 +826,6 @@ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
     memcpy(to, from, n);
 }
 
-static int load_aout_interp(void * exptr, int interp_fd);
-
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(struct elfhdr *ehdr)
 {
@@ -1069,7 +1063,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                    struct elfhdr * exec,
                                    abi_ulong load_addr,
                                    abi_ulong load_bias,
-                                   abi_ulong interp_load_addr, int ibcs,
+                                   abi_ulong interp_load_addr,
                                    struct image_info *info)
 {
     abi_ulong sp;
@@ -1099,7 +1093,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     size += DLINFO_ARCH_ITEMS * 2;
 #endif
     size += envc + argc + 2;
-    size += (!ibcs ? 3 : 1);    /* argc itself */
+    size += 1;  /* argc itself */
     size *= n;
     if (size & 15)
         sp -= 16 - (size & 15);
@@ -1141,7 +1135,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 
     info->saved_auxv = sp;
 
-    sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+    sp = loader_build_argptr(envc, argc, sp, p, 0);
     return sp;
 }
 
@@ -1394,11 +1388,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct elfhdr elf_ex;
     struct elfhdr interp_elf_ex;
-    struct exec interp_ex;
     int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned int interpreter_type = INTERPRETER_NONE;
     unsigned char ibcs2_interpreter;
     int i;
     abi_ulong mapped_addr;
@@ -1412,7 +1404,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong start_code, end_code, start_data, end_data;
     abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
-    char passed_fileno[6];
 
     ibcs2_interpreter = 0;
     status = 0;
@@ -1462,7 +1453,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_code = 0;
     start_data = 0;
     end_data = 0;
-    interp_ex.a_info = 0;
 
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
@@ -1527,59 +1517,22 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
             }
 
-            interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
-            interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
+            interp_elf_ex = *((struct elfhdr *) bprm->buf);
         }
         elf_ppnt++;
     }
 
     /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter){
-        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
-
-        /* Now figure out which format our binary is */
-        if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
-            (N_MAGIC(interp_ex) != QMAGIC)) {
-            interpreter_type = INTERPRETER_ELF;
-        }
-
+    if (elf_interpreter) {
         if (!elf_check_ident(&interp_elf_ex)) {
-            interpreter_type &= ~INTERPRETER_ELF;
-        }
-
-        if (!interpreter_type) {
             free(elf_interpreter);
             free(elf_phdata);
             close(bprm->fd);
+            close(interpreter_fd);
             return -ELIBBAD;
         }
     }
 
-    /* OK, we are done with that, now set up the arg stuff,
-       and then start this sucker up */
-
-    {
-        char * passed_p;
-
-        if (interpreter_type == INTERPRETER_AOUT) {
-            snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
-            passed_p = passed_fileno;
-
-            if (elf_interpreter) {
-                bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
-                bprm->argc++;
-            }
-        }
-        if (!bprm->p) {
-            if (elf_interpreter) {
-                free(elf_interpreter);
-            }
-            free (elf_phdata);
-            close(bprm->fd);
-            return -E2BIG;
-        }
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1772,15 +1725,9 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     end_data += load_bias;
 
     if (elf_interpreter) {
-        if (interpreter_type & 1) {
-            elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
-        } else if (interpreter_type & 2) {
-            elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                        &interp_load_addr, bprm->buf);
-        }
+        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
+                                    &interp_load_addr, bprm->buf);
         reloc_func_desc = interp_load_addr;
-
-        close(interpreter_fd);
         free(elf_interpreter);
 
         if (elf_entry == ~((abi_ulong)0UL)) {
@@ -1797,7 +1744,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         load_symbols(&elf_ex, bprm->fd, load_bias);
     }
 
-    if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
+    close(bprm->fd);
     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
 #ifdef LOW_ELF_STACK
@@ -1809,7 +1756,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                                 &elf_ex,
                                 load_addr, load_bias,
                                 interp_load_addr,
-                                (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
                                 info);
     info->load_addr = reloc_func_desc;
     info->start_brk = info->brk = elf_brk;
@@ -2692,15 +2638,8 @@ static int elf_core_dump(int signr, const CPUState *env)
         return (-errno);
     return (0);
 }
-
 #endif /* USE_ELF_CORE_DUMP */
 
-static int load_aout_interp(void * exptr, int interp_fd)
-{
-    printf("a.out interpreter not yet supported\n");
-    return(0);
-}
-
 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
     init_thread(regs, infop);
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (25 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

Moving toward a single copy of the elf binary loading code.
Fill in the details of the loaded image into a struct image_info.

Adjust create_elf_tables to read from such structures instead
of from a collection of passed arguments.  Don't return error
values from load_elf_interp; always exit(-1) with a message to
stderr.  Collect elf_interpreter handling in load_elf_binary
to a common spot.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  341 ++++++++++++++++++++++++-------------------------
 1 files changed, 167 insertions(+), 174 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 77267a4..0167414 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1060,11 +1060,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 }
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
-                                   struct elfhdr * exec,
-                                   abi_ulong load_addr,
-                                   abi_ulong load_bias,
-                                   abi_ulong interp_load_addr,
-                                   struct image_info *info)
+                                   struct elfhdr *exec,
+                                   struct image_info *info,
+                                   struct image_info *interp_info)
 {
     abi_ulong sp;
     int size;
@@ -1109,13 +1107,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT (AT_NULL, 0);
 
     /* There must be exactly DLINFO_ITEMS entries here.  */
-    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
@@ -1139,51 +1137,60 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
+/* Load an ELF image into the address space.
 
-static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
-                                 int interpreter_fd,
-                                 abi_ulong *interp_load_addr,
-                                 char bprm_buf[BPRM_BUF_SIZE])
+   IMAGE_NAME is the filename of the image, to use in error messages.
+   IMAGE_FD is the open file descriptor for the image.
+
+   BPRM_BUF is a copy of the beginning of the file; this of course
+   contains the elf file header at offset 0.  It is assumed that this
+   buffer is sufficiently aligned to present no problems to the host
+   in accessing data at aligned offsets within the buffer.
+
+   On return: INFO values will be filled in, as necessary or available.  */
+
+static void load_elf_image(const char *image_name, int image_fd,
+                           struct image_info *info,
+                           char bprm_buf[BPRM_BUF_SIZE])
 {
-    struct elf_phdr *elf_phdata  =  NULL;
-    abi_ulong load_addr, load_bias, loaddr, hiaddr;
-    int retval;
-    abi_ulong error;
-    int i;
+    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+    struct elf_phdr *phdr;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+    int i, retval;
+    const char *errmsg;
 
-    bswap_ehdr(interp_elf_ex);
-    if (!elf_check_ehdr(interp_elf_ex)) {
-        return ~((abi_ulong)0UL);
+    /* First of all, some simple consistency checks */
+    errmsg = "Invalid ELF image for this architecture";
+    if (!elf_check_ident(ehdr)) {
+        goto exit_errmsg;
+    }
+    bswap_ehdr(ehdr);
+    if (!elf_check_ehdr(ehdr)) {
+        goto exit_errmsg;
     }
 
-    /* Now read in all of the header information */
-    elf_phdata =  (struct elf_phdr *)
-        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    if (!elf_phdata)
-        return ~((abi_ulong)0UL);
-
-    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
-    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    i = ehdr->e_phnum * sizeof(struct elf_phdr);
+    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
+        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
     } else {
-        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        phdr = (struct elf_phdr *) alloca(i);
+        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
         if (retval != i) {
-            perror("load_elf_interp");
-            exit(-1);
+            goto exit_read;
         }
     }
-    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
+    bswap_phdr(phdr, ehdr->e_phnum);
 
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
-    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
-        if (elf_phdata[i].p_type == PT_LOAD) {
-            abi_ulong a = elf_phdata[i].p_vaddr;
+    for (i = 0; i < ehdr->e_phnum; ++i) {
+        if (phdr[i].p_type == PT_LOAD) {
+            abi_ulong a = phdr[i].p_vaddr;
             if (a < loaddr) {
                 loaddr = a;
             }
-            a += elf_phdata[i].p_memsz;
+            a += phdr[i].p_memsz;
             if (a > hiaddr) {
                 hiaddr = a;
             }
@@ -1191,7 +1198,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
 
     load_addr = loaddr;
-    if (interp_elf_ex->e_type == ET_DYN) {
+    if (ehdr->e_type == ET_DYN) {
         /* The image indicates that it can be loaded anywhere.  Find a
            location that can hold the memory space required.  If the
            image is pre-linked, LOADDR will be non-zero.  Since we do
@@ -1201,14 +1208,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
                                 -1, 0);
         if (load_addr == -1) {
-            perror("mmap");
-            exit(-1);
+            goto exit_perror;
         }
     }
     load_bias = load_addr - loaddr;
 
-    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
-        struct elf_phdr *eppnt = elf_phdata + i;
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = ehdr->e_entry + load_bias;
+    info->start_code = -1;
+    info->end_code = 0;
+    info->start_data = -1;
+    info->end_data = 0;
+    info->brk = 0;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+        struct elf_phdr *eppnt = phdr + i;
         if (eppnt->p_type == PT_LOAD) {
             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
             int elf_prot = 0;
@@ -1223,12 +1238,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
             error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
                                 elf_prot, MAP_PRIVATE | MAP_FIXED,
-                                interpreter_fd, eppnt->p_offset - vaddr_po);
+                                image_fd, eppnt->p_offset - vaddr_po);
             if (error == -1) {
-                /* Real error */
-                close(interpreter_fd);
-                free(elf_phdata);
-                return ~((abi_ulong)0UL);
+                goto exit_perror;
             }
 
             vaddr_ef = vaddr + eppnt->p_filesz;
@@ -1238,18 +1250,79 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (vaddr_ef < vaddr_em) {
                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
+
+            /* Find the full program boundaries.  */
+            if (elf_prot & PROT_EXEC) {
+                if (vaddr < info->start_code) {
+                    info->start_code = vaddr;
+                }
+                if (vaddr_ef > info->end_code) {
+                    info->end_code = vaddr_ef;
+                }
+            }
+            if (elf_prot & PROT_WRITE) {
+                if (vaddr < info->start_data) {
+                    info->start_data = vaddr;
+                }
+                if (vaddr_ef > info->end_data) {
+                    info->end_data = vaddr_ef;
+                }
+                if (vaddr_em > info->brk) {
+                    info->brk = vaddr_em;
+                }
+            }
         }
     }
 
+    if (info->end_data == 0) {
+        info->start_data = info->end_code;
+        info->end_data = info->end_code;
+        info->brk = info->end_code;
+    }
+
     if (qemu_log_enabled()) {
-        load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+        load_symbols(ehdr, image_fd, load_bias);
     }
 
-    close(interpreter_fd);
-    free(elf_phdata);
+    close(image_fd);
+    return;
+
+ exit_read:
+    if (retval >= 0) {
+        errmsg = "Incomplete read of file header";
+        goto exit_errmsg;
+    }
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", image_name, errmsg);
+    exit(-1);
+}
+
+static void load_elf_interp(const char *filename, struct image_info *info,
+                            char bprm_buf[BPRM_BUF_SIZE])
+{
+    int fd, retval;
+
+    fd = open(path(filename), O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
+
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(filename, fd, info, bprm_buf);
+    return;
 
-    *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
+ exit_perror:
+    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+    exit(-1);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1386,26 +1459,21 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
+    struct image_info interp_info;
     struct elfhdr elf_ex;
-    struct elfhdr interp_elf_ex;
-    int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned char ibcs2_interpreter;
     int i;
-    abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
     abi_ulong k, elf_brk;
     int retval;
-    char * elf_interpreter;
-    abi_ulong elf_entry, interp_load_addr = 0;
+    char *elf_interpreter = NULL;
+    abi_ulong elf_entry;
     int status;
     abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
 
-    ibcs2_interpreter = 0;
     status = 0;
     load_addr = 0;
     load_bias = 0;
@@ -1448,7 +1516,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     elf_brk = 0;
     elf_stack = ~((abi_ulong)0UL);
-    elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
     end_code = 0;
     start_data = 0;
@@ -1457,82 +1524,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
         if (elf_ppnt->p_type == PT_INTERP) {
-            if ( elf_interpreter != NULL )
-            {
-                free (elf_phdata);
-                free(elf_interpreter);
-                close(bprm->fd);
-                return -EINVAL;
-            }
-
-            /* This is the program interpreter used for
-             * shared libraries - for now assume that this
-             * is an a.out format binary
-             */
-
-            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-            if (elf_interpreter == NULL) {
-                free (elf_phdata);
-                close(bprm->fd);
-                return -ENOMEM;
-            }
-
             if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
-                       elf_ppnt->p_filesz);
+                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
             } else {
+                elf_interpreter = alloca(elf_ppnt->p_filesz);
                 retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
                                elf_ppnt->p_offset);
                 if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary2");
+                    perror("load_elf_binary");
                     exit(-1);
                 }
             }
-
-            /* If the program interpreter is one of these two,
-               then assume an iBCS2 image. Otherwise assume
-               a native linux image. */
-
-            /* JRP - Need to add X86 lib dir stuff here... */
-
-            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-                ibcs2_interpreter = 1;
-            }
-
-            retval = open(path(elf_interpreter), O_RDONLY);
-            if (retval < 0) {
-                perror(elf_interpreter);
-                exit(-1);
-            }
-            interpreter_fd = retval;
-
-            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
-            if (retval < 0) {
-                perror("load_elf_binary3");
-                exit(-1);
-            }
-            if (retval < BPRM_BUF_SIZE) {
-                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
-            }
-
-            interp_elf_ex = *((struct elfhdr *) bprm->buf);
         }
         elf_ppnt++;
     }
 
-    /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter) {
-        if (!elf_check_ident(&interp_elf_ex)) {
-            free(elf_interpreter);
-            free(elf_phdata);
-            close(bprm->fd);
-            close(interpreter_fd);
-            return -ELIBBAD;
-        }
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1691,7 +1697,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
-                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1724,19 +1729,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     start_data += load_bias;
     end_data += load_bias;
 
-    if (elf_interpreter) {
-        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                    &interp_load_addr, bprm->buf);
-        reloc_func_desc = interp_load_addr;
-        free(elf_interpreter);
-
-        if (elf_entry == ~((abi_ulong)0UL)) {
-            printf("Unable to load interpreter\n");
-            free(elf_phdata);
-            exit(-1);
-            return 0;
-        }
-    }
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = elf_entry;
+    info->start_brk = info->brk = elf_brk;
+    info->end_code = end_code;
+    info->start_code = start_code;
+    info->start_data = start_data;
+    info->end_data = end_data;
+    info->personality = PER_LINUX;
 
     free(elf_phdata);
 
@@ -1745,46 +1746,38 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     close(bprm->fd);
-    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
-#ifdef LOW_ELF_STACK
-    info->start_stack = bprm->p = elf_stack - 4;
-#endif
-    bprm->p = create_elf_tables(bprm->p,
-                                bprm->argc,
-                                bprm->envc,
-                                &elf_ex,
-                                load_addr, load_bias,
-                                interp_load_addr,
-                                info);
-    info->load_addr = reloc_func_desc;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->start_stack = bprm->p;
+    if (elf_interpreter) {
+        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
 
-#if 0
-    printf("(start_brk) %x\n" , info->start_brk);
-    printf("(end_code) %x\n" , info->end_code);
-    printf("(start_code) %x\n" , info->start_code);
-    printf("(end_data) %x\n" , info->end_data);
-    printf("(start_stack) %x\n" , info->start_stack);
-    printf("(brk) %x\n" , info->brk);
-#endif
+        /* If the program interpreter is one of these two, then assume
+           an iBCS2 image.  Otherwise assume a native linux image.  */
+
+        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
+            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
+            info->personality = PER_SVR4;
 
-    if ( info->personality == PER_SVR4 )
-    {
-        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-           and some applications "depend" upon this behavior.
-           Since we do not have the power to recompile these, we
-           emulate the SVr4 behavior.  Sigh.  */
-        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
+            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+               and some applications "depend" upon this behavior.  Since
+               we do not have the power to recompile these, we emulate
+               the SVr4 behavior.  Sigh.  */
+            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                        MAP_FIXED | MAP_PRIVATE, -1, 0);
+        }
     }
 
-    info->entry = elf_entry;
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+                                info, (elf_interpreter ? &interp_info : NULL));
+    info->start_stack = bprm->p;
+
+    /* If we have an interpreter, set that as the program's entry point.
+       Copy the load_addr as well, to help PPC64 interpret the entry
+       point as a function descriptor.  Do this after creating elf tables
+       so that we copy the original program entry point into the AUXV.  */
+    if (elf_interpreter) {
+        info->load_addr = interp_info.load_addr;
+        info->entry = interp_info.entry;
+    }
 
 #ifdef USE_ELF_CORE_DUMP
     bprm->core_dump = &elf_core_dump;
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary.
  2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
                   ` (26 preceding siblings ...)
  2010-05-05 18:07 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
@ 2010-05-05 18:07 ` Richard Henderson
  27 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-05-05 18:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: paul

This requires moving the PT_INTERP extraction and GUEST_BASE
handling into load_elf_image.  Key this off a non-null pointer
argument to receive the interpreter name.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  380 ++++++++++++++------------------------------------
 1 files changed, 103 insertions(+), 277 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0167414..d435564 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -811,9 +811,6 @@ struct exec
 #define ZMAGIC 0413
 #define QMAGIC 0314
 
-/* max code+data+bss+brk space allocated to ET_DYN executables */
-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-
 /* Necessary parameters */
 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
@@ -1150,7 +1147,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
    On return: INFO values will be filled in, as necessary or available.  */
 
 static void load_elf_image(const char *image_name, int image_fd,
-                           struct image_info *info,
+                           struct image_info *info, char **pinterp_name,
                            char bprm_buf[BPRM_BUF_SIZE])
 {
     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
@@ -1210,6 +1207,67 @@ static void load_elf_image(const char *image_name, int image_fd,
         if (load_addr == -1) {
             goto exit_perror;
         }
+    } else if (pinterp_name != NULL) {
+        /* This is the main executable.  Make sure that the low
+           address does not conflict with MMAP_MIN_ADDR or the
+           QEMU application itself.  */
+#if defined(CONFIG_USE_GUEST_BASE)
+        /*
+         * In case where user has not explicitly set the guest_base, we
+         * probe here that should we set it automatically.
+         */
+        if (!have_guest_base) {
+            unsigned long host_start, real_start, host_size;
+
+            /* Round addresses to page boundaries.  */
+            loaddr &= qemu_host_page_mask;
+            hiaddr = HOST_PAGE_ALIGN(hiaddr);
+
+            if (loaddr < mmap_min_addr) {
+                host_start = HOST_PAGE_ALIGN(mmap_min_addr);
+            } else {
+                host_start = loaddr;
+                if (host_start != loaddr) {
+                    errmsg = "Address overflow loading ELF binary";
+                    goto exit_errmsg;
+                }
+            }
+            host_size = hiaddr - loaddr;
+            while (1) {
+                /* Do not use mmap_find_vma here because that is limited to the
+                   guest address space.  We are going to make the
+                   guest address space fit whatever we're given.  */
+                real_start = (unsigned long)
+                    mmap((void *)host_start, host_size, PROT_NONE,
+                         MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
+                if (real_start == (unsigned long)-1) {
+                    goto exit_perror;
+                }
+                if (real_start == host_start) {
+                    break;
+                }
+                /* That address didn't work.  Unmap and try a different one.
+                   The address the host picked because is typically right at
+                   the top of the host address space and leaves the guest with
+                   no usable address space.  Resort to a linear search.  We
+                   already compensated for mmap_min_addr, so this should not
+                   happen often.  Probably means we got unlucky and host
+                   address space randomization put a shared library somewhere
+                   inconvenient.  */
+                munmap((void *)real_start, host_size);
+                host_start += qemu_host_page_size;
+                if (host_start == loaddr) {
+                    /* Theoretically possible if host doesn't have any suitably
+                       aligned areas.  Normally the first mmap will fail.  */
+                    errmsg = "Unable to find space for application";
+                    goto exit_errmsg;
+                }
+            }
+            qemu_log("Relocating guest address space from 0x"
+                     TARGET_ABI_FMT_lx " to 0x%lx\n", loaddr, real_start);
+            guest_base = real_start - loaddr;
+        }
+#endif
     }
     load_bias = load_addr - loaddr;
 
@@ -1271,6 +1329,33 @@ static void load_elf_image(const char *image_name, int image_fd,
                     info->brk = vaddr_em;
                 }
             }
+        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
+            char *interp_name;
+
+            if (*pinterp_name) {
+                errmsg = "Multiple PT_INTERP entries";
+                goto exit_errmsg;
+            }
+            interp_name = malloc(eppnt->p_filesz);
+            if (!interp_name) {
+                goto exit_perror;
+            }
+
+            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(interp_name, bprm_buf + eppnt->p_offset,
+                       eppnt->p_filesz);
+            } else {
+                retval = pread(image_fd, interp_name, eppnt->p_filesz,
+                               eppnt->p_offset);
+                if (retval != eppnt->p_filesz) {
+                    goto exit_perror;
+                }
+            }
+            if (interp_name[eppnt->p_filesz - 1] != 0) {
+                errmsg = "Invalid PT_INTERP entry";
+                goto exit_errmsg;
+            }
+            *pinterp_name = interp_name;
         }
     }
 
@@ -1317,7 +1402,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
     }
 
-    load_elf_image(filename, fd, info, bprm_buf);
+    load_elf_image(filename, fd, info, NULL, bprm_buf);
     return;
 
  exit_perror:
@@ -1461,291 +1546,31 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 {
     struct image_info interp_info;
     struct elfhdr elf_ex;
-    abi_ulong load_addr, load_bias;
-    int load_addr_set = 0;
-    int i;
-    struct elf_phdr * elf_ppnt;
-    struct elf_phdr *elf_phdata;
-    abi_ulong k, elf_brk;
-    int retval;
     char *elf_interpreter = NULL;
-    abi_ulong elf_entry;
-    int status;
-    abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong elf_stack;
 
-    status = 0;
-    load_addr = 0;
-    load_bias = 0;
-    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
+    info->start_mmap = (abi_ulong)ELF_START_MMAP;
+    info->mmap = 0;
+    info->rss = 0;
 
-    /* First of all, some simple consistency checks */
-    if (!elf_check_ident(&elf_ex)) {
-        return -ENOEXEC;
-    }
-    bswap_ehdr(&elf_ex);
-    if (!elf_check_ehdr(&elf_ex)) {
-        return -ENOEXEC;
-    }
+    load_elf_image(bprm->filename, bprm->fd, info,
+                   &elf_interpreter, bprm->buf);
+
+    /* ??? We need a copy of the elf header for passing to create_elf_tables.
+       If we do nothing, we'll have overwritten this when we re-use bprm->buf
+       when we load the interpreter.  */
+    elf_ex = *(struct elfhdr *)bprm->buf;
 
     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
     if (!bprm->p) {
-        retval = -E2BIG;
-    }
-
-    /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)
-        malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
-    if (elf_phdata == NULL) {
-        return -ENOMEM;
-    }
-
-    i = elf_ex.e_phnum * sizeof(struct elf_phdr);
-    if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
-    } else {
-        retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
-        if (retval != i) {
-            perror("load_elf_binary");
-            exit(-1);
-        }
-    }
-    bswap_phdr(elf_phdata, elf_ex.e_phnum);
-
-    elf_brk = 0;
-    elf_stack = ~((abi_ulong)0UL);
-    start_code = ~((abi_ulong)0UL);
-    end_code = 0;
-    start_data = 0;
-    end_data = 0;
-
-    elf_ppnt = elf_phdata;
-    for(i=0;i < elf_ex.e_phnum; i++) {
-        if (elf_ppnt->p_type == PT_INTERP) {
-            if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
-            } else {
-                elf_interpreter = alloca(elf_ppnt->p_filesz);
-                retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
-                               elf_ppnt->p_offset);
-                if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary");
-                    exit(-1);
-                }
-            }
-        }
-        elf_ppnt++;
-    }
-
-    /* OK, This is the point of no return */
-    info->end_data = 0;
-    info->end_code = 0;
-    info->start_mmap = (abi_ulong)ELF_START_MMAP;
-    info->mmap = 0;
-    elf_entry = (abi_ulong) elf_ex.e_entry;
-
-#if defined(CONFIG_USE_GUEST_BASE)
-    /*
-     * In case where user has not explicitly set the guest_base, we
-     * probe here that should we set it automatically.
-     */
-    if (!have_guest_base) {
-        /*
-         * Go through ELF program header table and find the address
-         * range used by loadable segments.  Check that this is available on
-         * the host, and if not find a suitable value for guest_base.  */
-        abi_ulong app_start = ~0;
-        abi_ulong app_end = 0;
-        abi_ulong addr;
-        unsigned long host_start;
-        unsigned long real_start;
-        unsigned long host_size;
-        for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
-             i++, elf_ppnt++) {
-            if (elf_ppnt->p_type != PT_LOAD)
-                continue;
-            addr = elf_ppnt->p_vaddr;
-            if (addr < app_start) {
-                app_start = addr;
-            }
-            addr += elf_ppnt->p_memsz;
-            if (addr > app_end) {
-                app_end = addr;
-            }
-        }
-
-        /* If we don't have any loadable segments then something
-           is very wrong.  */
-        assert(app_start < app_end);
-
-        /* Round addresses to page boundaries.  */
-        app_start = app_start & qemu_host_page_mask;
-        app_end = HOST_PAGE_ALIGN(app_end);
-        if (app_start < mmap_min_addr) {
-            host_start = HOST_PAGE_ALIGN(mmap_min_addr);
-        } else {
-            host_start = app_start;
-            if (host_start != app_start) {
-                fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
-                abort();
-            }
-        }
-        host_size = app_end - app_start;
-        while (1) {
-            /* Do not use mmap_find_vma here because that is limited to the
-               guest address space.  We are going to make the
-               guest address space fit whatever we're given.  */
-            real_start = (unsigned long)mmap((void *)host_start, host_size,
-                PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
-            if (real_start == (unsigned long)-1) {
-                fprintf(stderr, "qemu: Virtual memory exausted\n");
-                abort();
-            }
-            if (real_start == host_start) {
-                break;
-            }
-            /* That address didn't work.  Unmap and try a different one.
-               The address the host picked because is typically
-               right at the top of the host address space and leaves the
-               guest with no usable address space.  Resort to a linear search.
-               We already compensated for mmap_min_addr, so this should not
-               happen often.  Probably means we got unlucky and host address
-               space randomization put a shared library somewhere
-               inconvenient.  */
-            munmap((void *)real_start, host_size);
-            host_start += qemu_host_page_size;
-            if (host_start == app_start) {
-                /* Theoretically possible if host doesn't have any
-                   suitably aligned areas.  Normally the first mmap will
-                   fail.  */
-                fprintf(stderr, "qemu: Unable to find space for application\n");
-                abort();
-            }
-        }
-        qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
-                 " to 0x%lx\n", app_start, real_start);
-        guest_base = real_start - app_start;
+        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
+        exit(-1);
     }
-#endif /* CONFIG_USE_GUEST_BASE */
 
     /* Do this so that we can load the interpreter, if need be.  We will
        change some of these later */
-    info->rss = 0;
     bprm->p = setup_arg_pages(bprm->p, bprm, info);
-    info->start_stack = bprm->p;
-
-    /* Now we do a little grungy work by mmaping the ELF image into
-     * the correct location in memory.  At this point, we assume that
-     * the image should be loaded at fixed address, not at a variable
-     * address.
-     */
-
-    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
-        int elf_prot = 0;
-        int elf_flags = 0;
-        abi_ulong error;
-
-        if (elf_ppnt->p_type != PT_LOAD)
-            continue;
-
-        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
-        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
-        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
-            elf_flags |= MAP_FIXED;
-        } else if (elf_ex.e_type == ET_DYN) {
-            /* Try and get dynamic programs out of the way of the default mmap
-               base, as well as whatever program they might try to exec.  This
-               is because the brk will follow the loader, and is not movable.  */
-            /* NOTE: for qemu, we do a big mmap to get enough space
-               without hardcoding any address */
-            error = target_mmap(0, ET_DYN_MAP_SIZE,
-                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
-                                -1, 0);
-            if (error == -1) {
-                perror("mmap");
-                exit(-1);
-            }
-            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
-        }
-
-        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
-                            (elf_ppnt->p_filesz +
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-                            elf_prot,
-                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
-                            bprm->fd,
-                            (elf_ppnt->p_offset -
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
-        if (error == -1) {
-            perror("mmap");
-            exit(-1);
-        }
-
-#ifdef LOW_ELF_STACK
-        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
-            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
-#endif
-
-        if (!load_addr_set) {
-            load_addr_set = 1;
-            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-            if (elf_ex.e_type == ET_DYN) {
-                load_bias += error -
-                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
-                load_addr += load_bias;
-            }
-        }
-        k = elf_ppnt->p_vaddr;
-        if (k < start_code)
-            start_code = k;
-        if (start_data < k)
-            start_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-            end_code = k;
-        if (end_data < k)
-            end_data = k;
-        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-        if (k > elf_brk) {
-            elf_brk = TARGET_PAGE_ALIGN(k);
-        }
-
-        /* If the load segment requests extra zeros (e.g. bss), map it.  */
-        if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
-            abi_ulong base = load_bias + elf_ppnt->p_vaddr;
-            zero_bss(base + elf_ppnt->p_filesz,
-                     base + elf_ppnt->p_memsz, elf_prot);
-        }
-    }
-
-    elf_entry += load_bias;
-    elf_brk += load_bias;
-    start_code += load_bias;
-    end_code += load_bias;
-    start_data += load_bias;
-    end_data += load_bias;
-
-    info->load_bias = load_bias;
-    info->load_addr = load_addr;
-    info->entry = elf_entry;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->personality = PER_LINUX;
-
-    free(elf_phdata);
-
-    if (qemu_log_enabled()) {
-        load_symbols(&elf_ex, bprm->fd, load_bias);
-    }
-
-    close(bprm->fd);
 
     if (elf_interpreter) {
         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
@@ -1777,6 +1602,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     if (elf_interpreter) {
         info->load_addr = interp_info.load_addr;
         info->entry = interp_info.entry;
+        free(elf_interpreter);
     }
 
 #ifdef USE_ELF_CORE_DUMP
-- 
1.7.0.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp.
  2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
  2010-07-28 22:00   ` Edgar E. Iglesias
  0 siblings, 1 reply; 48+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 UTC (permalink / raw)
  To: qemu-devel

Moving toward a single copy of the elf binary loading code.
Fill in the details of the loaded image into a struct image_info.

Adjust create_elf_tables to read from such structures instead
of from a collection of passed arguments.  Don't return error
values from load_elf_interp; always exit(-1) with a message to
stderr.  Collect elf_interpreter handling in load_elf_binary
to a common spot.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 linux-user/elfload.c |  341 ++++++++++++++++++++++++-------------------------
 1 files changed, 167 insertions(+), 174 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 61167cd..8ff9b6a 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1079,11 +1079,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
 }
 
 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
-                                   struct elfhdr * exec,
-                                   abi_ulong load_addr,
-                                   abi_ulong load_bias,
-                                   abi_ulong interp_load_addr,
-                                   struct image_info *info)
+                                   struct elfhdr *exec,
+                                   struct image_info *info,
+                                   struct image_info *interp_info)
 {
     abi_ulong sp;
     int size;
@@ -1128,13 +1126,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT (AT_NULL, 0);
 
     /* There must be exactly DLINFO_ITEMS entries here.  */
-    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
-    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
-    NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+    NEW_AUX_ENT(AT_ENTRY, info->entry);
     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
@@ -1158,51 +1156,60 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     return sp;
 }
 
+/* Load an ELF image into the address space.
 
-static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
-                                 int interpreter_fd,
-                                 abi_ulong *interp_load_addr,
-                                 char bprm_buf[BPRM_BUF_SIZE])
+   IMAGE_NAME is the filename of the image, to use in error messages.
+   IMAGE_FD is the open file descriptor for the image.
+
+   BPRM_BUF is a copy of the beginning of the file; this of course
+   contains the elf file header at offset 0.  It is assumed that this
+   buffer is sufficiently aligned to present no problems to the host
+   in accessing data at aligned offsets within the buffer.
+
+   On return: INFO values will be filled in, as necessary or available.  */
+
+static void load_elf_image(const char *image_name, int image_fd,
+                           struct image_info *info,
+                           char bprm_buf[BPRM_BUF_SIZE])
 {
-    struct elf_phdr *elf_phdata  =  NULL;
-    abi_ulong load_addr, load_bias, loaddr, hiaddr;
-    int retval;
-    abi_ulong error;
-    int i;
+    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+    struct elf_phdr *phdr;
+    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+    int i, retval;
+    const char *errmsg;
 
-    bswap_ehdr(interp_elf_ex);
-    if (!elf_check_ehdr(interp_elf_ex)) {
-        return ~((abi_ulong)0UL);
+    /* First of all, some simple consistency checks */
+    errmsg = "Invalid ELF image for this architecture";
+    if (!elf_check_ident(ehdr)) {
+        goto exit_errmsg;
+    }
+    bswap_ehdr(ehdr);
+    if (!elf_check_ehdr(ehdr)) {
+        goto exit_errmsg;
     }
 
-    /* Now read in all of the header information */
-    elf_phdata =  (struct elf_phdr *)
-        malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
-    if (!elf_phdata)
-        return ~((abi_ulong)0UL);
-
-    i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
-    if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
-        memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
+    i = ehdr->e_phnum * sizeof(struct elf_phdr);
+    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
+        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
     } else {
-        retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
+        phdr = (struct elf_phdr *) alloca(i);
+        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
         if (retval != i) {
-            perror("load_elf_interp");
-            exit(-1);
+            goto exit_read;
         }
     }
-    bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
+    bswap_phdr(phdr, ehdr->e_phnum);
 
     /* Find the maximum size of the image and allocate an appropriate
        amount of memory to handle that.  */
     loaddr = -1, hiaddr = 0;
-    for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
-        if (elf_phdata[i].p_type == PT_LOAD) {
-            abi_ulong a = elf_phdata[i].p_vaddr;
+    for (i = 0; i < ehdr->e_phnum; ++i) {
+        if (phdr[i].p_type == PT_LOAD) {
+            abi_ulong a = phdr[i].p_vaddr;
             if (a < loaddr) {
                 loaddr = a;
             }
-            a += elf_phdata[i].p_memsz;
+            a += phdr[i].p_memsz;
             if (a > hiaddr) {
                 hiaddr = a;
             }
@@ -1210,7 +1217,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
     }
 
     load_addr = loaddr;
-    if (interp_elf_ex->e_type == ET_DYN) {
+    if (ehdr->e_type == ET_DYN) {
         /* The image indicates that it can be loaded anywhere.  Find a
            location that can hold the memory space required.  If the
            image is pre-linked, LOADDR will be non-zero.  Since we do
@@ -1220,14 +1227,22 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
                                 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
                                 -1, 0);
         if (load_addr == -1) {
-            perror("mmap");
-            exit(-1);
+            goto exit_perror;
         }
     }
     load_bias = load_addr - loaddr;
 
-    for (i = 0; i < interp_elf_ex->e_phnum; i++) {
-        struct elf_phdr *eppnt = elf_phdata + i;
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = ehdr->e_entry + load_bias;
+    info->start_code = -1;
+    info->end_code = 0;
+    info->start_data = -1;
+    info->end_data = 0;
+    info->brk = 0;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+        struct elf_phdr *eppnt = phdr + i;
         if (eppnt->p_type == PT_LOAD) {
             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
             int elf_prot = 0;
@@ -1242,12 +1257,9 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
 
             error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
                                 elf_prot, MAP_PRIVATE | MAP_FIXED,
-                                interpreter_fd, eppnt->p_offset - vaddr_po);
+                                image_fd, eppnt->p_offset - vaddr_po);
             if (error == -1) {
-                /* Real error */
-                close(interpreter_fd);
-                free(elf_phdata);
-                return ~((abi_ulong)0UL);
+                goto exit_perror;
             }
 
             vaddr_ef = vaddr + eppnt->p_filesz;
@@ -1257,18 +1269,79 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
             if (vaddr_ef < vaddr_em) {
                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
             }
+
+            /* Find the full program boundaries.  */
+            if (elf_prot & PROT_EXEC) {
+                if (vaddr < info->start_code) {
+                    info->start_code = vaddr;
+                }
+                if (vaddr_ef > info->end_code) {
+                    info->end_code = vaddr_ef;
+                }
+            }
+            if (elf_prot & PROT_WRITE) {
+                if (vaddr < info->start_data) {
+                    info->start_data = vaddr;
+                }
+                if (vaddr_ef > info->end_data) {
+                    info->end_data = vaddr_ef;
+                }
+                if (vaddr_em > info->brk) {
+                    info->brk = vaddr_em;
+                }
+            }
         }
     }
 
+    if (info->end_data == 0) {
+        info->start_data = info->end_code;
+        info->end_data = info->end_code;
+        info->brk = info->end_code;
+    }
+
     if (qemu_log_enabled()) {
-        load_symbols(interp_elf_ex, interpreter_fd, load_bias);
+        load_symbols(ehdr, image_fd, load_bias);
     }
 
-    close(interpreter_fd);
-    free(elf_phdata);
+    close(image_fd);
+    return;
+
+ exit_read:
+    if (retval >= 0) {
+        errmsg = "Incomplete read of file header";
+        goto exit_errmsg;
+    }
+ exit_perror:
+    errmsg = strerror(errno);
+ exit_errmsg:
+    fprintf(stderr, "%s: %s\n", image_name, errmsg);
+    exit(-1);
+}
+
+static void load_elf_interp(const char *filename, struct image_info *info,
+                            char bprm_buf[BPRM_BUF_SIZE])
+{
+    int fd, retval;
+
+    fd = open(path(filename), O_RDONLY);
+    if (fd < 0) {
+        goto exit_perror;
+    }
+
+    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+    if (retval < 0) {
+        goto exit_perror;
+    }
+    if (retval < BPRM_BUF_SIZE) {
+        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+    }
+
+    load_elf_image(filename, fd, info, bprm_buf);
+    return;
 
-    *interp_load_addr = load_addr;
-    return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
+ exit_perror:
+    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
+    exit(-1);
 }
 
 static int symfind(const void *s0, const void *s1)
@@ -1405,26 +1478,21 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                     struct image_info * info)
 {
+    struct image_info interp_info;
     struct elfhdr elf_ex;
-    struct elfhdr interp_elf_ex;
-    int interpreter_fd = -1; /* avoid warning */
     abi_ulong load_addr, load_bias;
     int load_addr_set = 0;
-    unsigned char ibcs2_interpreter;
     int i;
-    abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
     abi_ulong k, elf_brk;
     int retval;
-    char * elf_interpreter;
-    abi_ulong elf_entry, interp_load_addr = 0;
+    char *elf_interpreter = NULL;
+    abi_ulong elf_entry;
     int status;
     abi_ulong start_code, end_code, start_data, end_data;
-    abi_ulong reloc_func_desc = 0;
     abi_ulong elf_stack;
 
-    ibcs2_interpreter = 0;
     status = 0;
     load_addr = 0;
     load_bias = 0;
@@ -1467,7 +1535,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
 
     elf_brk = 0;
     elf_stack = ~((abi_ulong)0UL);
-    elf_interpreter = NULL;
     start_code = ~((abi_ulong)0UL);
     end_code = 0;
     start_data = 0;
@@ -1476,82 +1543,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_ppnt = elf_phdata;
     for(i=0;i < elf_ex.e_phnum; i++) {
         if (elf_ppnt->p_type == PT_INTERP) {
-            if ( elf_interpreter != NULL )
-            {
-                free (elf_phdata);
-                free(elf_interpreter);
-                close(bprm->fd);
-                return -EINVAL;
-            }
-
-            /* This is the program interpreter used for
-             * shared libraries - for now assume that this
-             * is an a.out format binary
-             */
-
-            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
-
-            if (elf_interpreter == NULL) {
-                free (elf_phdata);
-                close(bprm->fd);
-                return -ENOMEM;
-            }
-
             if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
-                       elf_ppnt->p_filesz);
+                elf_interpreter = bprm->buf + elf_ppnt->p_offset;
             } else {
+                elf_interpreter = alloca(elf_ppnt->p_filesz);
                 retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
                                elf_ppnt->p_offset);
                 if (retval != elf_ppnt->p_filesz) {
-                    perror("load_elf_binary2");
+                    perror("load_elf_binary");
                     exit(-1);
                 }
             }
-
-            /* If the program interpreter is one of these two,
-               then assume an iBCS2 image. Otherwise assume
-               a native linux image. */
-
-            /* JRP - Need to add X86 lib dir stuff here... */
-
-            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
-                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
-                ibcs2_interpreter = 1;
-            }
-
-            retval = open(path(elf_interpreter), O_RDONLY);
-            if (retval < 0) {
-                perror(elf_interpreter);
-                exit(-1);
-            }
-            interpreter_fd = retval;
-
-            retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
-            if (retval < 0) {
-                perror("load_elf_binary3");
-                exit(-1);
-            }
-            if (retval < BPRM_BUF_SIZE) {
-                memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
-            }
-
-            interp_elf_ex = *((struct elfhdr *) bprm->buf);
         }
         elf_ppnt++;
     }
 
-    /* Some simple consistency checks for the interpreter */
-    if (elf_interpreter) {
-        if (!elf_check_ident(&interp_elf_ex)) {
-            free(elf_interpreter);
-            free(elf_phdata);
-            close(bprm->fd);
-            close(interpreter_fd);
-            return -ELIBBAD;
-        }
-    }
-
     /* OK, This is the point of no return */
     info->end_data = 0;
     info->end_code = 0;
@@ -1710,7 +1716,6 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
                 load_bias += error -
                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
                 load_addr += load_bias;
-                reloc_func_desc = load_bias;
             }
         }
         k = elf_ppnt->p_vaddr;
@@ -1743,19 +1748,15 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     start_data += load_bias;
     end_data += load_bias;
 
-    if (elf_interpreter) {
-        elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
-                                    &interp_load_addr, bprm->buf);
-        reloc_func_desc = interp_load_addr;
-        free(elf_interpreter);
-
-        if (elf_entry == ~((abi_ulong)0UL)) {
-            printf("Unable to load interpreter\n");
-            free(elf_phdata);
-            exit(-1);
-            return 0;
-        }
-    }
+    info->load_bias = load_bias;
+    info->load_addr = load_addr;
+    info->entry = elf_entry;
+    info->start_brk = info->brk = elf_brk;
+    info->end_code = end_code;
+    info->start_code = start_code;
+    info->start_data = start_data;
+    info->end_data = end_data;
+    info->personality = PER_LINUX;
 
     free(elf_phdata);
 
@@ -1764,46 +1765,38 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     }
 
     close(bprm->fd);
-    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 
-#ifdef LOW_ELF_STACK
-    info->start_stack = bprm->p = elf_stack - 4;
-#endif
-    bprm->p = create_elf_tables(bprm->p,
-                                bprm->argc,
-                                bprm->envc,
-                                &elf_ex,
-                                load_addr, load_bias,
-                                interp_load_addr,
-                                info);
-    info->load_addr = reloc_func_desc;
-    info->start_brk = info->brk = elf_brk;
-    info->end_code = end_code;
-    info->start_code = start_code;
-    info->start_data = start_data;
-    info->end_data = end_data;
-    info->start_stack = bprm->p;
+    if (elf_interpreter) {
+        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
 
-#if 0
-    printf("(start_brk) %x\n" , info->start_brk);
-    printf("(end_code) %x\n" , info->end_code);
-    printf("(start_code) %x\n" , info->start_code);
-    printf("(end_data) %x\n" , info->end_data);
-    printf("(start_stack) %x\n" , info->start_stack);
-    printf("(brk) %x\n" , info->brk);
-#endif
+        /* If the program interpreter is one of these two, then assume
+           an iBCS2 image.  Otherwise assume a native linux image.  */
+
+        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
+            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
+            info->personality = PER_SVR4;
 
-    if ( info->personality == PER_SVR4 )
-    {
-        /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
-           and some applications "depend" upon this behavior.
-           Since we do not have the power to recompile these, we
-           emulate the SVr4 behavior.  Sigh.  */
-        mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
-                                  MAP_FIXED | MAP_PRIVATE, -1, 0);
+            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
+               and some applications "depend" upon this behavior.  Since
+               we do not have the power to recompile these, we emulate
+               the SVr4 behavior.  Sigh.  */
+            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+                        MAP_FIXED | MAP_PRIVATE, -1, 0);
+        }
     }
 
-    info->entry = elf_entry;
+    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
+                                info, (elf_interpreter ? &interp_info : NULL));
+    info->start_stack = bprm->p;
+
+    /* If we have an interpreter, set that as the program's entry point.
+       Copy the load_addr as well, to help PPC64 interpret the entry
+       point as a function descriptor.  Do this after creating elf tables
+       so that we copy the original program entry point into the AUXV.  */
+    if (elf_interpreter) {
+        info->load_addr = interp_info.load_addr;
+        info->entry = interp_info.entry;
+    }
 
 #ifdef USE_ELF_CORE_DUMP
     bprm->core_dump = &elf_core_dump;
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp.
  2010-07-27 17:25 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
@ 2010-07-28 22:00   ` Edgar E. Iglesias
  2010-07-28 23:18     ` Richard Henderson
  0 siblings, 1 reply; 48+ messages in thread
From: Edgar E. Iglesias @ 2010-07-28 22:00 UTC (permalink / raw)
  To: Richard Henderson; +Cc: qemu-devel

On Tue, Jul 27, 2010 at 10:25:37AM -0700, Richard Henderson wrote:
> Moving toward a single copy of the elf binary loading code.
> Fill in the details of the loaded image into a struct image_info.
> 
> Adjust create_elf_tables to read from such structures instead
> of from a collection of passed arguments.  Don't return error
> values from load_elf_interp; always exit(-1) with a message to
> stderr.  Collect elf_interpreter handling in load_elf_binary
> to a common spot.
> 
> Signed-off-by: Richard Henderson <rth@twiddle.net>
> ---
>  linux-user/elfload.c |  341 ++++++++++++++++++++++++-------------------------
>  1 files changed, 167 insertions(+), 174 deletions(-)
> 
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 61167cd..8ff9b6a 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1079,11 +1079,9 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
>  }
>  
>  static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
> -                                   struct elfhdr * exec,
> -                                   abi_ulong load_addr,
> -                                   abi_ulong load_bias,
> -                                   abi_ulong interp_load_addr,
> -                                   struct image_info *info)
> +                                   struct elfhdr *exec,
> +                                   struct image_info *info,
> +                                   struct image_info *interp_info)
>  {
>      abi_ulong sp;
>      int size;
> @@ -1128,13 +1126,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
>      NEW_AUX_ENT (AT_NULL, 0);
>  
>      /* There must be exactly DLINFO_ITEMS entries here.  */
> -    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
> +    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
>      NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
>      NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
>      NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
> -    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
> +    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));


Hi Richard,

I think this part breaks loading of statically linked ELFs (no
interpreter). I beleive Linux sets AT_BASE to zero in those cases.

Cheers

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp.
  2010-07-28 22:00   ` Edgar E. Iglesias
@ 2010-07-28 23:18     ` Richard Henderson
  0 siblings, 0 replies; 48+ messages in thread
From: Richard Henderson @ 2010-07-28 23:18 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: qemu-devel

On 07/28/2010 03:00 PM, Edgar E. Iglesias wrote:
>> -    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
>> +    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info->load_addr));
> 
> 
> Hi Richard,
> 
> I think this part breaks loading of statically linked ELFs (no
> interpreter). I beleive Linux sets AT_BASE to zero in those cases.

You're right.  This should be 

  interp_info ? interp_info->load_addr : 0


r~

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2010-07-29  0:00 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-05 16:47 [Qemu-devel] [PATCH 00/14] Implement VDSO for x86_64-linux-user Richard Henderson
2010-03-31 22:12 ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-04-04 18:38 ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
2010-04-04 19:07 ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
2010-04-04 19:34 ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-04-04 19:35 ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
2010-04-04 19:54 ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-04-04 21:16 ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
2010-04-04 22:04 ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-04-04 22:14 ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
2010-04-04 22:31 ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-04-05  0:46 ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-04-05  2:13 ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
2010-04-05 16:26 ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-04-05 16:37 ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-04-05 18:14   ` malc
2010-04-05 18:38     ` Richard Henderson
2010-04-28 19:36 ` [Qemu-devel] [PATCH 00/14] Implement VDSO for x86-64-linux-user, v2 Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 04/14] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 01/14] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 02/14] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 09/14] linux-user: Put the stack guard page at the top Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 10/14] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 05/14] linux-user: Fix ELF_DATA for Alpha Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 06/14] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 08/14] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 11/14] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 14/14] linux-user: Load a VDSO for x86-64 Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 13/14] linux-user: Build vdso for x64 Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 12/14] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 07/14] linux-user: Load symbols from the interpreter Richard Henderson
2010-04-28 19:39   ` [Qemu-devel] [PATCH 03/14] linux-user: Reindent elfload.c Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 00/12] Cleanup linux-user/elfload.c, v2 Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-05-05 18:07 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
  -- strict thread matches above, loose matches on Subject: below --
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
2010-07-28 22:00   ` Edgar E. Iglesias
2010-07-28 23:18     ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).