Bug 948

Summary: Wrong LMA for section with empty input section.
Product: binutils Reporter: Fabrice Gautier <fabrice_gautier>
Component: ldAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: bug-binutils, hjl.tools
Priority: P2    
Version: 2.15   
Target Milestone: ---   
Host: i386-pc-linux Target: i386-pc-linux
Build: Last reconfirmed:
Attachments: linker script and sample c code.

Description Fabrice Gautier 2005-05-12 19:48:08 UTC
When an output section is empty, the AT() attribute is ignored and LMA=VMA in
the output file. The LOADADDR(section) expression returns the correct value
nonetheless.

This is not really a problem when the section is really empty, ie size=0, but
its a real problem when the section is not of size=0 because of an .=ALIGN(4)
statement for example.

In this case doing a simple objcopy -O binary a.out a.bin will cause an enormous
a.bin.
Comment 1 Fabrice Gautier 2005-05-12 19:55:32 UTC
Created attachment 488 [details]
linker script and sample c code.

This is a linker script and c code to reproduce the issue:

$ gcc -c test-lma.c
$ ld -T script.ld test-lma.o
$ objdump -h a.out

a.out:	   file format elf32-i386

Sections:
Idx Name	  Size	    VMA       LMA	File off  Algn
  0 .text	  00000021  20000000  00000000	00001000  2**2
		  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data	  00000004  40000000  00001000	00002000  2**2
		  CONTENTS, ALLOC, LOAD, DATA
  2 .rodata	  0000000c  40000004  40000004	00002004  2**0
		  CONTENTS, ALLOC, LOAD, DATA
  3 .bss	  00000004  40000010  00001010	00002004  2**2
		  ALLOC
  4 .note.GNU-stack 00000000  00000000	00000000  00002004  2**0
		  CONTENTS, READONLY
  5 .comment	  00000026  00000000  00000000	00002004  2**0
		  CONTENTS, READONLY


The problem is :
  2 .rodata	  0000000c  40000004  40000004	00002004  2**0

It should be :
  2 .rodata	  0000000c  40000004  00001004	00002004  2**0


-- Fabrice
Comment 2 H.J. Lu 2005-05-16 18:51:16 UTC
I can't reproduce it with binutils in CVS nor the Linux binutils 2.16.90.0.3.
I got

[hjl@gnu empty-7]$ make
./ld -o x -T script.ld test-lma.o
./objdump -h x

x:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000002d  20000000  00000000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000004  40000000  00001000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .rodata       0000000c  40000004  40000004  00002004  2**0
                  CONTENTS
  3 .bss          00000004  40000010  00001010  00002004  2**2
                  ALLOC
  4 .comment      00000032  00000000  00000000  00002010  2**0
                  CONTENTS, READONLY
[hjl@gnu empty-7]$ ./objcopy -O binary x x.bin
[hjl@gnu empty-7]$ ls -l x.bin
-rwxrwxr-x  1 hjl hjl 4100 May 16 11:48 x.bin
Comment 3 Fabrice Gautier 2005-05-16 20:44:54 UTC
(In reply to comment #2)
> I can't reproduce it with binutils in CVS nor the Linux binutils 2.16.90.0.3.

Actually you did reproduce it just there ...

> I got
> [hjl@gnu empty-7]$ make
> ./ld -o x -T script.ld test-lma.o
> ./objdump -h x
> 
> x:     file format elf32-i386
> 
> Sections:
> Idx Name          Size      VMA       LMA       File off  Algn
>   0 .text         0000002d  20000000  00000000  00001000  2**2
>                   CONTENTS, ALLOC, LOAD, READONLY, CODE
>   1 .data         00000004  40000000  00001000  00002000  2**2
>                   CONTENTS, ALLOC, LOAD, DATA
>   2 .rodata       0000000c  40000004  40000004  00002004  2**0

Right Here -----------------------------^^^^^^^^

This should be (I believe): LMA=00001004  not LMA=VMA=40000004


>                   CONTENTS

>   3 .bss          00000004  40000010  00001010  00002004  2**2
>                   ALLOC
>   4 .comment      00000032  00000000  00000000  00002010  2**0
>                   CONTENTS, READONLY
> [hjl@gnu empty-7]$ ./objcopy -O binary x x.bin
> [hjl@gnu empty-7]$ ls -l x.bin
> -rwxrwxr-x  1 hjl hjl 4100 May 16 11:48 x.bin
------------------------^^^^
This is odd though.... Where did the rodata section go in this binary ??

I was testing with binutils 2.15 btw, I build a 2.16, and although the results
are a bit different I still think there is a bug, I'm not just sure what is the
bug but I can see that, with 2.16:

* The .rodata section doesnt have the LOAD flag. So doing an "objcopy -O binary
-j .rodata rodata.bin" will return an empty file.
*But .rodata has a section size non null
*But (unlike with 2.15) there is some space in the elf file reserverd for the
content of .rodata. (Easy to see by increasing the .=ALIGN(16) to .=ALIGN(256))
*But the content of .rodata is all zeroes even if we add a FILL expression in
the script. (objdump -Dz -j .rodata a.out will show that)

So I'm not sure exactly how this is supposed to work but I see three (related) bugs:
- LMA is wrong
- LOAD is not set
- FILL expression is not used

You my just want to say that this is expected behaviour because the .rodata
section is considered an empty section, but then I would report two bug:
- Size of an empty section is not null.
- Space is wasted in the elf file for an empty section.

In any case, my original intent in creating this linker script with the
.=ALIGN(16) in the .rodata section was to ensure that the size of my binary
image after objcopy would be a multiple of 16. Works fine except when there is
nothing in the input .rodata sections.

I'm reopening the bug. If you think that the current behaviour is the correct
one then please close again.

Thank you

-- Fabrice
Comment 4 H.J. Lu 2005-05-17 17:20:49 UTC
1. I didn't see a FILL statement in your linker script.
2. LMA of an ELF section is an artificial thing. You should use "readelf -lS"
to see the real segment/section/memory layout of an ELF binary.
3. If a section is empty and unused, why should it be marked as LOAD?
4. The non-zero size of empty rodata section is for aligment purpose.