Subject: ELF alignment: linker problem or not?
To: None <tech-toolchain@netbsd.org>
From: Matthias Drochner <M.Drochner@fz-juelich.de>
List: tech-toolchain
Date: 07/05/2006 19:12:56
This is a multipart MIME message.

--==_Exmh_4005704175120
Content-Type: text/plain; charset=us-ascii


Hi -

looking at PR bin/33909: modload fails with
  "section .eh_frame ... overlaps section .data"
I've found that modload (some code which tries to optimize
the packing of sections) doesn't agree with the linker's
behaviour. Here is what happens if I start "modload"
with debug options:

zel637: {12} /sbin/modload -d -v -S -o syscall_example syscall_example.o
ld -R /dev/ksyms -e syscall_example_lkmentry -o syscall_example -Ttext 0x0 
sysca
ll_example.o
.text: addr = 0x0 size = 0x1a0 align = 0x10
.shstrtab: addr = 0x0 size = 0x59 align = 0x1
.symtab: addr = 0x0 size = 0x31728 align = 0x8
.strtab: addr = 0x0 size = 0x1ec4e align = 0x1
.rodata: addr = 0x1a0 size = 0xce align = 0x1
.eh_frame: addr = 0x270 size = 0x58 align = 0x8
.data: addr = 0x102c8 size = 0x50 align = 0x8
.data section forced to offset 0x2c8 (was 0x102c8)
.got: addr = 0x10318 size = 0x18 align = 0x8
modload: reserving 8192 bytes of memory
ld -R /dev/ksyms -e syscall_example_lkmentry -o syscall_example -Ttext 
0xfffffe0
00f7a0000 -Tdata 0xfffffe000f7a02c8 syscall_example.o
ld: section .eh_frame [fffffe000f7a0270 -> fffffe000f7a02cf] overlaps section 
.d
ata [fffffe000f7a02c8 -> fffffe000f7a0317]
modload: can't link `syscall_example.o' creating `syscall_example' bound to 
0xff
fffe000f7a0000

The last section which will end up in the "text" segment (the executable
program section, or how you call it) is ".eh_frame". It has a size which
conforms to its own alignment, but not to the alignment of ".text".
Now the modload code (the "XXX" marked stuff in elf_mod_sizes())
allocates the .data segment immediately after .eh_frame.
The linker is different obviously: it pads .eh_frame to a boundary which
happens to be the alignment of .text (accidentally or not...).
Is the linker correct to do so?
If yes, we need to fix modload. What do yo think about the appended patch?
(Actually, I'd consider using PAGE_SIZE for the text->data alignment
because this is what will happen for a real program. But this would be
a waste for small LKMs.)

best regards
Matthias



--==_Exmh_4005704175120
Content-Type: text/plain ; name="ml.txt"; charset=us-ascii
Content-Description: ml.txt
Content-Disposition: attachment; filename="ml.txt"

Index: elf.c
===================================================================
RCS file: /cvsroot/src/sbin/modload/elf.c,v
retrieving revision 1.18
diff -u -p -r1.18 elf.c
--- elf.c	17 Mar 2006 15:53:46 -0000	1.18
+++ elf.c	5 Jul 2006 17:12:15 -0000
@@ -255,6 +255,7 @@ elf_mod_sizes(int fd,
 	size_t data_hole = 0;
 	char *shstrtab, *strtb;
 	struct elf_section *head, *s;
+	size_t textalign = 0;
 
 	if (read_elf_header(fd, &ehdr) < 0)
 		return -1;
@@ -270,11 +271,13 @@ elf_mod_sizes(int fd,
 			fprintf(stderr,
 			    "%s: addr = %p size = %#lx align = %#lx\n",
 			    s->name, s->addr, (u_long)s->size, (u_long)s->align);
+		if (strcmp(s->name, ".text") == 0)
+			textalign = s->align;
 		/* XXX try to get rid of the hole before the data
 		   section that GNU-ld likes to put there */
 		if (strcmp(s->name, ".data") == 0 && s->addr > (void *)off) {
 #define	ROUND(V, S) (((V) + (S) - 1) & ~((S) - 1))
-			data_offset = ROUND(off, s->align);
+			data_offset = ROUND(off, MAX(s->align, textalign));
 			if (debug)
 				fprintf(stderr, ".data section forced to "
 				    "offset %p (was %p)\n",

--==_Exmh_4005704175120--