summaryrefslogtreecommitdiff
path: root/patches/0004-gold-Enable-TLS-relocation-scan.patch
blob: ab57c81b50b18e5c072b5280e0956c308394b563 (plain)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
From edd3f277480c9cecafb1a286828c2257017c9e82 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 10 May 2020 09:44:52 -0700
Subject: [PATCH 4/7] gold: Enable TLS relocation scan

When creating a shared library, input object files can have GDesc and IE
relocations against the same symbol.  If IE relocation is scanned first,
GDesc relocation can be optimized to IE relocation.  Add an optional
early TLS relocation scan pass before the regular relocation scan to
detect IE relocations.

	PR gold/25476
	* object.cc (Sized_relobj_file<size, big_endian>::do_layout):
	Use 2 passes for TLS relocation scan.
	* object.h (Object): Initialize scan_tls_relocs_only_.
	Add set_scan_tls_relocs_only, clear_scan_tls_relocs_only,
	scan_tls_relocs_only and scan_tls_relocs_only_.
	* reloc.cc (Read_relocs::run): Support TLS relocation scan.
	(Sized_relobj_file<size, big_endian>::do_scan_relocs): Likewise.
	* reloc.h (Gc_process_relocs::Gc_process_relocs): Add 2 arguments,
	gc_process_relocs and tls_process_relocs.  Initialize
	gc_process_relocs_ and tls_process_relocs_.
	(Gc_process_relocs): Add gc_process_relocs_ and
	tls_process_relocs_.
---
 gold/object.cc | 11 +++++++++++
 gold/object.h  | 22 ++++++++++++++++++++--
 gold/reloc.cc  | 18 ++++++++++++++----
 gold/reloc.h   | 11 +++++++++--
 4 files changed, 54 insertions(+), 8 deletions(-)

diff --git a/gold/object.cc b/gold/object.cc
index c486a2011d..2551911f86 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -1419,10 +1419,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
   const unsigned int unwind_section_type =
       parameters->target().unwind_section_type();
   const unsigned int shnum = this->shnum();
+  Target* target = const_cast<Target*>(&parameters->target());
 
   /* Should this function be called twice?  */
   bool is_two_pass = (parameters->options().gc_sections()
 		      || parameters->options().icf_enabled()
+		      || target->need_tls_process_relocs()
 		      || layout->is_unique_segment_for_sections_specified());
 
   /* Only one of is_pass_one and is_pass_two is true.  Both are false when
@@ -1823,6 +1825,15 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 	      }
 	}
 
+      if (is_pass_two && target->need_tls_process_relocs())
+	{
+	  if (out_sections[i] == NULL)
+	    {
+	      gold_assert(out_section_offsets[i] == invalid_address);
+	      continue;
+	    }
+	}
+
       // Defer layout here if input files are claimed by plugins.  When gc
       // is turned on this function is called twice; we only want to do this
       // on the first pass.
diff --git a/gold/object.h b/gold/object.h
index b7bd38faaf..42e0449d72 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -402,8 +402,9 @@ class Object
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
       is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
       has_no_split_stack_(false), no_export_(false),
-      is_in_system_directory_(false), as_needed_(false), xindex_(NULL),
-      compressed_sections_(NULL)
+      is_in_system_directory_(false), as_needed_(false),
+      scan_tls_relocs_only_(false),
+      xindex_(NULL), compressed_sections_(NULL)
   {
     if (input_file != NULL)
       {
@@ -794,6 +795,21 @@ class Object
   as_needed() const
   { return this->as_needed_; }
 
+  // Set flag that this object is being scanned for TLS relocation only.
+  void
+  set_scan_tls_relocs_only()
+  { this->scan_tls_relocs_only_ = true; }
+
+  // Clear flag that this object is being scanned for TLS relocation only.
+  void
+  clear_scan_tls_relocs_only()
+  { this->scan_tls_relocs_only_ = false; }
+
+  // Return whether this object is being scanned for TLS relocation only.
+  bool
+  scan_tls_relocs_only() const
+  { return this->scan_tls_relocs_only_; }
+
   // Return whether we found this object by searching a directory.
   bool
   searched_for() const
@@ -1084,6 +1100,8 @@ class Object
   bool is_in_system_directory_ : 1;
   // True if the object was linked with --as-needed.
   bool as_needed_ : 1;
+  // True if the object is being scanned for TLS relocation only.
+  bool scan_tls_relocs_only_ : 1;
   // Many sections for objects with more than SHN_LORESERVE sections.
   Xindex* xindex_;
   // For compressed debug sections, map section index to uncompressed size
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 7cd9f859e0..ad0efba414 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -74,14 +74,23 @@ Read_relocs::run(Workqueue* workqueue)
   // If garbage collection or identical comdat folding is desired, we  
   // process the relocs first before scanning them.  Scanning of relocs is
   // done only after garbage or identical sections is identified.
-  if (parameters->options().gc_sections()
-      || parameters->options().icf_enabled())
+  bool do_gc_process_relocs = (parameters->options().gc_sections()
+			       || parameters->options().icf_enabled());
+
+  // If TLS relocation scan is desired, we scan TLS relocations first
+  // before scanning all relocations.
+  Target* target = const_cast<Target*>(&parameters->target());
+  bool do_tls_process_relocs = target->need_tls_process_relocs();
+
+  if (do_gc_process_relocs || do_tls_process_relocs)
     {
       workqueue->queue_next(new Gc_process_relocs(this->symtab_,
                                                   this->layout_, 
                                                   this->object_, rd,
                                                   this->this_blocker_,
-						  this->next_blocker_));
+						  this->next_blocker_,
+						  do_gc_process_relocs,
+						  do_tls_process_relocs));
     }
   else
     {
@@ -448,7 +457,8 @@ Sized_relobj_file<size, big_endian>::do_scan_relocs(Symbol_table* symtab,
       // in the link that would have been included normally. This is known only
       // after Read_relocs hence this check has to be done again.
       if (parameters->options().gc_sections()
-	  || parameters->options().icf_enabled())
+	  || parameters->options().icf_enabled()
+	  || target->need_tls_process_relocs())
         {
           if (p->output_section == NULL)
             continue;
diff --git a/gold/reloc.h b/gold/reloc.h
index 492c3fadfd..8ca31b2678 100644
--- a/gold/reloc.h
+++ b/gold/reloc.h
@@ -104,9 +104,12 @@ class Gc_process_relocs : public Task
   // running.
   Gc_process_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
 		    Read_relocs_data* rd, Task_token* this_blocker,
-		    Task_token* next_blocker)
+		    Task_token* next_blocker, bool gc_process_relocs,
+		    bool tls_process_relocs)
     : symtab_(symtab), layout_(layout), object_(object), rd_(rd),
-      this_blocker_(this_blocker), next_blocker_(next_blocker)
+      this_blocker_(this_blocker), next_blocker_(next_blocker),
+      gc_process_relocs_(gc_process_relocs),
+      tls_process_relocs_(tls_process_relocs)
   { }
 
   ~Gc_process_relocs();
@@ -132,6 +135,10 @@ class Gc_process_relocs : public Task
   Read_relocs_data* rd_;
   Task_token* this_blocker_;
   Task_token* next_blocker_;
+  // True if the object is being garbage collected.
+  bool gc_process_relocs_;
+  // True if the object is being scanned for TLS relocation only.
+  bool tls_process_relocs_;
 };
 
 // Scan the relocations for an object to see if they require any
-- 
2.26.2