* [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c
@ 2010-07-27 17:25 Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
` (13 more replies)
0 siblings, 14 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 UTC (permalink / raw)
To: qemu-devel
A re-based and re-tested version of a patch series I
posted back in April and May. These cleanups prepare
elfload.c for loading the VDSO for x86_64.
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 | 1791 ++++++++++++++++++++----------------------------
linux-user/linuxload.c | 17 +-
linux-user/qemu.h | 7 +-
4 files changed, 794 insertions(+), 1065 deletions(-)
^ permalink raw reply [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment.
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-27 17:25 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
` (12 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 accb44d..5a0d3d4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1034,60 +1034,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,
@@ -1179,12 +1166,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
@@ -1257,7 +1241,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;
@@ -1285,40 +1268,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;
@@ -1472,7 +1432,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;
@@ -1531,10 +1491,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);
@@ -1838,18 +1796,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;
@@ -1904,12 +1868,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h.
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 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
` (11 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 eb9e3be..7067c90 100644
--- a/elf.h
+++ b/elf.h
@@ -147,8 +147,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
@@ -207,6 +236,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 5a0d3d4..2727222 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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c.
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 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
` (10 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 UTC (permalink / raw)
To: qemu-devel
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 2727222..6ea1e8d 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_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
+#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_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;
@@ -665,11 +669,12 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#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. */
@@ -687,7 +692,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;
@@ -719,9 +725,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
@@ -734,14 +741,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;
@@ -777,7 +785,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
@@ -791,7 +799,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;
@@ -821,14 +830,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 */
};
@@ -857,7 +866,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);
@@ -865,31 +874,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)
@@ -942,24 +951,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);
@@ -967,20 +976,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;
}
@@ -1014,12 +1023,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;
@@ -1074,77 +1083,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;
}
@@ -1152,112 +1161,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) {
@@ -1265,15 +1274,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)
@@ -1375,8 +1384,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];
@@ -1444,8 +1453,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);
@@ -1458,20 +1467,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
@@ -1493,131 +1502,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 */
@@ -1644,7 +1653,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;
@@ -1728,7 +1737,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;
@@ -1812,30 +1821,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);
@@ -1844,13 +1853,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;
@@ -1870,12 +1879,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;
@@ -1888,7 +1897,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_"
@@ -2025,17 +2033,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 *);
@@ -2115,7 +2123,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;
@@ -2184,7 +2192,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;
@@ -2193,7 +2201,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;
@@ -2214,7 +2222,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));
@@ -2260,7 +2268,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;
@@ -2301,7 +2309,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);
@@ -2350,7 +2358,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;
@@ -2362,16 +2370,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);
@@ -2456,7 +2464,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);
@@ -2464,7 +2472,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;
@@ -2492,10 +2500,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;
@@ -2542,7 +2550,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);
}
@@ -2610,13 +2618,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);
/*
@@ -2705,7 +2713,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;
@@ -2716,7 +2724,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;
}
@@ -2725,7 +2733,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (2 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
` (9 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 UTC (permalink / raw)
To: qemu-devel
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 6ea1e8d..4a48c85 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1159,7 +1159,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;
@@ -1202,17 +1203,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;
@@ -1470,17 +1469,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
@@ -1524,13 +1521,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,
@@ -1544,39 +1544,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++;
}
@@ -1823,10 +1808,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 1878d5a..0a61274 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;
@@ -144,12 +145,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (3 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
` (8 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 UTC (permalink / raw)
To: qemu-devel
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 4a48c85..a757dc9 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_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_MICROBLAZE
static inline void init_thread(struct target_pt_regs *regs,
@@ -666,7 +652,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#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,
@@ -722,7 +707,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,
@@ -742,7 +726,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?
@@ -796,7 +779,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (4 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
` (7 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 a757dc9..3cbb1f4 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 */
/*
@@ -1154,9 +1155,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) ||
@@ -1195,12 +1194,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
@@ -1324,9 +1318,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
@@ -1334,9 +1326,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;
}
}
@@ -1360,9 +1350,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 ||
@@ -1428,9 +1416,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) ||
@@ -1461,17 +1447,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);
@@ -1480,6 +1458,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 )
@@ -2025,9 +2004,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);
@@ -2055,6 +2031,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 */
/*
@@ -2207,9 +2194,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)
@@ -2223,9 +2208,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)
@@ -2243,9 +2226,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)
@@ -2279,9 +2260,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);
}
@@ -2406,9 +2385,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (5 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 18:45 ` malc
2010-07-28 22:16 ` Edgar E. Iglesias
2010-07-27 17:25 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
` (6 subsequent siblings)
13 siblings, 2 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 3cbb1f4..6b57a91 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
@@ -1146,15 +1144,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 &&
@@ -1163,7 +1157,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)
@@ -1196,41 +1189,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);
@@ -1238,26 +1246,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)
@@ -1306,82 +1313,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;
}
@@ -1788,8 +1800,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (6 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
` (5 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 6b57a91..86872b2 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
@@ -1150,33 +1174,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);
@@ -1428,11 +1435,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;
}
@@ -1444,7 +1453,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;
}
@@ -1549,8 +1559,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (7 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
` (4 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 | 31 +++++++++++++++++--------------
1 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 86872b2..01020c5 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1002,29 +1002,32 @@ 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);
- info->stack_limit = error;
- 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);
+
+ info->stack_limit = error + guard;
+ stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
p += stack_base;
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
--
1.7.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (8 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
` (3 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 | 79 ++++++--------------------------------------------
1 files changed, 9 insertions(+), 70 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 01020c5..61167cd 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)
{
@@ -1088,7 +1082,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;
@@ -1118,7 +1112,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);
@@ -1160,7 +1154,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;
}
@@ -1413,11 +1407,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;
@@ -1431,7 +1423,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;
@@ -1481,7 +1472,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++) {
@@ -1546,59 +1536,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;
@@ -1791,15 +1744,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)) {
@@ -1816,7 +1763,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
@@ -1828,7 +1775,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;
@@ -2711,15 +2657,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.1.1
^ permalink raw reply related [flat|nested] 23+ 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
` (9 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-28 22:00 ` Edgar E. Iglesias
2010-07-27 17:25 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
` (2 subsequent siblings)
13 siblings, 1 reply; 23+ 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] 23+ messages in thread
* [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary.
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (10 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 11/12] linux-user: Extract load_elf_image from load_elf_interp Richard Henderson
@ 2010-07-27 17:25 ` Richard Henderson
2010-07-29 7:09 ` [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Edgar E. Iglesias
2010-08-09 16:52 ` Jan-Simon Möller
13 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 17:25 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 | 380 ++++++++++++++------------------------------------
1 files changed, 103 insertions(+), 277 deletions(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8ff9b6a..b4cf671 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))
@@ -1169,7 +1166,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;
@@ -1229,6 +1226,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 && !reserved_va) {
+ 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;
@@ -1290,6 +1348,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;
}
}
@@ -1336,7 +1421,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:
@@ -1480,291 +1565,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 || reserved_va)) {
- /*
- * 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);
@@ -1796,6 +1621,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.1.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
@ 2010-07-27 18:45 ` malc
2010-07-27 19:59 ` Richard Henderson
2010-07-28 22:16 ` Edgar E. Iglesias
1 sibling, 1 reply; 23+ messages in thread
From: malc @ 2010-07-27 18:45 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, 27 Jul 2010, Richard Henderson wrote:
> 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 3cbb1f4..6b57a91 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
> @@ -1146,15 +1144,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 &&
> @@ -1163,7 +1157,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)
> @@ -1196,41 +1189,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);
> @@ -1238,26 +1246,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)
> @@ -1306,82 +1313,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));
Realloc can fail here.
> 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;
> }
> @@ -1788,8 +1800,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);
>
--
mailto:av1474@comtv.ru
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 18:45 ` malc
@ 2010-07-27 19:59 ` Richard Henderson
2010-07-27 20:39 ` malc
0 siblings, 1 reply; 23+ messages in thread
From: Richard Henderson @ 2010-07-27 19:59 UTC (permalink / raw)
To: malc; +Cc: qemu-devel
On 07/27/2010 11:45 AM, malc wrote:
>> + syms = realloc(syms, nsyms * sizeof(*syms));
>
> Realloc can fail here.
I don't believe it can. This (pre-existing) statement *reduces*
the existing allocation of syms. I'd be surprised if any malloc
implementation fails on a size reduction.
That said, I'd be happy enough to eliminate the call entirely.
r~
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 19:59 ` Richard Henderson
@ 2010-07-27 20:39 ` malc
2010-07-27 20:44 ` malc
0 siblings, 1 reply; 23+ messages in thread
From: malc @ 2010-07-27 20:39 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, 27 Jul 2010, Richard Henderson wrote:
> On 07/27/2010 11:45 AM, malc wrote:
> >> + syms = realloc(syms, nsyms * sizeof(*syms));
> >
> > Realloc can fail here.
>
> I don't believe it can. This (pre-existing) statement *reduces*
> the existing allocation of syms. I'd be surprised if any malloc
> implementation fails on a size reduction.
Life is full of surprises.
realloc$ cat tr.c
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
void *ptr;
for (;;) {
ptr = malloc (2);
if (!ptr) break;
}
printf ("result = %p\n", realloc (ptr, 1));
return 0;
}
realloc$ \time -v ./a.out
result = (nil)
Command being timed: "./a.out"
User time (seconds): 5.62
[..snip..]
> That said, I'd be happy enough to eliminate the call entirely.
--
mailto:av1474@comtv.ru
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 20:39 ` malc
@ 2010-07-27 20:44 ` malc
0 siblings, 0 replies; 23+ messages in thread
From: malc @ 2010-07-27 20:44 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Wed, 28 Jul 2010, malc wrote:
> On Tue, 27 Jul 2010, Richard Henderson wrote:
>
> > On 07/27/2010 11:45 AM, malc wrote:
> > >> + syms = realloc(syms, nsyms * sizeof(*syms));
> > >
> > > Realloc can fail here.
> >
> > I don't believe it can. This (pre-existing) statement *reduces*
> > the existing allocation of syms. I'd be surprised if any malloc
> > implementation fails on a size reduction.
>
> Life is full of surprises.
>
> realloc$ cat tr.c
> #include <stdio.h>
> #include <stdlib.h>
>
> int main (void)
> {
> void *ptr;
>
> for (;;) {
> ptr = malloc (2);
> if (!ptr) break;
> }
> printf ("result = %p\n", realloc (ptr, 1));
> return 0;
> }
Uh, appologies, this doesn't quite do what i thought it should,
final realloc allocates without freeing. Guess i have to spend
more time trying to prove that i'm the smartest kid on the block.
--
mailto:av1474@comtv.ru
^ permalink raw reply [flat|nested] 23+ 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; 23+ 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] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter.
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
2010-07-27 18:45 ` malc
@ 2010-07-28 22:16 ` Edgar E. Iglesias
1 sibling, 0 replies; 23+ messages in thread
From: Edgar E. Iglesias @ 2010-07-28 22:16 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Jul 27, 2010 at 10:25:33AM -0700, Richard Henderson wrote:
> 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.
This was neat, I wish we've had this feature before :)
Cheers
>
> 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 3cbb1f4..6b57a91 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
> @@ -1146,15 +1144,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 &&
> @@ -1163,7 +1157,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)
> @@ -1196,41 +1189,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);
> @@ -1238,26 +1246,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)
> @@ -1306,82 +1313,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;
> }
> @@ -1788,8 +1800,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.1.1
>
>
^ permalink raw reply [flat|nested] 23+ 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; 23+ 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] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (11 preceding siblings ...)
2010-07-27 17:25 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
@ 2010-07-29 7:09 ` Edgar E. Iglesias
2010-08-09 16:52 ` Jan-Simon Möller
13 siblings, 0 replies; 23+ messages in thread
From: Edgar E. Iglesias @ 2010-07-29 7:09 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Tue, Jul 27, 2010 at 10:25:26AM -0700, Richard Henderson wrote:
> A re-based and re-tested version of a patch series I
> posted back in April and May. These cleanups prepare
> elfload.c for loading the VDSO for x86_64.
I got a whitespace warning when applying the patches:
Applying: linux-user: Reduce lseek+reads while loading elf files.
/home/edgar/src/c/qemu/git/qemu/.git/rebase-apply/patch:219: trailing whitespace.
/* Read a good amount of data initially, to hopefully get all the
warning: 1 line adds whitespace errors.
I removed the trailing whitespace and fixed the interpreter less
ELF loading on my side and applied the series.
If there are more issues with the pre-existing realloc malc
commented on, I think those can be handled with follow up patches.
Thanks,
Edgar
>
>
> 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 | 1791 ++++++++++++++++++++----------------------------
> linux-user/linuxload.c | 17 +-
> linux-user/qemu.h | 7 +-
> 4 files changed, 794 insertions(+), 1065 deletions(-)
>
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c
2010-07-27 17:25 [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Richard Henderson
` (12 preceding siblings ...)
2010-07-29 7:09 ` [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Edgar E. Iglesias
@ 2010-08-09 16:52 ` Jan-Simon Möller
2010-08-10 16:21 ` Richard Henderson
13 siblings, 1 reply; 23+ messages in thread
From: Jan-Simon Möller @ 2010-08-09 16:52 UTC (permalink / raw)
To: qemu-devel
Am Dienstag, 27. Juli 2010, 19:25:26 schrieb Richard Henderson:
> A re-based and re-tested version of a patch series I
> posted back in April and May. These cleanups prepare
> elfload.c for loading the VDSO for x86_64.
>
>
Do you have a repo where i could pull these from ?
Best,
Jan-Simon
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c
2010-08-09 16:52 ` Jan-Simon Möller
@ 2010-08-10 16:21 ` Richard Henderson
0 siblings, 0 replies; 23+ messages in thread
From: Richard Henderson @ 2010-08-10 16:21 UTC (permalink / raw)
To: Jan-Simon Möller; +Cc: qemu-devel
On 08/09/2010 09:52 AM, Jan-Simon Möller wrote:
>> A re-based and re-tested version of a patch series I
>> posted back in April and May. These cleanups prepare
>> elfload.c for loading the VDSO for x86_64.
>
> Do you have a repo where i could pull these from ?
Which, the vdso loading bits?
git://repo.or.cz/qemu/rth.git elfload-vdso
I still haven't worked out how to fix the makefile, and
there's still the question of how to load the vdso from
the build tree (as opposed to the install tree).
r~
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2010-08-10 17:20 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 01/12] linux-user: Handle filesz < memsz for any PT_LOAD segment Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 02/12] Add more DT_* and AT_* constants to qemu's copy of elf.h Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 03/12] linux-user: Reindent elfload.c Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 04/12] linux-user: Reduce lseek+reads while loading elf files Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 05/12] linux-user: Define ELF_DATA generically Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 06/12] linux-user: Clean up byte-swapping in elfload.c Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 07/12] linux-user: Load symbols from the interpreter Richard Henderson
2010-07-27 18:45 ` malc
2010-07-27 19:59 ` Richard Henderson
2010-07-27 20:39 ` malc
2010-07-27 20:44 ` malc
2010-07-28 22:16 ` Edgar E. Iglesias
2010-07-27 17:25 ` [Qemu-devel] [PATCH 08/12] linux-user: Improve consistency checking in elf headers Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 09/12] linux-user: Put the stack guard page at the top Richard Henderson
2010-07-27 17:25 ` [Qemu-devel] [PATCH 10/12] linux-user: Remove partial support for a.out interpreters 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
2010-07-27 17:25 ` [Qemu-devel] [PATCH 12/12] linux-user: Re-use load_elf_image for the main binary Richard Henderson
2010-07-29 7:09 ` [Qemu-devel] [PATCH 00/12 v4] Clean up linux-user/elfload.c Edgar E. Iglesias
2010-08-09 16:52 ` Jan-Simon Möller
2010-08-10 16:21 ` 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).