@@ -179,12 +179,30 @@ static reloc_howto_type x86_64_elf_howto_table[] =
179
179
HOWTO (R_X86_64_CODE_4_GOTPC32_TLSDESC , 0 , 4 , 32 , true, 0 ,
180
180
complain_overflow_bitfield , bfd_elf_generic_reloc ,
181
181
"R_X86_64_CODE_4_GOTPC32_TLSDESC" , false, 0 , 0xffffffff , true),
182
+ HOWTO (R_X86_64_CODE_5_GOTPCRELX , 0 , 4 , 32 , true, 0 ,
183
+ complain_overflow_signed , bfd_elf_generic_reloc ,
184
+ "R_X86_64_CODE_5_GOTPCRELX" , false, 0 , 0xffffffff , true),
185
+ HOWTO (R_X86_64_CODE_5_GOTTPOFF , 0 , 4 , 32 , true, 0 ,
186
+ complain_overflow_signed , bfd_elf_generic_reloc ,
187
+ "R_X86_64_CODE_5_GOTTPOFF" , false, 0 , 0xffffffff , true),
188
+ HOWTO (R_X86_64_CODE_5_GOTPC32_TLSDESC , 0 , 4 , 32 , true, 0 ,
189
+ complain_overflow_bitfield , bfd_elf_generic_reloc ,
190
+ "R_X86_64_CODE_5_GOTPC32_TLSDESC" , false, 0 , 0xffffffff , true),
191
+ HOWTO (R_X86_64_CODE_6_GOTPCRELX , 0 , 4 , 32 , true, 0 ,
192
+ complain_overflow_signed , bfd_elf_generic_reloc ,
193
+ "R_X86_64_CODE_6_GOTPCRELX" , false, 0 , 0xffffffff , true),
194
+ HOWTO (R_X86_64_CODE_6_GOTTPOFF , 0 , 4 , 32 , true, 0 ,
195
+ complain_overflow_signed , bfd_elf_generic_reloc ,
196
+ "R_X86_64_CODE_6_GOTTPOFF" , false, 0 , 0xffffffff , true),
197
+ HOWTO (R_X86_64_CODE_6_GOTPC32_TLSDESC , 0 , 4 , 32 , true, 0 ,
198
+ complain_overflow_bitfield , bfd_elf_generic_reloc ,
199
+ "R_X86_64_CODE_6_GOTPC32_TLSDESC" , false, 0 , 0xffffffff , true),
182
200
183
201
/* We have a gap in the reloc numbers here.
184
202
R_X86_64_standard counts the number up to this point, and
185
203
R_X86_64_vt_offset is the value to subtract from a reloc type of
186
204
R_X86_64_GNU_VT* to form an index into this table. */
187
- #define R_X86_64_standard (R_X86_64_CODE_4_GOTPC32_TLSDESC + 1 )
205
+ #define R_X86_64_standard (R_X86_64_CODE_6_GOTPC32_TLSDESC + 1 )
188
206
#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard )
189
207
190
208
/* GNU extension to record C++ vtable hierarchy. */
@@ -256,6 +274,12 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
256
274
{ BFD_RELOC_X86_64_CODE_4_GOTPCRELX , R_X86_64_CODE_4_GOTPCRELX , },
257
275
{ BFD_RELOC_X86_64_CODE_4_GOTTPOFF , R_X86_64_CODE_4_GOTTPOFF , },
258
276
{ BFD_RELOC_X86_64_CODE_4_GOTPC32_TLSDESC , R_X86_64_CODE_4_GOTPC32_TLSDESC , },
277
+ { BFD_RELOC_X86_64_CODE_5_GOTPCRELX , R_X86_64_CODE_5_GOTPCRELX , },
278
+ { BFD_RELOC_X86_64_CODE_5_GOTTPOFF , R_X86_64_CODE_5_GOTTPOFF , },
279
+ { BFD_RELOC_X86_64_CODE_5_GOTPC32_TLSDESC , R_X86_64_CODE_5_GOTPC32_TLSDESC , },
280
+ { BFD_RELOC_X86_64_CODE_6_GOTPCRELX , R_X86_64_CODE_6_GOTPCRELX , },
281
+ { BFD_RELOC_X86_64_CODE_6_GOTTPOFF , R_X86_64_CODE_6_GOTTPOFF , },
282
+ { BFD_RELOC_X86_64_CODE_6_GOTPC32_TLSDESC , R_X86_64_CODE_6_GOTPC32_TLSDESC , },
259
283
{ BFD_RELOC_VTABLE_INHERIT , R_X86_64_GNU_VTINHERIT , },
260
284
{ BFD_RELOC_VTABLE_ENTRY , R_X86_64_GNU_VTENTRY , },
261
285
};
@@ -1283,6 +1307,23 @@ elf_x86_64_check_tls_transition (bfd *abfd,
1283
1307
1284
1308
goto check_gottpoff ;
1285
1309
1310
+ case R_X86_64_CODE_6_GOTTPOFF :
1311
+ /* Check transition from IE access model:
1312
+ add %reg1, foo@gottpoff(%rip), %reg2
1313
+ where reg1/reg2 are one of r16 to r31. */
1314
+
1315
+ if (offset < 6
1316
+ || (offset + 4 ) > sec -> size
1317
+ || contents [offset - 6 ] != 0x62 )
1318
+ return false;
1319
+
1320
+ val = bfd_get_8 (abfd , contents + offset - 2 );
1321
+ if (val != 0x01 && val != 0x03 )
1322
+ return false;
1323
+
1324
+ val = bfd_get_8 (abfd , contents + offset - 1 );
1325
+ return (val & 0xc7 ) == 5 ;
1326
+
1286
1327
case R_X86_64_GOTTPOFF :
1287
1328
/* Check transition from IE access model:
1288
1329
mov foo@gottpoff(%rip), %reg
@@ -1417,6 +1458,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
1417
1458
case R_X86_64_TLSDESC_CALL :
1418
1459
case R_X86_64_GOTTPOFF :
1419
1460
case R_X86_64_CODE_4_GOTTPOFF :
1461
+ case R_X86_64_CODE_6_GOTTPOFF :
1420
1462
if (bfd_link_executable (info ))
1421
1463
{
1422
1464
if (h == NULL )
@@ -1464,6 +1506,8 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
1464
1506
/* Return TRUE if there is no transition. */
1465
1507
if (from_type == to_type
1466
1508
|| (from_type == R_X86_64_CODE_4_GOTTPOFF
1509
+ && to_type == R_X86_64_GOTTPOFF )
1510
+ || (from_type == R_X86_64_CODE_6_GOTTPOFF
1467
1511
&& to_type == R_X86_64_GOTTPOFF ))
1468
1512
return true;
1469
1513
@@ -2177,6 +2221,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
2177
2221
2178
2222
case R_X86_64_GOTTPOFF :
2179
2223
case R_X86_64_CODE_4_GOTTPOFF :
2224
+ case R_X86_64_CODE_6_GOTTPOFF :
2180
2225
if (!bfd_link_executable (info ))
2181
2226
info -> flags |= DF_STATIC_TLS ;
2182
2227
/* Fall through */
@@ -2214,6 +2259,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
2214
2259
break ;
2215
2260
case R_X86_64_GOTTPOFF :
2216
2261
case R_X86_64_CODE_4_GOTTPOFF :
2262
+ case R_X86_64_CODE_6_GOTTPOFF :
2217
2263
tls_type = GOT_TLS_IE ;
2218
2264
break ;
2219
2265
case R_X86_64_GOTPC32_TLSDESC :
@@ -2503,6 +2549,26 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
2503
2549
}
2504
2550
break ;
2505
2551
2552
+ case R_X86_64_CODE_5_GOTPCRELX :
2553
+ case R_X86_64_CODE_5_GOTTPOFF :
2554
+ case R_X86_64_CODE_5_GOTPC32_TLSDESC :
2555
+ case R_X86_64_CODE_6_GOTPCRELX :
2556
+ case R_X86_64_CODE_6_GOTPC32_TLSDESC :
2557
+ {
2558
+ /* These relocations are added only for completeness and
2559
+ aren't be used. */
2560
+ if (h )
2561
+ name = h -> root .root .string ;
2562
+ else
2563
+ name = bfd_elf_sym_name (abfd , symtab_hdr , isym ,
2564
+ NULL );
2565
+ _bfd_error_handler
2566
+ /* xgettext:c-format */
2567
+ (_ ("%pB: unsupported relocation %s against symbol `%s'" ),
2568
+ abfd , x86_64_elf_howto_table [r_type ].name , name );
2569
+ }
2570
+ break ;
2571
+
2506
2572
/* This relocation describes the C++ object vtable hierarchy.
2507
2573
Reconstruct it for later use during GC. */
2508
2574
case R_X86_64_GNU_VTINHERIT :
@@ -3570,6 +3636,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
3570
3636
case R_X86_64_TLSDESC_CALL :
3571
3637
case R_X86_64_GOTTPOFF :
3572
3638
case R_X86_64_CODE_4_GOTTPOFF :
3639
+ case R_X86_64_CODE_6_GOTTPOFF :
3573
3640
tls_type = GOT_UNKNOWN ;
3574
3641
if (h == NULL && local_got_offsets )
3575
3642
tls_type = elf_x86_local_got_tls_type (input_bfd ) [r_symndx ];
@@ -3920,6 +3987,50 @@ elf_x86_64_relocate_section (bfd *output_bfd,
3920
3987
contents + roff );
3921
3988
continue ;
3922
3989
}
3990
+ else if (r_type == R_X86_64_CODE_6_GOTTPOFF )
3991
+ {
3992
+ /* IE->LE transition:
3993
+ Originally it is
3994
+ add %reg1, foo@gottpoff(%rip), %reg2
3995
+ or
3996
+ add foo@gottpoff(%rip), %reg1, %reg2
3997
+ We change it into:
3998
+ add $foo@tpoff, %reg1, %reg2
3999
+ */
4000
+ unsigned int reg , byte1 ;
4001
+ unsigned int updated_byte1 ;
4002
+
4003
+ if (roff < 6 )
4004
+ goto corrupt_input ;
4005
+
4006
+ /* Move the R bits to the B bits in EVEX payload
4007
+ byte 1. */
4008
+ byte1 = bfd_get_8 (input_bfd , contents + roff - 5 );
4009
+ updated_byte1 = byte1 ;
4010
+
4011
+ /* Set the R bits since they is inverted. */
4012
+ updated_byte1 |= 1 << 7 | 1 << 4 ;
4013
+
4014
+ /* Update the B bits from the R bits. */
4015
+ if ((byte1 & (1 << 7 )) == 0 )
4016
+ updated_byte1 &= ~(1 << 5 );
4017
+ if ((byte1 & (1 << 4 )) == 0 )
4018
+ updated_byte1 |= 1 << 3 ;
4019
+
4020
+ reg = bfd_get_8 (input_bfd , contents + roff - 1 );
4021
+ reg >>= 3 ;
4022
+
4023
+ bfd_put_8 (output_bfd , updated_byte1 ,
4024
+ contents + roff - 5 );
4025
+ bfd_put_8 (output_bfd , 0x81 ,
4026
+ contents + roff - 2 );
4027
+ bfd_put_8 (output_bfd , 0xc0 | reg ,
4028
+ contents + roff - 1 );
4029
+ bfd_put_32 (output_bfd ,
4030
+ elf_x86_64_tpoff (info , relocation ),
4031
+ contents + roff );
4032
+ continue ;
4033
+ }
3923
4034
else
3924
4035
BFD_ASSERT (false);
3925
4036
}
0 commit comments