#ifdef TARGET_I386
+#define ELF_PLATFORM get_elf_platform()
+
+static const char *get_elf_platform(void)
+{
+ static char elf_platform[] = "i386";
+ int family = (global_env->cpuid_version >> 8) & 0xff;
+ if (family > 6)
+ family = 6;
+ if (family >= 3)
+ elf_platform[1] = '0' + family;
+ return elf_platform;
+}
+
+#define ELF_HWCAP get_elf_hwcap()
+
+static uint32_t get_elf_hwcap(void)
+{
+ return global_env->cpuid_features;
+}
+
#define ELF_START_MMAP 0x80000000
/*
#define USE_ELF_CORE_DUMP
#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,
+};
+
+#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)
+
#endif
#ifdef TARGET_SPARC
+#ifdef TARGET_SPARC64
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_SPARC )
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_DATA ELFDATA2MSB
+#define ELF_ARCH EM_SPARC
+
+/*XXX*/
+#define ELF_PLAT_INIT(_r)
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+ regs->tstate = 0;
+ regs->pc = infop->entry;
+ regs->npc = regs->pc + 4;
+ regs->y = 0;
+ regs->u_regs[14] = infop->start_stack - 16 * 4;
+}
+#else
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ( (x) == EM_SPARC )
}
#endif
+#endif
#ifdef TARGET_PPC
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
-#define DLINFO_ARCH_ITEMS 3
+#define DLINFO_ARCH_ITEMS 5
#define ARCH_DLINFO \
do { \
- sp -= DLINFO_ARCH_ITEMS * 2; \
- NEW_AUX_ENT(0, AT_DCACHEBSIZE, 0x20); \
- NEW_AUX_ENT(1, AT_ICACHEBSIZE, 0x20); \
- NEW_AUX_ENT(2, AT_UCACHEBSIZE, 0); \
+ NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
+ NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
+ NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
/* \
* Now handle glibc compatibility. \
*/ \
- sp -= 2*2; \
- NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
- NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
+ 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)
#endif
+#ifdef TARGET_MIPS
+
+#define ELF_START_MMAP 0x80000000
+
+#define elf_check_arch(x) ( (x) == EM_MIPS )
+
+#define ELF_CLASS ELFCLASS32
+#ifdef TARGET_WORDS_BIGENDIAN
+#define ELF_DATA ELFDATA2MSB
+#else
+#define ELF_DATA ELFDATA2LSB
+#endif
+#define ELF_ARCH EM_MIPS
+
+#define ELF_PLAT_INIT(_r)
+
+static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+{
+ regs->cp0_status = CP0St_UM;
+ regs->cp0_epc = infop->entry;
+ regs->regs[29] = infop->start_stack;
+}
+
+#endif /* TARGET_MIPS */
+
+#ifndef ELF_PLATFORM
+#define ELF_PLATFORM (NULL)
+#endif
+
+#ifndef ELF_HWCAP
+#define ELF_HWCAP 0
+#endif
+
#include "elf.h"
/*
#define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2
-#define DLINFO_ITEMS 11
+#define DLINFO_ITEMS 12
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
{
static int load_aout_interp(void * exptr, int interp_fd);
#ifdef BSWAP_NEEDED
-static void bswap_ehdr(Elf32_Ehdr *ehdr)
+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 */
- bswap32s(&ehdr->e_entry); /* Entry point virtual address */
- bswap32s(&ehdr->e_phoff); /* Program header table file offset */
- bswap32s(&ehdr->e_shoff); /* Section header table file offset */
+ 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_shstrndx); /* Section header string table index */
}
-static void bswap_phdr(Elf32_Phdr *phdr)
+static void bswap_phdr(struct elf_phdr *phdr)
{
bswap32s(&phdr->p_type); /* Segment type */
- bswap32s(&phdr->p_offset); /* Segment file offset */
- bswap32s(&phdr->p_vaddr); /* Segment virtual address */
- bswap32s(&phdr->p_paddr); /* Segment physical address */
- bswap32s(&phdr->p_filesz); /* Segment size in file */
- bswap32s(&phdr->p_memsz); /* Segment size in memory */
+ 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 */
- bswap32s(&phdr->p_align); /* Segment alignment */
+ bswaptls(&phdr->p_align); /* Segment alignment */
}
-static void bswap_shdr(Elf32_Shdr *shdr)
+static void bswap_shdr(struct elf_shdr *shdr)
{
bswap32s(&shdr->sh_name);
bswap32s(&shdr->sh_type);
- bswap32s(&shdr->sh_flags);
- bswap32s(&shdr->sh_addr);
- bswap32s(&shdr->sh_offset);
- bswap32s(&shdr->sh_size);
+ bswaptls(&shdr->sh_flags);
+ bswaptls(&shdr->sh_addr);
+ bswaptls(&shdr->sh_offset);
+ bswaptls(&shdr->sh_size);
bswap32s(&shdr->sh_link);
bswap32s(&shdr->sh_info);
- bswap32s(&shdr->sh_addralign);
- bswap32s(&shdr->sh_entsize);
+ bswaptls(&shdr->sh_addralign);
+ bswaptls(&shdr->sh_entsize);
}
static void bswap_sym(Elf32_Sym *sym)
{
target_ulong *argv, *envp;
target_ulong *sp, *csp;
+ target_ulong *u_platform;
+ const char *k_platform;
int v;
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = (unsigned int *) (~15UL & (unsigned long) p);
+ u_platform = NULL;
+ k_platform = ELF_PLATFORM;
+ if (k_platform) {
+ size_t len = strlen(k_platform) + 1;
+ sp -= (len + sizeof(target_ulong) - 1) / sizeof(target_ulong);
+ u_platform = (target_ulong *)sp;
+ __copy_to_user(u_platform, k_platform, len);
+ }
csp = sp;
csp -= (DLINFO_ITEMS + 1) * 2;
+ if (k_platform)
+ csp -= 2;
#ifdef DLINFO_ARCH_ITEMS
csp -= DLINFO_ARCH_ITEMS*2;
#endif
if ((unsigned long)csp & 15UL)
sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
-#define NEW_AUX_ENT(nr, id, val) \
- put_user (id, sp + (nr * 2)); \
- put_user (val, sp + (nr * 2 + 1))
- sp -= 2;
- NEW_AUX_ENT (0, AT_NULL, 0);
-
- sp -= DLINFO_ITEMS*2;
- NEW_AUX_ENT( 0, AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
- NEW_AUX_ENT( 1, AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
- NEW_AUX_ENT( 2, AT_PHNUM, (target_ulong)(exec->e_phnum));
- NEW_AUX_ENT( 3, AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
- NEW_AUX_ENT( 4, AT_BASE, (target_ulong)(interp_load_addr));
- NEW_AUX_ENT( 5, AT_FLAGS, (target_ulong)0);
- NEW_AUX_ENT( 6, AT_ENTRY, load_bias + exec->e_entry);
- NEW_AUX_ENT( 7, AT_UID, (target_ulong) getuid());
- NEW_AUX_ENT( 8, AT_EUID, (target_ulong) geteuid());
- NEW_AUX_ENT( 9, AT_GID, (target_ulong) getgid());
- NEW_AUX_ENT(11, AT_EGID, (target_ulong) getegid());
+#define NEW_AUX_ENT(id, val) \
+ sp -= 2; \
+ put_user (id, sp); \
+ put_user (val, sp + 1)
+ NEW_AUX_ENT (AT_NULL, 0);
+
+ /* There must be exactly DLINFO_ITEMS entries here. */
+ NEW_AUX_ENT(AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
+ NEW_AUX_ENT(AT_PHNUM, (target_ulong)(exec->e_phnum));
+ NEW_AUX_ENT(AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
+ NEW_AUX_ENT(AT_BASE, (target_ulong)(interp_load_addr));
+ NEW_AUX_ENT(AT_FLAGS, (target_ulong)0);
+ NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+ NEW_AUX_ENT(AT_UID, (target_ulong) getuid());
+ NEW_AUX_ENT(AT_EUID, (target_ulong) geteuid());
+ NEW_AUX_ENT(AT_GID, (target_ulong) getgid());
+ NEW_AUX_ENT(AT_EGID, (target_ulong) getegid());
+ NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP);
+ if (k_platform)
+ NEW_AUX_ENT(AT_PLATFORM, (target_ulong) u_platform);
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
unsigned int i;
struct elf_shdr sechdr, symtab, strtab;
char *strings;
+ struct syminfo *s;
lseek(fd, hdr->e_shoff, SEEK_SET);
for (i = 0; i < hdr->e_shnum; i++) {
found:
/* Now know where the strtab and symtab are. Snarf them. */
- disas_symtab = malloc(symtab.sh_size);
- disas_strtab = strings = malloc(strtab.sh_size);
- if (!disas_symtab || !disas_strtab)
+ s = malloc(sizeof(*s));
+ s->disas_symtab = malloc(symtab.sh_size);
+ s->disas_strtab = strings = malloc(strtab.sh_size);
+ if (!s->disas_symtab || !s->disas_strtab)
return;
lseek(fd, symtab.sh_offset, SEEK_SET);
- if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
+ if (read(fd, s->disas_symtab, symtab.sh_size) != symtab.sh_size)
return;
#ifdef BSWAP_NEEDED
for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
- bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
+ bswap_sym(s->disas_symtab + sizeof(struct elf_sym)*i);
#endif
lseek(fd, strtab.sh_offset, SEEK_SET);
if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
return;
- disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
+ s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
+ s->next = syminfos;
+ syminfos = s;
}
static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,