reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
# REQUIRES: hexagon
# RUN: echo '.globl bar, weak; .type bar,@function; .type weak,@function; bar: weak:' > %t1.s

# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %t1.s -o %t1.o
# RUN: ld.lld -shared %t1.o -soname=t1.so -o %t1.so
# RUN: llvm-mc -mno-fixup -filetype=obj -triple=hexagon-unknown-elf %s -o %t.o
# RUN: ld.lld %t.o %t1.so -z separate-code -o %t
# RUN: llvm-readelf -S -s %t | FileCheck --check-prefixes=SEC,NM %s
# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
# RUN: llvm-readelf -x .got.plt %t | FileCheck --check-prefix=GOTPLT %s
# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=DIS %s

# SEC: .plt PROGBITS {{0*}}00020040

## A canonical PLT has a non-zero st_value. bar and weak are called but their
## addresses are not taken, so a canonical PLT is not necessary.
# NM: {{0*}}00000000 0 FUNC GLOBAL DEFAULT UND bar
# NM: {{0*}}00000000 0 FUNC WEAK   DEFAULT UND weak

## The .got.plt slots relocated by .rela.plt point to .plt
## This is required by glibc.
# RELOC:      .rela.plt {
# RELOC-NEXT:    0x40078 R_HEX_JMP_SLOT bar 0x0
# RELOC-NEXT:    0x4007C R_HEX_JMP_SLOT weak 0x0
# RELOC-NEXT: }
# GOTPLT:      section '.got.plt'
# GOTPLT-NEXT: 0x00040068 00000000 00000000 00000000 00000000
# GOTPLT-NEXT: 0x00040078 00000000 00000000

# DIS:      _start:
## Direct call
## Call foo directly
# DIS-NEXT:   { call 0x2003c }
## Call bar via plt
# DIS-NEXT:   { call 0x20060 }
## Call weak via plt
# DIS-NEXT:   { call 0x20070 }
# DIS-NEXT: { 	immext(#0)

## Call foo directly
# DIS-NEXT: if (p0) jump:nt 0x2003c }
# DIS-NEXT: { 	immext(#64)
## Call bar via plt
# DIS-NEXT: if (p0) jump:nt 0x20060 }
# DIS-NEXT: { 	immext(#64)
## Call weak via plt
# DIS-NEXT: if (p0) jump:nt 0x20070 }
# DIS-NEXT: { 	immext(#0)

## Call foo directly
# DIS-NEXT: r0 = #0 ; jump 0x2003c }
# DIS-NEXT: { 	immext(#0)
## Call bar via plt
# DIS-NEXT: r0 = #0 ; jump 0x20060 }
# DIS-NEXT: { 	immext(#0)
## Call weak via plt
# DIS-NEXT: r0 = #0 ; jump 0x20070 }

# DIS:      foo:
# DIS-NEXT:   2003c:


# DIS: Disassembly of section .plt:

# DIS: 00020040 .plt:
# DIS-NEXT:   20040: { 	immext(#131072)
# DIS-NEXT:   20044:   	r28 = add(pc,##131112) }
# DIS-NEXT:   20048: { 	r14 -= add(r28,#16)
# DIS-NEXT:   2004c:   	r15 = memw(r28+#8)
# DIS-NEXT:   20050:   	r28 = memw(r28+#4) }
# DIS-NEXT:   20054: { 	r14 = asr(r14,#2)
# DIS-NEXT:   20058:   	jumpr r28 }
# DIS-NEXT:   2005c: { 	trap0(#219) }
## bar's plt slot
# DIS-NEXT:   20060: { 	immext(#131072)
# DIS-NEXT:   20064:   	r14 = add(pc,##131096) }
# DIS-NEXT:   20068: { 	r28 = memw(r14+#0) }
# DIS-NEXT:   2006c: { 	jumpr r28 }
## weak's plt slot
# DIS-NEXT:   20070: { 	immext(#131072)
# DIS-NEXT:   20074:   	r14 = add(pc,##131084) }
# DIS-NEXT:   20078: { 	r28 = memw(r14+#0) }
# DIS-NEXT:   2007c: { 	jumpr r28 }


.global _start, foo, bar
.weak weak

_start:
  call foo
  call bar
  call weak
  if (p0) jump foo
  if (p0) jump bar
  if (p0) jump weak
  { r0 = #0; jump foo }
  { r0 = #0; jump bar }
  { r0 = #0; jump weak }

## foo is local and non-preemptale, no PLT is generated.
foo:
  jumpr r31