Skip to content

lld: no error for referenced symbols defined in sections discarded by linker script #58891

Closed
@bevin-hansson

Description

@bevin-hansson

lld has some very dubious behavior when dealing with symbols that would have been included in the binary, but weren't due to their section being discarded by a linker script.
I've constructed the following example; four objects, with one referencing the three others:
a.c:

void foo();
void bar();
void baz();

int main() {
  foo(); bar(); baz();
}

b.c, c.c, d.c:

void foo|bar|baz() { }

Linking these files normally with main as an entry point works fine:

$ lld -flavor ld a.o b.o c.o d.o -e main -Map=m
$

m:
...
          2011f4           2011f4       3b     1 .text
          2011f4           2011f4       29     1         a.o:(.text)
          2011f4           2011f4       29     1                 main
          20121d           20121d        6     1         b.o:(.text)
          20121d           20121d        6     1                 foo
          201223           201223        6     1         c.o:(.text)
          201223           201223        6     1                 bar
          201229           201229        6     1         d.o:(.text)
          201229           201229        6     1                 baz

But if we add a linker script that discards the .text section of d:

SECTIONS {
  /DISCARD/ : {
    d.o(.text)
  }
}

The link still succeeds, even though the binary no longer contains baz:

$ lld -flavor ld a.o b.o c.o d.o -e main -Map=m script
$

m:
              7c               7c       35     1 .text
              7c               7c       29     1         a.o:(.text)
              7c               7c       29     1                 main
              a5               a5        6     1         b.o:(.text)
              a5               a5        6     1                 foo
              ab               ab        6     1         c.o:(.text)
              ab               ab        6     1                 bar

Should it be like this? The relocation to baz in main will contain an invalid value, since baz's section was never assigned an offset. I would expect an error about referenced symbols in discarded sections, but it doesn't appear. The binary is simply silently broken.

Regular ld is also silent, but it keeps baz even though its section was /DISCARD/:

Symbol table '.symtab' contains 15 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000004000b0     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000004000f0     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
     5: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.c
     6: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS c.c
     7: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS d.c
     8: 00000000004000e5     6 FUNC    GLOBAL DEFAULT    1 baz
     9: 0000000000601000     0 NOTYPE  GLOBAL DEFAULT    2 __bss_start
    10: 00000000004000b0    41 FUNC    GLOBAL DEFAULT    1 main
    11: 00000000004000d9     6 FUNC    GLOBAL DEFAULT    1 foo
    12: 0000000000601000     0 NOTYPE  GLOBAL DEFAULT    2 _edata
    13: 0000000000601000     0 NOTYPE  GLOBAL DEFAULT    2 _end
    14: 00000000004000df     6 FUNC    GLOBAL DEFAULT    1 bar

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions