Skip to content

Commit da49faf

Browse files
author
George Rimar
committedApr 18, 2019
[LLD][ELF] - Fix the different behavior of the linker script symbols on different platforms.
This generalizes code and also fixes the broken behavior shown in one of our test cases for some targets, like x86-64. The issue occurs when the forward declarations are used in the script. One of the samples is: SECTIONS { foo = ADDR(.text) - ABSOLUTE(ADDR(.text)); }; In that case, we have a broken output when output target does not use thunks. That happens because thunks creating code (called from maybeAddThunks) calls Script->assignAddresses() at least one more time, what fixups the values. As a result final symbols values can be different on AArch64 and x86, for example. In this patch, I generalize and rename maybeAddThunks to finalizeAddressDependentContent and now it is used and called by all targets. Differential revision: https://reviews.llvm.org/D55550 llvm-svn: 358646
1 parent 957c356 commit da49faf

File tree

2 files changed

+39
-26
lines changed

2 files changed

+39
-26
lines changed
 

‎lld/ELF/Writer.cpp

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ template <class ELFT> class Writer {
5555
void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn);
5656
void sortSections();
5757
void resolveShfLinkOrder();
58-
void maybeAddThunks();
58+
void finalizeAddressDependentContent();
5959
void sortInputSections();
6060
void finalizeSections();
6161
void checkExecuteOnly();
@@ -1460,19 +1460,15 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
14601460
}
14611461
}
14621462

1463-
// For most RISC ISAs, we need to generate content that depends on the address
1464-
// of InputSections. For example some architectures such as AArch64 use small
1465-
// displacements for jump instructions that is the linker's responsibility for
1466-
// creating range extension thunks for. As the generation of the content may
1467-
// also alter InputSection addresses we must converge to a fixed point.
1468-
template <class ELFT> void Writer<ELFT>::maybeAddThunks() {
1469-
if (!Target->NeedsThunks && !Config->AndroidPackDynRelocs &&
1470-
!Config->RelrPackDynRelocs)
1471-
return;
1472-
1463+
// We need to generate and finalize the content that depends on the address of
1464+
// InputSections. As the generation of the content may also alter InputSection
1465+
// addresses we must converge to a fixed point. We do that here. See the comment
1466+
// in Writer<ELFT>::finalizeSections().
1467+
template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
14731468
ThunkCreator TC;
14741469
AArch64Err843419Patcher A64P;
14751470

1471+
// For some targets, like x86, this loop iterates only once.
14761472
for (;;) {
14771473
bool Changed = false;
14781474

@@ -1756,19 +1752,30 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
17561752
// known but before addresses are allocated.
17571753
resolveShfLinkOrder();
17581754

1759-
// Jump instructions in many ISAs have small displacements, and therefore they
1760-
// cannot jump to arbitrary addresses in memory. For example, RISC-V JAL
1761-
// instruction can target only +-1 MiB from PC. It is a linker's
1762-
// responsibility to create and insert small pieces of code between sections
1763-
// to extend the ranges if jump targets are out of range. Such code pieces are
1764-
// called "thunks".
1755+
// This is used to:
1756+
// 1) Create "thunks":
1757+
// Jump instructions in many ISAs have small displacements, and therefore
1758+
// they cannot jump to arbitrary addresses in memory. For example, RISC-V
1759+
// JAL instruction can target only +-1 MiB from PC. It is a linker's
1760+
// responsibility to create and insert small pieces of code between
1761+
// sections to extend the ranges if jump targets are out of range. Such
1762+
// code pieces are called "thunks".
1763+
//
1764+
// We add thunks at this stage. We couldn't do this before this point
1765+
// because this is the earliest point where we know sizes of sections and
1766+
// their layouts (that are needed to determine if jump targets are in
1767+
// range).
1768+
//
1769+
// 2) Update the sections. We need to generate content that depends on the
1770+
// address of InputSections. For example, MIPS GOT section content or
1771+
// android packed relocations sections content.
17651772
//
1766-
// We add thunks at this stage. We couldn't do this before this point because
1767-
// this is the earliest point where we know sizes of sections and their
1768-
// layouts (that are needed to determine if jump targets are in range).
1769-
maybeAddThunks();
1773+
// 3) Assign the final values for the linker script symbols. Linker scripts
1774+
// sometimes using forward symbol declarations. We want to set the correct
1775+
// values. They also might change after adding the thunks.
1776+
finalizeAddressDependentContent();
17701777

1771-
// maybeAddThunks may have added local symbols to the static symbol table.
1778+
// finalizeAddressDependentContent may have added local symbols to the static symbol table.
17721779
finalizeSynthetic(In.SymTab);
17731780
finalizeSynthetic(In.PPC64LongBranchTarget);
17741781

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1-
# REQUIRES: x86
1+
# REQUIRES: x86, aarch64
22
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o
33
# RUN: ld.lld -o %t.so --script %s %t.o -shared
44
# RUN: llvm-readobj --symbols %t.so | FileCheck %s
55

6-
# Test that the script creates a non absolute symbol with value
7-
# 0 I.E., a symbol that refers to the load address.
6+
## Test that the script creates a non absolute symbol with value
7+
## 0 I.E., a symbol that refers to the load address.
88

99
# CHECK: Symbol {
1010
# CHECK: Name: foo
11-
# CHECK-NEXT: Value: 0x70
11+
# CHECK-NEXT: Value: 0x0
1212
# CHECK-NEXT: Size: 0
1313
# CHECK-NEXT: Binding: Global
1414
# CHECK-NEXT: Type: None
1515
# CHECK-NEXT: Other: 0
1616
# CHECK-NEXT: Section: .text
1717
# CHECK-NEXT: }
1818

19+
## Because of a bug we had a different behavior (different symbol 'foo' value)
20+
## on a platforms that might use thunks, like AArch64. Check that issue is fixed.
21+
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnux /dev/null -o %t.o
22+
# RUN: ld.lld -o %t.so --script %s %t.o -shared
23+
# RUN: llvm-readobj --symbols %t.so | FileCheck %s
24+
1925
SECTIONS {
2026
foo = ADDR(.text) - ABSOLUTE(ADDR(.text));
2127
};

0 commit comments

Comments
 (0)
Please sign in to comment.