llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.92k stars 11.53k forks source link

Should `PROVIDE` provide symbols that are only referenced by garbage-collected symbols? #106223

Open partaror opened 2 weeks ago

partaror commented 2 weeks ago

PROVIDE linker script directive provide symbols that are referenced by the link but are not defined anywhere. But what should be the PROVIDE behavior for symbols that are only referenced by symbols which are garbage-collected? Please consider this concrete example:

#!/usr/bin/env bash

cat >1.c <<\EOF
extern int foo;

int bar() { return foo; }
int baz() { return 1; }

int main() { return baz(); }
EOF

cat >script.t <<\EOF
PROVIDE(foo = 3);
EOF

clang-14 -o 1.o 1.c -c -ffunction-sections
ld.lld -o 1.out 1.o -T script.t -e main --gc-sections --print-gc-sections 
# Output:
# removing unused section 1.o:(.text)
# removing unused section 1.o:(.text.bar)

llvm-readelf -s 1.out
# Output: 
# Symbol table '.symtab' contains 5 entries:
#   Num:    Value          Size Type    Bind   Vis       Ndx Name
#     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   UND
#     1: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS 1.c
#     2: 0000000000000003     0 NOTYPE  GLOBAL DEFAULT   ABS foo
#     3: 0000000000201180    11 FUNC    GLOBAL DEFAULT     2 baz
#     4: 0000000000201190    26 FUNC    GLOBAL DEFAULT     2 main

In the above example, foo is inserted into the link by PROVIDE(foo = 3) because it is referenced by bar. However, bar is itself not used anywhere and is garbage-collected during the link. So, from one perspective foo is not used anywhere. Is it right to provide a symbol from PROVIDE if the symbol is not used anywhere?

I am looking forward to more thoughts and opinions on this.

llvmbot commented 2 weeks ago

@llvm/issue-subscribers-lld-elf

Author: Parth Arora (partaror)

`PROVIDE` linker script directive provide symbols that are referenced by the link but are not defined anywhere. But what should be the `PROVIDE` behavior for symbols that are only referenced by symbols which are garbage-collected? Please consider this concrete example: ```bash #!/usr/bin/env bash cat >1.c <<\EOF extern int foo; int bar() { return foo; } int baz() { return 1; } int main() { return baz(); } EOF cat >script.t <<\EOF PROVIDE(foo = 3); EOF clang-14 -o 1.o 1.c -c -ffunction-sections ld.lld -o 1.out 1.o -T script.t -e main --gc-sections --print-gc-sections # Output: # removing unused section 1.o:(.text) # removing unused section 1.o:(.text.bar) llvm-readelf -s 1.out # Output: # Symbol table '.symtab' contains 5 entries: # Num: Value Size Type Bind Vis Ndx Name # 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND # 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS 1.c # 2: 0000000000000003 0 NOTYPE GLOBAL DEFAULT ABS foo # 3: 0000000000201180 11 FUNC GLOBAL DEFAULT 2 baz # 4: 0000000000201190 26 FUNC GLOBAL DEFAULT 2 main ``` In the above example, `foo` is inserted into the link by `PROVIDE(foo = 3)` because it is referenced by `bar`. However, `bar` is itself not used anywhere and is garbage-collected during the link. So, from one perspective `foo` is not used anywhere. Is it right to provide a symbol from `PROVIDE` if the symbol is not used anywhere? I am looking forward to more thoughts and opinions on this.