diff mbox series

[x86] Change EH pointer encodings to PC relative on Windows

Message ID 3361197.V25eIC5XRa@fomalhaut
State New
Headers show
Series [x86] Change EH pointer encodings to PC relative on Windows | expand

Commit Message

Eric Botcazou July 1, 2021, 4:43 p.m. UTC
Hi,

a big difference between ELF and PE-COFF is that, with the latter, you can 
build position-independent executables or DLLs without generating PIC; as a 
matter of fact, flag_pic has historically been forced to 0 for 32-bit:

/* Don't allow flag_pic to propagate since gas may produce invalid code
   otherwise.  */

#undef  SUBTARGET_OVERRIDE_OPTIONS
#define SUBTARGET_OVERRIDE_OPTIONS					
\
do {								
	\
  flag_pic = TARGET_64BIT ? 1 : 0;                                      \
} while (0)

The reason is that the linker builds a .reloc section that collects all the 
absolute relocations in the generated binary, and the loader uses them to 
relocate it at load time if need be (e.g. if --dynamicbase is enabled).

Up to binutils 2.35, the GNU linker didn't build the .reloc section for 
executables and defaulted to --enable-auto-image-base for DLLs, which means 
that DLLs had an essentially unique load address and, therefore, need not be 
relocated by the loader in most cases.

With binutils 2.36 and later, the GNU linker builds a .reloc section for 
executables (thus making them PIE), --enable-auto-image-base is disabled and 
--dynamicbase is enabled by default, which means that essentially all the 
binaries are relocated at load time.

This badly breaks the 32-bit compiler configured to use DWARF-2 EH (the 64-bit 
compiler always uses the native SEH) because the loader corrupts the .eh_frame 
section when processing the relocations contained in the .reloc section.

The attached patch simply forces the PIC encodings for EH on PE-COFF targets.

Tested on x86/Windows, OK for all active branches?


2021-07-01  Eric Botcazou  <ebotcazou@adacore.com>

	* config/i386/i386.c (asm_preferred_eh_data_format): Always use the
	PIC encodings for PE-COFF targets.

Comments

Richard Biener July 2, 2021, 7:29 a.m. UTC | #1
On Thu, Jul 1, 2021 at 6:44 PM Eric Botcazou <botcazou@adacore.com> wrote:
>
> Hi,
>
> a big difference between ELF and PE-COFF is that, with the latter, you can
> build position-independent executables or DLLs without generating PIC; as a
> matter of fact, flag_pic has historically been forced to 0 for 32-bit:
>
> /* Don't allow flag_pic to propagate since gas may produce invalid code
>    otherwise.  */
>
> #undef  SUBTARGET_OVERRIDE_OPTIONS
> #define SUBTARGET_OVERRIDE_OPTIONS
> \
> do {
>         \
>   flag_pic = TARGET_64BIT ? 1 : 0;                                      \
> } while (0)
>
> The reason is that the linker builds a .reloc section that collects all the
> absolute relocations in the generated binary, and the loader uses them to
> relocate it at load time if need be (e.g. if --dynamicbase is enabled).
>
> Up to binutils 2.35, the GNU linker didn't build the .reloc section for
> executables and defaulted to --enable-auto-image-base for DLLs, which means
> that DLLs had an essentially unique load address and, therefore, need not be
> relocated by the loader in most cases.
>
> With binutils 2.36 and later, the GNU linker builds a .reloc section for
> executables (thus making them PIE), --enable-auto-image-base is disabled and
> --dynamicbase is enabled by default, which means that essentially all the
> binaries are relocated at load time.
>
> This badly breaks the 32-bit compiler configured to use DWARF-2 EH (the 64-bit
> compiler always uses the native SEH) because the loader corrupts the .eh_frame
> section when processing the relocations contained in the .reloc section.
>
> The attached patch simply forces the PIC encodings for EH on PE-COFF targets.
>
> Tested on x86/Windows, OK for all active branches?

OK.

Richard.

>
> 2021-07-01  Eric Botcazou  <ebotcazou@adacore.com>
>
>         * config/i386/i386.c (asm_preferred_eh_data_format): Always use the
>         PIC encodings for PE-COFF targets.
>
> --
> Eric Botcazou
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2fbaae7cd02..cff26909292 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -21930,10 +21930,12 @@  ix86_stack_protect_fail (void)
    After all, the relocation needed is the same as for the call insn.
    Whether or not a particular assembler allows us to enter such, I
    guess we'll have to see.  */
+
 int
 asm_preferred_eh_data_format (int code, int global)
 {
-  if (flag_pic)
+  /* PE-COFF is effectively always -fPIC because of the .reloc section.  */
+  if (flag_pic || TARGET_PECOFF)
     {
       int type = DW_EH_PE_sdata8;
       if (!TARGET_64BIT
@@ -21942,9 +21944,11 @@  asm_preferred_eh_data_format (int code, int global)
 	type = DW_EH_PE_sdata4;
       return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
     }
+
   if (ix86_cmodel == CM_SMALL
       || (ix86_cmodel == CM_MEDIUM && code))
     return DW_EH_PE_udata4;
+
   return DW_EH_PE_absptr;
 }