diff mbox series

[i386] Fix PR C++/64697

Message ID 2183660.iZASKD2KPV@fomalhaut
State New
Headers show
Series [i386] Fix PR C++/64697 | expand

Commit Message

Eric Botcazou Sept. 3, 2021, 9:13 a.m. UTC
Hi,

this old PR is about a link failure on x86-64/Cygwin with thread-local
storage variables:

use.o:use.cxx:(.text$_ZTWN1N3ptdE[_ZTWN1N3ptdE]+0x15): relocation
truncated to fit: R_X86_64_PC32 against undefined symbol `TLS init
function for N::ptd'
collect2: error: ld returned 1 exit status

At the time MinGW was not affected because the base address of executables was
within the lower 4GB.  This was changed in binutils 2.36 and the bug was then
reported for MinGW to binutils's Bugzilla:
  https://sourceware.org/bugzilla/show_bug.cgi?id=26659

The BFD fix eliminates the link failure and working code is generated at -O0,
but _not_ when optimization is enabled because the optimizer changes:

	movq	.refptr._ZTH1s(%rip), %rax
	testq	%rax, %rax
	je	.L2
	call	_ZTH1s

into:

	leaq	_ZTH1s(%rip), %rax
	testq	%rax, %rax
	je	.L2
	call	_ZTH1s

and the leaq now also gets the relocation overflow.  So the fix is to
teach legitimate_pic_address_disp_p to reject the transformation when
the symbol is an external weak function, which yields:

	cmpq	$0, .refptr._ZTH1s(%rip)
	je	.L2
	call	_ZTH1s

and the cmpq keeps a relocation that does not overflow.

Tested on x86-64/Windows, OK for mainline, 11 and 10 branches?


2021-09-03  Eric Botcazou  <ebotcazou@adacore.com>

	* config/i386/i386.c (legitimate_pic_address_disp_p): For PE-COFF, do
	not return true for external weak function symbols in the medium model.
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index bfefbd718bb..2f708a1cf1c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10664,24 +10664,19 @@  legitimate_pic_address_disp_p (rtx disp)
 	      if (is_imported_p (op0))
 		return true;
 
-	      if (SYMBOL_REF_FAR_ADDR_P (op0)
-		  || !SYMBOL_REF_LOCAL_P (op0))
+	      if (SYMBOL_REF_FAR_ADDR_P (op0) || !SYMBOL_REF_LOCAL_P (op0))
 		break;
 
-	      /* Function-symbols need to be resolved only for
-	         large-model.
-	         For the small-model we don't need to resolve anything
-	         here.  */
+	      /* Non-external-weak function symbols need to be resolved only
+		 for the large model.  Non-external symbols don't need to be
+		 resolved for large and medium models.  For the small model,
+		 we don't need to resolve anything here.  */
 	      if ((ix86_cmodel != CM_LARGE_PIC
-	           && SYMBOL_REF_FUNCTION_P (op0))
+		   && SYMBOL_REF_FUNCTION_P (op0)
+		   && !(SYMBOL_REF_EXTERNAL_P (op0) && SYMBOL_REF_WEAK (op0)))
+		  || !SYMBOL_REF_EXTERNAL_P (op0)
 		  || ix86_cmodel == CM_SMALL_PIC)
 		return true;
-	      /* Non-external symbols don't need to be resolved for
-	         large, and medium-model.  */
-	      if ((ix86_cmodel == CM_LARGE_PIC
-		   || ix86_cmodel == CM_MEDIUM_PIC)
-		  && !SYMBOL_REF_EXTERNAL_P (op0))
-		return true;
 	    }
 	  else if (!SYMBOL_REF_FAR_ADDR_P (op0)
 		   && (SYMBOL_REF_LOCAL_P (op0)