* [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE @ 2021-02-23 12:15 H.J. Lu 2021-02-23 13:15 ` Jan Beulich 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-23 12:15 UTC (permalink / raw) To: binutils When linking PE/x86-64 inputs to generate ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation. 1. Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing PE/x86-64 inputs. 2. Pass link_info to bfd_perform_relocation to lookup __ImageBase. 3. Subtract __ImageBase for R_AMD64_IMAGEBASE. bfd/ PR ld/27425 PR ld/27432 * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Pass link_info to bfd_perform_relocation. * elf32-nds32.c (nds32_elf_get_relocated_section_contents): Likewise. * elfxx-mips.c (_bfd_elf_mips_get_relocated_section_contents): Likewise. * elf32-mips.c (mips32_64bit_reloc): Pass NULL as link_info to bfd_perform_relocation. * reloc.c (bfd_perform_relocation): Add a link_info argument. Subtract __ImageBase for R_AMD64_IMAGEBASE. (bfd_generic_get_relocated_section_contents): Pass link_info to bfd_perform_relocation. * bfd-in2.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_load_symbols): Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing PE/x86-64 inputs. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd-in2.h | 1 + bfd/coff-alpha.c | 12 +-- bfd/elf32-mips.c | 2 +- bfd/elf32-nds32.c | 4 +- bfd/elfxx-mips.c | 1 + bfd/reloc.c | 40 +++++++-- ld/ldelf.c | 24 ++++++ ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 16 files changed, 173 insertions(+), 19 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index d142bb52213..44d67b44bc4 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2222,6 +2222,7 @@ bfd_boolean bfd_reloc_offset_in_range bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 8031ab95902..79b95db404b 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -836,8 +836,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, rel->address += input_section->output_offset; break; } - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); break; case ALPHA_R_GPREL32: @@ -848,8 +848,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, addend. We adjust the addend and let bfd_perform_relocation finish the job. */ rel->addend -= gp; - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); if (r == bfd_reloc_ok && gp_undefined) { r = bfd_reloc_dangerous; @@ -884,8 +884,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, || ((insn >> 26) & 0x3f) == 0x28); rel->addend -= gp; - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); if (r == bfd_reloc_ok && gp_undefined) { r = bfd_reloc_dangerous; diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 34e61865cd9..9bd30ca95cf 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1905,7 +1905,7 @@ mips32_64bit_reloc (bfd *abfd, arelent *reloc_entry, if (bfd_big_endian (abfd)) reloc32.address += 4; reloc32.howto = &elf_mips_howto_table_rel[R_MIPS_32]; - r = bfd_perform_relocation (abfd, &reloc32, data, input_section, + r = bfd_perform_relocation (abfd, NULL, &reloc32, data, input_section, output_bfd, error_message); /* Sign extend into the upper 32 bits. */ diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c index 01d0702255a..215803ea949 100644 --- a/bfd/elf32-nds32.c +++ b/bfd/elf32-nds32.c @@ -13098,8 +13098,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, r = bfd_reloc_ok; } else - r = bfd_perform_relocation (input_bfd, *parent, data, - input_section, + r = bfd_perform_relocation (input_bfd, link_info, *parent, + data, input_section, relocatable ? abfd : NULL, &error_message); diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 86e15b61edf..325d6d30adf 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -13356,6 +13356,7 @@ _bfd_elf_mips_get_relocated_section_contents data, gp); else r = bfd_perform_relocation (input_bfd, + link_info, *parent, data, input_section, diff --git a/bfd/reloc.c b/bfd/reloc.c index 4f4b95a0b7f..b22966348d1 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -647,6 +647,7 @@ FUNCTION SYNOPSIS bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, @@ -673,6 +674,7 @@ DESCRIPTION bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, @@ -917,16 +919,35 @@ space consuming. For each target: object files to generate ELF output, _bfd_relocate_contents isn't called and bfd_perform_relocation is used. We need to adjust relocation here. */ - relocation -= reloc_entry->addend; - if (howto->type >= R_AMD64_PCRLONG_1 - && howto->type <= R_AMD64_PCRLONG_5) - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); - else if (howto->type == R_AMD64_DIR64 - || howto->type == R_AMD64_DIR32) + if (howto->type == R_AMD64_IMAGEBASE) + { + /* Subtract __ImageBase. */ + struct bfd_link_hash_entry *h + = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + abort (); + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + relocation -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + } + else { - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, - howto); - relocation -= val & howto->src_mask; + relocation -= reloc_entry->addend; + if (howto->type >= R_AMD64_PCRLONG_1 + && howto->type <= R_AMD64_PCRLONG_5) + relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); + else if (howto->type == R_AMD64_DIR64 + || howto->type == R_AMD64_DIR32) + { + bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, + howto); + relocation -= val & howto->src_mask; + } } } @@ -8457,6 +8478,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, } else r = bfd_perform_relocation (input_bfd, + link_info, *parent, data, input_section, diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..4693d73d576 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) { int link_class = 0; + if (bfd_link_pde (&link_info) + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) + { + /* NB: When linking PE/x86-64 inputs to generate ELF executable, + create an indirect reference to __executable_start for + __ImageBase to support R_AMD64_IMAGEBASE relocation which + is relative to __ImageBase. */ + struct elf_link_hash_table *htab = elf_hash_table (&link_info); + struct elf_link_hash_entry *h, *hi; + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->root.type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = elf_link_hash_lookup (htab, "__executable_start", + TRUE, FALSE, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + } + } + /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 12:15 [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE H.J. Lu @ 2021-02-23 13:15 ` Jan Beulich 2021-02-23 13:31 ` H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Jan Beulich @ 2021-02-23 13:15 UTC (permalink / raw) To: H.J. Lu; +Cc: binutils On 23.02.2021 13:15, H.J. Lu via Binutils wrote: > When linking PE/x86-64 inputs to generate ELF executable, we need to > subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE > relocation. Do you really mean PE/x86-64, not the respective COFF objects? In the description this may not matter much, but since there's at least one code comment also saying so, which may confuse readers, I'd like to understand this. Also, in how far is this x86-64-specific? > --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od > +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od > @@ -2,6 +2,7 @@ > .*: +file format .* > > SYMBOL TABLE: > +0+400000 g .text\$mn 0000000000000000 __executable_start > 0+401000 g .text\$mn 0000000000000000 getaddr1 > 0+401020 g .text\$mn 0000000000000000 begin > 0+403014 g .bss 0000000000000000 __bss_start I don't think this artifical symbol should appear in the symbol table. I also wonder what the consequences are if a set of linked object files specifies a symbol of this name. Jan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 13:15 ` Jan Beulich @ 2021-02-23 13:31 ` H.J. Lu 2021-02-23 14:10 ` Jan Beulich 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-23 13:31 UTC (permalink / raw) To: Jan Beulich; +Cc: Binutils On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.02.2021 13:15, H.J. Lu via Binutils wrote: > > When linking PE/x86-64 inputs to generate ELF executable, we need to > > subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE > > relocation. > > Do you really mean PE/x86-64, not the respective COFF objects? In the What is the difference? How should I call object files generated by Microsoft Visual Studio? > description this may not matter much, but since there's at least one > code comment also saying so, which may confuse readers, I'd like to > understand this. > > Also, in how far is this x86-64-specific? I don't know. > > --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od > > +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od > > @@ -2,6 +2,7 @@ > > .*: +file format .* > > > > SYMBOL TABLE: > > +0+400000 g .text\$mn 0000000000000000 __executable_start > > 0+401000 g .text\$mn 0000000000000000 getaddr1 > > 0+401020 g .text\$mn 0000000000000000 begin > > 0+403014 g .bss 0000000000000000 __bss_start > > I don't think this artifical symbol should appear in the symbol This symbol is generated by linker. It should be harmless. > table. I also wonder what the consequences are if a set of linked > object files specifies a symbol of this name. __executable_start is generated by linker. If __ImageBase is defined to another value, that value will be used as image base. -- H.J. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 13:31 ` H.J. Lu @ 2021-02-23 14:10 ` Jan Beulich 2021-02-23 14:47 ` H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Jan Beulich @ 2021-02-23 14:10 UTC (permalink / raw) To: H.J. Lu; +Cc: Binutils On 23.02.2021 14:31, H.J. Lu wrote: > On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: >> >> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: >>> When linking PE/x86-64 inputs to generate ELF executable, we need to >>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE >>> relocation. >> >> Do you really mean PE/x86-64, not the respective COFF objects? In the > > What is the difference? How should I call object files generated by > Microsoft Visual Studio? The call them COFF themselves, I believe. >> description this may not matter much, but since there's at least one >> code comment also saying so, which may confuse readers, I'd like to >> understand this. >> >> Also, in how far is this x86-64-specific? > > I don't know. > >>> --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od >>> +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od >>> @@ -2,6 +2,7 @@ >>> .*: +file format .* >>> >>> SYMBOL TABLE: >>> +0+400000 g .text\$mn 0000000000000000 __executable_start >>> 0+401000 g .text\$mn 0000000000000000 getaddr1 >>> 0+401020 g .text\$mn 0000000000000000 begin >>> 0+403014 g .bss 0000000000000000 __bss_start >> >> I don't think this artifical symbol should appear in the symbol > > This symbol is generated by linker. It should be harmless. According to my experience, stray symbols can be confusing or worse. >> table. I also wonder what the consequences are if a set of linked >> object files specifies a symbol of this name. > > __executable_start is generated by linker. If __ImageBase is > defined to another value, that value will be used as image base. So if I have an object defining __executable_start, which of the two will relocations be resolved against? Jan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 14:10 ` Jan Beulich @ 2021-02-23 14:47 ` H.J. Lu 2021-02-23 15:02 ` Jan Beulich 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-23 14:47 UTC (permalink / raw) To: Jan Beulich; +Cc: Binutils On Tue, Feb 23, 2021 at 6:10 AM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.02.2021 14:31, H.J. Lu wrote: > > On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: > >> > >> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: > >>> When linking PE/x86-64 inputs to generate ELF executable, we need to > >>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE > >>> relocation. > >> > >> Do you really mean PE/x86-64, not the respective COFF objects? In the > > > > What is the difference? How should I call object files generated by > > Microsoft Visual Studio? > > The call them COFF themselves, I believe. I have an impression that Windows relocations are different from regular COFF relocations. coff-x86_64.c has COFF_WITH_PE in many places. My patch is only for Windows/PE: && strcmp (abfd->xvec->name, "pe-x86-64") == 0 > >> description this may not matter much, but since there's at least one > >> code comment also saying so, which may confuse readers, I'd like to > >> understand this. > >> > >> Also, in how far is this x86-64-specific? > > > > I don't know. > > > >>> --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od > >>> +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od > >>> @@ -2,6 +2,7 @@ > >>> .*: +file format .* > >>> > >>> SYMBOL TABLE: > >>> +0+400000 g .text\$mn 0000000000000000 __executable_start > >>> 0+401000 g .text\$mn 0000000000000000 getaddr1 > >>> 0+401020 g .text\$mn 0000000000000000 begin > >>> 0+403014 g .bss 0000000000000000 __bss_start > >> > >> I don't think this artifical symbol should appear in the symbol > > > > This symbol is generated by linker. It should be harmless. > > According to my experience, stray symbols can be confusing or worse. __executable_start is well defined by linker. > >> table. I also wonder what the consequences are if a set of linked > >> object files specifies a symbol of this name. > > > > __executable_start is generated by linker. If __ImageBase is > > defined to another value, that value will be used as image base. > > So if I have an object defining __executable_start, which of the > two will relocations be resolved against? > Your __executable_start will be used. -- H.J. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 14:47 ` H.J. Lu @ 2021-02-23 15:02 ` Jan Beulich 2021-02-23 15:07 ` H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Jan Beulich @ 2021-02-23 15:02 UTC (permalink / raw) To: H.J. Lu; +Cc: Binutils On 23.02.2021 15:47, H.J. Lu wrote: > On Tue, Feb 23, 2021 at 6:10 AM Jan Beulich <jbeulich@suse.com> wrote: >> >> On 23.02.2021 14:31, H.J. Lu wrote: >>> On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: >>>> >>>> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: >>>>> When linking PE/x86-64 inputs to generate ELF executable, we need to >>>>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE >>>>> relocation. >>>> >>>> Do you really mean PE/x86-64, not the respective COFF objects? In the >>> >>> What is the difference? How should I call object files generated by >>> Microsoft Visual Studio? >> >> The call them COFF themselves, I believe. > > I have an impression that Windows relocations are different from regular > COFF relocations. coff-x86_64.c has COFF_WITH_PE in many places. Right - there are differences. > My patch is only for Windows/PE: > > && strcmp (abfd->xvec->name, "pe-x86-64") == 0 That's (imo) bfd-internal naming that's not helpful to understand what it really is that talk is about. Comments would hence likely benefit from naming things like they are called commonly. Jan ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 15:02 ` Jan Beulich @ 2021-02-23 15:07 ` H.J. Lu 2021-02-23 15:11 ` Jan Beulich 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-23 15:07 UTC (permalink / raw) To: Jan Beulich; +Cc: Binutils On Tue, Feb 23, 2021 at 7:02 AM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.02.2021 15:47, H.J. Lu wrote: > > On Tue, Feb 23, 2021 at 6:10 AM Jan Beulich <jbeulich@suse.com> wrote: > >> > >> On 23.02.2021 14:31, H.J. Lu wrote: > >>> On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: > >>>> > >>>> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: > >>>>> When linking PE/x86-64 inputs to generate ELF executable, we need to > >>>>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE > >>>>> relocation. > >>>> > >>>> Do you really mean PE/x86-64, not the respective COFF objects? In the > >>> > >>> What is the difference? How should I call object files generated by > >>> Microsoft Visual Studio? > >> > >> The call them COFF themselves, I believe. > > > > I have an impression that Windows relocations are different from regular > > COFF relocations. coff-x86_64.c has COFF_WITH_PE in many places. > > Right - there are differences. > > > My patch is only for Windows/PE: > > > > && strcmp (abfd->xvec->name, "pe-x86-64") == 0 > > That's (imo) bfd-internal naming that's not helpful to understand what > it really is that talk is about. Comments would hence likely benefit > from naming things like they are called commonly. Will "Windows x86-64 relocatable inputs" be better? -- H.J. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 15:07 ` H.J. Lu @ 2021-02-23 15:11 ` Jan Beulich 2021-02-23 17:50 ` [PATCH v2] " H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Jan Beulich @ 2021-02-23 15:11 UTC (permalink / raw) To: H.J. Lu; +Cc: Binutils On 23.02.2021 16:07, H.J. Lu wrote: > On Tue, Feb 23, 2021 at 7:02 AM Jan Beulich <jbeulich@suse.com> wrote: >> >> On 23.02.2021 15:47, H.J. Lu wrote: >>> On Tue, Feb 23, 2021 at 6:10 AM Jan Beulich <jbeulich@suse.com> wrote: >>>> >>>> On 23.02.2021 14:31, H.J. Lu wrote: >>>>> On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: >>>>>> >>>>>> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: >>>>>>> When linking PE/x86-64 inputs to generate ELF executable, we need to >>>>>>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE >>>>>>> relocation. >>>>>> >>>>>> Do you really mean PE/x86-64, not the respective COFF objects? In the >>>>> >>>>> What is the difference? How should I call object files generated by >>>>> Microsoft Visual Studio? >>>> >>>> The call them COFF themselves, I believe. >>> >>> I have an impression that Windows relocations are different from regular >>> COFF relocations. coff-x86_64.c has COFF_WITH_PE in many places. >> >> Right - there are differences. >> >>> My patch is only for Windows/PE: >>> >>> && strcmp (abfd->xvec->name, "pe-x86-64") == 0 >> >> That's (imo) bfd-internal naming that's not helpful to understand what >> it really is that talk is about. Comments would hence likely benefit >> from naming things like they are called commonly. > > Will "Windows x86-64 relocatable inputs" be better? I think so, yes. Of course I continue to be puzzled by the x86-64 special casing here. The concept of image base and image base relative relocations is architecture independent afaik. Jan ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 15:11 ` Jan Beulich @ 2021-02-23 17:50 ` H.J. Lu 2021-02-25 2:09 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-23 17:50 UTC (permalink / raw) To: Jan Beulich; +Cc: Binutils [-- Attachment #1: Type: text/plain, Size: 1802 bytes --] On Tue, Feb 23, 2021 at 7:11 AM Jan Beulich <jbeulich@suse.com> wrote: > > On 23.02.2021 16:07, H.J. Lu wrote: > > On Tue, Feb 23, 2021 at 7:02 AM Jan Beulich <jbeulich@suse.com> wrote: > >> > >> On 23.02.2021 15:47, H.J. Lu wrote: > >>> On Tue, Feb 23, 2021 at 6:10 AM Jan Beulich <jbeulich@suse.com> wrote: > >>>> > >>>> On 23.02.2021 14:31, H.J. Lu wrote: > >>>>> On Tue, Feb 23, 2021 at 5:15 AM Jan Beulich <jbeulich@suse.com> wrote: > >>>>>> > >>>>>> On 23.02.2021 13:15, H.J. Lu via Binutils wrote: > >>>>>>> When linking PE/x86-64 inputs to generate ELF executable, we need to > >>>>>>> subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE > >>>>>>> relocation. > >>>>>> > >>>>>> Do you really mean PE/x86-64, not the respective COFF objects? In the > >>>>> > >>>>> What is the difference? How should I call object files generated by > >>>>> Microsoft Visual Studio? > >>>> > >>>> The call them COFF themselves, I believe. > >>> > >>> I have an impression that Windows relocations are different from regular > >>> COFF relocations. coff-x86_64.c has COFF_WITH_PE in many places. > >> > >> Right - there are differences. > >> > >>> My patch is only for Windows/PE: > >>> > >>> && strcmp (abfd->xvec->name, "pe-x86-64") == 0 > >> > >> That's (imo) bfd-internal naming that's not helpful to understand what > >> it really is that talk is about. Comments would hence likely benefit > >> from naming things like they are called commonly. > > > > Will "Windows x86-64 relocatable inputs" be better? > > I think so, yes. Of course I continue to be puzzled by the x86-64 > special casing here. The concept of image base and image base > relative relocations is architecture independent afaik. If there is such a testcase, we can update it. > Jan Here is the updated patch. -- H.J. [-- Attachment #2: v2-0001-elf-x86-64-Subtract-__ImageBase-for-R_AMD64_IMAGE.patch --] [-- Type: text/x-patch, Size: 21028 bytes --] From eb2dbfdfb55ad6a27f8311c96a028365c713bbcf Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 15 Feb 2021 18:53:18 -0800 Subject: [PATCH v2] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE When linking Windows x86-64 relocatable object files to generate ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation. 1. Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable object files. 2. Pass link_info to bfd_perform_relocation to lookup __ImageBase. 3. Subtract __ImageBase for R_AMD64_IMAGEBASE. bfd/ PR ld/27425 PR ld/27432 * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Pass link_info to bfd_perform_relocation. * elf32-nds32.c (nds32_elf_get_relocated_section_contents): Likewise. * elfxx-mips.c (_bfd_elf_mips_get_relocated_section_contents): Likewise. * elf32-mips.c (mips32_64bit_reloc): Pass NULL as link_info to bfd_perform_relocation. * reloc.c (bfd_perform_relocation): Add a link_info argument. Subtract __ImageBase for R_AMD64_IMAGEBASE. (bfd_generic_get_relocated_section_contents): Pass link_info to bfd_perform_relocation. * bfd-in2.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_load_symbols): Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable inputs. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd-in2.h | 1 + bfd/coff-alpha.c | 12 +-- bfd/elf32-mips.c | 2 +- bfd/elf32-nds32.c | 4 +- bfd/elfxx-mips.c | 1 + bfd/reloc.c | 48 ++++++++--- ld/ldelf.c | 24 ++++++ ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 16 files changed, 177 insertions(+), 23 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index d142bb52213..44d67b44bc4 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2222,6 +2222,7 @@ bfd_boolean bfd_reloc_offset_in_range bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 8031ab95902..79b95db404b 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -836,8 +836,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, rel->address += input_section->output_offset; break; } - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); break; case ALPHA_R_GPREL32: @@ -848,8 +848,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, addend. We adjust the addend and let bfd_perform_relocation finish the job. */ rel->addend -= gp; - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); if (r == bfd_reloc_ok && gp_undefined) { r = bfd_reloc_dangerous; @@ -884,8 +884,8 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, || ((insn >> 26) & 0x3f) == 0x28); rel->addend -= gp; - r = bfd_perform_relocation (input_bfd, rel, data, input_section, - output_bfd, &err); + r = bfd_perform_relocation (input_bfd, link_info, rel, data, + input_section, output_bfd, &err); if (r == bfd_reloc_ok && gp_undefined) { r = bfd_reloc_dangerous; diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 34e61865cd9..9bd30ca95cf 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -1905,7 +1905,7 @@ mips32_64bit_reloc (bfd *abfd, arelent *reloc_entry, if (bfd_big_endian (abfd)) reloc32.address += 4; reloc32.howto = &elf_mips_howto_table_rel[R_MIPS_32]; - r = bfd_perform_relocation (abfd, &reloc32, data, input_section, + r = bfd_perform_relocation (abfd, NULL, &reloc32, data, input_section, output_bfd, error_message); /* Sign extend into the upper 32 bits. */ diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c index 01d0702255a..215803ea949 100644 --- a/bfd/elf32-nds32.c +++ b/bfd/elf32-nds32.c @@ -13098,8 +13098,8 @@ nds32_elf_get_relocated_section_contents (bfd *abfd, r = bfd_reloc_ok; } else - r = bfd_perform_relocation (input_bfd, *parent, data, - input_section, + r = bfd_perform_relocation (input_bfd, link_info, *parent, + data, input_section, relocatable ? abfd : NULL, &error_message); diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 86e15b61edf..325d6d30adf 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -13356,6 +13356,7 @@ _bfd_elf_mips_get_relocated_section_contents data, gp); else r = bfd_perform_relocation (input_bfd, + link_info, *parent, data, input_section, diff --git a/bfd/reloc.c b/bfd/reloc.c index 4f4b95a0b7f..562cd7804a7 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -647,6 +647,7 @@ FUNCTION SYNOPSIS bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, @@ -673,6 +674,7 @@ DESCRIPTION bfd_reloc_status_type bfd_perform_relocation (bfd *abfd, + struct bfd_link_info *link_info, arelent *reloc_entry, void *data, asection *input_section, @@ -913,20 +915,39 @@ space consuming. For each target: "elf64-x86-64") == 0) { /* NB: bfd_perform_relocation isn't called to generate PE binary. - _bfd_relocate_contents is called instead. When linking PE - object files to generate ELF output, _bfd_relocate_contents - isn't called and bfd_perform_relocation is used. We need to - adjust relocation here. */ - relocation -= reloc_entry->addend; - if (howto->type >= R_AMD64_PCRLONG_1 - && howto->type <= R_AMD64_PCRLONG_5) - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); - else if (howto->type == R_AMD64_DIR64 - || howto->type == R_AMD64_DIR32) + _bfd_relocate_contents is called instead. When linking Windows + x86-64 relocatable object files to generate ELF output, + _bfd_relocate_contents isn't called and bfd_perform_relocation + is used. We need to adjust relocation here. */ + if (howto->type == R_AMD64_IMAGEBASE) + { + /* Subtract __ImageBase. */ + struct bfd_link_hash_entry *h + = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + abort (); + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + relocation -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + } + else { - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, - howto); - relocation -= val & howto->src_mask; + relocation -= reloc_entry->addend; + if (howto->type >= R_AMD64_PCRLONG_1 + && howto->type <= R_AMD64_PCRLONG_5) + relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); + else if (howto->type == R_AMD64_DIR64 + || howto->type == R_AMD64_DIR32) + { + bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, + howto); + relocation -= val & howto->src_mask; + } } } @@ -8457,6 +8478,7 @@ bfd_generic_get_relocated_section_contents (bfd *abfd, } else r = bfd_perform_relocation (input_bfd, + link_info, *parent, data, input_section, diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..c7de958dbdc 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) { int link_class = 0; + if (bfd_link_pde (&link_info) + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) + { + /* NB: When linking Windows x86-64 relocatable object files to + generate ELF executable, create an indirect reference to + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE + relocation which is relative to __ImageBase. */ + struct elf_link_hash_table *htab = elf_hash_table (&link_info); + struct elf_link_hash_entry *h, *hi; + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->root.type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = elf_link_hash_lookup (htab, "__executable_start", + TRUE, FALSE, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + } + } + /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v2] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-23 17:50 ` [PATCH v2] " H.J. Lu @ 2021-02-25 2:09 ` Alan Modra 2021-02-28 2:38 ` [PATCH v3] " H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-02-25 2:09 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > * reloc.c (bfd_perform_relocation): Add a link_info argument. > Subtract __ImageBase for R_AMD64_IMAGEBASE. H.J., did you consider moving all of this, including the code you added in git commit 36068e2fa54, to the relevant howto special functions? None of it really belongs in bfd_perform_relocation. You might even be able to do without a link_info parameter, instead passing the image base value in output_elf_obj_tdata. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-25 2:09 ` Alan Modra @ 2021-02-28 2:38 ` H.J. Lu 2021-03-01 12:19 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-02-28 2:38 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils [-- Attachment #1: Type: text/plain, Size: 1014 bytes --] On Wed, Feb 24, 2021 at 6:09 PM Alan Modra <amodra@gmail.com> wrote: > > On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > > * reloc.c (bfd_perform_relocation): Add a link_info argument. > > Subtract __ImageBase for R_AMD64_IMAGEBASE. > > H.J., did you consider moving all of this, including the code you > added in git commit 36068e2fa54, to the relevant howto special > functions? None of it really belongs in bfd_perform_relocation. The howto special function, coff_amd64_reloc, isn't changed since 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. 2. bfd_perform_relocation changes are safe since they are limited to generating x86-64 ELF executable from Windows x86-64 relocatable object files. > You might even be able to do without a link_info parameter, instead > passing the image base value in output_elf_obj_tdata. I added "struct bfd_link_info *link_info;" to output_elf_obj_tdata. Here is the updated patch. OK for master? Thanks. -- H.J. [-- Attachment #2: v3-0001-elf-x86-64-Subtract-__ImageBase-for-R_AMD64_IMAGE.patch --] [-- Type: text/x-patch, Size: 20346 bytes --] From 6b5ae13f2f8b5c19617f2352f71425a9772c547b Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 15 Feb 2021 18:53:18 -0800 Subject: [PATCH v3] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE When linking Windows x86-64 relocatable object files to generate x86-64 ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation. 1. Add link_info to struct output_elf_obj_tdata to store optional linker information and _bfd_get_link_info() to retrieve it. 2. Set link_info up in _bfd_elf_linker_x86_set_options. 3. Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable object files. 4. Subtract __ImageBase for R_AMD64_IMAGEBASE in R_AMD64_IMAGEBASE. The howto special function, coff_amd64_reloc, isn't changed since 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. 2. bfd_perform_relocation changes are safe since they are limited to generating x86-64 ELF executable from Windows x86-64 relocatable object files. bfd/ PR ld/27425 PR ld/27432 * bfd.c (_bfd_get_link_info): New function. * elf-bfd.h (output_elf_obj_tdata): Add link_info. (elf_link_info): New. * elfxx-x86.c (_bfd_elf_linker_x86_set_options): Set up link_info. * libbfd-in.h (_bfd_get_link_info): New prototype. * reloc.c (bfd_perform_relocation): Subtract __ImageBase for R_AMD64_IMAGEBASE. * libbfd.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_load_symbols): Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable inputs. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd.c | 11 +++ bfd/elf-bfd.h | 4 + bfd/elfxx-x86.c | 2 + bfd/libbfd-in.h | 2 + bfd/libbfd.h | 2 + bfd/reloc.c | 50 ++++++++--- ld/ldelf.c | 24 ++++++ ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 16 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd.c b/bfd/bfd.c index f1944338838..2cf7b47bca1 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2808,3 +2808,14 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, *ptr_size = size; return TRUE; } + +/* Get the optional linker information. */ + +struct bfd_link_info * +_bfd_get_link_info (bfd *abfd) +{ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return NULL; + + return elf_link_info (abfd); +} diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dd66d98883e..c2aaab0e5bf 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata /* Used when laying out sections. */ file_ptr next_file_pos; + /* Optional linker information. */ + struct bfd_link_info *link_info; + int num_section_syms; unsigned int shstrtab_section, strtab_section; @@ -2064,6 +2067,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 93ad38c5eb0..e60d87ff981 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -3174,6 +3174,8 @@ _bfd_elf_linker_x86_set_options (struct bfd_link_info * info, = get_elf_backend_data (info->output_bfd); struct elf_x86_link_hash_table *htab = elf_x86_hash_table (info, bed->target_id); + if (info->output_bfd->xvec->flavour == bfd_target_elf_flavour) + elf_link_info (info->output_bfd) = info; if (htab != NULL) htab->params = params; } diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 2dc20ec1b19..62b1cee0af0 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 7271a2ad5a1..3a481ea468f 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/reloc.c b/bfd/reloc.c index 4f4b95a0b7f..c893fbc2489 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -913,20 +913,44 @@ space consuming. For each target: "elf64-x86-64") == 0) { /* NB: bfd_perform_relocation isn't called to generate PE binary. - _bfd_relocate_contents is called instead. When linking PE - object files to generate ELF output, _bfd_relocate_contents - isn't called and bfd_perform_relocation is used. We need to - adjust relocation here. */ - relocation -= reloc_entry->addend; - if (howto->type >= R_AMD64_PCRLONG_1 - && howto->type <= R_AMD64_PCRLONG_5) - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); - else if (howto->type == R_AMD64_DIR64 - || howto->type == R_AMD64_DIR32) + _bfd_relocate_contents is called instead. When linking Windows + x86-64 relocatable object files to generate ELF output, + _bfd_relocate_contents isn't called and bfd_perform_relocation + is used. We need to adjust relocation here. */ + if (howto->type == R_AMD64_IMAGEBASE) { - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, - howto); - relocation -= val & howto->src_mask; + /* Subtract __ImageBase. */ + struct bfd_link_info *link_info; + struct bfd_link_hash_entry *h; + link_info + = _bfd_get_link_info (input_section->output_section->owner); + if (link_info == NULL) + abort (); + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + abort (); + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + relocation -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + } + else + { + relocation -= reloc_entry->addend; + if (howto->type >= R_AMD64_PCRLONG_1 + && howto->type <= R_AMD64_PCRLONG_5) + relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); + else if (howto->type == R_AMD64_DIR64 + || howto->type == R_AMD64_DIR32) + { + bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, + howto); + relocation -= val & howto->src_mask; + } } } diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..c7de958dbdc 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) { int link_class = 0; + if (bfd_link_pde (&link_info) + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) + { + /* NB: When linking Windows x86-64 relocatable object files to + generate ELF executable, create an indirect reference to + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE + relocation which is relative to __ImageBase. */ + struct elf_link_hash_table *htab = elf_hash_table (&link_info); + struct elf_link_hash_entry *h, *hi; + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->root.type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = elf_link_hash_lookup (htab, "__executable_start", + TRUE, FALSE, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + } + } + /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-02-28 2:38 ` [PATCH v3] " H.J. Lu @ 2021-03-01 12:19 ` Alan Modra 2021-03-01 13:44 ` H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-03-01 12:19 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Sat, Feb 27, 2021 at 06:38:24PM -0800, H.J. Lu wrote: > On Wed, Feb 24, 2021 at 6:09 PM Alan Modra <amodra@gmail.com> wrote: > > > > On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > > > * reloc.c (bfd_perform_relocation): Add a link_info argument. > > > Subtract __ImageBase for R_AMD64_IMAGEBASE. > > > > H.J., did you consider moving all of this, including the code you > > added in git commit 36068e2fa54, to the relevant howto special > > functions? None of it really belongs in bfd_perform_relocation. > > The howto special function, coff_amd64_reloc, isn't changed since > > 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. I am sure you are capable of making those changes without breaking windows. > 2. bfd_perform_relocation changes are safe since they are limited to > generating x86-64 ELF executable from Windows x86-64 relocatable object > files. It is the wrong place. Every time bfd_perform_relocation is called with a coff input it now needs to test for output to ELF. If you did this properly in a howto function then the extra tests would only be done for x86_64 coff. Besides the performance impact, nobody maintaining reloc.c wants to deal with code specially for pe-x86-64 and elf64-x84-64. The special case for coff there is already horrible. It shouldn't be made worse. Did anyone review your commit 36068e2fa54? -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-01 12:19 ` Alan Modra @ 2021-03-01 13:44 ` H.J. Lu 2021-03-04 13:14 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-03-01 13:44 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils On Mon, Mar 1, 2021 at 4:19 AM Alan Modra <amodra@gmail.com> wrote: > > On Sat, Feb 27, 2021 at 06:38:24PM -0800, H.J. Lu wrote: > > On Wed, Feb 24, 2021 at 6:09 PM Alan Modra <amodra@gmail.com> wrote: > > > > > > On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > > > > * reloc.c (bfd_perform_relocation): Add a link_info argument. > > > > Subtract __ImageBase for R_AMD64_IMAGEBASE. > > > > > > H.J., did you consider moving all of this, including the code you > > > added in git commit 36068e2fa54, to the relevant howto special > > > functions? None of it really belongs in bfd_perform_relocation. > > > > The howto special function, coff_amd64_reloc, isn't changed since > > > > 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. > > I am sure you are capable of making those changes without breaking > windows. The difficult part is I can't test it. > > 2. bfd_perform_relocation changes are safe since they are limited to > > generating x86-64 ELF executable from Windows x86-64 relocatable object > > files. > > It is the wrong place. Every time bfd_perform_relocation is called > with a coff input it now needs to test for output to ELF. If you did > this properly in a howto function then the extra tests would only be bfd_perform_relocation is called with r = bfd_perform_relocation (input_bfd, *parent, data, input_section, relocatable ? abfd : NULL, <<< output_bfd &error_message); and coff_amd64_reloc is very hard to understand. > done for x86_64 coff. Besides the performance impact, nobody > maintaining reloc.c wants to deal with code specially for pe-x86-64 > and elf64-x84-64. The special case for coff there is already > horrible. It shouldn't be made worse. I made the change in bfd_perform_relocation since the COFF linker is very delicate. > Did anyone review your commit 36068e2fa54? No. My change is limited to a very special case of ELF/x86-64. bfd_perform_relocation has /* WTF?? */ if (abfd->xvec->flavour == bfd_target_coff_flavour && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) { with a long comment. I added: else if (abfd->xvec->flavour == bfd_target_coff_flavour && (input_section->output_section->owner->xvec->flavour == bfd_target_elf_flavour) && strcmp (abfd->xvec->name, "pe-x86-64") == 0 && strcmp (input_section->output_section->owner->xvec->name, "elf64-x86-64") == 0) Its performance impact should be low. -- H.J. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-01 13:44 ` H.J. Lu @ 2021-03-04 13:14 ` Alan Modra 2021-03-04 13:54 ` [PATCH v4] " H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-03-04 13:14 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Mon, Mar 01, 2021 at 05:44:48AM -0800, H.J. Lu wrote: > On Mon, Mar 1, 2021 at 4:19 AM Alan Modra <amodra@gmail.com> wrote: > > > > On Sat, Feb 27, 2021 at 06:38:24PM -0800, H.J. Lu wrote: > > > On Wed, Feb 24, 2021 at 6:09 PM Alan Modra <amodra@gmail.com> wrote: > > > > > > > > On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > > > > > * reloc.c (bfd_perform_relocation): Add a link_info argument. > > > > > Subtract __ImageBase for R_AMD64_IMAGEBASE. > > > > > > > > H.J., did you consider moving all of this, including the code you > > > > added in git commit 36068e2fa54, to the relevant howto special > > > > functions? None of it really belongs in bfd_perform_relocation. > > > > > > The howto special function, coff_amd64_reloc, isn't changed since > > > > > > 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. > > > > I am sure you are capable of making those changes without breaking > > windows. > > The difficult part is I can't test it. Which says that you also can't test your bfd_perform_relocation changes on windows. > > > 2. bfd_perform_relocation changes are safe since they are limited to > > > generating x86-64 ELF executable from Windows x86-64 relocatable object > > > files. > > > > It is the wrong place. Every time bfd_perform_relocation is called > > with a coff input it now needs to test for output to ELF. If you did > > this properly in a howto function then the extra tests would only be > > bfd_perform_relocation is called with > > r = bfd_perform_relocation (input_bfd, > *parent, > data, > input_section, > relocatable ? abfd : NULL, > <<< output_bfd > &error_message); > > and coff_amd64_reloc is very hard to understand. Yes, it surely is. You do realize that coff_amd64_reloc has already made changes to the section contents before you again make changes in bfd_perform_relocation. Arguing that it is easier to support ELF output in bfd_perform_relocation doesn't make much sense. To do it correctly there you need to understand coff_amd64_reloc anyway. Are your bfd_perform_relocation changes correct for every x86_64 PE reloc, and for weak and common symbols? > > > done for x86_64 coff. Besides the performance impact, nobody > > maintaining reloc.c wants to deal with code specially for pe-x86-64 > > and elf64-x84-64. The special case for coff there is already > > horrible. It shouldn't be made worse. > > I made the change in bfd_perform_relocation since the COFF > linker is very delicate. > > > Did anyone review your commit 36068e2fa54? > > No. My change is limited to a very special case of ELF/x86-64. > > bfd_perform_relocation has > > /* WTF?? */ > if (abfd->xvec->flavour == bfd_target_coff_flavour > && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 > && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) > { > > with a long comment. I added: Right, and the "WTF??" is exclaiming that this sort of thing should not be done in bfd_perform_relocation. The long comment is trying to explain why it is there anyway, and reinforcing what I'm saying says this: "The first obvious point is that bfd_perform_relocation should not have any tests that depend upon the flavour." I'm going to revert your bfd_perform_relocation changes, and possibly apply a much simpler coff_amd64_reloc change that happens to make things work for the testcases you added. I have no confidence that the coff_amd64_reloc patch is correct in all cases, but it looks more reasonable to me. I'd appreciate you checking it. * reloc.c (bfd_perform_relocation): Revert 2021-01-12 and 2020-09-16 changes. * coff-x86_64.c (coff_amd64_reloc): Do more or less the same adjustments here instead. Tidy comments and formatting. diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index adab60cd11..63a7f06f9b 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -75,14 +75,14 @@ coff_amd64_reloc (bfd *abfd, { symvalue diff; -#if !defined(COFF_WITH_PE) +#if !defined (COFF_WITH_PE) if (output_bfd == NULL) return bfd_reloc_continue; #endif if (bfd_is_com_section (symbol->section)) { -#if !defined(COFF_WITH_PE) +#if !defined (COFF_WITH_PE) /* We are relocating a common symbol. The current value in the object file is ORIG + OFFSET, where ORIG is the value of the common symbol as seen by the object file when it was compiled @@ -113,14 +113,14 @@ coff_amd64_reloc (bfd *abfd, /* Although PC relative relocations are very similar between PE and non-PE formats, but they are off by 1 << howto->size - bytes. For the external relocation, PE is very different - from others. See md_apply_fix3 () in gas/config/tc-amd64.c. + bytes. For the external relocation, PE is very different + from others. See md_apply_fix in gas/config/tc-i386.c. When we link PE and non-PE object files together to generate a non-PE executable, we have to compensate it here. */ - if(howto->pc_relative && howto->pcrel_offset) + if (howto->pc_relative && howto->pcrel_offset) diff = -(1 << howto->size); - else if(symbol->flags & BSF_WEAK) + else if (symbol->flags & BSF_WEAK) diff = reloc_entry->addend - symbol->value; else diff = -reloc_entry->addend; @@ -130,7 +130,20 @@ coff_amd64_reloc (bfd *abfd, diff = reloc_entry->addend; } -#if defined(COFF_WITH_PE) +#if defined (COFF_WITH_PE) + if (output_bfd == NULL + && (bfd_get_flavour (input_section->output_section->owner) + == bfd_target_elf_flavour)) + { + if (reloc_entry->howto->pc_relative) + { + diff -= reloc_entry->addend; + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) + diff -= (bfd_vma) (reloc_entry->howto->type - R_AMD64_PCRLONG); + } + } + /* FIXME: How should this case be handled? */ if (reloc_entry->howto->type == R_AMD64_IMAGEBASE && output_bfd != NULL diff --git a/bfd/reloc.c b/bfd/reloc.c index a7547187eb..5ed7bb8e59 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -51,7 +51,7 @@ SECTION #include "bfdlink.h" #include "libbfd.h" #include "bfdver.h" -#include "coff/x86_64.h" + /* DOCDD INODE @@ -905,30 +905,6 @@ space consuming. For each target: } } } - else if (abfd->xvec->flavour == bfd_target_coff_flavour - && (input_section->output_section->owner->xvec->flavour - == bfd_target_elf_flavour) - && strcmp (abfd->xvec->name, "pe-x86-64") == 0 - && strcmp (input_section->output_section->owner->xvec->name, - "elf64-x86-64") == 0) - { - /* NB: bfd_perform_relocation isn't called to generate PE binary. - _bfd_relocate_contents is called instead. When linking PE - object files to generate ELF output, _bfd_relocate_contents - isn't called and bfd_perform_relocation is used. We need to - adjust relocation here. */ - relocation -= reloc_entry->addend; - if (howto->type >= R_AMD64_PCRLONG_1 - && howto->type <= R_AMD64_PCRLONG_5) - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); - else if (howto->type == R_AMD64_DIR64 - || howto->type == R_AMD64_DIR32) - { - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, - howto); - relocation -= val & howto->src_mask; - } - } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v4] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-04 13:14 ` Alan Modra @ 2021-03-04 13:54 ` H.J. Lu 2021-03-05 5:17 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-03-04 13:54 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils On Thu, Mar 4, 2021 at 5:14 AM Alan Modra <amodra@gmail.com> wrote: > > On Mon, Mar 01, 2021 at 05:44:48AM -0800, H.J. Lu wrote: > > On Mon, Mar 1, 2021 at 4:19 AM Alan Modra <amodra@gmail.com> wrote: > > > > > > On Sat, Feb 27, 2021 at 06:38:24PM -0800, H.J. Lu wrote: > > > > On Wed, Feb 24, 2021 at 6:09 PM Alan Modra <amodra@gmail.com> wrote: > > > > > > > > > > On Tue, Feb 23, 2021 at 09:50:20AM -0800, H.J. Lu via Binutils wrote: > > > > > > * reloc.c (bfd_perform_relocation): Add a link_info argument. > > > > > > Subtract __ImageBase for R_AMD64_IMAGEBASE. > > > > > > > > > > H.J., did you consider moving all of this, including the code you > > > > > added in git commit 36068e2fa54, to the relevant howto special > > > > > functions? None of it really belongs in bfd_perform_relocation. > > > > > > > > The howto special function, coff_amd64_reloc, isn't changed since > > > > > > > > 1. Any changes to coff_amd64_reloc may break Windows x86-64 linker. > > > > > > I am sure you are capable of making those changes without breaking > > > windows. > > > > The difficult part is I can't test it. > > Which says that you also can't test your bfd_perform_relocation > changes on windows. > > > > > 2. bfd_perform_relocation changes are safe since they are limited to > > > > generating x86-64 ELF executable from Windows x86-64 relocatable object > > > > files. > > > > > > It is the wrong place. Every time bfd_perform_relocation is called > > > with a coff input it now needs to test for output to ELF. If you did > > > this properly in a howto function then the extra tests would only be > > > > bfd_perform_relocation is called with > > > > r = bfd_perform_relocation (input_bfd, > > *parent, > > data, > > input_section, > > relocatable ? abfd : NULL, > > <<< output_bfd > > &error_message); > > > > and coff_amd64_reloc is very hard to understand. > > Yes, it surely is. You do realize that coff_amd64_reloc has already > made changes to the section contents before you again make changes in > bfd_perform_relocation. Arguing that it is easier to support ELF > output in bfd_perform_relocation doesn't make much sense. To do it > correctly there you need to understand coff_amd64_reloc anyway. > > Are your bfd_perform_relocation changes correct for every x86_64 PE > reloc, and for weak and common symbols? > > > > > > done for x86_64 coff. Besides the performance impact, nobody > > > maintaining reloc.c wants to deal with code specially for pe-x86-64 > > > and elf64-x84-64. The special case for coff there is already > > > horrible. It shouldn't be made worse. > > > > I made the change in bfd_perform_relocation since the COFF > > linker is very delicate. > > > > > Did anyone review your commit 36068e2fa54? > > > > No. My change is limited to a very special case of ELF/x86-64. > > > > bfd_perform_relocation has > > > > /* WTF?? */ > > if (abfd->xvec->flavour == bfd_target_coff_flavour > > && strcmp (abfd->xvec->name, "coff-Intel-little") != 0 > > && strcmp (abfd->xvec->name, "coff-Intel-big") != 0) > > { > > > > with a long comment. I added: > > Right, and the "WTF??" is exclaiming that this sort of thing should > not be done in bfd_perform_relocation. The long comment is trying to > explain why it is there anyway, and reinforcing what I'm saying says > this: "The first obvious point is that bfd_perform_relocation should > not have any tests that depend upon the flavour." > > I'm going to revert your bfd_perform_relocation changes, and possibly > apply a much simpler coff_amd64_reloc change that happens to make > things work for the testcases you added. I have no confidence that > the coff_amd64_reloc patch is correct in all cases, but it looks more > reasonable to me. I'd appreciate you checking it. > > * reloc.c (bfd_perform_relocation): Revert 2021-01-12 and > 2020-09-16 changes. > * coff-x86_64.c (coff_amd64_reloc): Do more or less the same > adjustments here instead. Tidy comments and formatting. > Here is the v4 patch on top of yours. Thanks. -- H.J. ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-04 13:54 ` [PATCH v4] " H.J. Lu @ 2021-03-05 5:17 ` Alan Modra 2021-03-05 5:29 ` H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-03-05 5:17 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Thu, Mar 04, 2021 at 05:54:20AM -0800, H.J. Lu wrote: > Here is the v4 patch on top of yours. No patch? This is what I'm about to commit, now rather than in a week's time since you seem happy with it. Changes from the previous patch are: - removed test of ELF output, the fixes are generic - untangled and corrected pc-relative adjustment to use bfd_get_reloc_size There are some further obvious fixes to make as noted in the commit log, but I'll leave that to someone with better access to PE compilers. ---- Subject: Move x86_64 PE changes out of bfd_perform_relocation bfd_perform_relocation should not have special case target code. This patch moves the code that was there for x86_64 PE linking to ELF output into the x86_64 PE howto special function, correcting that function for linking to targets other than ELF too. The fixes in bfd_perform_relocation were over-complicated due to needing to compensate for things that had already gone wrong in coff_amd64_reloc. In particular, an adjustment for pc-relative relocs was done in a way that meant adjustment for things related to symbol offsets was lost. I think those two things are orthogonal, but who knows with COFF where addends and symbol values are found randomly in the section contents. Note that linking natively to an x86_64 PE output relocates by coff_pe_amd64_relocate_section, which does not use arelent relocs or bfd_perform_relocation, but be aware of coff_amd64_rtype_to_howto hacking addends for relocations. The adjustments for a particular relocation type there and in coff_amd64_reloc ought to match after taking into consideration CALC_ADDEND. They don't. For example, the pc-relative adjustment for R_PCRWORD is 2 bytes in coff_amd64_reloc and 4 bytes in coff_amd64_rtype_to_howto. * reloc.c (bfd_perform_relocation): Revert 2021-01-12 and 2020-09-16 changes. * coff-x86_64.c (coff_amd64_reloc): Do more or less the same adjustments here instead. Separate pc-relative adjustments from symbol related adjustments. Tidy comments and formatting. diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index adab60cd11..5b09023f3c 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -75,14 +75,14 @@ coff_amd64_reloc (bfd *abfd, { symvalue diff; -#if !defined(COFF_WITH_PE) +#if !defined (COFF_WITH_PE) if (output_bfd == NULL) return bfd_reloc_continue; #endif if (bfd_is_com_section (symbol->section)) { -#if !defined(COFF_WITH_PE) +#if !defined (COFF_WITH_PE) /* We are relocating a common symbol. The current value in the object file is ORIG + OFFSET, where ORIG is the value of the common symbol as seen by the object file when it was compiled @@ -106,21 +106,10 @@ coff_amd64_reloc (bfd *abfd, ignores the addend for a COFF target when producing relocatable output. This seems to be always wrong for 386 COFF, so we handle the addend here instead. */ -#if defined(COFF_WITH_PE) +#if defined (COFF_WITH_PE) if (output_bfd == NULL) { - reloc_howto_type *howto = reloc_entry->howto; - - /* Although PC relative relocations are very similar between - PE and non-PE formats, but they are off by 1 << howto->size - bytes. For the external relocation, PE is very different - from others. See md_apply_fix3 () in gas/config/tc-amd64.c. - When we link PE and non-PE object files together to - generate a non-PE executable, we have to compensate it - here. */ - if(howto->pc_relative && howto->pcrel_offset) - diff = -(1 << howto->size); - else if(symbol->flags & BSF_WEAK) + if (symbol->flags & BSF_WEAK) diff = reloc_entry->addend - symbol->value; else diff = -reloc_entry->addend; @@ -130,7 +119,18 @@ coff_amd64_reloc (bfd *abfd, diff = reloc_entry->addend; } -#if defined(COFF_WITH_PE) +#if defined (COFF_WITH_PE) + if (output_bfd == NULL) + { + /* PC relative relocations are off by their size. */ + if (reloc_entry->howto->pc_relative) + diff -= bfd_get_reloc_size (reloc_entry->howto); + + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) + diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; + } + /* FIXME: How should this case be handled? */ if (reloc_entry->howto->type == R_AMD64_IMAGEBASE && output_bfd != NULL diff --git a/bfd/reloc.c b/bfd/reloc.c index a7547187eb..5ed7bb8e59 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -51,7 +51,7 @@ SECTION #include "bfdlink.h" #include "libbfd.h" #include "bfdver.h" -#include "coff/x86_64.h" + /* DOCDD INODE @@ -905,30 +905,6 @@ space consuming. For each target: } } } - else if (abfd->xvec->flavour == bfd_target_coff_flavour - && (input_section->output_section->owner->xvec->flavour - == bfd_target_elf_flavour) - && strcmp (abfd->xvec->name, "pe-x86-64") == 0 - && strcmp (input_section->output_section->owner->xvec->name, - "elf64-x86-64") == 0) - { - /* NB: bfd_perform_relocation isn't called to generate PE binary. - _bfd_relocate_contents is called instead. When linking PE - object files to generate ELF output, _bfd_relocate_contents - isn't called and bfd_perform_relocation is used. We need to - adjust relocation here. */ - relocation -= reloc_entry->addend; - if (howto->type >= R_AMD64_PCRLONG_1 - && howto->type <= R_AMD64_PCRLONG_5) - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); - else if (howto->type == R_AMD64_DIR64 - || howto->type == R_AMD64_DIR32) - { - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, - howto); - relocation -= val & howto->src_mask; - } - } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-05 5:17 ` Alan Modra @ 2021-03-05 5:29 ` H.J. Lu 2021-03-05 13:57 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-03-05 5:29 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils [-- Attachment #1: Type: text/plain, Size: 6573 bytes --] On Thu, Mar 4, 2021 at 9:17 PM Alan Modra <amodra@gmail.com> wrote: > > On Thu, Mar 04, 2021 at 05:54:20AM -0800, H.J. Lu wrote: > > Here is the v4 patch on top of yours. > > No patch? > > This is what I'm about to commit, now rather than in a week's time > since you seem happy with it. Changes from the previous patch are: > - removed test of ELF output, the fixes are generic > - untangled and corrected pc-relative adjustment to use > bfd_get_reloc_size > > There are some further obvious fixes to make as noted in the commit > log, but I'll leave that to someone with better access to PE > compilers. > > ---- > Subject: Move x86_64 PE changes out of bfd_perform_relocation > > bfd_perform_relocation should not have special case target code. This > patch moves the code that was there for x86_64 PE linking to ELF > output into the x86_64 PE howto special function, correcting that > function for linking to targets other than ELF too. The fixes in > bfd_perform_relocation were over-complicated due to needing to > compensate for things that had already gone wrong in coff_amd64_reloc. > In particular, an adjustment for pc-relative relocs was done in a way > that meant adjustment for things related to symbol offsets was lost. > I think those two things are orthogonal, but who knows with COFF where > addends and symbol values are found randomly in the section contents. > > Note that linking natively to an x86_64 PE output relocates by > coff_pe_amd64_relocate_section, which does not use arelent relocs or > bfd_perform_relocation, but be aware of coff_amd64_rtype_to_howto > hacking addends for relocations. The adjustments for a particular > relocation type there and in coff_amd64_reloc ought to match after > taking into consideration CALC_ADDEND. They don't. For example, > the pc-relative adjustment for R_PCRWORD is 2 bytes in > coff_amd64_reloc and 4 bytes in coff_amd64_rtype_to_howto. > > * reloc.c (bfd_perform_relocation): Revert 2021-01-12 and > 2020-09-16 changes. > * coff-x86_64.c (coff_amd64_reloc): Do more or less the same > adjustments here instead. Separate pc-relative adjustments > from symbol related adjustments. Tidy comments and formatting. > > diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c > index adab60cd11..5b09023f3c 100644 > --- a/bfd/coff-x86_64.c > +++ b/bfd/coff-x86_64.c > @@ -75,14 +75,14 @@ coff_amd64_reloc (bfd *abfd, > { > symvalue diff; > > -#if !defined(COFF_WITH_PE) > +#if !defined (COFF_WITH_PE) > if (output_bfd == NULL) > return bfd_reloc_continue; > #endif > > if (bfd_is_com_section (symbol->section)) > { > -#if !defined(COFF_WITH_PE) > +#if !defined (COFF_WITH_PE) > /* We are relocating a common symbol. The current value in the > object file is ORIG + OFFSET, where ORIG is the value of the > common symbol as seen by the object file when it was compiled > @@ -106,21 +106,10 @@ coff_amd64_reloc (bfd *abfd, > ignores the addend for a COFF target when producing > relocatable output. This seems to be always wrong for 386 > COFF, so we handle the addend here instead. */ > -#if defined(COFF_WITH_PE) > +#if defined (COFF_WITH_PE) > if (output_bfd == NULL) > { > - reloc_howto_type *howto = reloc_entry->howto; > - > - /* Although PC relative relocations are very similar between > - PE and non-PE formats, but they are off by 1 << howto->size > - bytes. For the external relocation, PE is very different > - from others. See md_apply_fix3 () in gas/config/tc-amd64.c. > - When we link PE and non-PE object files together to > - generate a non-PE executable, we have to compensate it > - here. */ > - if(howto->pc_relative && howto->pcrel_offset) > - diff = -(1 << howto->size); > - else if(symbol->flags & BSF_WEAK) > + if (symbol->flags & BSF_WEAK) > diff = reloc_entry->addend - symbol->value; > else > diff = -reloc_entry->addend; > @@ -130,7 +119,18 @@ coff_amd64_reloc (bfd *abfd, > diff = reloc_entry->addend; > } > > -#if defined(COFF_WITH_PE) > +#if defined (COFF_WITH_PE) > + if (output_bfd == NULL) > + { > + /* PC relative relocations are off by their size. */ > + if (reloc_entry->howto->pc_relative) > + diff -= bfd_get_reloc_size (reloc_entry->howto); > + > + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 > + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) > + diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; > + } > + > /* FIXME: How should this case be handled? */ > if (reloc_entry->howto->type == R_AMD64_IMAGEBASE > && output_bfd != NULL > diff --git a/bfd/reloc.c b/bfd/reloc.c > index a7547187eb..5ed7bb8e59 100644 > --- a/bfd/reloc.c > +++ b/bfd/reloc.c > @@ -51,7 +51,7 @@ SECTION > #include "bfdlink.h" > #include "libbfd.h" > #include "bfdver.h" > -#include "coff/x86_64.h" > + > /* > DOCDD > INODE > @@ -905,30 +905,6 @@ space consuming. For each target: > } > } > } > - else if (abfd->xvec->flavour == bfd_target_coff_flavour > - && (input_section->output_section->owner->xvec->flavour > - == bfd_target_elf_flavour) > - && strcmp (abfd->xvec->name, "pe-x86-64") == 0 > - && strcmp (input_section->output_section->owner->xvec->name, > - "elf64-x86-64") == 0) > - { > - /* NB: bfd_perform_relocation isn't called to generate PE binary. > - _bfd_relocate_contents is called instead. When linking PE > - object files to generate ELF output, _bfd_relocate_contents > - isn't called and bfd_perform_relocation is used. We need to > - adjust relocation here. */ > - relocation -= reloc_entry->addend; > - if (howto->type >= R_AMD64_PCRLONG_1 > - && howto->type <= R_AMD64_PCRLONG_5) > - relocation -= (bfd_vma)(howto->type - R_AMD64_PCRLONG); > - else if (howto->type == R_AMD64_DIR64 > - || howto->type == R_AMD64_DIR32) > - { > - bfd_vma val = read_reloc (abfd, (bfd_byte *) data + octets, > - howto); > - relocation -= val & howto->src_mask; > - } > - } > > /* FIXME: This overflow checking is incomplete, because the value > might have overflowed before we get here. For a correct check we > Here is the v4 patch. OK for master? Thanks. -- H.J. [-- Attachment #2: v4-0001-elf-x86-64-Subtract-__ImageBase-for-R_AMD64_IMAGE.patch --] [-- Type: text/x-patch, Size: 19560 bytes --] From 5d2172fe937794079721186041538d3bdb0e3ac2 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 15 Feb 2021 18:53:18 -0800 Subject: [PATCH v4] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE When linking Windows x86-64 relocatable object files to generate x86-64 ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation. 1. Add link_info to struct output_elf_obj_tdata to store optional linker information and _bfd_get_link_info() to retrieve it. 2. Set link_info up in _bfd_elf_linker_x86_set_options. 3. Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable object files. 4. Subtract __ImageBase for R_AMD64_IMAGEBASE in R_AMD64_IMAGEBASE. bfd/ PR ld/27425 PR ld/27432 * bfd.c (_bfd_get_link_info): New function. * elf-bfd.h (output_elf_obj_tdata): Add link_info. (elf_link_info): New. * elfxx-x86.c (_bfd_elf_linker_x86_set_options): Set up link_info. * libbfd-in.h (_bfd_get_link_info): New prototype. * coff-x86_64.c (coff_amd64_reloc): Subtract __ImageBase for R_AMD64_IMAGEBASE. * libbfd.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_load_symbols): Create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when seeing Windows x86-64 relocatable inputs. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd.c | 11 +++ bfd/coff-x86_64.c | 38 +++++++-- bfd/elf-bfd.h | 4 + bfd/elfxx-x86.c | 2 + bfd/libbfd-in.h | 2 + bfd/libbfd.h | 2 + ld/ldelf.c | 24 ++++++ ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 16 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd.c b/bfd/bfd.c index f1944338838..2cf7b47bca1 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2808,3 +2808,14 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, *ptr_size = size; return TRUE; } + +/* Get the optional linker information. */ + +struct bfd_link_info * +_bfd_get_link_info (bfd *abfd) +{ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return NULL; + + return elf_link_info (abfd); +} diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index 5b09023f3c2..be20da165d9 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -122,13 +122,39 @@ coff_amd64_reloc (bfd *abfd, #if defined (COFF_WITH_PE) if (output_bfd == NULL) { - /* PC relative relocations are off by their size. */ - if (reloc_entry->howto->pc_relative) - diff -= bfd_get_reloc_size (reloc_entry->howto); + if ((bfd_get_flavour (input_section->output_section->owner) + == bfd_target_elf_flavour) + && reloc_entry->howto->type == R_AMD64_IMAGEBASE) + { + /* Subtract __ImageBase. */ + struct bfd_link_info *link_info; + struct bfd_link_hash_entry *h; + link_info + = _bfd_get_link_info (input_section->output_section->owner); + if (link_info == NULL) + abort (); + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + abort (); + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + diff -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + } + else + { + /* PC relative relocations are off by their size. */ + if (reloc_entry->howto->pc_relative) + diff -= bfd_get_reloc_size (reloc_entry->howto); - if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 - && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) - diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) + diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; + } } /* FIXME: How should this case be handled? */ diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index dd66d98883e..c2aaab0e5bf 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata /* Used when laying out sections. */ file_ptr next_file_pos; + /* Optional linker information. */ + struct bfd_link_info *link_info; + int num_section_syms; unsigned int shstrtab_section, strtab_section; @@ -2064,6 +2067,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 93ad38c5eb0..e60d87ff981 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -3174,6 +3174,8 @@ _bfd_elf_linker_x86_set_options (struct bfd_link_info * info, = get_elf_backend_data (info->output_bfd); struct elf_x86_link_hash_table *htab = elf_x86_hash_table (info, bed->target_id); + if (info->output_bfd->xvec->flavour == bfd_target_elf_flavour) + elf_link_info (info->output_bfd) = info; if (htab != NULL) htab->params = params; } diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 2dc20ec1b19..62b1cee0af0 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 7271a2ad5a1..3a481ea468f 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..c7de958dbdc 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) { int link_class = 0; + if (bfd_link_pde (&link_info) + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) + { + /* NB: When linking Windows x86-64 relocatable object files to + generate ELF executable, create an indirect reference to + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE + relocation which is relative to __ImageBase. */ + struct elf_link_hash_table *htab = elf_hash_table (&link_info); + struct elf_link_hash_entry *h, *hi; + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->root.type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = elf_link_hash_lookup (htab, "__executable_start", + TRUE, FALSE, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + } + } + /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v4] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-05 5:29 ` H.J. Lu @ 2021-03-05 13:57 ` Alan Modra 2021-03-05 18:26 ` [PATCH v5] " H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-03-05 13:57 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Thu, Mar 04, 2021 at 09:29:48PM -0800, H.J. Lu wrote: > --- a/bfd/coff-x86_64.c > +++ b/bfd/coff-x86_64.c > @@ -122,13 +122,39 @@ coff_amd64_reloc (bfd *abfd, > #if defined (COFF_WITH_PE) > if (output_bfd == NULL) > { > - /* PC relative relocations are off by their size. */ > - if (reloc_entry->howto->pc_relative) > - diff -= bfd_get_reloc_size (reloc_entry->howto); > + if ((bfd_get_flavour (input_section->output_section->owner) > + == bfd_target_elf_flavour) > + && reloc_entry->howto->type == R_AMD64_IMAGEBASE) > + { > + /* Subtract __ImageBase. */ > + struct bfd_link_info *link_info; > + struct bfd_link_hash_entry *h; > + link_info > + = _bfd_get_link_info (input_section->output_section->owner); > + if (link_info == NULL) > + abort (); > + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", > + FALSE, FALSE, FALSE); > + if (h == NULL) > + abort (); > + while (h->type == bfd_link_hash_indirect) > + h = h->u.i.link; > + /* ELF symbols in relocatable files are section relative, > + but in nonrelocatable files they are virtual addresses. */ > + diff -= (h->u.def.value > + + h->u.def.section->output_offset > + + h->u.def.section->output_section->vma); > + } > + else > + { > + /* PC relative relocations are off by their size. */ > + if (reloc_entry->howto->pc_relative) > + diff -= bfd_get_reloc_size (reloc_entry->howto); > > - if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 > - && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) > - diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; > + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 > + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) > + diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; > + } > } I think this would be better style if the pc_relative and PCRLONG adjustments were left as they were, and then write if (reloc_entry->howto->type == R_AMD64_IMAGEBASE) { bfd *obfd = input_section->output_section->owner; switch (bfd_get_flavour (obfd)) { case bfd_target_coff_flavour: diff -= pe_data (obfd)->pe_opthdr.ImageBase; break; case bfd_target_elf_flavour: { your new code } break; } } That should get rid of the FIXME. > > /* FIXME: How should this case be handled? */ > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > index dd66d98883e..c2aaab0e5bf 100644 > --- a/bfd/elf-bfd.h > +++ b/bfd/elf-bfd.h > @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata > /* Used when laying out sections. */ > file_ptr next_file_pos; > > + /* Optional linker information. */ > + struct bfd_link_info *link_info; > + That's a nice trick that might be handy elsewhere, if you always set it rather than making it optional. > int num_section_syms; > unsigned int shstrtab_section, strtab_section; > > @@ -2064,6 +2067,7 @@ struct elf_obj_tdata > #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) > #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) > #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) > +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) > #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) > #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) > #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) > diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c > index 93ad38c5eb0..e60d87ff981 100644 > --- a/bfd/elfxx-x86.c > +++ b/bfd/elfxx-x86.c > @@ -3174,6 +3174,8 @@ _bfd_elf_linker_x86_set_options (struct bfd_link_info * info, > = get_elf_backend_data (info->output_bfd); > struct elf_x86_link_hash_table *htab > = elf_x86_hash_table (info, bed->target_id); > + if (info->output_bfd->xvec->flavour == bfd_target_elf_flavour) > + elf_link_info (info->output_bfd) = info; Move this to somewhere all ELF targets will have elf_link_info, a new ldelf.c:elf_set_output_arch perhaps? > if (htab != NULL) > htab->params = params; > } > diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h > index 2dc20ec1b19..62b1cee0af0 100644 > --- a/bfd/libbfd-in.h > +++ b/bfd/libbfd-in.h > @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 > extern bfd_byte * _bfd_write_unsigned_leb128 > (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; > > +extern struct bfd_link_info *_bfd_get_link_info (bfd *); > + > #if GCC_VERSION >= 7000 > #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) > #else > diff --git a/bfd/libbfd.h b/bfd/libbfd.h > index 7271a2ad5a1..3a481ea468f 100644 > --- a/bfd/libbfd.h > +++ b/bfd/libbfd.h > @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 > extern bfd_byte * _bfd_write_unsigned_leb128 > (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; > > +extern struct bfd_link_info *_bfd_get_link_info (bfd *); > + > #if GCC_VERSION >= 7000 > #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) > #else > diff --git a/ld/ldelf.c b/ld/ldelf.c > index 049992544a2..c7de958dbdc 100644 > --- a/ld/ldelf.c > +++ b/ld/ldelf.c > @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) > { > int link_class = 0; > > + if (bfd_link_pde (&link_info) > + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour > + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 > + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) > + { > + /* NB: When linking Windows x86-64 relocatable object files to > + generate ELF executable, create an indirect reference to > + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE > + relocation which is relative to __ImageBase. */ > + struct elf_link_hash_table *htab = elf_hash_table (&link_info); > + struct elf_link_hash_entry *h, *hi; > + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, > + FALSE); > + if (hi->root.type == bfd_link_hash_new > + || hi->type == bfd_link_hash_undefined > + || hi->type == bfd_link_hash_undefweak) > + { > + h = elf_link_hash_lookup (htab, "__executable_start", > + TRUE, FALSE, TRUE); > + hi->root.type = bfd_link_hash_indirect; > + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; > + } > + } > + > /* Tell the ELF linker that we don't want the output file to have a > DT_NEEDED entry for this file, unless it is used to resolve > references in a regular object. */ This doesn't look like the right place to set up a reference to __executable_start. Doing so in a new check_relocs in pei-x86_64.c that tests for an ELF output would be better. I'm not suggesting that you run over relocs looking for R_AMD64_IMAGEBASE, that could be done but seems unnecessary. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v5] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-05 13:57 ` Alan Modra @ 2021-03-05 18:26 ` H.J. Lu 2021-03-06 0:11 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-03-05 18:26 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils [-- Attachment #1: Type: text/plain, Size: 7820 bytes --] On Fri, Mar 5, 2021 at 5:57 AM Alan Modra <amodra@gmail.com> wrote: > > On Thu, Mar 04, 2021 at 09:29:48PM -0800, H.J. Lu wrote: > > --- a/bfd/coff-x86_64.c > > +++ b/bfd/coff-x86_64.c > > @@ -122,13 +122,39 @@ coff_amd64_reloc (bfd *abfd, > > #if defined (COFF_WITH_PE) > > if (output_bfd == NULL) > > { > > - /* PC relative relocations are off by their size. */ > > - if (reloc_entry->howto->pc_relative) > > - diff -= bfd_get_reloc_size (reloc_entry->howto); > > + if ((bfd_get_flavour (input_section->output_section->owner) > > + == bfd_target_elf_flavour) > > + && reloc_entry->howto->type == R_AMD64_IMAGEBASE) > > + { > > + /* Subtract __ImageBase. */ > > + struct bfd_link_info *link_info; > > + struct bfd_link_hash_entry *h; > > + link_info > > + = _bfd_get_link_info (input_section->output_section->owner); > > + if (link_info == NULL) > > + abort (); > > + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", > > + FALSE, FALSE, FALSE); > > + if (h == NULL) > > + abort (); > > + while (h->type == bfd_link_hash_indirect) > > + h = h->u.i.link; > > + /* ELF symbols in relocatable files are section relative, > > + but in nonrelocatable files they are virtual addresses. */ > > + diff -= (h->u.def.value > > + + h->u.def.section->output_offset > > + + h->u.def.section->output_section->vma); > > + } > > + else > > + { > > + /* PC relative relocations are off by their size. */ > > + if (reloc_entry->howto->pc_relative) > > + diff -= bfd_get_reloc_size (reloc_entry->howto); > > > > - if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 > > - && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) > > - diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; > > + if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 > > + && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) > > + diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; > > + } > > } > > I think this would be better style if the pc_relative and PCRLONG > adjustments were left as they were, and then write > > if (reloc_entry->howto->type == R_AMD64_IMAGEBASE) > { > bfd *obfd = input_section->output_section->owner; > > switch (bfd_get_flavour (obfd)) > { > case bfd_target_coff_flavour: > diff -= pe_data (obfd)->pe_opthdr.ImageBase; > break; > > case bfd_target_elf_flavour: > { > your new code > } > break; > } > } > > That should get rid of the FIXME. Fixed. > > > > /* FIXME: How should this case be handled? */ > > > > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > > index dd66d98883e..c2aaab0e5bf 100644 > > --- a/bfd/elf-bfd.h > > +++ b/bfd/elf-bfd.h > > @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata > > /* Used when laying out sections. */ > > file_ptr next_file_pos; > > > > + /* Optional linker information. */ > > + struct bfd_link_info *link_info; > > + > > That's a nice trick that might be handy elsewhere, if you always set > it rather than making it optional. Fixed. > > int num_section_syms; > > unsigned int shstrtab_section, strtab_section; > > > > @@ -2064,6 +2067,7 @@ struct elf_obj_tdata > > #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) > > #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) > > #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) > > +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) > > #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) > > #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) > > #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) > > diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c > > index 93ad38c5eb0..e60d87ff981 100644 > > --- a/bfd/elfxx-x86.c > > +++ b/bfd/elfxx-x86.c > > @@ -3174,6 +3174,8 @@ _bfd_elf_linker_x86_set_options (struct bfd_link_info * info, > > = get_elf_backend_data (info->output_bfd); > > struct elf_x86_link_hash_table *htab > > = elf_x86_hash_table (info, bed->target_id); > > + if (info->output_bfd->xvec->flavour == bfd_target_elf_flavour) > > + elf_link_info (info->output_bfd) = info; > > Move this to somewhere all ELF targets will have elf_link_info, a new > ldelf.c:elf_set_output_arch perhaps? Added ldelf_set_output_arch. > > if (htab != NULL) > > htab->params = params; > > } > > diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h > > index 2dc20ec1b19..62b1cee0af0 100644 > > --- a/bfd/libbfd-in.h > > +++ b/bfd/libbfd-in.h > > @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 > > extern bfd_byte * _bfd_write_unsigned_leb128 > > (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; > > > > +extern struct bfd_link_info *_bfd_get_link_info (bfd *); > > + > > #if GCC_VERSION >= 7000 > > #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) > > #else > > diff --git a/bfd/libbfd.h b/bfd/libbfd.h > > index 7271a2ad5a1..3a481ea468f 100644 > > --- a/bfd/libbfd.h > > +++ b/bfd/libbfd.h > > @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 > > extern bfd_byte * _bfd_write_unsigned_leb128 > > (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; > > > > +extern struct bfd_link_info *_bfd_get_link_info (bfd *); > > + > > #if GCC_VERSION >= 7000 > > #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) > > #else > > diff --git a/ld/ldelf.c b/ld/ldelf.c > > index 049992544a2..c7de958dbdc 100644 > > --- a/ld/ldelf.c > > +++ b/ld/ldelf.c > > @@ -81,6 +81,30 @@ ldelf_load_symbols (lang_input_statement_type *entry) > > { > > int link_class = 0; > > > > + if (bfd_link_pde (&link_info) > > + && entry->the_bfd->xvec->flavour == bfd_target_coff_flavour > > + && strcmp (entry->the_bfd->xvec->name, "pe-x86-64") == 0 > > + && strcmp (link_info.output_bfd->xvec->name, "elf64-x86-64") == 0) > > + { > > + /* NB: When linking Windows x86-64 relocatable object files to > > + generate ELF executable, create an indirect reference to > > + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE > > + relocation which is relative to __ImageBase. */ > > + struct elf_link_hash_table *htab = elf_hash_table (&link_info); > > + struct elf_link_hash_entry *h, *hi; > > + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, > > + FALSE); > > + if (hi->root.type == bfd_link_hash_new > > + || hi->type == bfd_link_hash_undefined > > + || hi->type == bfd_link_hash_undefweak) > > + { > > + h = elf_link_hash_lookup (htab, "__executable_start", > > + TRUE, FALSE, TRUE); > > + hi->root.type = bfd_link_hash_indirect; > > + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; > > + } > > + } > > + > > /* Tell the ELF linker that we don't want the output file to have a > > DT_NEEDED entry for this file, unless it is used to resolve > > references in a regular object. */ > > This doesn't look like the right place to set up a reference to > __executable_start. Doing so in a new check_relocs in pei-x86_64.c > that tests for an ELF output would be better. I'm not suggesting that > you run over relocs looking for R_AMD64_IMAGEBASE, that could be done > but seems unnecessary. check_relocs is too late. We need to do it in load_symbols (). Otherwise, __executable_start won't be defined. I added pex64_link_add_symbols to do it. Here is the v5 patch. OK for master? Thanks. -- H.J. [-- Attachment #2: v5-0001-elf-x86-64-Subtract-__ImageBase-for-R_AMD64_IMAGE.patch --] [-- Type: text/x-patch, Size: 20616 bytes --] From 242301311a4face0f4c0b3d3673606d17adc05c5 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 15 Feb 2021 18:53:18 -0800 Subject: [PATCH v5] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE When linking Windows x86-64 relocatable object files to generate x86-64 ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation: 1. Add link_info to struct output_elf_obj_tdata to store linker info and _bfd_get_link_info() to retrieve it. 2. Add ldelf_set_output_arch to set up link_info. 3. Add pex64_link_add_symbols to create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when adding symbols from Windows x86-64 relocatable object files to generate x86-64 ELF executable. 4. Also subtract __ImageBase for R_AMD64_IMAGEBASE when generating x86-64 ELF executable. bfd/ PR ld/27425 PR ld/27432 * bfd.c (_bfd_get_link_info): New function. * elf-bfd.h (output_elf_obj_tdata): Add link_info. (elf_link_info): New. * libbfd-in.h (_bfd_get_link_info): New prototype. * coff-x86_64.c (coff_amd64_reloc): Also subtract __ImageBase for R_AMD64_IMAGEBASE when generating x86-64 ELF executable. * pe-x86_64.c (pex64_link_add_symbols): New function. (coff_bfd_link_add_symbols): New macro. * libbfd.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_set_output_arch): New function. * ldelf.h (ldelf_set_output_arch): New prototype. * emultempl/elf.em (LDEMUL_SET_OUTPUT_ARCH): Default to ldelf_set_output_arch. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd.c | 11 +++ bfd/coff-x86_64.c | 36 ++++++-- bfd/elf-bfd.h | 4 + bfd/libbfd-in.h | 2 + bfd/libbfd.h | 2 + bfd/pe-x86_64.c | 34 +++++++- ld/emultempl/elf.em | 2 +- ld/ldelf.c | 8 ++ ld/ldelf.h | 1 + ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 18 files changed, 200 insertions(+), 8 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd.c b/bfd/bfd.c index f1944338838..2cf7b47bca1 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2808,3 +2808,14 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, *ptr_size = size; return TRUE; } + +/* Get the optional linker information. */ + +struct bfd_link_info * +_bfd_get_link_info (bfd *abfd) +{ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return NULL; + + return elf_link_info (abfd); +} diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index 5b09023f3c2..0b98b434422 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -131,11 +131,37 @@ coff_amd64_reloc (bfd *abfd, diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; } - /* FIXME: How should this case be handled? */ - if (reloc_entry->howto->type == R_AMD64_IMAGEBASE - && output_bfd != NULL - && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour) - diff -= pe_data (output_bfd)->pe_opthdr.ImageBase; + if (reloc_entry->howto->type == R_AMD64_IMAGEBASE) + { + bfd *obfd = input_section->output_section->owner; + struct bfd_link_info *link_info; + struct bfd_link_hash_entry *h; + switch (bfd_get_flavour (obfd)) + { + case bfd_target_coff_flavour: + diff -= pe_data (obfd)->pe_opthdr.ImageBase; + break; + case bfd_target_elf_flavour: + /* Subtract __ImageBase. */ + link_info = _bfd_get_link_info (obfd); + if (link_info == NULL) + abort (); + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + abort (); + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + diff -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + break; + default: + break; + } + } #endif #define DOIT(x) \ diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index c40030bdca6..04785a814e8 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata /* Used when laying out sections. */ file_ptr next_file_pos; + /* Linker information. */ + struct bfd_link_info *link_info; + int num_section_syms; unsigned int shstrtab_section, strtab_section; @@ -2064,6 +2067,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 2dc20ec1b19..62b1cee0af0 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 7271a2ad5a1..3a481ea468f 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/pe-x86_64.c b/bfd/pe-x86_64.c index 5b734442e3b..e2fc471cd34 100644 --- a/bfd/pe-x86_64.c +++ b/bfd/pe-x86_64.c @@ -22,6 +22,9 @@ #include "sysdep.h" #include "bfd.h" +#include "coff/internal.h" +#include "libcoff.h" +#include "elf-bfd.h" #define TARGET_SYM x86_64_pe_vec #define TARGET_NAME "pe-x86-64" @@ -66,5 +69,34 @@ extern bfd_boolean pex64_bfd_print_pdata (bfd *, void *); #define bfd_pe_print_pdata pex64_bfd_print_pdata -#include "coff-x86_64.c" +static bfd_boolean +pex64_link_add_symbols (bfd *abfd, struct bfd_link_info *info) +{ + if (bfd_link_pde (info) + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + { + /* NB: When linking Windows x86-64 relocatable object files to + generate ELF executable, create an indirect reference to + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE + relocation which is relative to __ImageBase. */ + struct elf_link_hash_table *htab = elf_hash_table (info); + struct elf_link_hash_entry *h, *hi; + hi = elf_link_hash_lookup (htab, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->root.type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = elf_link_hash_lookup (htab, "__executable_start", + TRUE, FALSE, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + } + } + + return _bfd_coff_link_add_symbols (abfd, info); +} +#define coff_bfd_link_add_symbols pex64_link_add_symbols + +#include "coff-x86_64.c" diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index cea89e57e25..9e7c3d86a9e 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -919,7 +919,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default}, ${LDEMUL_BEFORE_PLACE_ORPHANS-ldelf_before_place_orphans}, ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation}, - ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, + ${LDEMUL_SET_OUTPUT_ARCH-ldelf_set_output_arch}, ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}, ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..a733131e51c 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -2206,3 +2206,11 @@ ldelf_before_place_orphans (void) } } } + +void +ldelf_set_output_arch (void) +{ + set_output_arch_default (); + if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour) + elf_link_info (link_info.output_bfd) = &link_info; +} diff --git a/ld/ldelf.h b/ld/ldelf.h index 629e7c1543a..aaf264ae239 100644 --- a/ld/ldelf.h +++ b/ld/ldelf.h @@ -31,3 +31,4 @@ extern bfd_boolean ldelf_open_dynamic_archive extern lang_output_section_statement_type *ldelf_place_orphan (asection *, const char *, int); extern void ldelf_before_place_orphans (void); +extern void ldelf_set_output_arch (void); diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v5] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-05 18:26 ` [PATCH v5] " H.J. Lu @ 2021-03-06 0:11 ` Alan Modra 2021-03-06 1:00 ` [PATCH v6] " H.J. Lu 0 siblings, 1 reply; 22+ messages in thread From: Alan Modra @ 2021-03-06 0:11 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Fri, Mar 05, 2021 at 10:26:35AM -0800, H.J. Lu wrote: > On Fri, Mar 5, 2021 at 5:57 AM Alan Modra <amodra@gmail.com> wrote: > > This doesn't look like the right place to set up a reference to > > __executable_start. Doing so in a new check_relocs in pei-x86_64.c > > that tests for an ELF output would be better. I'm not suggesting that > > you run over relocs looking for R_AMD64_IMAGEBASE, that could be done > > but seems unnecessary. > > check_relocs is too late. We need to do it in load_symbols (). Otherwise, > __executable_start won't be defined. I added pex64_link_add_symbols to > do it. Ah, I was forgetting that check_relocs now runs much later. Even so, I would have thought that the PROVIDE would define the symbol? The question is academic, I'm happy with pex64_link_add_symbols. > Here is the v5 patch. OK for master? OK with three further changes. 1) The R_AMD64_IMAGEBASE handling should to be inside the output_bfd == NULL block. It is wrong to apply the image base adjustment to the section for relocatable linking. Doing so would effectively change the reloc addend. 2) I worry about the abort, which I think you might hit if trying to link PE objects into a pie. One possible fix would be to change the bfd_link_pde in pex64_link_add_symbols to !bfd_link_relocatable. That might just be sweeping a problem under the rug, so an alternative fix would be to remove the abort and instead return with bfd_reloc_dangerous. Either fix is fine with me. 3) No need to check for bfd_target_elf_flavour in set_output_arch. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v6] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-06 0:11 ` Alan Modra @ 2021-03-06 1:00 ` H.J. Lu 2021-03-07 4:16 ` Alan Modra 0 siblings, 1 reply; 22+ messages in thread From: H.J. Lu @ 2021-03-06 1:00 UTC (permalink / raw) To: Alan Modra; +Cc: Jan Beulich, Binutils [-- Attachment #1: Type: text/plain, Size: 2704 bytes --] On Fri, Mar 5, 2021 at 4:11 PM Alan Modra <amodra@gmail.com> wrote: > > On Fri, Mar 05, 2021 at 10:26:35AM -0800, H.J. Lu wrote: > > On Fri, Mar 5, 2021 at 5:57 AM Alan Modra <amodra@gmail.com> wrote: > > > This doesn't look like the right place to set up a reference to > > > __executable_start. Doing so in a new check_relocs in pei-x86_64.c > > > that tests for an ELF output would be better. I'm not suggesting that > > > you run over relocs looking for R_AMD64_IMAGEBASE, that could be done > > > but seems unnecessary. > > > > check_relocs is too late. We need to do it in load_symbols (). Otherwise, > > __executable_start won't be defined. I added pex64_link_add_symbols to > > do it. > > Ah, I was forgetting that check_relocs now runs much later. Even so, > I would have thought that the PROVIDE would define the symbol? The > question is academic, I'm happy with pex64_link_add_symbols. > > > Here is the v5 patch. OK for master? > > OK with three further changes. > 1) The R_AMD64_IMAGEBASE handling should to be inside the > output_bfd == NULL block. It is wrong to apply the image base > adjustment to the section for relocatable linking. Doing so would > effectively change the reloc addend. Fixed. > 2) I worry about the abort, which I think you might hit if trying to > link PE objects into a pie. One possible fix would be to change > the bfd_link_pde in pex64_link_add_symbols to !bfd_link_relocatable. > That might just be sweeping a problem under the rug, so an > alternative fix would be to remove the abort and instead return > with bfd_reloc_dangerous. Either fix is fine with me. Changed to return bfd_reloc_dangerous. > 3) No need to check for bfd_target_elf_flavour in set_output_arch. > The check is needed for ./ld-new -z norelro -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-elf -T pr21884.t -o tmpdir/dump tmpdir/pr21884a.o tmpdir/pr21884b.o Executing on host: sh -c {./ld-new -z norelro -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-elf -T pr21884.t -o tmpdir/dump tmpdir/pr21884a.o tmpdir/pr21884b.o 2>&1} /dev/null dump.tmp (timeout = 300) spawn [open ...]^M sh: line 1: 1894243 Segmentation fault (core dumped) ./ld-new -z norelro -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-elf -T pr21884.t -o tmpdir/dump tmpdir/pr21884a.o tmpdir/pr21884b.o 2>&1 failed with: <sh: line 1: 1894243 Segmentation fault (core dumped) ./ld-new -z norelro -L/export/gnu/import/git/gitlab/x86-binutils/ld/testsuite/ld-elf -T pr21884.t -o tmpdir/dump tmpdir/pr21884a.o tmpdir/pr21884b.o 2>&1>, no expected output FAIL: ld-elf/pr21884 This is the patch I am checking in. Thanks. -- H.J. [-- Attachment #2: v6-0001-elf-x86-64-Subtract-__ImageBase-for-R_AMD64_IMAGE.patch --] [-- Type: text/x-patch, Size: 20543 bytes --] From 1d4a687b2651ce8de36c4e7cf1d92ed3a007e09a Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Mon, 15 Feb 2021 18:53:18 -0800 Subject: [PATCH v6] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE When linking Windows x86-64 relocatable object files to generate x86-64 ELF executable, we need to subtract __ImageBase, aka __executable_start, for R_AMD64_IMAGEBASE relocation: 1. Add link_info to struct output_elf_obj_tdata to store linker info and _bfd_get_link_info() to retrieve it. 2. Add ldelf_set_output_arch to set up link_info. 3. Add pex64_link_add_symbols to create an indirect reference to __executable_start for __ImageBase to support R_AMD64_IMAGEBASE relocation when adding symbols from Windows x86-64 relocatable object files to generate x86-64 ELF executable. 4. Also subtract __ImageBase for R_AMD64_IMAGEBASE when generating x86-64 ELF executable. bfd/ PR ld/27425 PR ld/27432 * bfd.c (_bfd_get_link_info): New function. * elf-bfd.h (output_elf_obj_tdata): Add link_info. (elf_link_info): New. * libbfd-in.h (_bfd_get_link_info): New prototype. * coff-x86_64.c (coff_amd64_reloc): Also subtract __ImageBase for R_AMD64_IMAGEBASE when generating x86-64 ELF executable. * pe-x86_64.c: Include "coff/internal.h" and "libcoff.h". (pex64_link_add_symbols): New function. (coff_bfd_link_add_symbols): New macro. * libbfd.h: Regenerated. ld/ PR ld/27425 PR ld/27432 * ldelf.c (ldelf_set_output_arch): New function. * ldelf.h (ldelf_set_output_arch): New prototype. * emultempl/elf.em (LDEMUL_SET_OUTPUT_ARCH): Default to ldelf_set_output_arch. * ld-x86-64/pe-x86-64-1.od: Expect __executable_start. * testsuite/ld-x86-64/pe-x86-64-2.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-3.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-4.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.od: Likewise. * testsuite/ld-x86-64/pe-x86-64-5.rd: Likewise. * testsuite/ld-x86-64/pe-x86-64-6.obj.bz2: New file. * testsuite/ld-x86-64/pe-x86-64-6.od: Likewise. * testsuite/ld-x86-64/pe-x86-64.exp: Run ld/27425 test. --- bfd/bfd.c | 11 +++ bfd/coff-x86_64.c | 35 +++++++- bfd/elf-bfd.h | 4 + bfd/libbfd-in.h | 2 + bfd/libbfd.h | 2 + bfd/pe-x86_64.c | 32 +++++++- ld/emultempl/elf.em | 2 +- ld/ldelf.c | 8 ++ ld/ldelf.h | 1 + ld/testsuite/ld-x86-64/pe-x86-64-1.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-2.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-3.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-4.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.od | 1 + ld/testsuite/ld-x86-64/pe-x86-64-5.rd | 3 +- ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 | Bin 0 -> 1366 bytes ld/testsuite/ld-x86-64/pe-x86-64-6.od | 91 +++++++++++++++++++++ ld/testsuite/ld-x86-64/pe-x86-64.exp | 9 ++ 18 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 create mode 100644 ld/testsuite/ld-x86-64/pe-x86-64-6.od diff --git a/bfd/bfd.c b/bfd/bfd.c index f1944338838..2c620857863 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2808,3 +2808,14 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, *ptr_size = size; return TRUE; } + +/* Get the linker information. */ + +struct bfd_link_info * +_bfd_get_link_info (bfd *abfd) +{ + if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) + return NULL; + + return elf_link_info (abfd); +} diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index 5b09023f3c2..870df2b2b7a 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -131,11 +131,38 @@ coff_amd64_reloc (bfd *abfd, diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; } - /* FIXME: How should this case be handled? */ if (reloc_entry->howto->type == R_AMD64_IMAGEBASE - && output_bfd != NULL - && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour) - diff -= pe_data (output_bfd)->pe_opthdr.ImageBase; + && output_bfd == NULL) + { + bfd *obfd = input_section->output_section->owner; + struct bfd_link_info *link_info; + struct bfd_link_hash_entry *h; + switch (bfd_get_flavour (obfd)) + { + case bfd_target_coff_flavour: + diff -= pe_data (obfd)->pe_opthdr.ImageBase; + break; + case bfd_target_elf_flavour: + /* Subtract __ImageBase. */ + link_info = _bfd_get_link_info (obfd); + if (link_info == NULL) + return bfd_reloc_dangerous; + h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", + FALSE, FALSE, FALSE); + if (h == NULL) + return bfd_reloc_dangerous; + while (h->type == bfd_link_hash_indirect) + h = h->u.i.link; + /* ELF symbols in relocatable files are section relative, + but in nonrelocatable files they are virtual addresses. */ + diff -= (h->u.def.value + + h->u.def.section->output_offset + + h->u.def.section->output_section->vma); + break; + default: + break; + } + } #endif #define DOIT(x) \ diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index c40030bdca6..04785a814e8 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1887,6 +1887,9 @@ struct output_elf_obj_tdata /* Used when laying out sections. */ file_ptr next_file_pos; + /* Linker information. */ + struct bfd_link_info *link_info; + int num_section_syms; unsigned int shstrtab_section, strtab_section; @@ -2064,6 +2067,7 @@ struct elf_obj_tdata #define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) #define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) #define elf_seg_map(bfd) (elf_tdata(bfd) -> o->seg_map) +#define elf_link_info(bfd) (elf_tdata(bfd) -> o->link_info) #define elf_next_file_pos(bfd) (elf_tdata(bfd) -> o->next_file_pos) #define elf_eh_frame_hdr(bfd) (elf_tdata(bfd) -> o->eh_frame_hdr) #define elf_stack_flags(bfd) (elf_tdata(bfd) -> o->stack_flags) diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 2dc20ec1b19..62b1cee0af0 100644 --- a/bfd/libbfd-in.h +++ b/bfd/libbfd-in.h @@ -899,6 +899,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 7271a2ad5a1..3a481ea468f 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -904,6 +904,8 @@ extern bfd_vma _bfd_safe_read_leb128 extern bfd_byte * _bfd_write_unsigned_leb128 (bfd_byte *, bfd_byte *, bfd_vma) ATTRIBUTE_HIDDEN; +extern struct bfd_link_info *_bfd_get_link_info (bfd *); + #if GCC_VERSION >= 7000 #define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res) #else diff --git a/bfd/pe-x86_64.c b/bfd/pe-x86_64.c index 5b734442e3b..771651aba89 100644 --- a/bfd/pe-x86_64.c +++ b/bfd/pe-x86_64.c @@ -22,6 +22,8 @@ #include "sysdep.h" #include "bfd.h" +#include "coff/internal.h" +#include "libcoff.h" #define TARGET_SYM x86_64_pe_vec #define TARGET_NAME "pe-x86-64" @@ -66,5 +68,33 @@ extern bfd_boolean pex64_bfd_print_pdata (bfd *, void *); #define bfd_pe_print_pdata pex64_bfd_print_pdata -#include "coff-x86_64.c" +static bfd_boolean +pex64_link_add_symbols (bfd *abfd, struct bfd_link_info *info) +{ + if (bfd_link_pde (info) + && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) + { + /* NB: When linking Windows x86-64 relocatable object files to + generate ELF executable, create an indirect reference to + __executable_start for __ImageBase to support R_AMD64_IMAGEBASE + relocation which is relative to __ImageBase. */ + struct bfd_link_hash_entry *h, *hi; + hi = bfd_link_hash_lookup (info->hash, "__ImageBase", TRUE, FALSE, + FALSE); + if (hi->type == bfd_link_hash_new + || hi->type == bfd_link_hash_undefined + || hi->type == bfd_link_hash_undefweak) + { + h = bfd_link_hash_lookup (info->hash, "__executable_start", + TRUE, FALSE, TRUE); + hi->type = bfd_link_hash_indirect; + hi->u.i.link = h; + } + } + + return _bfd_coff_link_add_symbols (abfd, info); +} +#define coff_bfd_link_add_symbols pex64_link_add_symbols + +#include "coff-x86_64.c" diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em index cea89e57e25..9e7c3d86a9e 100644 --- a/ld/emultempl/elf.em +++ b/ld/emultempl/elf.em @@ -919,7 +919,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default}, ${LDEMUL_BEFORE_PLACE_ORPHANS-ldelf_before_place_orphans}, ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation}, - ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default}, + ${LDEMUL_SET_OUTPUT_ARCH-ldelf_set_output_arch}, ${LDEMUL_CHOOSE_TARGET-ldemul_default_target}, ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation}, ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, diff --git a/ld/ldelf.c b/ld/ldelf.c index 049992544a2..a733131e51c 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -2206,3 +2206,11 @@ ldelf_before_place_orphans (void) } } } + +void +ldelf_set_output_arch (void) +{ + set_output_arch_default (); + if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour) + elf_link_info (link_info.output_bfd) = &link_info; +} diff --git a/ld/ldelf.h b/ld/ldelf.h index 629e7c1543a..aaf264ae239 100644 --- a/ld/ldelf.h +++ b/ld/ldelf.h @@ -31,3 +31,4 @@ extern bfd_boolean ldelf_open_dynamic_archive extern lang_output_section_statement_type *ldelf_place_orphan (asection *, const char *, int); extern void ldelf_before_place_orphans (void); +extern void ldelf_set_output_arch (void); diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-1.od b/ld/testsuite/ld-x86-64/pe-x86-64-1.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-1.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-1.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-2.od b/ld/testsuite/ld-x86-64/pe-x86-64-2.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-2.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-2.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-3.od b/ld/testsuite/ld-x86-64/pe-x86-64-3.od index 4966d55fb5a..227875f82dc 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-3.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-3.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 getaddr1 0+401020 g .text\$mn 0000000000000000 begin 0+403014 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-4.od b/ld/testsuite/ld-x86-64/pe-x86-64-4.od index e0bde11d84e..320c6be5e14 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-4.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-4.od @@ -2,6 +2,7 @@ .*: +file format .* SYMBOL TABLE: +0+400000 g .text\$mn 0000000000000000 __executable_start 0+403038 g .bss 0000000000000000 c 0+401000 g .text\$mn 0000000000000000 begin 0+403038 g .bss 0000000000000000 __bss_start diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.od b/ld/testsuite/ld-x86-64/pe-x86-64-5.od index 8a4f4a633ac..6ef13abbc94 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.od +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.od @@ -4,6 +4,7 @@ SYMBOL TABLE: 0+402014 g .bss 0000000000000000 non_initdummy 0+402010 g .data 0000000000000000 initdummy +0+400000 g .text\$mn 0000000000000000 __executable_start 0+401000 g .text\$mn 0000000000000000 begin 0+402012 g .bss 0000000000000000 __bss_start 0+402000 g .data 0000000000000000 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd index 8370665f99f..237052805e9 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64-5.rd +++ b/ld/testsuite/ld-x86-64/pe-x86-64-5.rd @@ -1,9 +1,10 @@ -Symbol table '.symtab' contains 10 entries: +Symbol table '.symtab' contains 11 entries: Num: Value Size Type Bind Vis Ndx Name +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +[a-f0-9]+: 0000000000402014 0 NOTYPE GLOBAL DEFAULT 3 non_initdummy +[a-f0-9]+: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 2 initdummy + +[a-f0-9]+: 0000000000400000 0 NOTYPE GLOBAL DEFAULT 1 __executable_start +[a-f0-9]+: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 1 begin +[a-f0-9]+: 0000000000402012 0 NOTYPE GLOBAL DEFAULT 3 __bss_start +[a-f0-9]+: 0000000000402000 0 NOTYPE GLOBAL DEFAULT 2 Struct diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 b/ld/testsuite/ld-x86-64/pe-x86-64-6.obj.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..38255045d45ed918857b2c966400c13a13ea6c07 GIT binary patch literal 1366 zcmV-c1*!T%T4*^jL0KkKSr(o^9smO9fB*mf|Nh_a|NQ^||Nj5~-}TM^Q*@d9YgPW; zd+eHR_F&KhxOk{DUEM>1DTr#B8Vxi9QxnNB$qe;OMn*LZjWonG!KBke34qcKG#-Lu zO+n}oJfkP-n1+}m6BA7tp+8jd3aO!pXvlhuKmni)7)=4727@32A)%%dK*9h3GyobJ zF#(`ypa1~S&<2Qtn+c+6qtZ`M(<VowN$4g48fl<tXa<3x8X7%78Z>F3218950002c z8UPw-&;$&OhMHssLqH6JBSwQEplP9@hychk8Z-t#7$DFx0MG!_Kn#r-BS2^XN+L#+ zMDk%qX+0wvnd*n6$Y=o5O#sjXO#o;B000^Q000000BC8T01Y)6t0Ij%1~1Zx-ljTP zv7~$gP4n@oNq~cfwyu(S%%**p^kz*r4rRAWRcTbfRNzb)2)m)XQMb&4JUVWwY*_%P z_N_!via~?|2}vgnKR75Sr_AXg#*K-lYBJ6&yOYkj3SvkC7BnqXI+`VjgE9yrmM|#Z zAcU!thFfPL@ogO(W&_wPR?O<Nl`>0!yz(SMNI$pgD>nP`qq5&di9Y(;<tzfve#7RV zLQq7sR8<iKE~*d}9#I&mh}9UVJg8-r7@=xZ2NcmYhaEyPiYfpN6hw+h7>GbrM+HPo z!i9>{yG<#;mMI1E_Jr`*O+8>~P!*e8kP;V5^pWooq=L*qp)SmVWvfu>f>_r&r(rc; zFlw0LN0dbVEA<6bekiD-s;40s%X>e{Bpb{0V*cpCy@Z%%2(;IT0ltH`?_5}n<UzB5 zf*?Wx?9SUxvoz5xvF*HU!`az<4cefwMgW_uK?W~)_YEp5)<A$@1UQMSt7Vh|X$!8S zrYkdd%PnrQQ=JI}l%S=Jf?!qja8)kH^@O)sYfeI3m645L`q5BGerN)K?of-0r#>n| zIJ>G_Jer_3(hAJw3_-j#7s1%O?->CeCR~1-d~uAqlkd=kBse0+P!fP8Gf5HP-!7%i zY9#t2m+xTN{>23e(7a+I0;{Zo0pKlR8D<0+3~@0q!8UtF@$=vS%Ru|zVD9FpjySx} zt{H?(&9Uu<p2jzU;|+yP-xYy^SQTmsWFw3b42s1?DxF}&SjcKo)TM}4B<*K1;RKpr zB9L9W4U0w48Omi$FhV&*nXBTNgK+&nY+(ea!;BBmP6EO12PwtkmC_%#RsA$z@0JaQ zK;1$!^T@K75<Qv*kCpFrll-gW?LaFYfjkRsvaL~}G=vHfYrg~uZV?6S9IpF-0+5}A z_)^1T9VRd5A4+zwe~%URaNDw|ovUUIblXiY&aNu_D<Fy>a;O36%A;_CC4P{I;g8Lc z_oIb1Th5wd#<v-tRhnyBD_BF4(rrdPfGi+1Cj(c?t7>6DvSmSitld-B7DP!ulPV)v zjtH{yhbV)vqPiypj+2XeCuKWhP+%%5BxPTeR&+A6ME(Spj<8A+AT>of%9IL${b3$W zT;V{<37R=3O12yjn;D3J_1es%R~rCwc#07V>0~}6Ocbcd(xo^hbFZ_E5g`dK4J43; zL!(RF%z~VRcxJ6*mWojmVMt69!e|;&A4@D>YChtn2o?5O0qUo}T)OBf@?k*9{q-V& zj?~DI4x)@7n$%$cCX*@q$)0{8UXMIXT<xV^S2T@qb<#e0E#AcXnZlt{eAv$l(KnN1 zj%}2QO$7taoaiC>k}0dYOV~!Q%X-@vZSVa^tl(<I`&6AfE`zbF1)s_=HB>Bd6H=xt Y$~B;AV5AHi$*u8sBvXY60cqp`;GR@oQ~&?~ literal 0 HcmV?d00001 diff --git a/ld/testsuite/ld-x86-64/pe-x86-64-6.od b/ld/testsuite/ld-x86-64/pe-x86-64-6.od new file mode 100644 index 00000000000..cc23658a806 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pe-x86-64-6.od @@ -0,0 +1,91 @@ + +.*: +file format .* + +SYMBOL TABLE: +0+4010a8 g .text\$mn 0000000000000000 xfunc +0+402000 g .rdata 0000000000000000 \?\?_C@_02LDKJOMJN@AB@ +0+400000 g .text\$mn 0000000000000000 __executable_start +0+403058 g .data 0000000000000000 __bss_start +0+401000 g .text\$mn 0000000000000000 main +0+403038 g .data 0000000000000000 deadloopvar +0+4010ac g .text\$mn 0000000000000000 xstring +0+403058 g .data 0000000000000000 _edata +0+403058 g .data 0000000000000000 _end + + + +Disassembly of section .text\$mn: + +0+401000 <main>: + +[a-f0-9]+: 48 89 5c 24 08 mov %rbx,0x8\(%rsp\) + +[a-f0-9]+: 48 89 6c 24 10 mov %rbp,0x10\(%rsp\) + +[a-f0-9]+: 48 89 74 24 20 mov %rsi,0x20\(%rsp\) + +[a-f0-9]+: 57 push %rdi + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: cc int3 + +[a-f0-9]+: 8b 05 1d 20 00 00 mov 0x201d\(%rip\),%eax # 403038 <deadloopvar> + +[a-f0-9]+: 83 f8 01 cmp \$0x1,%eax + +[a-f0-9]+: 74 f5 je 401015 <main\+0x15> + +[a-f0-9]+: 0f 31 rdtsc + +[a-f0-9]+: 48 c1 e2 20 shl \$0x20,%rdx + +[a-f0-9]+: 48 0b c2 or %rdx,%rax + +[a-f0-9]+: 74 5d je 401088 <main\+0x88> + +[a-f0-9]+: 33 ff xor %edi,%edi + +[a-f0-9]+: 48 8d 2d cc ef ff ff lea -0x1034\(%rip\),%rbp # 400000 <__executable_start> + +[a-f0-9]+: 33 db xor %ebx,%ebx + +[a-f0-9]+: 48 8d 35 ff 1f 00 00 lea 0x1fff\(%rip\),%rsi # 40303c <deadloopvar\+0x4> + +[a-f0-9]+: 48 8b 8c 2b 50 30 00 00 mov 0x3050\(%rbx,%rbp,1\),%rcx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 74 28 je 401075 <main\+0x75> + +[a-f0-9]+: b8 05 00 00 00 mov \$0x5,%eax + +[a-f0-9]+: 2b 84 2b 48 30 00 00 sub 0x3048\(%rbx,%rbp,1\),%eax + +[a-f0-9]+: 99 cltd + +[a-f0-9]+: 2b c2 sub %edx,%eax + +[a-f0-9]+: d1 f8 sar %eax + +[a-f0-9]+: 48 63 d0 movslq %eax,%rdx + +[a-f0-9]+: 48 03 d6 add %rsi,%rdx + +[a-f0-9]+: 48 ff c1 inc %rcx + +[a-f0-9]+: 44 88 02 mov %r8b,\(%rdx\) + +[a-f0-9]+: 48 ff c2 inc %rdx + +[a-f0-9]+: 44 8a 01 mov \(%rcx\),%r8b + +[a-f0-9]+: 45 84 c0 test %r8b,%r8b + +[a-f0-9]+: 75 ef jne 401064 <main\+0x64> + +[a-f0-9]+: 48 8b ce mov %rsi,%rcx + +[a-f0-9]+: e8 2f 00 00 00 call 4010ac <xstring> + +[a-f0-9]+: ff c7 inc %edi + +[a-f0-9]+: 48 83 c3 08 add \$0x8,%rbx + +[a-f0-9]+: 83 ff 01 cmp \$0x1,%edi + +[a-f0-9]+: 72 b5 jb 40103d <main\+0x3d> + +[a-f0-9]+: b1 aa mov \$0xaa,%cl + +[a-f0-9]+: e8 19 00 00 00 call 4010a8 <xfunc> + +[a-f0-9]+: 48 8b 5c 24 30 mov 0x30\(%rsp\),%rbx + +[a-f0-9]+: 33 c0 xor %eax,%eax + +[a-f0-9]+: 48 8b 6c 24 38 mov 0x38\(%rsp\),%rbp + +[a-f0-9]+: 48 8b 74 24 48 mov 0x48\(%rsp\),%rsi + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5f pop %rdi + +[a-f0-9]+: c3 ret + +[a-f0-9]+: 66 90 xchg %ax,%ax + +0+4010a8 <xfunc>: + +[a-f0-9]+: 66 90 xchg %ax,%ax + +[a-f0-9]+: cc int3 + +[a-f0-9]+: c3 ret + +0+4010ac <xstring>: + +[a-f0-9]+: 40 53 rex push %rbx + +[a-f0-9]+: 48 83 ec 20 sub \$0x20,%rsp + +[a-f0-9]+: 8a 01 mov \(%rcx\),%al + +[a-f0-9]+: 48 8b d9 mov %rcx,%rbx + +[a-f0-9]+: eb 0c jmp 4010c5 <xstring\+0x19> + +[a-f0-9]+: 8a c8 mov %al,%cl + +[a-f0-9]+: e8 e8 ff ff ff call 4010a8 <xfunc> + +[a-f0-9]+: 48 ff c3 inc %rbx + +[a-f0-9]+: 8a 03 mov \(%rbx\),%al + +[a-f0-9]+: 84 c0 test %al,%al + +[a-f0-9]+: 75 f0 jne 4010b9 <xstring\+0xd> + +[a-f0-9]+: 48 83 c4 20 add \$0x20,%rsp + +[a-f0-9]+: 5b pop %rbx + +[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-x86-64/pe-x86-64.exp b/ld/testsuite/ld-x86-64/pe-x86-64.exp index ccfcdfaddfb..f5d2c84f283 100644 --- a/ld/testsuite/ld-x86-64/pe-x86-64.exp +++ b/ld/testsuite/ld-x86-64/pe-x86-64.exp @@ -73,4 +73,13 @@ run_ld_link_tests [list \ {readelf {-s -x .data} pe-x86-64-5.rd}} \ "pe-x86-64-5" \ ] \ + [list \ + "Build pe-x86-64-6" \ + "-m elf_x86_64 --entry=main" \ + "" \ + "" \ + {pe-x86-64-6.obj.bz2 } \ + {{objdump {-dw --sym} pe-x86-64-6.od}} \ + "pe-x86-64-6" \ + ] \ ] -- 2.29.2 ^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v6] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE 2021-03-06 1:00 ` [PATCH v6] " H.J. Lu @ 2021-03-07 4:16 ` Alan Modra 0 siblings, 0 replies; 22+ messages in thread From: Alan Modra @ 2021-03-07 4:16 UTC (permalink / raw) To: H.J. Lu; +Cc: Jan Beulich, Binutils On Fri, Mar 05, 2021 at 05:00:23PM -0800, H.J. Lu wrote: > > 3) No need to check for bfd_target_elf_flavour in set_output_arch. > > The check is needed for [cases where the output format is non-ELF] Yes indeed, my mental gears slipped a cog. -- Alan Modra Australia Development Lab, IBM ^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2021-03-07 4:16 UTC | newest] Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-02-23 12:15 [PATCH] elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE H.J. Lu 2021-02-23 13:15 ` Jan Beulich 2021-02-23 13:31 ` H.J. Lu 2021-02-23 14:10 ` Jan Beulich 2021-02-23 14:47 ` H.J. Lu 2021-02-23 15:02 ` Jan Beulich 2021-02-23 15:07 ` H.J. Lu 2021-02-23 15:11 ` Jan Beulich 2021-02-23 17:50 ` [PATCH v2] " H.J. Lu 2021-02-25 2:09 ` Alan Modra 2021-02-28 2:38 ` [PATCH v3] " H.J. Lu 2021-03-01 12:19 ` Alan Modra 2021-03-01 13:44 ` H.J. Lu 2021-03-04 13:14 ` Alan Modra 2021-03-04 13:54 ` [PATCH v4] " H.J. Lu 2021-03-05 5:17 ` Alan Modra 2021-03-05 5:29 ` H.J. Lu 2021-03-05 13:57 ` Alan Modra 2021-03-05 18:26 ` [PATCH v5] " H.J. Lu 2021-03-06 0:11 ` Alan Modra 2021-03-06 1:00 ` [PATCH v6] " H.J. Lu 2021-03-07 4:16 ` Alan Modra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).