Patchwork [06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64

login
register
mail settings
Submitter Stacey Son
Date June 24, 2013, 2:03 a.m.
Message ID <1372039435-41921-7-git-send-email-sson@FreeBSD.org>
Download mbox | patch
Permalink /patch/253940/
State New
Headers show

Comments

Stacey Son - June 24, 2013, 2:03 a.m.
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 <sson@FreeBSD.org>
---
 bsd-user/elfload.c |  185 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 103 insertions(+), 82 deletions(-)

Patch

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; 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
@@ -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; i<elf_ex.e_phnum; i++, elf_ppnt++) {
-        bswap_phdr(elf_ppnt);
-    }
-#endif
+    bswap_phdr(elf_phdata, elf_ex.e_phnum);
     elf_ppnt = elf_phdata;
 
     elf_bss = 0;
@@ -1288,9 +1300,9 @@  int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
 
             /* 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 (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 ||
+                    strcmp(elf_interpreter, "/usr/lib/ld-elf.so.1") == 0) {
+                ibcs2_interpreter = 1;
             }
 
 #if 0
@@ -1437,7 +1449,7 @@  int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
         } 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.  */
+               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,
@@ -1550,19 +1562,22 @@  int load_elf_binary(struct bsd_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 */
+    /*
+     * 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;
 }