This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: ldd and ld-2.0.7.so (fwd)


For those of you who don't necessarily follow the linux-kernel mailing
list and have had trouble with 2.0.99 and some of the newer linux 2.1
kernels, this patch seems to work for me.

-- 
     +--------------------------+----------------------------------------+
     | by-tor@by-tor.tacorp.net | UNIX _is_ user-friendly. It's just not |
     |       By-Tor@EfNet       | ignorant-friendly and idiot-friendly.  |
     +--------------------------+----------------------------------------+
---------- Forwarded message ----------
Date: Tue, 27 Oct 1998 16:31:26 +0100
From: ralf@uni-koblenz.de
To: torvalds@transmeta.com
Cc: Ralf Wierzbicki <rafal@boa1.cas.McMaster.CA>,
     Kernel Mailing List <linux-kernel@vger.rutgers.edu>
Subject: Patch: ldd and ld-2.0.7.so

On Sat, Oct 24, 1998 at 04:02:00AM -0400, Ralf Wierzbicki wrote:

> The dynamic loader (2.0.7) coredumps in linux 2.1.126 with a segmentation
> fault.  I checked in 2.1.125 and ldd works fine, the problem occurs
> only in 2.1.126 when trying to run ld-2.0.7 --verify (ldd). 

The problem was in my fix to binfmt_elf to handle certain address
combinations, certain executables linked to addresses != 0 would have
dumped core.  This is (for the sake of tradition ...) the case on MIPS.

The fix has a bug which crashes ET_DYN executables like ld-2.0.7.so on
certain architectures like Intel where addresses are just right.  The
appended patch fixes this.  The patch looks quite a bit bigger than it
actually is since I used the occassion to rewrite and reformat the code
in question a bit so it is less heavily indented.  The actuall functional
fix is a two liner or so.  Tested on Intel and MIPS.  Linus, please include
the appended fix.

  Ralf

--- linux-2.1.126.orig/fs/binfmt_elf.c	Tue Oct 27 04:41:35 1998
+++ linux-2.1.126/fs/binfmt_elf.c	Tue Oct 27 13:15:35 1998
@@ -608,7 +608,7 @@
 	   base, as well as whatever program they might try to exec.  This
 	   is because the brk will follow the loader, and is not movable.  */
 
-	load_bias = (elf_ex.e_type == ET_DYN ? ELF_ET_DYN_BASE : 0);
+	load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0);
 
 	/* Now we do a little grungy work by mmaping the ELF image into
 	   the correct location in memory.  At this point, we assume that
@@ -618,51 +618,50 @@
 	old_fs = get_fs();
 	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, elf_flags;
-			unsigned long vaddr;
-
-			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;
-
-			vaddr = elf_ppnt->p_vaddr;
-			if (elf_ex.e_type == ET_EXEC || load_addr_set) {
-				elf_flags |= MAP_FIXED;
-			}
+		int elf_prot = 0, elf_flags;
+		unsigned long vaddr;
+
+		if (elf_ppnt->p_type != PT_LOAD)
+			continue;
+
+		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;
+
+		vaddr = elf_ppnt->p_vaddr;
+		if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+			elf_flags |= MAP_FIXED;
+		}
 
-			error = do_mmap(file,
-					ELF_PAGESTART(load_bias + vaddr),
-					(elf_ppnt->p_filesz +
-					 ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
-					elf_prot, elf_flags,
-					(elf_ppnt->p_offset -
-					 ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
-
-			if (!load_addr_set) {
-				load_addr_set = 1;
-				load_addr = (elf_ppnt->p_vaddr -
-					     elf_ppnt->p_offset);
-				if (elf_ex.e_type == ET_DYN) {
-					load_bias = error - ELF_PAGESTART(load_bias + vaddr);
-					load_addr += error;
-				}
+		error = do_mmap(file, ELF_PAGESTART(load_bias + vaddr),
+		                (elf_ppnt->p_filesz +
+		                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
+		                elf_prot, elf_flags, (elf_ppnt->p_offset -
+		                ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
+
+		if (!load_addr_set) {
+			load_addr_set = 1;
+			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
+			if (elf_ex.e_type == ET_DYN) {
+				load_bias += error -
+				             ELF_PAGESTART(load_bias + vaddr);
+				load_addr += error;
 			}
-			k = elf_ppnt->p_vaddr;
-			if (k < start_code) start_code = k;
-			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-			if (k > elf_bss)
-				elf_bss = k;
-			if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
-				end_code = k;
-			if (end_data < k)
-				end_data = k;
-			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-			if (k > elf_brk)
-				elf_brk = k;
 		}
+		k = elf_ppnt->p_vaddr;
+		if (k < start_code) start_code = k;
+		k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
+		if (k > elf_bss)
+			elf_bss = k;
+		if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
+			end_code = k;
+		if (end_data < k)
+			end_data = k;
+		k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
+		if (k > elf_brk)
+			elf_brk = k;
 	}
 	set_fs(old_fs);
 	fput(file); /* all done with the file */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]