Bug 12524 - Linking with --oformat=binary discards non-static global variables
Summary: Linking with --oformat=binary discards non-static global variables
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.21
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-03-01 00:07 UTC by morgon.kanter
Modified: 2016-05-16 18:29 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
linker script (127 bytes, application/octet-stream)
2011-03-01 01:07 UTC, morgon.kanter
Details

Note You need to log in before you can comment on or make changes to this bug.
Description morgon.kanter 2011-03-01 00:07:57 UTC
Take the following example piece of C code, call it test.c:

------------------
int global;
int main() { global = 1; global = 2; return 0; }
------------------

When this code is compiled, using the following command, which is executable:
$ gcc -o test test.c

The global variable gets put in the .bss section. In addition, if you compile and link with the following commands, the end of which is not executable (as the compiler never puts in the startup bits), the variable also ends up in the .bss section in the end:

$ gcc -c test.c
$ ld -o test test.o -lc

However, if you link with a flat binary target instead of ELF, the variable gets lost and, interestingly, the following code gets emitted where normally the value would get moved to the variable's location:

movl $0x1,0x0(%rip)

...later...

movl $0x2,0x0(%rip)

This is very similar to a bug I at first thought was in Clang before encountering it here, which can be found here: http://llvm.org/bugs/show_bug.cgi?id=9297

If we explicitly define a section, ie have: 'int global __attribute__ ((section (".bss")));', this will still fail. I tested it with clang as well, and it fails in the same fashion. However -- I have a larger project that outputs to a binary format and defines a global variable in this fashion; interestingly, gcc fails similarly but clang works successfully in this case where I explicitly define the section. I haven't been able to reproduce this behavior, though.
Comment 1 Alan Modra 2011-03-01 00:41:00 UTC
Did you mean --oformat=binary?
Comment 2 morgon.kanter 2011-03-01 01:07:31 UTC
Created attachment 5268 [details]
linker script
Comment 3 morgon.kanter 2011-03-01 01:08:08 UTC
Yeah, that's what I meant. I've included a linker script to run so that sort of mistake isn't made and the output is easily readable with objdump. Both gcc and clang work correctly when you have:
------
int global __attribute__ ((section (".bss")));
------

But not simply:
------
int global;
------

The instructions emitted in the bad case are the same as in the first post here. Link with:

ld -N -S -T test.ld -o test test.o
Comment 4 Alan Modra 2011-03-01 01:54:16 UTC
ld --oformat is a misfeature.  Don't use it.  As you have found, it doesn't work except for the simplest of object files, and only then on a very limited set of targets.  You are much better off linking to your usual target, then converting the file with objcopy.

I'll leave this bug open rather than closing as WONTFIX in the hope that the next pers
Comment 5 Alan Modra 2011-03-01 01:58:07 UTC
ld --oformat is a misfeature.  Don't use it.  As you have found, it doesn't work except for the simplest of object files, and only then on a very limited set of targets.  You are much better off linking to your usual target, then converting the file with objcopy.

I'll leave this bug open rather than closing as WONTFIX in the hope that the next person intending to report a problem with --oformat will first look in our bug database and see this one.  I doubt very much that any of the active binutils maintainers will do anything to improve ld --oformat support.
Comment 6 Ian Lance Taylor 2011-03-01 03:36:34 UTC
Just a note: gold supports --oformat=binary in the only way I think it can work: it does the whole link producing an ELF file in memory, and then walks the PT_LOAD segments writing out the contents.

I only added support for --oformat=binary to gold because the Linux kernel build uses it.