# REQUIRES: x86 # RUN: rm -rf %t && split-file %s %t && cd %t # RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o shared.o shared.s # RUN: ld.lld -shared shared.o -o a.so # RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o a.o a.s #--- shared.s .globl test_shared .section .test_shared,"ax",@progbits test_shared: jmp test_shared #--- a.s ## Simple live section .globl _start .section ._start,"ax",@progbits _start: jmp test_simple .quad .Lanonymous .quad .Lanonymous_within_symbol jmp test_shared .quad test_local .size _start, .-_start .globl test_simple .section .test_simple,"ax",@progbits test_simple: jmp test_simple jmp test_from_unsized # RUN: ld.lld a.o a.so --gc-sections --why-live=test_simple | FileCheck %s --check-prefix=SIMPLE # SIMPLE: live symbol: a.o:(test_simple) # SIMPLE-NEXT: >>> referenced by: a.o:(_start) (entry point) # SIMPLE-EMPTY: ## Live only by being a member of .test_simple .globl test_incidental test_incidental: jmp test_incidental # RUN: ld.lld a.o a.so --gc-sections --why-live=test_incidental | FileCheck %s --check-prefix=INCIDENTAL # INCIDENTAL: live symbol: a.o:(test_incidental) # INCIDENTAL-NEXT: >>> in live section: a.o:(.test_simple) # INCIDENTAL-NEXT: >>> contained live symbol: a.o:(test_simple) # INCIDENTAL-NEXT: >>> referenced by: a.o:(_start) (entry point) # INCIDENTAL-EMPTY: ## Reached from a reference in section .test_simple directly, since test_simple is an unsized symbol. .globl test_from_unsized .section .test_from_unsized,"ax",@progbits test_from_unsized: jmp test_from_unsized # RUN: ld.lld a.o a.so --gc-sections --why-live=test_from_unsized | FileCheck %s --check-prefix=FROM-UNSIZED # FROM-UNSIZED: live symbol: a.o:(test_from_unsized) # FROM-UNSIZED-NEXT: >>> referenced by: a.o:(.test_simple) # FROM-UNSIZED-NEXT: >>> contained live symbol: a.o:(test_simple) # FROM-UNSIZED-NEXT: >>> referenced by: a.o:(_start) (entry point) # FROM-UNSIZED-EMPTY: ## Symbols in dead sections are dead and not reported. .globl test_dead .section .test_dead,"ax",@progbits test_dead: jmp test_dead # RUN: ld.lld a.o a.so --gc-sections --why-live=test_dead | count 0 ## Undefined symbols are considered live, since they are not in dead sections. # RUN: ld.lld a.o a.so --gc-sections --why-live=test_undef -u test_undef | FileCheck %s --check-prefix=UNDEFINED # UNDEFINED: live symbol: :(test_undef) (no section) # UNDEFINED-EMPTY: ## Defined symbols without input section parents are live. .globl test_absolute test_absolute = 1234 # RUN: ld.lld a.o a.so --gc-sections --why-live=test_absolute | FileCheck %s --check-prefix=ABSOLUTE # ABSOLUTE: live symbol: a.o:(test_absolute) (no section) # ABSOLUTE-EMPTY: ## Retained sections are intrinsically live, and they make contained symbols live. .globl test_retained .section .test_retained,"axR",@progbits test_retained: jmp test_retained # RUN: ld.lld a.o a.so --gc-sections --why-live=test_retained | FileCheck %s --check-prefix=RETAINED # RETAINED: live symbol: a.o:(test_retained) # RETAINED-NEXT: >>> in live section: a.o:(.test_retained) (retained) # RETAINED-EMPTY: ## Relocs that reference offsets from sections (e.g., from anonymous symbols) are considered to point to the section if no enclosing symbol exists. .globl test_section_offset .section .test_section_offset,"ax",@progbits test_section_offset: jmp test_section_offset .Lanonymous: jmp test_section_offset # RUN: ld.lld a.o a.so --gc-sections --why-live=test_section_offset | FileCheck %s --check-prefix=SECTION-OFFSET # SECTION-OFFSET: live symbol: a.o:(test_section_offset) # SECTION-OFFSET-NEXT: >>> in live section: a.o:(.test_section_offset) # SECTION-OFFSET-NEXT: >>> referenced by: a.o:(_start) (entry point) # SECTION-OFFSET-EMPTY: ## Relocs that reference offsets from sections (e.g., from anonymous symbols) are considered to point to the enclosing symbol if one exists. .globl test_section_offset_within_symbol .section .test_section_offset_within_symbol,"ax",@progbits test_section_offset_within_symbol: jmp test_section_offset_within_symbol .Lanonymous_within_symbol: jmp test_section_offset_within_symbol .size test_section_offset_within_symbol, .-test_section_offset_within_symbol # RUN: ld.lld a.o a.so --gc-sections --why-live=test_section_offset_within_symbol | FileCheck %s --check-prefix=SECTION-OFFSET-WITHIN-SYMBOL # SECTION-OFFSET-WITHIN-SYMBOL: live symbol: a.o:(test_section_offset_within_symbol) # SECTION-OFFSET-WITHIN-SYMBOL-NEXT: >>> referenced by: a.o:(_start) (entry point) # SECTION-OFFSET-WITHIN-SYMBOL-EMPTY: ## Local symbols can be queried just like global symbols. .section .test_local,"ax",@progbits test_local: jmp test_local .size test_local, .-test_local # RUN: ld.lld a.o a.so --gc-sections --why-live=test_local | FileCheck %s --check-prefix=LOCAL # LOCAL: live symbol: a.o:(test_local) # LOCAL-NEXT: >>> referenced by: a.o:(_start) (entry point) # LOCAL-EMPTY: ## Shared symbols # RUN: ld.lld a.o a.so --gc-sections --why-live=test_shared | FileCheck %s --check-prefix=SHARED # SHARED: live symbol: a.so:(test_shared) # SHARED-NEXT: >>> referenced by: a.o:(_start) (entry point) # SHARED-EMPTY: ## Globs match multiple cases. Multiple --why-live flags union. # RUN: ld.lld a.o a.so --gc-sections --why-live="test_se*" --why-live="test_se*" | FileCheck %s --check-prefix=MULTIPLE # RUN: ld.lld a.o a.so --gc-sections --why-live=test_section_offset --why-live=test_section_offset_within_symbol | FileCheck %s --check-prefix=MULTIPLE # MULTIPLE-DAG: live symbol: a.o:(test_section_offset) # MULTIPLE-DAG: live symbol: a.o:(test_section_offset_within_symbol) # MULTIPLE-NOT: live symbol