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.
Did you mean --oformat=binary?
Created attachment 5268 [details] linker script
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
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
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.
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.