bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/23648] New: Symbols based on MEMORY regions confuse --gc-section


From: nbowler at draconx dot ca
Subject: [Bug ld/23648] New: Symbols based on MEMORY regions confuse --gc-sections.
Date: Thu, 13 Sep 2018 08:40:49 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=23648

            Bug ID: 23648
           Summary: Symbols based on MEMORY regions confuse --gc-sections.
           Product: binutils
           Version: 2.32 (HEAD)
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: nbowler at draconx dot ca
  Target Milestone: ---

It seems that ld's --gc-sections feature can get confused by the
MEMORY command.

It is possible to define symbols that depend on the memory regions in a
linker script.  The --gc-sections function appears to discard sections
as if the MEMORY command was omitted from the linker script.

If removing the MEMORY command affects which sections get referenced,
this means --gc-sections will discard sections that are actually needed
by the link.  The results are obviously not good.

For example, consider the following linker script:

  % cat >test.ld <<'EOF'
  MEMORY { code : ORIGIN = 0, LENGTH = 8M }

  SECTIONS {
     ENTRY(entry)
     .text 1M : { *(.text*) } >code
  }

  foo = LENGTH(code) > 32M ? test0 : test1;
EOF

And a C source file that uses the linker-defined "foo" like this:

  % cat >test.c <<'EOF'
  void test0(void) { }
  void test1(void) { }

  void entry(void)
  {
     extern void foo(void);
     foo();
  }
EOF

Compiled like this:

  % gcc -ffunction-sections -c test.c

The intention of the example is to call one or the other function based
on the link-time MEMORY configuration.  This works fine normally:

  % ld -Ttest.ld test.o
  % readelf -Ws a.out
  [...]
  6: 0000000000100007     7 FUNC    GLOBAL DEFAULT    1 test1
  7: 0000000000100007     0 FUNC    GLOBAL DEFAULT    1 foo
  8: 0000000000100000     7 FUNC    GLOBAL DEFAULT    1 test0

So foo = test1, as expected since LENGTH(code) is less than 32M.

However, if we add --gc-sections, things go awry:

  % ld -Ttest.ld --gc-sections --print-gc-sections test.o
  ld: Removing unused section '.text.test1' in file 'test.o'

Uhoh...

  % readelf -Ws a.out
  [...]
  5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  ABS foo
  6: 0000000000100000     7 FUNC    GLOBAL DEFAULT    1 test0

So test1 is discarded, the unused test0 is kept, and foo is set to
garbage.  The resulting code is correspondingly broken.

Testing suggests that --gc-sections evaluates "foo" as if LENGTH(code)
returned -1, regardless of what is specified in the MEMORY command.
This is equivalent to what you'd get if the MEMORY command was omitted.

This appears to be independent of target, as I tried several targets
(and versions) with identical effect.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]