Skip to content

Commit 85197a0

Browse files
committedMay 24, 2018
[PPC64] Add .toc section after .got section
PPC64 maintains a compiler managed got in the .toc section. When accessing a global variable through got-indirect access, a .toc entry is created for the variable. The relocation for the got-indirect access will refer to the .toc section rather than the symbol that is actually accessed. The .toc entry contains the address of the global variable. We evaluate the offset from r2 (which is the TOC base) to the address of the toc entry for the global variable. Currently, the .toc is not near the .got. This causes errors because the offset from r2 to the toc section is too large. The linker needs to add all the .toc input sections to the .got output section, merging the compiler managed got with the linker got. This ensures that the offsets from the TOC base to the toc entries are not too large. This patch puts the .toc section right after the .got section. Differential Revision: https://reviews.llvm.org/D45833 llvm-svn: 333199
1 parent dfbe6fa commit 85197a0

File tree

4 files changed

+128
-6
lines changed

4 files changed

+128
-6
lines changed
 

‎lld/ELF/Writer.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,9 @@ static bool isRelroSection(const OutputSection *Sec) {
663663
if (InX::Got && Sec == InX::Got->getParent())
664664
return true;
665665

666+
if (Sec->Name.equals(".toc"))
667+
return true;
668+
666669
// .got.plt contains pointers to external function symbols. They are
667670
// by default resolved lazily, so we usually cannot put it into RELRO.
668671
// However, if "-z now" is given, the lazy symbol resolution is
@@ -707,8 +710,9 @@ enum RankFlags {
707710
RF_BSS = 1 << 8,
708711
RF_NOTE = 1 << 7,
709712
RF_PPC_NOT_TOCBSS = 1 << 6,
710-
RF_PPC_TOCL = 1 << 4,
711-
RF_PPC_TOC = 1 << 3,
713+
RF_PPC_TOCL = 1 << 5,
714+
RF_PPC_TOC = 1 << 4,
715+
RF_PPC_GOT = 1 << 3,
712716
RF_PPC_BRANCH_LT = 1 << 2,
713717
RF_MIPS_GPREL = 1 << 1,
714718
RF_MIPS_NOT_GOT = 1 << 0
@@ -827,6 +831,9 @@ static unsigned getSectionRank(const OutputSection *Sec) {
827831
if (Name == ".toc")
828832
Rank |= RF_PPC_TOC;
829833

834+
if (Name == ".got")
835+
Rank |= RF_PPC_GOT;
836+
830837
if (Name == ".branch_lt")
831838
Rank |= RF_PPC_BRANCH_LT;
832839
}

‎lld/test/ELF/ppc64-func-entry-points.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,6 @@ glob:
7575
// CHECK: foo_external_diff:
7676
// CHECK-NEXT: 10010080: {{.*}} addis 2, 12, 2
7777
// CHECK-NEXT: 10010084: {{.*}} addi 2, 2, 32640
78-
// CHECK-NEXT: 10010088: {{.*}} addis 5, 2, -1
78+
// CHECK-NEXT: 10010088: {{.*}} addis 5, 2, 0
7979
// CHECK: foo_external_same:
8080
// CHECK-NEXT: 100100b0: {{.*}} add 3, 4, 3

‎lld/test/ELF/ppc64-got-indirect.s

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# REQUIRES: ppc
2+
3+
# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4+
# RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-LE %s
5+
# RUN: ld.lld %t.o -o %t2
6+
# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=CHECK-LE
7+
# RUN: llvm-objdump -D %t2 | FileCheck %s
8+
9+
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10+
# RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-BE %s
11+
# RUN: ld.lld %t.o -o %t2
12+
# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=CHECK-BE
13+
# RUN: llvm-objdump -D %t2 | FileCheck %s
14+
15+
# Make sure we calculate the offset correctly for a got-indirect access to a
16+
# global variable as described by the PPC64 ELF V2 abi.
17+
.text
18+
.abiversion 2
19+
.globl _start # -- Begin function _start
20+
.p2align 4
21+
.type _start,@function
22+
_start: # @_start
23+
.Lfunc_begin0:
24+
.Lfunc_gep0:
25+
addis 2, 12, .TOC.-.Lfunc_gep0@ha
26+
addi 2, 2, .TOC.-.Lfunc_gep0@l
27+
.Lfunc_lep0:
28+
.localentry _start, .Lfunc_lep0-.Lfunc_gep0
29+
# %bb.0: # %entry
30+
addis 3, 2, .LC0@toc@ha
31+
ld 3, .LC0@toc@l(3)
32+
li 4, 0
33+
stw 4, -12(1)
34+
li 0,1
35+
lwa 3, 0(3)
36+
sc
37+
.long 0
38+
.quad 0
39+
.Lfunc_end0:
40+
.size _start, .Lfunc_end0-.Lfunc_begin0
41+
# -- End function
42+
.section .toc,"aw",@progbits
43+
.LC0:
44+
.tc glob[TC],glob
45+
.type glob,@object # @glob
46+
.data
47+
.globl glob
48+
.p2align 2
49+
glob:
50+
.long 55 # 0x37
51+
.size glob, 4
52+
53+
# Verify the relocations emitted for glob are through the .toc
54+
55+
# RELOCS-LE: Relocations [
56+
# RELOCS-LE: .rela.text {
57+
# RELOCS-LE: 0x0 R_PPC64_REL16_HA .TOC. 0x0
58+
# RELOCS-LE: 0x4 R_PPC64_REL16_LO .TOC. 0x4
59+
# RELOCS-LE: 0x8 R_PPC64_TOC16_HA .toc 0x0
60+
# RELOCS-LE: 0xC R_PPC64_TOC16_LO_DS .toc 0x0
61+
# RELOCS-LE: }
62+
# RELOCS-LE: .rela.toc {
63+
# RELOCS-LE: 0x0 R_PPC64_ADDR64 glob 0x0
64+
# RELOCS-LE: }
65+
66+
# RELOCS-BE: Relocations [
67+
# RELOCS-BE: .rela.text {
68+
# RELOCS-BE: 0x2 R_PPC64_REL16_HA .TOC. 0x2
69+
# RELOCS-BE: 0x6 R_PPC64_REL16_LO .TOC. 0x6
70+
# RELOCS-BE: 0xA R_PPC64_TOC16_HA .toc 0x0
71+
# RELOCS-BE: 0xE R_PPC64_TOC16_LO_DS .toc 0x0
72+
# RELOCS-BE: }
73+
# RELOCS-BE: .rela.toc {
74+
# RELOCS-BE: 0x0 R_PPC64_ADDR64 glob 0x0
75+
# RELOCS-BE: }
76+
# RELOCS-BE:]
77+
78+
# Verify that the global variable access is done through the correct
79+
# toc entry:
80+
# r2 = .TOC. = 0x10038000.
81+
# r3 = r2 - 32760 = 0x10030008 -> .toc entry for glob.
82+
83+
# CHECK: _start:
84+
# CHECK-NEXT: 10010000: {{.*}} addis 2, 12, 3
85+
# CHECK-NEXT: 10010004: {{.*}} addi 2, 2, -32768
86+
# CHECK-NEXT: 10010008: {{.*}} addis 3, 2, 0
87+
# CHECK-NEXT: 1001000c: {{.*}} ld 3, -32760(3)
88+
# CHECK: 1001001c: {{.*}} lwa 3, 0(3)
89+
90+
# CHECK-LE: Disassembly of section .data:
91+
# CHECK-LE-NEXT: glob:
92+
# CHECK-LE-NEXT: 10020000: 37 00 00 00
93+
94+
# CHECK-LE: Disassembly of section .got:
95+
# CHECK-LE-NEXT: .got:
96+
# CHECK-LE-NEXT: 10030000: 00 80 03 10
97+
# CHECK-LE-NEXT: 10030004: 00 00 00 00
98+
99+
# Verify that .toc comes right after .got
100+
# CHECK-LE: Disassembly of section .toc:
101+
# CHECK-LE: 10030008: 00 00 02 10
102+
103+
# CHECK-BE: Disassembly of section .data:
104+
# CHECK-BE-NEXT: glob:
105+
# CHECK-BE-NEXT: 10020000: 00 00 00 37
106+
107+
# CHECK-BE: Disassembly of section .got:
108+
# CHECK-BE-NEXT: .got:
109+
# CHECK-BE-NEXT: 10030000: 00 00 00 00
110+
# CHECK-BE-NEXT: 10030004: 10 03 80 00
111+
112+
# Verify that .toc comes right after .got
113+
# CHECK-BE: Disassembly of section .toc:
114+
# CHECK-BE: 10030008: 00 00 00 00
115+
# CHECK-BE: 1003000c: 10 02 00 00

‎lld/test/ELF/ppc64-relocs.s

+3-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ _start:
5454

5555
# CHECK: Disassembly of section .R_PPC64_TOC16_HI:
5656
# CHECK: .FR_PPC64_TOC16_HI:
57-
# CHECK: 10010014: {{.*}} addis 1, 2, -2
57+
# CHECK: 10010014: {{.*}} addis 1, 2, -1
5858

5959
.section .R_PPC64_TOC16_HA,"ax",@progbits
6060
.globl .FR_PPC64_TOC16_HA
@@ -63,7 +63,7 @@ _start:
6363

6464
# CHECK: Disassembly of section .R_PPC64_TOC16_HA:
6565
# CHECK: .FR_PPC64_TOC16_HA:
66-
# CHECK: 10010018: {{.*}} addis 1, 2, -1
66+
# CHECK: 10010018: {{.*}} addis 1, 2, 0
6767

6868
.section .R_PPC64_REL24,"ax",@progbits
6969
.globl .FR_PPC64_REL24
@@ -160,7 +160,7 @@ _start:
160160
# 0x10000190 + 0xfeb4 = 0x10010044
161161
# CHECK: Disassembly of section .R_PPC64_REL32:
162162
# CHECK: .FR_PPC64_REL32:
163-
# CHECK: 1001003c: {{.*}} addis 5, 2, -1
163+
# CHECK: 1001003c: {{.*}} addis 5, 2, 0
164164
# CHECK: 10010040: {{.*}} ld 5, -32736(5)
165165
# CHECK: 10010044: {{.*}} add 3, 3, 4
166166

0 commit comments

Comments
 (0)
Please sign in to comment.