@@ -55,6 +55,7 @@ X86_64::X86_64() {
55
55
PltRel = R_X86_64_JUMP_SLOT;
56
56
RelativeRel = R_X86_64_RELATIVE;
57
57
IRelativeRel = R_X86_64_IRELATIVE;
58
+ TlsDescRel = R_X86_64_TLSDESC;
58
59
TlsGotRel = R_X86_64_TPOFF64;
59
60
TlsModuleIndexRel = R_X86_64_DTPMOD64;
60
61
TlsOffsetRel = R_X86_64_DTPOFF64;
@@ -88,6 +89,8 @@ RelExpr X86_64::getRelExpr(RelType Type, const Symbol &S,
88
89
return R_DTPREL;
89
90
case R_X86_64_TPOFF32:
90
91
return R_TLS;
92
+ case R_X86_64_TLSDESC_CALL:
93
+ return R_TLSDESC_CALL;
91
94
case R_X86_64_TLSLD:
92
95
return R_TLSLD_PC;
93
96
case R_X86_64_TLSGD:
@@ -105,6 +108,8 @@ RelExpr X86_64::getRelExpr(RelType Type, const Symbol &S,
105
108
case R_X86_64_GOT32:
106
109
case R_X86_64_GOT64:
107
110
return R_GOTPLT;
111
+ case R_X86_64_GOTPC32_TLSDESC:
112
+ return R_TLSDESC_PC;
108
113
case R_X86_64_GOTPCREL:
109
114
case R_X86_64_GOTPCRELX:
110
115
case R_X86_64_REX_GOTPCRELX:
@@ -173,45 +178,82 @@ RelType X86_64::getDynRel(RelType Type) const {
173
178
}
174
179
175
180
void X86_64::relaxTlsGdToLe (uint8_t *Loc, RelType Type, uint64_t Val) const {
176
- // Convert
177
- // .byte 0x66
178
- // leaq x@tlsgd(%rip), %rdi
179
- // .word 0x6666
180
- // rex64
181
- // call __tls_get_addr@plt
182
- // to
183
- // mov %fs:0x0,%rax
184
- // lea x@tpoff,%rax
185
- const uint8_t Inst[] = {
186
- 0x64 , 0x48 , 0x8b , 0x04 , 0x25 , 0x00 , 0x00 , 0x00 , 0x00 , // mov %fs:0x0,%rax
187
- 0x48 , 0x8d , 0x80 , 0 , 0 , 0 , 0 , // lea x@tpoff,%rax
188
- };
189
- memcpy (Loc - 4 , Inst, sizeof (Inst));
190
-
191
- // The original code used a pc relative relocation and so we have to
192
- // compensate for the -4 in had in the addend.
193
- write32le (Loc + 8 , Val + 4 );
181
+ if (Type == R_X86_64_TLSGD) {
182
+ // Convert
183
+ // .byte 0x66
184
+ // leaq x@tlsgd(%rip), %rdi
185
+ // .word 0x6666
186
+ // rex64
187
+ // call __tls_get_addr@plt
188
+ // to the following two instructions.
189
+ const uint8_t Inst[] = {
190
+ 0x64 , 0x48 , 0x8b , 0x04 , 0x25 , 0x00 , 0x00 ,
191
+ 0x00 , 0x00 , // mov %fs:0x0,%rax
192
+ 0x48 , 0x8d , 0x80 , 0 , 0 , 0 , 0 , // lea x@tpoff,%rax
193
+ };
194
+ memcpy (Loc - 4 , Inst, sizeof (Inst));
195
+
196
+ // The original code used a pc relative relocation and so we have to
197
+ // compensate for the -4 in had in the addend.
198
+ write32le (Loc + 8 , Val + 4 );
199
+ } else {
200
+ // Convert
201
+ // lea x@tlsgd(%rip), %rax
202
+ // call *(%rax)
203
+ // to the following two instructions.
204
+ assert (Type == R_X86_64_GOTPC32_TLSDESC);
205
+ if (memcmp (Loc - 3 , " \x48\x8d\x05 " , 3 )) {
206
+ error (getErrorLocation (Loc - 3 ) + " R_X86_64_GOTPC32_TLSDESC must be used "
207
+ " in callq *x@tlsdesc(%rip), %rax" );
208
+ return ;
209
+ }
210
+ // movq $x@tpoff(%rip),%rax
211
+ Loc[-2 ] = 0xc7 ;
212
+ Loc[-1 ] = 0xc0 ;
213
+ write32le (Loc, Val + 4 );
214
+ // xchg ax,ax
215
+ Loc[4 ] = 0x66 ;
216
+ Loc[5 ] = 0x90 ;
217
+ }
194
218
}
195
219
196
220
void X86_64::relaxTlsGdToIe (uint8_t *Loc, RelType Type, uint64_t Val) const {
197
- // Convert
198
- // .byte 0x66
199
- // leaq x@tlsgd(%rip), %rdi
200
- // .word 0x6666
201
- // rex64
202
- // call __tls_get_addr@plt
203
- // to
204
- // mov %fs:0x0,%rax
205
- // addq x@tpoff,%rax
206
- const uint8_t Inst[] = {
207
- 0x64 , 0x48 , 0x8b , 0x04 , 0x25 , 0x00 , 0x00 , 0x00 , 0x00 , // mov %fs:0x0,%rax
208
- 0x48 , 0x03 , 0x05 , 0 , 0 , 0 , 0 , // addq x@tpoff,%rax
209
- };
210
- memcpy (Loc - 4 , Inst, sizeof (Inst));
211
-
212
- // Both code sequences are PC relatives, but since we are moving the constant
213
- // forward by 8 bytes we have to subtract the value by 8.
214
- write32le (Loc + 8 , Val - 8 );
221
+ if (Type == R_X86_64_TLSGD) {
222
+ // Convert
223
+ // .byte 0x66
224
+ // leaq x@tlsgd(%rip), %rdi
225
+ // .word 0x6666
226
+ // rex64
227
+ // call __tls_get_addr@plt
228
+ // to the following two instructions.
229
+ const uint8_t Inst[] = {
230
+ 0x64 , 0x48 , 0x8b , 0x04 , 0x25 , 0x00 , 0x00 ,
231
+ 0x00 , 0x00 , // mov %fs:0x0,%rax
232
+ 0x48 , 0x03 , 0x05 , 0 , 0 , 0 , 0 , // addq x@gottpoff(%rip),%rax
233
+ };
234
+ memcpy (Loc - 4 , Inst, sizeof (Inst));
235
+
236
+ // Both code sequences are PC relatives, but since we are moving the
237
+ // constant forward by 8 bytes we have to subtract the value by 8.
238
+ write32le (Loc + 8 , Val - 8 );
239
+ } else {
240
+ // Convert
241
+ // lea x@tlsgd(%rip), %rax
242
+ // call *(%rax)
243
+ // to the following two instructions.
244
+ assert (Type == R_X86_64_GOTPC32_TLSDESC);
245
+ if (memcmp (Loc - 3 , " \x48\x8d\x05 " , 3 )) {
246
+ error (getErrorLocation (Loc - 3 ) + " R_X86_64_GOTPC32_TLSDESC must be used "
247
+ " in callq *x@tlsdesc(%rip), %rax" );
248
+ return ;
249
+ }
250
+ // movq x@gottpoff(%rip),%rax
251
+ Loc[-2 ] = 0x8b ;
252
+ write32le (Loc, Val);
253
+ // xchg ax,ax
254
+ Loc[4 ] = 0x66 ;
255
+ Loc[5 ] = 0x90 ;
256
+ }
215
257
}
216
258
217
259
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
@@ -331,6 +373,7 @@ void X86_64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
331
373
case R_X86_64_TPOFF32:
332
374
case R_X86_64_GOT32:
333
375
case R_X86_64_GOTPC32:
376
+ case R_X86_64_GOTPC32_TLSDESC:
334
377
case R_X86_64_GOTPCREL:
335
378
case R_X86_64_GOTPCRELX:
336
379
case R_X86_64_REX_GOTPCRELX:
0 commit comments