LLD bug causing objcopy ELF to binary generation to create large binaries

Hi LLVM devs,

I came across an LLD bug in v 10.x where ELF parser / processor is setting .PROGBITS attribute for .heap and .stack sections, which leads to large binaries when we do `llvm-objcopy -o binary` to generate the binary output for armv6m. (e.g. for a 57Kb elf would yield a ~400Mb binary).

This in comparison with LLVM 7.x , would produce the correct binary size of 35Kb and the elf sections have NOBITS for .heap and .stack sections.

I narrowed down the problem to the following commit and the commits around this....Please see below:

commit ccba42c7eb3cdfe7824cd4b473a9688e5738fa3a
Author: Andrew Ng <anng.sw@gmail.com>

Hi Kasun,

The purpose of commit ccba42c7eb3cdfe7824cd4b473a9688e5738fa3a was to fix an issue that was causing incorrect segment file offset alignment for any non-empty segment that happens to start with a section that only contains symbols and no other content. If you look at the test case “ELF/linkerscript/symbol-only-align.test” that might help demonstrate the situation. This particular issue actually resulted in invalid ELF output.

I don’t remember all the details, but at the time, this was the simplest fix given the code at that point. The alternatives would have required more significant and riskier changes, and it was a relatively urgent fix given that it was producing invalid ELF output.

In your issue, just to clarify, is the ELF output from LLD also “large”, or is it just the output from the llvm-objcopy operating on that ELF that is “large”? Do you have a simple sample to demonstrate this issue?

Thank you.

Regards,
Andrew

Hi Andrew,

Thanks for the background and context.

“In your issue, just to clarify, is the ELF output from LLD also “large”, or is it just the output from the llvm-objcopy operating on that ELF that is “large”? Do you have a simple sample to demonstrate this issue?”

The ELF size is actually smaller, compared to what was generated from LLVM 7.x. (~900Kb vs ~250Kb)

When we run llvm-objcopy -O Binary blah.elf blah.bin, it would generate a 400Mb binary file.

I presume the noload flag used in InputSection is not properly enforced throughout the code. CommitSection is not applied to .heap and .stack section as I can recall during my debug…

Hi Kasun,

Great that you have already found a fix for your issue. The commitSection method would only be called if the output section actually contains an input section. So for “empty” output sections the “noload” was not having any effect. This is basically what D76981 fixes.

Thanks.

Regards,
Andrew

The original issue which motivated D60131 "[ELF] Change default output section type to SHT_PROGBITS"
appeared to have been fixed by a subsequent change.

Keeping the default output section type as SHT_PROGBITS still seems fine
to me, because it is a more consistent rule, and a user can use `(NOLOAD)`
to restore the SHT_NOBITS behavior.