elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE

Message ID 20210223121558.3529429-1-hjl.tools@gmail.com
State New
Headers show
Series
  • elf/x86-64: Subtract __ImageBase for R_AMD64_IMAGEBASE
Related show

Commit Message

Alan Modra via Binutils Feb. 23, 2021, 12:15 p.m.
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

-- 
2.29.2

Comments

Alan Modra via Binutils Feb. 23, 2021, 1:15 p.m. | #1
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
Alan Modra via Binutils Feb. 23, 2021, 1:31 p.m. | #2
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.
Alan Modra via Binutils Feb. 23, 2021, 2:10 p.m. | #3
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
Alan Modra via Binutils Feb. 23, 2021, 2:47 p.m. | #4
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.
Alan Modra via Binutils Feb. 23, 2021, 3:02 p.m. | #5
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
Alan Modra via Binutils Feb. 23, 2021, 3:07 p.m. | #6
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.
Alan Modra via Binutils Feb. 23, 2021, 3:11 p.m. | #7
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

Patch

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" \
+    ] \
 ]