Bug 4007 - Linker failed to issue an error on bad section in segment
Summary: Linker failed to issue an error on bad section in segment
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.18
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-02-08 19:07 UTC by Etienne Lorrain
Modified: 2007-03-22 15:54 UTC (History)
2 users (show)

See Also:
Host: i386-redhat-linux
Target: i386-redhat-linux
Build: i386-redhat-linux
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Etienne Lorrain 2007-02-08 19:07:04 UTC
I just want to report that, I do not know if it shall be considered as a bug,
as bad use, as undocumented feature:

 Lets compile some Linux kernel with Fedora 6 default toolchain:
[etienne@localhost ~]$ ld --version
GNU ld version 2.17.50.0.3-6 20060715
[etienne@localhost ~]$ readelf -v
GNU readelf 2.17.50.0.3-6 20060715

[etienne@localhost tmp]$ tar xjf ../linux2/linux-2.6.20.tar.bz2
[etienne@localhost tmp]$ cd linux-2.6.20
[etienne@localhost linux-2.6.20]$ cp ../../linux2/linux-2.6.20-gujin/.config .
[etienne@localhost linux-2.6.20]$ make oldconfig > log
[etienne@localhost linux-2.6.20]$ make vmlinux >> log
... few warnings ...
[etienne@localhost linux-2.6.20]$ readelf -l vmlinux

Elf file type is EXEC (Executable file)
Entry point 0x100000
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xc0100000 0x00100000 0x3995e0 0x3995e0 R E 0x1000
  LOAD           0x39b000 0xc049a000 0x0049a000 0x75085 0xaf000 RWE 0x1000
  NOTE           0x000000 0x00000000 0x00000000 0x00000 0x00000 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .text __ex_table .rodata .pci_fixup __param
   01     .data .data_nosave .data.page_aligned .data.cacheline_aligned
.data.read_mostly
.data.init_task .init.text .init.data .init.setup .initcall.init .con_initcall.init
.security_initcall.init .altinstructions .altinstr_replacement .exit.text
.init.ramfs
.bss
   02
[etienne@localhost linux-2.6.20]$

  OK, everything is fine. The ld script affects manually the program header by:
  /* arch/i386/kernel/vmlinux.lds.S */
PHDRS {
        text PT_LOAD FLAGS(5);  /* R_E */
        data PT_LOAD FLAGS(7);  /* RWE */
        note PT_NOTE FLAGS(4);  /* R__ */
}
  And the text section goes to the :text program header, it is linked at a fixed
address.
  .text : AT(ADDR(.text) - LOAD_OFFSET) {
...
  } :text = 0x9090

 Now I want to create another text section - I was thinking that a new program
header would be added or an error message because I create it a another address,
using the patch at sourceforge at:
http://sourceforge.net/project/showfiles.php?group_id=15465&package_id=174813&release_id=482035

The important extract is:
SECTIONS
{
  .realmode 0 : AT (ADDR(.bss) + SIZEOF(.bss) - LOAD_OFFSET) {
     ... all my sections ...
  } :text = 0x9090
  . = 0xc0000000 ; /* or more */
  .text : AT(ADDR(.text) - LOAD_OFFSET) {
     ... original part ...
  } :text = 0x9090


[etienne@localhost linux-2.6.20]$ patch -p1 < ../../linux/gujin-patch-2.6.20-rc5
patching file arch/i386/Kconfig
patching file arch/i386/kernel/Makefile
patching file arch/i386/kernel/realmode.c
patching file arch/i386/kernel/setup.c
patching file arch/i386/kernel/vmlinux.lds.S
patching file arch/i386/Makefile
patching file include/asm-i386/realmode.h
patching file Makefile
patching file scripts/gzcopy.c
patching file scripts/gzparam.c
[etienne@localhost linux-2.6.20]$ make linux-2.6.20.kgz > log

 But nothing change and I do not get any warning or error for a section
containing code not linked to a program header:

[etienne@localhost linux-2.6.20]$ readelf -l vmlinux

Elf file type is EXEC (Executable file)
Entry point 0x100000
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xc0100000 0x00100000 0x44a830 0x44a830 R E 0x1000
  LOAD           0x44c000 0xc049a000 0x0049a000 0x75085 0xaf000 RWE 0x1000
  NOTE           0x000000 0x00000000 0x00000000 0x00000 0x00000 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .bss .text __ex_table .rodata .pci_fixup __param .data .data_nosave
.data.page_aligned .data.cacheline_aligned .data.read_mostly .data.init_task
.init.text
.init.data .init.setup .initcall.init .con_initcall.init .security_initcall.init
.altinstructions .altinstr_replacement .exit.text .init.ramfs
   01     .bss .data .data_nosave .data.page_aligned .data.cacheline_aligned
.data.read_mostly .data.init_task .init.text .init.data .init.setup .initcall.init
.con_initcall.init .security_initcall.init .altinstructions .altinstr_replacement
.exit.text .init.ramfs
   02
[etienne@localhost linux-2.6.20]$

 And there is something wrong once using strip from this file:

[etienne@localhost linux-2.6.20]$ objcopy -S vmlinux vmlinux.stripped
BFD: vmlinux.stripped: warning: allocated section `.realmode' not in segment
[etienne@localhost linux-2.6.20]$ readelf -l vmlinux.stripped

Elf file type is EXEC (Executable file)
Entry point 0x100000
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xc0100000 0x00100000 0x40f085 0x449000 R E 0x1000
  LOAD           0x411000 0xc049a000 0x0049a000 0x75085 0xaf000 RWE 0x1000
  NOTE           0x000000 0x00000000 0x00000000 0x00000 0x00000 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     .bss .text __ex_table .rodata .pci_fixup __param .data .data_nosave
.data.page_aligned .data.cacheline_aligned .data.read_mostly .data.init_task
.init.text
.init.data .init.setup .initcall.init .con_initcall.init .security_initcall.init
.altinstructions .altinstr_replacement .exit.text .init.ramfs
   01     .bss .data .data_nosave .data.page_aligned .data.cacheline_aligned
.data.read_mostly .data.init_task .init.text .init.data .init.setup .initcall.init
.con_initcall.init .security_initcall.init .altinstructions .altinstr_replacement
.exit.text .init.ramfs
   02
[etienne@localhost linux-2.6.20]$

  Note that the first program header MemSiz overlap the second program header:
0x00100000 + 0x449000 > 0x0049a000
 And the two FileSiz are not aligned so the memset at PhysAddr+FileSiz is done
 at an unaligned address so will be slow.

 I do not know what should be the behaviour, just something seems wrong.



 Something completely different, when using the linux patch I posted on LKM,
where a new program header is created for this section, and is removed if i want
to get rid of the section .realmode completely because I want to generate the
old target, you can ask me the question:
[etienne@localhost linux-2.6.20-gujin]$ objcopy -R .note -R .comment -R .realmode -S
vmlinux vmlinux.tmp
BFD: vmlinux: warning: Empty loadable segment detected, is this intentional ?

[etienne@localhost linux-2.6.20-gujin]$
 My answer is that it is not needed to keep this empty loadable segment, you can
strip it.
 I do not care of the warning because that command is used "-O binary" by Linux
Makefile and does not produce the warning.


 Thanks,
 Etienne.
Comment 1 H.J. Lu 2007-02-14 14:50:10 UTC
It is very hard for people to reproduce it exactly. Please provide
all necessary input object files. I will take a look.
Comment 2 Etienne Lorrain 2007-02-15 13:46:14 UTC
  I have the vmlinux ELF file here, but it is bigger than the maximum
 attachement size. Is there a public ftp server useable or shall I
 mail it somewhere? (compressed: 2.5 Mbytes).
Comment 3 H.J. Lu 2007-02-23 09:48:31 UTC
The problem is the linker script:

 .realmode 0 : AT (ADDR(.bss) + SIZEOF(.bss) - 0xC0000000) {
...
  } :text = 0x9090

You put .realmode in the text segment. But its address doesn't belong to
the text segment. I suggest you put .realmode in a separate segment.
Comment 4 Etienne Lorrain 2007-02-23 11:19:04 UTC
 I have already put .realmode in a separate segment, that was not the problem.
 I just would have liked a linker warning/error in this case, instead of
droping silently the section, and having an "unsupported configuration"
i.e. this vmlinuz file which cannot "strip".
Comment 5 H.J. Lu 2007-02-23 13:09:04 UTC
Linker should issue an error when a section is placed into a segment
improperly:

[hjl@gnu-2 objcopy-2]$ cat foo.t
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
PHDRS {
 text PT_LOAD FLAGS(5); /* R_E */
 data PT_LOAD FLAGS(7); /* RWE */
}
SECTIONS
{
  . = 0xC0000000 + ((0x100000 + (0x100000 - 1)) & ~(0x100000 - 1));
  .bar : AT(ADDR(.bar) - 0xC0000000) { *(.bar) } :text
  .bss : AT(ADDR(.bss) - 0xC0000000) { *(.bss) }
  .foo 0 : AT(ADDR(.bss) + SIZEOF(.bss) - 0xC0000000) { *(.foo) } :text
  /DISCARD/ : { *(.*) }
}
[hjl@gnu-2 objcopy-2]$ cat foo.s
        .section .bar,"ax","progbits"
        .byte 0
        .section .foo,"aw","progbits"
        .byte 0
        .bss
        .long 0
[hjl@gnu-2 objcopy-2]$ make copy
as --32  -o foo.o foo.s
./ld -m elf_i386 -o foo -T foo.t foo.o
objcopy foo foo-cpy
BFD: foo-cpy: warning: allocated section `.foo' not in segment
[hjl@gnu-2 objcopy-2]$ make
readelf -lS foo
There are 7 section headers, starting at offset 0x1034:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .bar              PROGBITS        c0100000 001000 000001 00  AX  0   0  1
  [ 2] .bss              NOBITS          c0100004 001001 000004 00  WA  0   0  4
  [ 3] .foo              PROGBITS        00000000 001008 000001 00  WA  0   0  1
  [ 4] .shstrtab         STRTAB          00000000 001009 00002a 00      0   0  1
  [ 5] .symtab           SYMTAB          00000000 00114c 000040 10      6   4  4
  [ 6] .strtab           STRTAB          00000000 00118c 000001 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0x0
There are 1 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xc0100000 0x00100000 0x00009 0x00010 R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .bar .bss
[hjl@gnu-2 objcopy-2]$
Comment 6 H.J. Lu 2007-02-27 01:28:22 UTC
A patch is posted at

http://sourceware.org/ml/binutils/2007-02/msg00375.html
Comment 7 Etienne Lorrain 2007-02-27 19:54:20 UTC
 Patch works nicely (did it on 2.17 vanilia):
/home/etienne/linux/binutils-2.17/ld/ld-new: vmlinux: section `.realmode' can't
be allocated in segement 0
/home/etienne/linux/binutils-2.17/ld/ld-new: final link failed: Bad value

 Just maybe "s/segement/segment/", but do not take me as a reference in English.
 Thanks.
Comment 8 H.J. Lu 2007-03-22 15:54:50 UTC
Fixed by

http://sourceware.org/ml/binutils/2007-03/msg00308.html