@@ -170,12 +170,15 @@ static reloc_howto_type x86_64_elf_howto_table[] =
170170 HOWTO (R_X86_64_REX_GOTPCRELX , 0 , 4 , 32 , true, 0 , complain_overflow_signed ,
171171 bfd_elf_generic_reloc , "R_X86_64_REX_GOTPCRELX" , false, 0 , 0xffffffff ,
172172 true),
173+ HOWTO (R_X86_64_CODE_4_GOTPCRELX , 0 , 4 , 32 , true, 0 , complain_overflow_signed ,
174+ bfd_elf_generic_reloc , "R_X86_64_CODE_4_GOTPCRELX" , false, 0 , 0xffffffff ,
175+ true),
173176
174177 /* We have a gap in the reloc numbers here.
175178 R_X86_64_standard counts the number up to this point, and
176179 R_X86_64_vt_offset is the value to subtract from a reloc type of
177180 R_X86_64_GNU_VT* to form an index into this table. */
178- #define R_X86_64_standard (R_X86_64_REX_GOTPCRELX + 1 )
181+ #define R_X86_64_standard (R_X86_64_CODE_4_GOTPCRELX + 1 )
179182#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard )
180183
181184/* GNU extension to record C++ vtable hierarchy. */
@@ -244,6 +247,7 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
244247 { BFD_RELOC_X86_64_PLT32_BND , R_X86_64_PLT32_BND , },
245248 { BFD_RELOC_X86_64_GOTPCRELX , R_X86_64_GOTPCRELX , },
246249 { BFD_RELOC_X86_64_REX_GOTPCRELX , R_X86_64_REX_GOTPCRELX , },
250+ { BFD_RELOC_X86_64_CODE_4_GOTPCRELX , R_X86_64_CODE_4_GOTPCRELX , },
247251 { BFD_RELOC_VTABLE_INHERIT , R_X86_64_GNU_VTINHERIT , },
248252 { BFD_RELOC_VTABLE_ENTRY , R_X86_64_GNU_VTENTRY , },
249253};
@@ -1586,7 +1590,8 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
15861590 bfd_vma roff = irel -> r_offset ;
15871591 bfd_vma abs_relocation ;
15881592
1589- if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2 ))
1593+ if (roff < (r_type == R_X86_64_CODE_4_GOTPCRELX
1594+ ? 4 : (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2 )))
15901595 return true;
15911596
15921597 raddend = irel -> r_addend ;
@@ -1597,8 +1602,18 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
15971602 htab = elf_x86_hash_table (link_info , X86_64_ELF_DATA );
15981603 is_pic = bfd_link_pic (link_info );
15991604
1600- relocx = (r_type == R_X86_64_GOTPCRELX
1601- || r_type == R_X86_64_REX_GOTPCRELX );
1605+ if (r_type == R_X86_64_CODE_4_GOTPCRELX )
1606+ {
1607+ /* Skip if this isn't a REX2 instruction. */
1608+ opcode = bfd_get_8 (abfd , contents + roff - 4 );
1609+ if (opcode != 0xd5 )
1610+ return true;
1611+
1612+ relocx = true;
1613+ }
1614+ else
1615+ relocx = (r_type == R_X86_64_GOTPCRELX
1616+ || r_type == R_X86_64_REX_GOTPCRELX );
16021617
16031618 /* TRUE if --no-relax is used. */
16041619 no_overflow = link_info -> disable_target_specific_optimizations > 1 ;
@@ -1610,9 +1625,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
16101625 /* Convert mov to lea since it has been done for a while. */
16111626 if (opcode != 0x8b )
16121627 {
1613- /* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX
1614- for call, jmp or one of adc, add, and, cmp, or, sbb, sub ,
1615- test, xor instructions. */
1628+ /* Only convert R_X86_64_GOTPCRELX, R_X86_64_REX_GOTPCRELX
1629+ and R_X86_64_CODE_4_GOTPCRELX for call, jmp or one of adc,
1630+ add, and, cmp, or, sbb, sub, test, xor instructions. */
16161631 if (!relocx )
16171632 return true;
16181633 }
@@ -1797,13 +1812,22 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
17971812 }
17981813 else
17991814 {
1800- unsigned int rex ;
1815+ unsigned int rex = 0 ;
18011816 unsigned int rex_mask = REX_R ;
1817+ unsigned int rex2 = 0 ;
1818+ unsigned int rex2_mask = REX_R | REX_R << 4 ;
1819+ bool rex_w = false;
18021820
1803- if (r_type == R_X86_64_REX_GOTPCRELX )
1804- rex = bfd_get_8 (abfd , contents + roff - 3 );
1805- else
1806- rex = 0 ;
1821+ if (r_type == R_X86_64_CODE_4_GOTPCRELX )
1822+ {
1823+ rex2 = bfd_get_8 (abfd , contents + roff - 3 );
1824+ rex_w = (rex2 & REX_W ) != 0 ;
1825+ }
1826+ else if (r_type == R_X86_64_REX_GOTPCRELX )
1827+ {
1828+ rex = bfd_get_8 (abfd , contents + roff - 3 );
1829+ rex_w = (rex & REX_W ) != 0 ;
1830+ }
18071831
18081832 if (opcode == 0x8b )
18091833 {
@@ -1824,8 +1848,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
18241848 opcode = 0xc7 ;
18251849 modrm = bfd_get_8 (abfd , contents + roff - 1 );
18261850 modrm = 0xc0 | (modrm & 0x38 ) >> 3 ;
1827- if ((rex & REX_W ) != 0
1828- && ABI_64_P (link_info -> output_bfd ))
1851+ if (rex_w && ABI_64_P (link_info -> output_bfd ))
18291852 {
18301853 /* Keep the REX_W bit in REX byte for LP64. */
18311854 r_type = R_X86_64_32S ;
@@ -1837,8 +1860,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
18371860 use R_X86_64_32 and clear the W bit to avoid
18381861 sign-extend imm32 to imm64. */
18391862 r_type = R_X86_64_32 ;
1840- /* Clear the W bit in REX byte. */
1863+ /* Clear the W bit in REX byte and REX2 payload . */
18411864 rex_mask |= REX_W ;
1865+ rex2_mask |= REX_W ;
18421866 goto rewrite_modrm_rex ;
18431867 }
18441868 }
@@ -1867,7 +1891,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
18671891
18681892 /* Use R_X86_64_32 with 32-bit operand to avoid relocation
18691893 overflow when sign-extending imm32 to imm64. */
1870- r_type = ( rex & REX_W ) != 0 ? R_X86_64_32S : R_X86_64_32 ;
1894+ r_type = rex_w ? R_X86_64_32S : R_X86_64_32 ;
18711895
18721896 rewrite_modrm_rex :
18731897 if (abs_relocation )
@@ -1893,6 +1917,13 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
18931917 rex = (rex & ~rex_mask ) | (rex & REX_R ) >> 2 ;
18941918 bfd_put_8 (abfd , rex , contents + roff - 3 );
18951919 }
1920+ else if (rex2 )
1921+ {
1922+ /* Move the R bits to the B bits in REX2 payload byte. */
1923+ rex2 = ((rex2 & ~rex2_mask )
1924+ | (rex2 & (REX_R | REX_R << 4 )) >> 2 );
1925+ bfd_put_8 (abfd , rex2 , contents + roff - 3 );
1926+ }
18961927
18971928 /* No addend for R_X86_64_32/R_X86_64_32S relocations. */
18981929 irel -> r_addend = 0 ;
@@ -2058,7 +2089,8 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
20582089 converted_reloc = false;
20592090 if ((r_type == R_X86_64_GOTPCREL
20602091 || r_type == R_X86_64_GOTPCRELX
2061- || r_type == R_X86_64_REX_GOTPCRELX )
2092+ || r_type == R_X86_64_REX_GOTPCRELX
2093+ || r_type == R_X86_64_CODE_4_GOTPCRELX )
20622094 && (h == NULL || h -> type != STT_GNU_IFUNC ))
20632095 {
20642096 Elf_Internal_Rela * irel = (Elf_Internal_Rela * ) rel ;
@@ -2108,6 +2140,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
21082140 case R_X86_64_GOTPCREL :
21092141 case R_X86_64_GOTPCRELX :
21102142 case R_X86_64_REX_GOTPCRELX :
2143+ case R_X86_64_CODE_4_GOTPCRELX :
21112144 case R_X86_64_TLSGD :
21122145 case R_X86_64_GOT64 :
21132146 case R_X86_64_GOTPCREL64 :
@@ -2710,6 +2743,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
27102743 case R_X86_64_GOTPCREL :
27112744 case R_X86_64_GOTPCRELX :
27122745 case R_X86_64_REX_GOTPCRELX :
2746+ case R_X86_64_CODE_4_GOTPCRELX :
27132747 case R_X86_64_GOTPCREL64 :
27142748 base_got = htab -> elf .sgot ;
27152749 off = h -> got .offset ;
@@ -2935,6 +2969,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
29352969 case R_X86_64_GOTPCREL :
29362970 case R_X86_64_GOTPCRELX :
29372971 case R_X86_64_REX_GOTPCRELX :
2972+ case R_X86_64_CODE_4_GOTPCRELX :
29382973 case R_X86_64_GOTPCREL64 :
29392974 /* Use global offset table entry as symbol value. */
29402975 case R_X86_64_GOTPLT64 :
@@ -3025,7 +3060,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
30253060 && !(sym -> st_shndx == SHN_ABS
30263061 && (r_type == R_X86_64_GOTPCREL
30273062 || r_type == R_X86_64_GOTPCRELX
3028- || r_type == R_X86_64_REX_GOTPCRELX )))
3063+ || r_type == R_X86_64_REX_GOTPCRELX
3064+ || r_type == R_X86_64_CODE_4_GOTPCRELX )))
30293065 relative_reloc = true;
30303066 }
30313067 }
@@ -3063,6 +3099,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
30633099 if (r_type != R_X86_64_GOTPCREL
30643100 && r_type != R_X86_64_GOTPCRELX
30653101 && r_type != R_X86_64_REX_GOTPCRELX
3102+ && r_type != R_X86_64_CODE_4_GOTPCRELX
30663103 && r_type != R_X86_64_GOTPCREL64 )
30673104 relocation -= htab -> elf .sgotplt -> output_section -> vma
30683105 - htab -> elf .sgotplt -> output_offset ;
0 commit comments