blob: 1b36d8562cf4bda8059dbfdd552311fd30bcfe51 [file] [edit]
# 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
# RUN: llvm-mc -n -filetype=obj -triple=x86_64 -o b.o b.s
#--- shared.s
.globl test_shared
.section .test_shared,"ax",@progbits
test_shared:
jmp test_shared
#--- a.s
.weak __start_cident
.weak __stop_cident
## 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
.quad __start_cident - .
.quad __stop_cident - .
call test_group
call test_eh
.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: <internal>:(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
.section cident,"a",@progbits
.globl test_atexit
test_atexit:
.quad 0
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_atexit -z nostart-stop-gc | FileCheck %s --check-prefix=ATEXIT
# ATEXIT: live symbol: a.o:(test_atexit)
# ATEXIT-NEXT: >>> in live section: a.o:(cident)
# ATEXIT-NEXT: >>> referenced by: a.o:(_start) (entry point)
# ATEXIT-EMPTY:
## A live section's nextInSectionGroup is enqueued from the non-parallel mark().
.section .text.test_group,"axG",@progbits,test_group_signature,comdat
.globl test_group
test_group:
ret
.section .data.test_group,"awG",@progbits,test_group_signature,comdat
.globl test_group_data
test_group_data:
.quad 0
# RUN: ld.lld a.o a.so --gc-sections --why-live=test_group_data | FileCheck %s --check-prefix=GROUP
# GROUP: live symbol: a.o:(test_group_data)
# GROUP-NEXT: >>> in live section: a.o:(.data.test_group)
# GROUP-NEXT: >>> in section group with: a.o:(.text.test_group)
# GROUP-NEXT: >>> contained live symbol: a.o:(test_group)
# GROUP-NEXT: >>> referenced by: a.o:(_start) (entry point)
# GROUP-EMPTY:
## CIE personality relocation traced through scanEhFrameSection.
.section .text.personality,"ax",@progbits
.globl personality
personality:
ret
.section .text.test_eh,"ax",@progbits
.globl test_eh
test_eh:
.cfi_startproc
.cfi_personality 3, personality
ret
.cfi_endproc
# RUN: ld.lld a.o a.so --gc-sections --why-live=personality | FileCheck %s --check-prefix=PERSONALITY
# PERSONALITY: live symbol: a.o:(personality)
# PERSONALITY-NEXT: >>> referenced by: a.o:(.eh_frame) (exception handling frame)
# PERSONALITY-EMPTY:
## Symbols exported into the dynamic symbol table are GC roots.
.globl test_exported
.section .test_exported,"ax",@progbits
test_exported:
jmp test_exported
# RUN: ld.lld a.o a.so --gc-sections --export-dynamic --why-live=test_exported | FileCheck %s --check-prefix=EXPORTED
# EXPORTED: live symbol: a.o:(test_exported) (externally visible symbol)
# EXPORTED-EMPTY:
#--- b.s
## --why-live='*' skips symbol at index 0 and section symbols.
# RUN: ld.lld b.o --threads=1 --gc-sections --why-live="*" | FileCheck %s --check-prefix=STAR --match-full-lines
# STAR-NOT: {{.}}
# STAR: live symbol: b.o:(_start) (entry point)
# STAR-NEXT: live symbol: b.o:(b.s) (no section)
# STAR-NEXT: live symbol: b.o:(str1)
# STAR-NEXT: >>> referenced by: b.o:(.alloc)
# STAR-NEXT: >>> referenced by: b.o:(.text)
# STAR-NEXT: >>> contained live symbol: b.o:(_start) (entry point)
# STAR-NEXT: live symbol: b.o:(note1)
# STAR-NEXT: >>> in live section: b.o:(.note.1) (reserved)
# STAR-NEXT: live symbol: b.o:(__FRAME_END__)
# STAR-NEXT: >>> in live section: b.o:(.eh_frame) (exception handling frame)
# STAR-NOT: {{.}}
## STT_FILE symbol
.file "b.s"
.text
.globl _start
_start:
call .alloc
.section .alloc,"a"
lea str1(%rip), %rax
.section .nonalloc
.long .nonalloc
.section .note.1,"a",@note
note1:
## GCC crtendS.o has such a local symbol relative to an explicit .eh_frame
## section.
.section .eh_frame,"a"
__FRAME_END__:
.long 0
.section .rodata.str1.1,"aMS",@progbits,1
str1:
.asciz "str1"