Juan Cespedes wrote:
>       Hi.
> 
>       I have been trying to compile a new glibc many, many times,
> wasting a lot of time :), and it always failed in a point where the
> dynamic linker (ld-linux.so.2) was executed with one program as the
> argument.  IMHO, that is one of the best things the new libc has, but
> it never worked for me in sparc.  Example:
> 
> [i386] $ /lib/ld-linux.so.2 /bin/ls -al
> total 2
> drwxr-xr-x   2 root     root         1024 Nov 17 11:43 .
> drwxr-xr-x   8 root     root         1024 Nov 17 11:43 ..
> 
> [sparc] $ /lib/ld-linux.so.2 /bin/ls -al
>       [it hangs]
> 
>       Well, it sometimes hangs, but sometimes dies with SIGSEGV,
> sometimes with SIGBUS, sometimes with SIGILL...

ld-linux is to big to fit in the 64kb reserved for loader in the memory when
loading executables.  There is a patch against 2.0.30 to fix this bug (maybe
already fixed in newer kernels, don't know).
I attached it to this mail.

Regards.

-- 
 Eric Delaunay                 | "La guerre justifie l'existence des militaires.
 [EMAIL PROTECTED] | En les supprimant." Henri Jeanson (1900-1970)
diff -ruNp sparclinux-stable/fs/binfmt_elf.c sls-rth/fs/binfmt_elf.c
--- sparclinux-stable/fs/binfmt_elf.c   Tue May 27 22:47:19 1997
+++ sls-rth/fs/binfmt_elf.c     Sun Jun 15 07:38:35 1997
@@ -119,15 +119,15 @@ unsigned long * create_elf_tables(char *
        /*
         * Force 16 byte alignment here for generality.
         */
-       sp = (unsigned long *) (~15UL & (unsigned long) p);
-#ifdef __sparc__
+       sp = (unsigned long *) (-sizeof(long) & (unsigned long)p);
        csp = sp;
        csp -= exec ? DLINFO_ITEMS*2 : 2;
        csp -= envc+1;
        csp -= argc+1;
-       if (!(((unsigned long) csp) & 4))
-               sp--;
-#endif
+       csp -= 1;  /* argc */
+       if ((unsigned long) csp & 15UL)
+               sp -= (16 - ((unsigned long) csp & 15UL)) / sizeof(long);
+
        sp -= exec ? DLINFO_ITEMS*2 : 2;
        dlinfo = sp;
        sp -= envc+1;
@@ -385,13 +385,13 @@ do_load_elf_binary(struct linux_binprm *
        struct file * file;
        struct exec interp_ex;
        struct inode *interpreter_inode;
-       unsigned long load_addr;
+       unsigned long load_addr, load_bias;
        int load_addr_set = 0;
        unsigned int interpreter_type = INTERPRETER_NONE;
        unsigned char ibcs2_interpreter;
        int i;
        int old_fs;
-       int error;
+       unsigned long error;
        struct elf_phdr * elf_ppnt, *elf_phdata;
        int elf_exec_fileno;
        unsigned long elf_bss, k, elf_brk;
@@ -405,7 +405,7 @@ do_load_elf_binary(struct linux_binprm *
        
        ibcs2_interpreter = 0;
        status = 0;
-       load_addr = 0;
+       load_addr = load_bias = 0;
        elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
        
        if (elf_ex.e_ident[0] != 0x7f ||
@@ -582,6 +582,19 @@ do_load_elf_binary(struct linux_binprm *
        bprm->p = setup_arg_pages(bprm->p, bprm);
        current->mm->start_stack = bprm->p;
        
+       /* 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.  */
+
+       if (elf_ex.e_type == ET_DYN) {
+#ifdef __sparc__
+               load_bias = TASK_UNMAPPED_BASE - 0x10000000;
+#else
+               load_bias = 2 * TASK_SIZE / 3;
+#endif
+       }
+
        /* 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
@@ -591,29 +604,41 @@ do_load_elf_binary(struct linux_binprm *
        set_fs(get_ds());
        for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
                if (elf_ppnt->p_type == PT_LOAD) {
-                       int elf_prot = 0;
+                       int elf_flags, elf_prot = 0;
+                       unsigned long vaddr = 0;
+
                        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|MAP_EXECUTABLE;
+
+                       if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+                               vaddr = elf_ppnt->p_vaddr;
+                               elf_flags |= MAP_FIXED;
+                       }
+
                        error = do_mmap(file,
-                                       ELF_PAGESTART(elf_ppnt->p_vaddr),
+                                       ELF_PAGESTART(load_bias + vaddr),
                                        (elf_ppnt->p_filesz +
                                         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-                                       elf_prot,
-                                       (MAP_FIXED | MAP_PRIVATE |
-                                        MAP_DENYWRITE | MAP_EXECUTABLE),
+                                       elf_prot, elf_flags,
                                        (elf_ppnt->p_offset -
                                         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
                        
 #ifdef LOW_ELF_STACK
-                       if (ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) 
-                               elf_stack = ELF_PAGESTART(elf_ppnt->p_vaddr);
+                       if (error < elf_stack) 
+                               elf_stack = error-1;
 #endif
                        
                        if (!load_addr_set) { 
-                         load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
-                         load_addr_set = 1;
+                               load_addr_set = 1;
+                               load_addr = (elf_ppnt->p_vaddr -
+                                            elf_ppnt->p_offset);
+                               if (elf_ex.e_type == ET_DYN) {
+                                       load_bias = error;
+                                       load_addr += error;
+                               }
                        }
                        k = elf_ppnt->p_vaddr;
                        if (k < start_code) start_code = k;
@@ -632,6 +657,13 @@ do_load_elf_binary(struct linux_binprm *
        }
        set_fs(old_fs);
 
+       elf_entry += load_bias;
+       elf_bss += load_bias;
+       elf_brk += load_bias;
+       start_code += load_bias;
+       end_code += load_bias;
+       end_data += load_bias;
+
        if (elf_interpreter) {
                if (interpreter_type & 1) 
                        elf_entry = load_aout_interp(&interp_ex,
@@ -673,7 +705,7 @@ do_load_elf_binary(struct linux_binprm *
        bprm->inode->i_count++;
 #endif
 #ifdef LOW_ELF_STACK
-       current->start_stack = bprm->p = elf_stack - 4;
+       current->start_stack = bprm->p = elf_stack;
 #endif
        current->suid = current->euid = current->fsuid = bprm->e_uid;
        current->sgid = current->egid = current->fsgid = bprm->e_gid;

Reply via email to