From e2e15e2cf944342701b61522132d064bf2ba5eba Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Sun, 26 May 2013 10:58:24 -0500 Subject: [PATCH 06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64 To: Cc: Initialize all the registers correctly for mips/mips64 in init_thread(), use the correct ELF_START_MMAP for mips64, use the correct run-time linker, and clean up the code by eliminating some #if's. Also, fix all the checkpatch.pl warnings and errors. Signed-off-by: Stacey Son --- bsd-user/elfload.c | 185 +++++++++++++++++++++++++++++----------------------- 1 files changed, 103 insertions(+), 82 deletions(-) diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 0f6c3db..8c8ed6a 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -45,10 +45,11 @@ * 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) - */ + 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, @@ -163,7 +164,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #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; @@ -198,7 +200,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #endif #define ELF_ARCH EM_ARM -static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) { abi_long stack = infop->start_stack; memset(regs, 0, sizeof(*regs)); @@ -255,7 +258,8 @@ enum #define STACK_BIAS 2047 -static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) { #ifndef TARGET_ABI32 regs->tstate = 0; @@ -287,7 +291,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; @@ -355,7 +360,8 @@ do { \ NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ } while (0) -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_ulong pos = infop->start_stack; abi_ulong tmp; @@ -391,13 +397,13 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * #ifdef TARGET_MIPS -#define ELF_START_MMAP 0x80000000 - #define elf_check_arch(x) ( (x) == EM_MIPS ) #ifdef TARGET_MIPS64 +#define ELF_START_MMAP 0x2aaaaab000ULL #define ELF_CLASS ELFCLASS64 #else +#define ELF_START_MMAP 0x80000000 #define ELF_CLASS ELFCLASS32 #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -407,11 +413,14 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * #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; - regs->regs[29] = infop->start_stack; + regs->regs[25] = regs->cp0_epc = infop->entry & ~3; /* t9/pc = entry */ + regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0/sp = stack */ + regs->regs[5] = regs->regs[6] = 0; /* a1/a2 = 0 */ + regs->regs[7] = TARGET_PS_STRINGS; /* a3 = ps_strings */ } #define USE_ELF_CORE_DUMP @@ -429,7 +438,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_SH -static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +static inline void init_thread(struct target_pt_regs *regs, + struct image_info *infop) { /* Check other registers XXXXX */ regs->pc = infop->entry; @@ -451,7 +461,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #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; } @@ -474,7 +485,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i /* ??? Does this need to do anything? #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; @@ -496,7 +508,8 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #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; @@ -555,7 +568,8 @@ struct exec /* Necessary parameters */ #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE -#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) +#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 @@ -574,7 +588,7 @@ static int load_aout_interp(void * exptr, int interp_fd); #ifdef BSWAP_NEEDED static void bswap_ehdr(struct elfhdr *ehdr) { - bswap16s(&ehdr->e_type); /* Object file type */ + bswap16s(&ehdr->e_type); /* Object file type */ bswap16s(&ehdr->e_machine); /* Architecture */ bswap32s(&ehdr->e_version); /* Object file version */ bswaptls(&ehdr->e_entry); /* Entry point virtual address */ @@ -582,37 +596,45 @@ static void bswap_ehdr(struct elfhdr *ehdr) bswaptls(&ehdr->e_shoff); /* Section header table file offset */ bswap32s(&ehdr->e_flags); /* Processor-specific flags */ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ - bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ + bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ bswap16s(&ehdr->e_phnum); /* Program header table entry count */ - bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ + bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ bswap16s(&ehdr->e_shnum); /* Section header table entry count */ - bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ + bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ } -static void bswap_phdr(struct elf_phdr *phdr) +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 */ + 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) +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) @@ -622,7 +644,15 @@ static void bswap_sym(struct elf_sym *sym) bswaptls(&sym->st_size); bswap16s(&sym->st_shndx); } -#endif + +#else /* ! BSWAP_NEEDED */ + +static void bswap_ehdr(struct elfhdr *ehdr) { } +static void bswap_phdr(struct elf_phdr *phdr, int phnum) { } +static void bswap_shdr(struct elf_shdr *shdr, int shnum) { } +static void bswap_sym(struct elf_sym *sym) { } + +#endif /* ! BSWAP_NEEDED */ /* * 'copy_elf_strings()' copies argument/envelope strings from user @@ -868,9 +898,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, last_bss = 0; 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) || @@ -911,12 +939,7 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, free (elf_phdata); return retval; } -#ifdef BSWAP_NEEDED - eppnt = elf_phdata; - for (i=0; ie_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 @@ -1065,9 +1088,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 @@ -1075,9 +1096,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; } } @@ -1110,9 +1129,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 || @@ -1194,9 +1211,7 @@ int load_elf_binary(struct bsd_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) || @@ -1204,12 +1219,14 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, return -ENOEXEC; } +#ifndef __FreeBSD__ 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; } +#endif /* ! __FreeBSD__ */ /* Now read in all of the header information */ elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); @@ -1230,12 +1247,7 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, return -errno; } -#ifdef BSWAP_NEEDED - elf_ppnt = elf_phdata; - for (i=0; iend_data = end_data; info->start_stack = bprm->p; - /* Calling set_brk effectively mmaps the pages that we need for the bss and break - sections */ + /* + * 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); - 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); + printf("(start_brk) 0x" TARGET_FMT_lx "\n" , info->start_brk); + printf("(end_code) 0x" TARGET_FMT_lx "\n" , info->end_code); + printf("(start_code) 0x" TARGET_FMT_lx "\n" , info->start_code); + printf("(start_data) 0x" TARGET_FMT_lx "\n" , info->start_data); + printf("(end_data) 0x" TARGET_FMT_lx "\n" , info->end_data); + printf("(start_stack) 0x" TARGET_FMT_lx "\n" , info->start_stack); + printf("(brk) 0x" TARGET_FMT_lx "\n" , info->brk); #endif if ( info->personality == PER_SVR4 ) @@ -1571,12 +1586,18 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs, 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); + mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | + PROT_EXEC, MAP_FIXED | MAP_PRIVATE, -1, 0); } info->entry = elf_entry; +#ifdef USE_ELF_CORE_DUMP + /* not yet */ + /* bprm->core_dump = &elf_core_dump; */ + bprm->core_dump = NULL; +#endif + return 0; } -- 1.7.8