Bug 29861 - ld: Output Section Type can't be Overwritten / Documentation Unclear
Summary: ld: Output Section Type can't be Overwritten / Documentation Unclear
Status: ASSIGNED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.39
: P2 minor
Target Milestone: ---
Assignee: Nick Clifton
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-12-07 09:22 UTC by Philipp Schuster
Modified: 2022-12-08 13:07 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2022-12-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Philipp Schuster 2022-12-07 09:22:05 UTC
Since GNU binutils 2.39, specifically commit c212f39d (2022-02-16), the linker script language allows setting a dedicated type for an output section (https://sourceware.org/binutils/docs/ld/Output-Section-Type.html). This works with sections that are only defined by content provided in the linker script, as the following example shows:

SECTIONS {
  foobar (TYPE = SHT_PROGBITS) : { BYTE(1) }
}

readelf shows exactly the expected type for the foobar section.

However, GNU ld ignores this type when an output section contains input sections that already have a certain section type. The following is not possible:

    .bss . (TYPE = SHT_PROGBITS) : 
    {
        *(COMMON)
        *(.bss)
    }

The type is always SHT_NOBITS, no matter what the linker script specifies. This is not only the case for special pre-defined sections, such as .bss. It also applies to custom sections. For example, take a look at the following GAS example:

    .section .foobar, "ax", @nobits
    zeroed_buffer:
    .fill 1024, 1, 0

The section will always be of type SHT_NOBITS, even if the linker script specifies

    .foobar . (TYPE=SHT_PROGBITS) :
    {
        *(.foobar)
    } 

So I wonder, is this a bug or intended? If it is intended, the documentation should describe more precisely what this feature is capable of and what the limits are.


PS: I work in a project where we need to ensure that memsize==filesize for each section. One solution is to link *(COMMON) and *(.bss) into .data which is of type SHT_PROGBITS. However, I thought the new approach might be more obvious when someone looks at the linker script. However, it doesn't work as I expect.
Comment 1 Nick Clifton 2022-12-08 13:04:36 UTC
Hi Philipp,

> However, GNU ld ignores this type when an output section contains input
> sections that already have a certain section type.

This is basically the result of a poorly specified new feature.  It was 
only intended to allow linker created sections to have a specific type
and no thought was given to how it might interact with incoming sections.

 
> The section will always be of type SHT_NOBITS, even if the linker script
> specifies
> 
>     .foobar . (TYPE=SHT_PROGBITS) :
>     {
>         *(.foobar)
>     } 
 
It turns out that there is a workaround.  If you add in some untyped data
then the link works as expected:

  % cat foobar.ld
  SECTIONS { .foobar . (TYPE=SHT_PROGBITS) : { BYTE (1); *(.foobar); } }
  % ld foobar.o -T foobar.ld -o fred
  % readelf -SW fred | grep foobar
  [ 1] .foobar      PROGBITS   0000000000000000 001000 000401 00  AX  0   0  1

I should note however, that if you add the data at the *end* of the section
rather than the start, you do get a warning message from the linker:

  % cat foobar.ld
  SECTIONS { .foobar . (TYPE=SHT_PROGBITS) : { *(.foobar); BYTE (1) } }
  % foobar.o -T foobar.ld -o fred
  ld: warning: section `.foobar' type changed to PROGBITS

It does still work though.

Given that this is a new(ish) feature and the fact that changing the current
behaviour might break things, I think that it would be best to just document
what currently happens.  Thus I am going to check in a patch which updates the
description of the TYPE directive to:

     Set the section type to the integer TYPE.  When generating an ELF
     output file, type names 'SHT_PROGBITS', 'SHT_STRTAB', 'SHT_NOTE',
     'SHT_NOBITS', 'SHT_INIT_ARRAY', 'SHT_FINI_ARRAY', and
     'SHT_PREINIT_ARRAY' are also allowed for TYPE.  It is the user's
     responsibility to ensure that any special requirements of the
     section type are met.

     Note - the TYPE only is used if some or all of the contents of the
     section do not have an implicit type of their own.  So for example:
            .foo . TYPE = SHT_PROGBITS { *(.bar) }
     will set the type of section '.foo' to the type of the section
     '.bar' in the input files, which may not be the SHT_PROGBITS type.
     Whereas:
            .foo . TYPE = SHT_PROGBITS { BYTE(1) }
     will set the type of '.foo' to SHT_PROGBBITS. If it is necessary to
     override the type of incoming sections and force the output section
     type then an extra piece of untyped data will be needed:
            .foo . TYPE = SHT_PROGBITS { BYTE(1); *(.bar) }

Cheers
  Nick
Comment 2 cvs-commit@gcc.gnu.org 2022-12-08 13:07:07 UTC
The master branch has been updated by Nick Clifton <nickc@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=dcb53d93eb0e773c5e63c1fdbc10ec19940e6e02

commit dcb53d93eb0e773c5e63c1fdbc10ec19940e6e02
Author: Nick Clifton <nickc@redhat.com>
Date:   Thu Dec 8 13:06:31 2022 +0000

    Update the description of the linker script's TYPE directive.
    
            PR 29861
            * ld.texi (Output Section Type): Note that setting the output
            section type only works if the section contains untyped data.