This is an archive of the discontinued LLVM Phabricator instance.

[lld][ELF] Add option for suppressing section type mismatch warnings
AbandonedPublic

Authored by leonardchan on May 15 2023, 10:28 PM.

Details

Reviewers
phosek
MaskRay
Summary

Usually when seeing this warning, the best approach would be to ensure the input section has the same type as the output section. However, if the input section comes from something like a prebuilt library, updating it won't be very quick/easy. To prevent potentially spamming the user with these warnings, having a toggle would be nice for temporarily suppressing them.

Diff Detail

Event Timeline

leonardchan created this revision.May 15 2023, 10:28 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2023, 10:28 PM
leonardchan requested review of this revision.May 15 2023, 10:28 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2023, 10:28 PM

It may be worth pointing out that --no-warn-section-type-mismatch is the current GNU ld behavior which differs from LLD. I think that --warn-section-type-mismatch is a better default, but it's useful to have a switch to control the behavior for codebases that need to support both linkers.

In such a case, can you specify --no-fatal-warnings if the build system defaults to --fatal-warnings?

In such a case, can you specify --no-fatal-warnings if the build system defaults to --fatal-warnings?

Oh it's not that these warnings are treated as errors, it's that we see a lot of them for sections coming from prebuilts and there's just so much of them that we'd like to just silence them in the meantime while we sort out fixing the prebuilt lib.

In such a case, can you specify --no-fatal-warnings if the build system defaults to --fatal-warnings?

Oh it's not that these warnings are treated as errors, it's that we see a lot of them for sections coming from prebuilts and there's just so much of them that we'd like to just silence them in the meantime while we sort out fixing the prebuilt lib.

To better describe our use case, we're porting an existing embedded project from GCC/ld to Clang/LLD and this is one of the differences we encountered. We can still link the targets, but it results in a lot of noise; hundreds of these messages in a full build. Unfortunately, the issue originates in third party driver code that was supplied by an external vendor and it's not something we can easily address.

We're open to other suggestions, but we believe that other LLD users working in the embedded domain might eventually encounter this issue as well and having an option to suppress this warning might be helpful.

Apologies for the long answer. The TL;DR is that I'd prefer we not give the warning at all for NOLOAD as that is what it is designed to do, and working around the warning can be awkward for people not familiar with linkers.

We have been seeing similar problems within Arm with some of our open source projects Thanks for bringing this up. In all of these cases the projects wanted to work with both GNU and LLVM toolchains and at least one of them would not turn off fatal warnings.

I had been working on a patch for this area myself during some down time at Euro LLVM. My suggestion was to:

  • Record the intention to use NOLOAD (currently I don't think we can tell the difference between OutputSection <address> TYPE = SHT_NOBITS : { ... } and OutputSection <address> (NOLOAD).
  • Do not warn at all for NOLOAD as changing section type is what it is designed to do (see below). Make the mismatch between SHT_NOBITS an error.

Another thought I had was to read the contents of the section, only warn if the contents of the section are non-zero. This would handle the most common source of these warnings (small memory mapped peripherals).

As I understand it NOLOAD is used for two purposes. The first is memory mapped peripherals in C. An example:

// C code, by convention .gicd is SHT_PROGBITS even though it is 0.
GICv3_distributor __attribute__((section(".gicd"))) gicd;

// linker script, place section
 .gicd 0x2f000000 (NOLOAD): { *(.gicd) }

Which provokes:

ld.lld: warning: section type mismatch for .gicd
>>> obj/GICv3_gicd.o:(.gicd): SHT_PROGBITS
>>> output section .gicd: SHT_NOBITS

This can sometimes be worked around by using the naming convention of .bss. prefix __attribute__((section(".bss.gicd"))) which does produce a SHT_NOBITS section. However the .bss. prefix means that any linker script with

.bss : { *(.bss .bss.*) }

will match .bss.gicd before it gets to .gicd 0x2f000000 (NOLOAD): { *(.gicd) }

So this can be made to work, but it is error prone, and difficult for a user trying to transition from GNU ld as the match is easy to miss.

The second use for NOLOAD is not something I've seen in person (https://stackoverflow.com/questions/57181652/understanding-linker-script-noload-sections-in-embedded-software) . My understanding is that it is used when parts of an embedded system are built separately. For example assume that there is a ROM kernel with entry points available at a specific address. This ROM is already on the device so we don't want it in the ELF file but we do want access to its symbols and we don't want to use any of its addresses. In this case we can use NOLOAD for the ROM which permits the program to link against the addresses but not be part of the program. Something like:

ROM 0x0 (NOLOAD) : { rom_*.o (.text) ... }
/* Rest of program */
FLASH 0x10000 : { *(.text) ... }

I think relinking all the objects with NOLOAD is more error prone than just linking against a list of symbol entry points, which I think is the more common approach.

To summarise:

  • I would prefer we not put out the warning with NOLOAD as default as I think it is working as designed.
  • An option to suppress/enable the warning is a good second choice. I'd prefer us to suppress by default, particularly for NOLOAD.

Apologies for the long answer. The TL;DR is that I'd prefer we not give the warning at all for NOLOAD as that is what it is designed to do, and working around the warning can be awkward for people not familiar with linkers.

We have been seeing similar problems within Arm with some of our open source projects Thanks for bringing this up. In all of these cases the projects wanted to work with both GNU and LLVM toolchains and at least one of them would not turn off fatal warnings.

I had been working on a patch for this area myself during some down time at Euro LLVM. My suggestion was to:

  • Record the intention to use NOLOAD (currently I don't think we can tell the difference between OutputSection <address> TYPE = SHT_NOBITS : { ... } and OutputSection <address> (NOLOAD).
  • Do not warn at all for NOLOAD as changing section type is what it is designed to do (see below). Make the mismatch between SHT_NOBITS an error.

Another thought I had was to read the contents of the section, only warn if the contents of the section are non-zero. This would handle the most common source of these warnings (small memory mapped peripherals).

As I understand it NOLOAD is used for two purposes. The first is memory mapped peripherals in C. An example:

// C code, by convention .gicd is SHT_PROGBITS even though it is 0.
GICv3_distributor __attribute__((section(".gicd"))) gicd;

// linker script, place section
 .gicd 0x2f000000 (NOLOAD): { *(.gicd) }

Which provokes:

ld.lld: warning: section type mismatch for .gicd
>>> obj/GICv3_gicd.o:(.gicd): SHT_PROGBITS
>>> output section .gicd: SHT_NOBITS

This can sometimes be worked around by using the naming convention of .bss. prefix __attribute__((section(".bss.gicd"))) which does produce a SHT_NOBITS section. However the .bss. prefix means that any linker script with

.bss : { *(.bss .bss.*) }

will match .bss.gicd before it gets to .gicd 0x2f000000 (NOLOAD): { *(.gicd) }

So this can be made to work, but it is error prone, and difficult for a user trying to transition from GNU ld as the match is easy to miss.

+1 for the non-zero check. A lot of the cases I've seen fall under this and this could also be an alternative approach to https://github.com/llvm/llvm-project/issues/62690.

The second use for NOLOAD is not something I've seen in person (https://stackoverflow.com/questions/57181652/understanding-linker-script-noload-sections-in-embedded-software) . My understanding is that it is used when parts of an embedded system are built separately. For example assume that there is a ROM kernel with entry points available at a specific address. This ROM is already on the device so we don't want it in the ELF file but we do want access to its symbols and we don't want to use any of its addresses. In this case we can use NOLOAD for the ROM which permits the program to link against the addresses but not be part of the program. Something like:

ROM 0x0 (NOLOAD) : { rom_*.o (.text) ... }
/* Rest of program */
FLASH 0x10000 : { *(.text) ... }

I think relinking all the objects with NOLOAD is more error prone than just linking against a list of symbol entry points, which I think is the more common approach.

To summarise:

  • I would prefer we not put out the warning with NOLOAD as default as I think it is working as designed.
  • An option to suppress/enable the warning is a good second choice. I'd prefer us to suppress by default, particularly for NOLOAD.

I'd also be fine with keeping the warning suppression but having it off by default.

...

To summarise:

  • I would prefer we not put out the warning with NOLOAD as default as I think it is working as designed.
  • An option to suppress/enable the warning is a good second choice. I'd prefer us to suppress by default, particularly for NOLOAD.

Thanks for the write-up. I prefer that we don't give a warning with NOLOAD.
For 2, I prefer that we don't have an option to toggle the warning.

https://reviews.llvm.org/D151144 as the alternative patch for removing the warning for NOLOAD.

MaskRay requested changes to this revision.May 24 2023, 12:12 PM
This revision now requires changes to proceed.May 24 2023, 12:12 PM

The alternative has landed. This can be abandoned now.