aboutsummaryrefslogtreecommitdiff
path: root/linux-user/elfload.c
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-06 08:56:50 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-04-06 08:56:50 +0000
commit84409ddbda9b4d8f2d2ad4f580e987800b8e7c4e (patch)
tree72e2fd0d27817fb60a24b88a1d7b3b25dd5a111d /linux-user/elfload.c
parent9ead1a126356a05b61eb4388ef0729f08454a78c (diff)
Code provision for x86_64 and PowerPC 64 linux user mode support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2619 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/elfload.c')
-rw-r--r--linux-user/elfload.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5caa44eafd..1256dba953 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -44,6 +44,23 @@ static uint32_t get_elf_hwcap(void)
return global_env->cpuid_features;
}
+#ifdef TARGET_X86_64
+#define ELF_START_MMAP 0x2aaaaab000ULL
+#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)
+{
+ regs->rax = 0;
+ regs->rsp = infop->start_stack;
+ regs->rip = infop->entry;
+}
+
+#else
+
#define ELF_START_MMAP 0x80000000
/*
@@ -72,6 +89,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
A value of 0 tells we have no such handler. */
regs->edx = 0;
}
+#endif
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
@@ -177,9 +195,20 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define ELF_START_MMAP 0x80000000
+#ifdef TARGET_PPC64
+
+#define elf_check_arch(x) ( (x) == EM_PPC64 )
+
+#define ELF_CLASS ELFCLASS64
+
+#else
+
#define elf_check_arch(x) ( (x) == EM_PPC )
#define ELF_CLASS ELFCLASS32
+
+#endif
+
#ifdef TARGET_WORDS_BIGENDIAN
#define ELF_DATA ELFDATA2MSB
#else
@@ -222,9 +251,18 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
{
target_ulong pos = infop->start_stack;
target_ulong tmp;
+#ifdef TARGET_PPC64
+ target_ulong entry, toc;
+#endif
_regs->msr = 1 << MSR_PR; /* Set user mode */
_regs->gpr[1] = infop->start_stack;
+#ifdef TARGET_PPC64
+ entry = ldq_raw(infop->entry) + infop->load_addr;
+ toc = ldq_raw(infop->entry + 8) + infop->load_addr;
+ _regs->gpr[2] = toc;
+ infop->entry = entry;
+#endif
_regs->nip = infop->entry;
/* Note that isn't exactly what regular kernel does
* but this is what the ABI wants and is needed to allow
@@ -917,6 +955,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
unsigned long elf_entry, interp_load_addr = 0;
int status;
unsigned long start_code, end_code, end_data;
+ unsigned long reloc_func_desc = 0;
unsigned long elf_stack;
char passed_fileno[6];
@@ -1181,6 +1220,7 @@ 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;
@@ -1213,6 +1253,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
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);