[llvm-dev] LLD bug causing objcopy ELF to binary generation to create large binaries
Fangrui Song via llvm-dev
llvm-dev at lists.llvm.org
Tue Mar 31 11:58:13 PDT 2020
On 2020-03-30, Andrew Ng via llvm-dev wrote:
>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
>
>On Mon, 30 Mar 2020 at 12:57, Kasun Fernando <kasunf at blackmagicdesign.com>
>wrote:
>
>> 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....
>>
>> .stack (NOLOAD) : ALIGN(4) {
>> _StackLow = .;
>> . += _STACK_SIZE; /* Multiple of 4, asserted above. */
>> _StackHigh = .;
>>
>> _StackLowIrq = .;
>> . += _IRQ_STACK_SIZE; /* Multiple of 4, asserted above. */
>> _StackHighIrq = .;
>> } > Memory_SRAM
>> ..../* Finally we do the heap */
>> .heap (NOLOAD) : ALIGN(4) {
>> ASSERT((_HEAP_SIZE % 4 == 0), "Error: _HEAP_SIZE must be a multiple of 4.");
>> _HeapLow = .;
>> /* Use as much space as we can for the heap */
>> . = ORIGIN(Memory_SRAM) + LENGTH(Memory_SRAM);
>> _HeapHigh = .;
>> ASSERT((_HeapLow + _HEAP_SIZE < _HeapHigh), "Error: Not enough space for the heap: data section too big.");
>> } > Memory_SRAM
>>
>>
>>
>> void OutputSection::commitSection(InputSection *isec) {
>> if (!hasInputSections) {
>> // If IS is the first section to be added to this section,
>> // initialize type, entsize and flags from isec.
>> hasInputSections = true;
>> type = isec->type;
>> entsize = isec->entsize;
>> flags = isec->flags;
>> } else {
>> // Otherwise, check if new type or flags are compatible with existing ones.
>> unsigned mask = SHF_TLS | SHF_LINK_ORDER;
>> if ((flags & mask) != (isec->flags & mask))
>> error("incompatible section flags for " + name + "\n>>> " + toString(isec) +
>> ": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name +
>> ": 0x" + utohexstr(flags));
>> if (type != isec->type) {
>> if (!canMergeToProgbits(type) || !canMergeToProgbits(isec->type))
>> error("section type mismatch for " + isec->name + "\n>>> " +
>> toString(isec) + ": " +
>> getELFSectionTypeName(config->emachine, isec->type) +
>> "\n>>> output section " + name + ": " +
>> getELFSectionTypeName(config->emachine, type));
>> type = SHT_PROGBITS;
>> }
>> }
>> if (noload)
>> type = SHT_NOBITS;
>>
>>
>> However, having said that, I think the following fix (although not the
>> cleanest nor addresses any shortcommings in other parts of the code) seems
>> to fix my issue.
>> https://reviews.llvm.org/D76981
>>
>>
>> I'm also hoping to get involve in the LLVM development in near future.....
>>
>>
>> regards
>> Kasun
>>
>>
>> On 30/3/20 9:50 pm, Andrew Ng wrote:
>>
>> 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
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.
More information about the llvm-dev
mailing list