public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code
@ 2018-06-12 15:22 Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 01/11] MdePkg/ProcessorBind.h: define macro to decorate module entry points Ard Biesheuvel
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:22 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

The GCC toolchain uses PIE mode when building code for X64, because it
is the most efficient in size: it uses relative references where
possible, but still uses 64-bit quantities for absolute symbol
references, which is optimal for executables that need to be converted
to PE/COFF using GenFw.

Enabling PIE mode has a couple of side effects though, primarily caused
by the fact that the primary application area of GCC is to build programs
for userland. GCC will assume that ELF symbols should be preemptible (which
makes sense for PIC but not for PIE, but this simply seems to be the result
of code being shared between the two modes), and it will attempt to keep
absolute references close to each other so that dynamic relocations that
trigger CoW for text pages have the smallest possible footprint.

These side effects can be mititgated by overriding the visibility of all
symbol definitions *and* symbol references, using a special #pragma. This
will inform the compiler that symbol preemption and dynamic relocations
are not a concern, and that all symbol references can be emitted as direct
relative references rather than relative references to a GOT entry containing
the absolute address. Unsurprisingly, this leads to better and smaller code.

Unfortunately, we have not been able to set this override when LTO is in
effect, because the LTO code generator infers from the hidden visibility
of all symbols that none of the code is reachable, and discards it all,
leading to corrupt, empty binaries.

We can work around this by overriding the visibility for symbols that are
module entry points. So implement this for all occcurrences of the symbol
'_ModuleEntryPoint', and enable 'hidden' visibility in LTO builds as well.

Note that all the changes in this series resolve to no-ops if USING_LTO
is not #defined.

Code can be found here:
https://github.com/ardbiesheuvel/edk2/tree/x64-lto-visibility

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Hao Wu <hao.a.wu@intel.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Zenith432 <zenith432@users.sourceforge.net>
Cc: "Shi, Steven" <steven.shi@intel.com>

Ard Biesheuvel (11):
  MdePkg/ProcessorBind.h: define macro to decorate module entry points
  DuetPkg: annotate module entry points with EFI_ENTRYPOINT
  EdkCompatibilityPkg: annotate module entry points with EFI_ENTRYPOINT
  EmbeddedPkg: annotate module entry points with EFI_ENTRYPOINT
  EmulatorPkg: annotate module entry points with EFI_ENTRYPOINT
  IntelFrameWorkPkg: annotate module entry points with EFI_ENTRYPOINT
  MdeModulePkg: annotate module entry points with EFI_ENTRYPOINT
  MdePkg: annotate module entry points with EFI_ENTRYPOINT
  Nt32Pkg: annotate module entry points with EFI_ENTRYPOINT
  UefiCpuPkg: annotate module entry points with EFI_ENTRYPOINT
  MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity
    override

 DuetPkg/DxeIpl/DxeInit.c                         |  1 +
 DuetPkg/EfiLdr/EfiLoader.c                       |  1 +
 .../EntryPoints/EdkIIGlueDxeDriverEntryPoint.c   |  1 +
 .../EntryPoints/EdkIIGluePeimEntryPoint.c        |  1 +
 .../EntryPoints/EdkIIGlueSmmDriverEntryPoint.c   |  1 +
 .../Library/EdkIIGlueDxeSmmDriverEntryPoint.h    |  1 +
 .../Include/Library/EdkIIGluePeimEntryPoint.h    |  1 +
 .../Library/EdkIIGlueUefiDriverEntryPoint.h      |  1 +
 EmbeddedPkg/TemplateSec/TemplateSec.c            |  1 +
 EmulatorPkg/Sec/Sec.c                            |  1 +
 .../DxeSmmDriverEntryPoint/DriverEntryPoint.c    |  1 +
 MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c |  1 +
 MdePkg/Include/Base.h                            |  7 +++++++
 MdePkg/Include/Library/DxeCoreEntryPoint.h       |  1 +
 MdePkg/Include/Library/PeiCoreEntryPoint.h       |  1 +
 MdePkg/Include/Library/PeimEntryPoint.h          |  1 +
 .../Include/Library/UefiApplicationEntryPoint.h  |  1 +
 MdePkg/Include/Library/UefiDriverEntryPoint.h    |  1 +
 MdePkg/Include/X64/ProcessorBind.h               | 16 +++++++++++-----
 .../DxeCoreEntryPoint/DxeCoreEntryPoint.c        |  1 +
 .../PeiCoreEntryPoint/PeiCoreEntryPoint.c        |  1 +
 MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c   |  1 +
 .../ApplicationEntryPoint.c                      |  1 +
 .../UefiDriverEntryPoint/DriverEntryPoint.c      |  1 +
 Nt32Pkg/Sec/SecMain.c                            |  1 +
 .../PlatformSecLibNull/PlatformSecLibNull.c      |  1 +
 26 files changed, 42 insertions(+), 5 deletions(-)

-- 
2.17.1



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFC PATCH 01/11] MdePkg/ProcessorBind.h: define macro to decorate module entry points
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
@ 2018-06-12 15:22 ` Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 02/11] DuetPkg: annotate module entry points with EFI_ENTRYPOINT Ard Biesheuvel
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:22 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Add a macro EFI_ENTRYPOINT that we will use to decorate functions that
serve as the entry points for EFI modules. This is necessary to work
around a limitation in GCC, which may prune such routines from the
ELF binary if they are defined with hidden visibility, even if they
are explicitly referenced as the entry point on the linker command
line.

The hidden visibility is required to inform the compiler that, even
though we are building the code in PIE mode, we are only doing so
to get code that can run anywhere in the address space without
requiring 64-bit wide absolute symbol references, and we are not
interested in other things that PIE code typically provides, such
as symbol preemptability and a reduced CoW footprint due to the
fact that all dynamic relocations target the same area in the binary.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/Base.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/MdePkg/Include/Base.h b/MdePkg/Include/Base.h
index 4f7bd4449c36..eee48dcd4b29 100644
--- a/MdePkg/Include/Base.h
+++ b/MdePkg/Include/Base.h
@@ -274,6 +274,13 @@ VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
   #define PACKED
 #endif
 
+#ifndef EFI_ENTRYPOINT
+  //
+  // Set to empty value if not already set by the arch-specific header
+  //
+  #define EFI_ENTRYPOINT
+#endif
+
 ///
 /// 128 bit buffer containing a unique identifier value.
 /// Unless otherwise specified, aligned on a 64 bit boundary.
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 02/11] DuetPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 01/11] MdePkg/ProcessorBind.h: define macro to decorate module entry points Ard Biesheuvel
@ 2018-06-12 15:22 ` Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 03/11] EdkCompatibilityPkg: " Ard Biesheuvel
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:22 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 DuetPkg/DxeIpl/DxeInit.c   | 1 +
 DuetPkg/EfiLdr/EfiLoader.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/DuetPkg/DxeIpl/DxeInit.c b/DuetPkg/DxeIpl/DxeInit.c
index b9a40a8209c1..9c86279c17c1 100644
--- a/DuetPkg/DxeIpl/DxeInit.c
+++ b/DuetPkg/DxeIpl/DxeInit.c
@@ -269,6 +269,7 @@ Returns:
 
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFILDRHANDOFF  *Handoff
   )
diff --git a/DuetPkg/EfiLdr/EfiLoader.c b/DuetPkg/EfiLdr/EfiLoader.c
index ac950b55fa6d..89c8ff3885ff 100644
--- a/DuetPkg/EfiLdr/EfiLoader.c
+++ b/DuetPkg/EfiLdr/EfiLoader.c
@@ -282,6 +282,7 @@ PrintHeader ('F');
 
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   UINT32    BiosMemoryMapBaseAddress
   )
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 03/11] EdkCompatibilityPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 01/11] MdePkg/ProcessorBind.h: define macro to decorate module entry points Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 02/11] DuetPkg: annotate module entry points with EFI_ENTRYPOINT Ard Biesheuvel
@ 2018-06-12 15:22 ` Ard Biesheuvel
  2018-06-12 15:22 ` [RFC PATCH 04/11] EmbeddedPkg: " Ard Biesheuvel
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:22 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueDxeDriverEntryPoint.c        | 1 +
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGluePeimEntryPoint.c             | 1 +
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueSmmDriverEntryPoint.c        | 1 +
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueDxeSmmDriverEntryPoint.h | 1 +
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGluePeimEntryPoint.h         | 1 +
 EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueUefiDriverEntryPoint.h   | 1 +
 6 files changed, 6 insertions(+)

diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueDxeDriverEntryPoint.c b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueDxeDriverEntryPoint.c
index 2b71b1ad42ee..03100f15014f 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueDxeDriverEntryPoint.c
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueDxeDriverEntryPoint.c
@@ -563,6 +563,7 @@ __EDKII_GLUE_MODULE_ENTRY_POINT__ (
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGluePeimEntryPoint.c b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGluePeimEntryPoint.c
index 3a9ed9b4b5fe..a88915a403b8 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGluePeimEntryPoint.c
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGluePeimEntryPoint.c
@@ -75,6 +75,7 @@ __EDKII_GLUE_MODULE_ENTRY_POINT__ (
 --*/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_FFS_FILE_HEADER       *FfsHeader,
   IN EFI_PEI_SERVICES          **PeiServices
diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueSmmDriverEntryPoint.c b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueSmmDriverEntryPoint.c
index 954f7e9c39da..b66e87d87b8e 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueSmmDriverEntryPoint.c
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/EntryPoints/EdkIIGlueSmmDriverEntryPoint.c
@@ -307,6 +307,7 @@ __EDKII_GLUE_MODULE_ENTRY_POINT__ (
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueDxeSmmDriverEntryPoint.h b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueDxeSmmDriverEntryPoint.h
index 4a04b9909888..c1c078c4e07b 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueDxeSmmDriverEntryPoint.h
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueDxeSmmDriverEntryPoint.h
@@ -49,6 +49,7 @@ extern const UINT8                    _gDriverUnloadImageCount;
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGluePeimEntryPoint.h b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGluePeimEntryPoint.h
index 537d3951e1fd..461c0e4874ae 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGluePeimEntryPoint.h
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGluePeimEntryPoint.h
@@ -39,6 +39,7 @@ extern const UINT32                   _gPeimRevision;
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_FFS_FILE_HEADER       *FfsHeader,
   IN EFI_PEI_SERVICES          **PeiServices
diff --git a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueUefiDriverEntryPoint.h b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueUefiDriverEntryPoint.h
index 07a7775abc46..f17aefaf48e7 100644
--- a/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueUefiDriverEntryPoint.h
+++ b/EdkCompatibilityPkg/Foundation/Library/EdkIIGlueLib/Include/Library/EdkIIGlueUefiDriverEntryPoint.h
@@ -60,6 +60,7 @@ extern const EFI_EVENT_NOTIFY         _gDriverSetVirtualAddressMapEvent[];
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 04/11] EmbeddedPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (2 preceding siblings ...)
  2018-06-12 15:22 ` [RFC PATCH 03/11] EdkCompatibilityPkg: " Ard Biesheuvel
@ 2018-06-12 15:22 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 05/11] EmulatorPkg: " Ard Biesheuvel
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:22 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 EmbeddedPkg/TemplateSec/TemplateSec.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/EmbeddedPkg/TemplateSec/TemplateSec.c b/EmbeddedPkg/TemplateSec/TemplateSec.c
index c63adbb6f90f..09bc779aced3 100644
--- a/EmbeddedPkg/TemplateSec/TemplateSec.c
+++ b/EmbeddedPkg/TemplateSec/TemplateSec.c
@@ -21,6 +21,7 @@
 #include <Ppi/GuidedSectionExtraction.h>
 
 VOID
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   VOID
   )
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 05/11] EmulatorPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (3 preceding siblings ...)
  2018-06-12 15:22 ` [RFC PATCH 04/11] EmbeddedPkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 06/11] IntelFrameWorkPkg: " Ard Biesheuvel
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 EmulatorPkg/Sec/Sec.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/EmulatorPkg/Sec/Sec.c b/EmulatorPkg/Sec/Sec.c
index 8a015682ddd0..266e57240a87 100644
--- a/EmulatorPkg/Sec/Sec.c
+++ b/EmulatorPkg/Sec/Sec.c
@@ -67,6 +67,7 @@ EFI_PEI_PPI_DESCRIPTOR  gPrivateDispatchTable[] = {
 **/
 VOID
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_SEC_PEI_HAND_OFF   *SecCoreData,
   IN EFI_PEI_PPI_DESCRIPTOR *PpiList
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 06/11] IntelFrameWorkPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (4 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 05/11] EmulatorPkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 07/11] MdeModulePkg: " Ard Biesheuvel
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c b/IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c
index e6892cbafefd..e1b6f065e455 100644
--- a/IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c
+++ b/IntelFrameworkPkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c
@@ -156,6 +156,7 @@ _DriverUnloadHandler (
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 07/11] MdeModulePkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (5 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 06/11] IntelFrameWorkPkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 08/11] MdePkg: " Ard Biesheuvel
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c b/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c
index e1871c3c2ad5..0dc0b819e57e 100644
--- a/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c
+++ b/MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c
@@ -219,6 +219,7 @@ PageFaultHandler (
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   SWITCH_32_TO_64_CONTEXT       *EntrypointContext,
   SWITCH_64_TO_32_CONTEXT       *ReturnContext
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 08/11] MdePkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (6 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 07/11] MdeModulePkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 09/11] Nt32Pkg: " Ard Biesheuvel
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/Library/DxeCoreEntryPoint.h                       | 1 +
 MdePkg/Include/Library/PeiCoreEntryPoint.h                       | 1 +
 MdePkg/Include/Library/PeimEntryPoint.h                          | 1 +
 MdePkg/Include/Library/UefiApplicationEntryPoint.h               | 1 +
 MdePkg/Include/Library/UefiDriverEntryPoint.h                    | 1 +
 MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c             | 1 +
 MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c             | 1 +
 MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c                   | 1 +
 MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c | 1 +
 MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c           | 1 +
 10 files changed, 10 insertions(+)

diff --git a/MdePkg/Include/Library/DxeCoreEntryPoint.h b/MdePkg/Include/Library/DxeCoreEntryPoint.h
index acf514a61665..a90b6b41d9dc 100644
--- a/MdePkg/Include/Library/DxeCoreEntryPoint.h
+++ b/MdePkg/Include/Library/DxeCoreEntryPoint.h
@@ -35,6 +35,7 @@ extern VOID  *gHobList;
 **/
 VOID
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN VOID  *HobStart
   );
diff --git a/MdePkg/Include/Library/PeiCoreEntryPoint.h b/MdePkg/Include/Library/PeiCoreEntryPoint.h
index 7485f7a40e98..8601a0b106e6 100644
--- a/MdePkg/Include/Library/PeiCoreEntryPoint.h
+++ b/MdePkg/Include/Library/PeiCoreEntryPoint.h
@@ -47,6 +47,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 VOID
 EFIAPI 
+EFI_ENTRYPOINT
 _ModuleEntryPoint(
   IN CONST  EFI_SEC_PEI_HAND_OFF    *SecCoreData,
   IN CONST  EFI_PEI_PPI_DESCRIPTOR  *PpiList
diff --git a/MdePkg/Include/Library/PeimEntryPoint.h b/MdePkg/Include/Library/PeimEntryPoint.h
index f4b752ef9609..b8b2928b087c 100644
--- a/MdePkg/Include/Library/PeimEntryPoint.h
+++ b/MdePkg/Include/Library/PeimEntryPoint.h
@@ -36,6 +36,7 @@ extern CONST UINT32       _gPeimRevision;
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_PEI_FILE_HANDLE       FileHandle,
   IN CONST EFI_PEI_SERVICES    **PeiServices
diff --git a/MdePkg/Include/Library/UefiApplicationEntryPoint.h b/MdePkg/Include/Library/UefiApplicationEntryPoint.h
index ec568ab6c5ad..9fe54aceceee 100644
--- a/MdePkg/Include/Library/UefiApplicationEntryPoint.h
+++ b/MdePkg/Include/Library/UefiApplicationEntryPoint.h
@@ -40,6 +40,7 @@ extern CONST UINT32        _gUefiDriverRevision;
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/MdePkg/Include/Library/UefiDriverEntryPoint.h b/MdePkg/Include/Library/UefiDriverEntryPoint.h
index f9d9befb9c12..107b6e45bd6e 100644
--- a/MdePkg/Include/Library/UefiDriverEntryPoint.h
+++ b/MdePkg/Include/Library/UefiDriverEntryPoint.h
@@ -57,6 +57,7 @@ extern CONST UINT8                    _gDriverUnloadImageCount;
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c
index d3d8c4c47c51..ea71ab8d8eb6 100644
--- a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c
+++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c
@@ -39,6 +39,7 @@ VOID *gHobList = NULL;
 **/
 VOID
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN VOID  *HobStart
   )
diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c
index 5662ccff15f0..eef27651c35a 100644
--- a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c
+++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c
@@ -56,6 +56,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 VOID
 EFIAPI 
+EFI_ENTRYPOINT
 _ModuleEntryPoint(
   IN CONST  EFI_SEC_PEI_HAND_OFF    *SecCoreData,
   IN CONST  EFI_PEI_PPI_DESCRIPTOR  *PpiList
diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c
index 83a1bd8ccc32..201445ed69a8 100644
--- a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c
+++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c
@@ -34,6 +34,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_PEI_FILE_HANDLE       FileHandle,
   IN CONST EFI_PEI_SERVICES    **PeiServices
diff --git a/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c b/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c
index dc05b23fd823..a7cdbfa13d89 100644
--- a/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c
+++ b/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c
@@ -38,6 +38,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
diff --git a/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c b/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c
index f5da5ac4ad10..a14874df2bea 100644
--- a/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c
+++ b/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c
@@ -92,6 +92,7 @@ _DriverUnloadHandler (
 **/
 EFI_STATUS
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 09/11] Nt32Pkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (7 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 08/11] MdePkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 10/11] UefiCpuPkg: " Ard Biesheuvel
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 Nt32Pkg/Sec/SecMain.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Nt32Pkg/Sec/SecMain.c b/Nt32Pkg/Sec/SecMain.c
index 74871a67c8ca..e9583504d153 100644
--- a/Nt32Pkg/Sec/SecMain.c
+++ b/Nt32Pkg/Sec/SecMain.c
@@ -1087,6 +1087,7 @@ SecNt32PeCoffRelocateImage (
 
 
 VOID
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   VOID
   )
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 10/11] UefiCpuPkg: annotate module entry points with EFI_ENTRYPOINT
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (8 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 09/11] Nt32Pkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 15:23 ` [RFC PATCH 11/11] MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity override Ard Biesheuvel
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

Annotate module entry points with EFI_ENTRYPOINT so we can classify
the resulting symbol as global explicitly at link time.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.c b/UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.c
index ad3e9090c63f..3ca9ac64a0f8 100644
--- a/UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.c
+++ b/UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.c
@@ -82,6 +82,7 @@ SecPlatformDisableTemporaryMemory (
 **/
 VOID
 EFIAPI
+EFI_ENTRYPOINT
 _ModuleEntryPoint (
   VOID
   )
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [RFC PATCH 11/11] MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity override
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (9 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 10/11] UefiCpuPkg: " Ard Biesheuvel
@ 2018-06-12 15:23 ` Ard Biesheuvel
  2018-06-12 18:33 ` [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Laszlo Ersek
  2018-06-13  2:08 ` Shi, Steven
  12 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 15:23 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ard Biesheuvel, Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu,
	Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng, Eric Dong,
	Laszlo Ersek, Zenith432, Shi, Steven

When LTO is in effect, overriding the symbol visibility to 'hidden'
using a GCC pragma used to result in module entry points being discarded,
and along with them all other code in the binary.

Now that we annotated all module entry points explicitly as having
'default' visibility, this is no longer the case, and we can drop this
restriction. This prevents GCC's LTO code generator from emitting GOT
based relocations that are non-trivial to deal with in GenFw.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 MdePkg/Include/X64/ProcessorBind.h | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/MdePkg/Include/X64/ProcessorBind.h b/MdePkg/Include/X64/ProcessorBind.h
index 38ef2665390f..7f78489bc2c4 100644
--- a/MdePkg/Include/X64/ProcessorBind.h
+++ b/MdePkg/Include/X64/ProcessorBind.h
@@ -27,18 +27,24 @@
 #pragma pack()
 #endif
 
-#if defined(__GNUC__) && defined(__pic__) && !defined(USING_LTO)
+#if defined(__GNUC__) && defined(__pic__)
 //
 // Mark all symbol declarations and references as hidden, meaning they will
 // not be subject to symbol preemption. This allows the compiler to refer to
 // symbols directly using relative references rather than via the GOT, which
 // contains absolute symbol addresses that are subject to runtime relocation.
 //
-// The LTO linker will not emit GOT based relocations when all symbol
-// references can be resolved locally, and so there is no need to set the
-// pragma in that case (and doing so will cause other issues).
-//
 #pragma GCC visibility push (hidden)
+
+//
+// When LTO is in effect, symbols with hidden visibility will get discarded,
+// since by definition, they cannot be referenced externally, even if they
+// are the entry point of the executable. So we will have to change the
+// visibility back to 'default' explicitly for all such entry points.
+//
+#ifdef USING_LTO
+#define EFI_ENTRYPOINT __attribute__((__visibility__("default")))
+#endif
 #endif
 
 #if defined(__INTEL_COMPILER)
-- 
2.17.1



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (10 preceding siblings ...)
  2018-06-12 15:23 ` [RFC PATCH 11/11] MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity override Ard Biesheuvel
@ 2018-06-12 18:33 ` Laszlo Ersek
  2018-06-12 18:58   ` Ard Biesheuvel
  2018-06-13  2:08 ` Shi, Steven
  12 siblings, 1 reply; 15+ messages in thread
From: Laszlo Ersek @ 2018-06-12 18:33 UTC (permalink / raw)
  To: Ard Biesheuvel, edk2-devel
  Cc: Michael D Kinney, Liming Gao, Ruiyu Ni, Hao Wu, Leif Lindholm,
	Jordan Justen, Andrew Fish, Star Zeng, Eric Dong, Zenith432,
	Shi, Steven

Some super-naive questions, which are supposed to educate me, and not to
question the series:

On 06/12/18 17:22, Ard Biesheuvel wrote:
> The GCC toolchain uses PIE mode when building code for X64, because it
> is the most efficient in size: it uses relative references where
> possible, but still uses 64-bit quantities for absolute symbol
> references,

Absolute symbol references such as? References to fixed (constant)
addresses?

> which is optimal for executables that need to be converted
> to PE/COFF using GenFw.

Why is that approach optimal? As few relocations records are required as
possible?

> Enabling PIE mode has a couple of side effects though, primarily caused
> by the fact that the primary application area of GCC is to build programs
> for userland. GCC will assume that ELF symbols should be preemptible (which
> makes sense for PIC but not for PIE,

Why don't preemptible symbols make sense for PIE?

For example, if a userspace program loads a plugin with dlopen(), and
the plugin (.so) uses helper functions from the main executable, then
the main executable has to be (well, had to be, earlier?) built with
"-rdynamic". Wouldn't this mean the main executable could both be PIE
and sensibly have preemptible symbols?

(My apologies if I'm disturbingly ignorant about this and the question
doesn't even make sense.)

> but this simply seems to be the result
> of code being shared between the two modes), and it will attempt to keep
> absolute references close to each other so that dynamic relocations that
> trigger CoW for text pages have the smallest possible footprint.

So... Given this behavior, why is it a problem for us? What are the bad
symptoms? What is currently broken?

Sorry about my naivety here.

Thanks,
Laszlo

> These side effects can be mititgated by overriding the visibility of all
> symbol definitions *and* symbol references, using a special #pragma. This
> will inform the compiler that symbol preemption and dynamic relocations
> are not a concern, and that all symbol references can be emitted as direct
> relative references rather than relative references to a GOT entry containing
> the absolute address. Unsurprisingly, this leads to better and smaller code.
> 
> Unfortunately, we have not been able to set this override when LTO is in
> effect, because the LTO code generator infers from the hidden visibility
> of all symbols that none of the code is reachable, and discards it all,
> leading to corrupt, empty binaries.
> 
> We can work around this by overriding the visibility for symbols that are
> module entry points. So implement this for all occcurrences of the symbol
> '_ModuleEntryPoint', and enable 'hidden' visibility in LTO builds as well.
> 
> Note that all the changes in this series resolve to no-ops if USING_LTO
> is not #defined.
> 
> Code can be found here:
> https://github.com/ardbiesheuvel/edk2/tree/x64-lto-visibility
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Hao Wu <hao.a.wu@intel.com>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Zenith432 <zenith432@users.sourceforge.net>
> Cc: "Shi, Steven" <steven.shi@intel.com>
> 
> Ard Biesheuvel (11):
>   MdePkg/ProcessorBind.h: define macro to decorate module entry points
>   DuetPkg: annotate module entry points with EFI_ENTRYPOINT
>   EdkCompatibilityPkg: annotate module entry points with EFI_ENTRYPOINT
>   EmbeddedPkg: annotate module entry points with EFI_ENTRYPOINT
>   EmulatorPkg: annotate module entry points with EFI_ENTRYPOINT
>   IntelFrameWorkPkg: annotate module entry points with EFI_ENTRYPOINT
>   MdeModulePkg: annotate module entry points with EFI_ENTRYPOINT
>   MdePkg: annotate module entry points with EFI_ENTRYPOINT
>   Nt32Pkg: annotate module entry points with EFI_ENTRYPOINT
>   UefiCpuPkg: annotate module entry points with EFI_ENTRYPOINT
>   MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity
>     override
> 
>  DuetPkg/DxeIpl/DxeInit.c                         |  1 +
>  DuetPkg/EfiLdr/EfiLoader.c                       |  1 +
>  .../EntryPoints/EdkIIGlueDxeDriverEntryPoint.c   |  1 +
>  .../EntryPoints/EdkIIGluePeimEntryPoint.c        |  1 +
>  .../EntryPoints/EdkIIGlueSmmDriverEntryPoint.c   |  1 +
>  .../Library/EdkIIGlueDxeSmmDriverEntryPoint.h    |  1 +
>  .../Include/Library/EdkIIGluePeimEntryPoint.h    |  1 +
>  .../Library/EdkIIGlueUefiDriverEntryPoint.h      |  1 +
>  EmbeddedPkg/TemplateSec/TemplateSec.c            |  1 +
>  EmulatorPkg/Sec/Sec.c                            |  1 +
>  .../DxeSmmDriverEntryPoint/DriverEntryPoint.c    |  1 +
>  MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c |  1 +
>  MdePkg/Include/Base.h                            |  7 +++++++
>  MdePkg/Include/Library/DxeCoreEntryPoint.h       |  1 +
>  MdePkg/Include/Library/PeiCoreEntryPoint.h       |  1 +
>  MdePkg/Include/Library/PeimEntryPoint.h          |  1 +
>  .../Include/Library/UefiApplicationEntryPoint.h  |  1 +
>  MdePkg/Include/Library/UefiDriverEntryPoint.h    |  1 +
>  MdePkg/Include/X64/ProcessorBind.h               | 16 +++++++++++-----
>  .../DxeCoreEntryPoint/DxeCoreEntryPoint.c        |  1 +
>  .../PeiCoreEntryPoint/PeiCoreEntryPoint.c        |  1 +
>  MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c   |  1 +
>  .../ApplicationEntryPoint.c                      |  1 +
>  .../UefiDriverEntryPoint/DriverEntryPoint.c      |  1 +
>  Nt32Pkg/Sec/SecMain.c                            |  1 +
>  .../PlatformSecLibNull/PlatformSecLibNull.c      |  1 +
>  26 files changed, 42 insertions(+), 5 deletions(-)
> 



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code
  2018-06-12 18:33 ` [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Laszlo Ersek
@ 2018-06-12 18:58   ` Ard Biesheuvel
  0 siblings, 0 replies; 15+ messages in thread
From: Ard Biesheuvel @ 2018-06-12 18:58 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: edk2-devel@lists.01.org, Michael D Kinney, Liming Gao, Ruiyu Ni,
	Hao Wu, Leif Lindholm, Jordan Justen, Andrew Fish, Star Zeng,
	Eric Dong, Zenith432, Shi, Steven

On 12 June 2018 at 20:33, Laszlo Ersek <lersek@redhat.com> wrote:
> Some super-naive questions, which are supposed to educate me, and not to
> question the series:
>
> On 06/12/18 17:22, Ard Biesheuvel wrote:
>> The GCC toolchain uses PIE mode when building code for X64, because it
>> is the most efficient in size: it uses relative references where
>> possible, but still uses 64-bit quantities for absolute symbol
>> references,
>
> Absolute symbol references such as? References to fixed (constant)
> addresses?
>

I should have been clearer here: from the GCC man page (apologies for
the whitespace soup)

"""
       -mcmodel=small
           Generate code for the small code model: the program and its
symbols must be linked in the lower 2 GB of the address space.
Pointers are 64 bits.  Programs can be statically or
           dynamically linked.  This is the default code model.

       -mcmodel=kernel
           Generate code for the kernel code model.  The kernel runs
in the negative 2 GB of the address space.  This model has to be used
for Linux kernel code.

       -mcmodel=medium
           Generate code for the medium model: the program is linked
in the lower 2 GB of the address space.  Small symbols are also placed
there.  Symbols with sizes larger than
           -mlarge-data-threshold are put into large data or BSS
sections and can be located above 2GB.  Programs can be statically or
dynamically linked.

       -mcmodel=large
           Generate code for the large model.  This model makes no
assumptions about addresses and sizes of sections.
"""

Formerly, we used the large model because UEFI can load PE/COFF
executables anywhere in the lower address space, not only in the first
2 GB. The small PIE model is the best fit for UEFI because it does not
have this limitation, but [unlike the large model] only uses absolute
references when necessary, and will use relative references when it
can. (I.e., it assumes the program will fit in 4 GB of memory, which
the large model does not)

Absolute symbol references are things like statically initialized
function pointer variables or other quantities whose value cannot be
obtained programmatically at runtime using a relative reference.

>> which is optimal for executables that need to be converted
>> to PE/COFF using GenFw.
>
> Why is that approach optimal? As few relocations records are required as
> possible?
>

Because GenFw translates ELF relocations into PE/COFF relocations, but
only for the subset that requires fixing up at runtime. Relative
references do not require such fixups, so a code model that minimizes
the number of absolute relocations is therefore optimal. Note that
absolute references typically require twice the space as well.

>> Enabling PIE mode has a couple of side effects though, primarily caused
>> by the fact that the primary application area of GCC is to build programs
>> for userland. GCC will assume that ELF symbols should be preemptible (which
>> makes sense for PIC but not for PIE,
>
> Why don't preemptible symbols make sense for PIE?
>
> For example, if a userspace program loads a plugin with dlopen(), and
> the plugin (.so) uses helper functions from the main executable, then
> the main executable has to be (well, had to be, earlier?) built with
> "-rdynamic". Wouldn't this mean the main executable could both be PIE
> and sensibly have preemptible symbols?
>
> (My apologies if I'm disturbingly ignorant about this and the question
> doesn't even make sense.)
>

I mean that the symbols defined by the PIE executable [i.e., not
shared library] can never be preempted. Only symbols in shared
libraries can be preempted by the symbols in the main executable, not
the other way around.

>> but this simply seems to be the result
>> of code being shared between the two modes), and it will attempt to keep
>> absolute references close to each other so that dynamic relocations that
>> trigger CoW for text pages have the smallest possible footprint.
>
> So... Given this behavior, why is it a problem for us? What are the bad
> symptoms? What is currently broken?
>

The bad symptoms are that PIC code will use GOT entries for all symbol
references, meaning that instead of a direct relative reference from
the code, it will emit a relative reference to the GOT entry
containing the absolute address of the symbol. This involves an
additional memory reference, and it requires the GOT entry (which by
definition contains an absolute address) to be fixed up at load time.

What is broken [as reported by Zenith432] is that GCC in LTO mode may
in some cases still emit GOT based relocations that GenFw currently
cannot handle. If the address of a symbol is used in a calculation, or
when the address of a symbol is taken but not dereferenced (but only
passed to a function, for instance), GCC in -Os mode will optimize
this into a GOTPCREL reference.

Quoting from a private email from Zenith432 (who has already proposed
GenFw changes to handle these relocations

"""
I figured out what's going on with LTO build in GCC5 that is compiled
with -Os -flto -DUSING_LTO and does not use visibility #pragma.

When compiling with LTO enabled, what happens is that all C source
files are transformed during compilation stage to LTO intermediate
bytecode (gimple in GCC).

Then when static link (ld) takes place, all LTO intermediate bytecode
is sent back to compiler code-generation backend to have machine code
generated for it as if all the source code is one big C source file
("whole program optimization").

As a result of this, all the extern symbols become local symbols !
like file-level static.  Because it's as if all the code is in one big
source file.  Since there is no dynamic linking, there are no more
"extern", and all symbols are like file-level static and treated the
same.

This is why the LTO build stops emitting GOT loads for
size-optimization purposes.  GCC doesn't emit GOT loads for file-level
static, and in LTO build they're all like that - so no GOT loads.

But there is still something that fouls this up...

If an extern symbol is defined in assembly source file.

Because assembly source files don't participate in LTO.  They are
transformed by assembler into X64 machine code.  During ld, any extern
symbol that is defined in an assembly source file and declared and
used by C source file is treated as before like external symbol.
Which means code generator can go back to its practice of emitting GOT
loads if they reduce code size.
"""

Instead of 'fixing' GenFw, I attempted to go back to the original
changes Steven and I did for LTO, to try and remember why we could not
use the GCC visibility #pragma when enabling LTO. That is the issue
this series aims to fix (but it is an RFC, so comments welcome)

-- 
Ard.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code
  2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
                   ` (11 preceding siblings ...)
  2018-06-12 18:33 ` [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Laszlo Ersek
@ 2018-06-13  2:08 ` Shi, Steven
  12 siblings, 0 replies; 15+ messages in thread
From: Shi, Steven @ 2018-06-13  2:08 UTC (permalink / raw)
  To: Ard Biesheuvel, Zenith432
  Cc: Kinney, Michael D, Gao, Liming, Ni, Ruiyu, Wu, Hao A,
	Leif Lindholm, Justen, Jordan L, Andrew Fish, Zeng, Star,
	Dong, Eric, Laszlo Ersek, edk2-devel@lists.01.org

Hi Ard, Zenith,
Thank you both explained the complete knowledge about ELF GOT, LTO, PIC/PIE, machine code mode and GCC visibility #pragma. It is pretty good to read them all in one picture. And I believe copying these explain to a edk2 wiki page in GitHub could be very useful for other edk2 developers. 

>From code change impact view, I see to use the hidden visibility for LTO, which is to remove the !defined(USING_LTO) in X64/ProcessorBind.h actually, need to change other 20+ files overall the edk2. The cost looks not small. We might need more justification to accept such change.  Does the hidden visibility in LTO can improve the LTO build code size? Is there any other benefit?

Steven Shi
Intel\SSG\STO\UEFI Firmware

Tel: +86 021-61166522
iNet: 821-6522

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Tuesday, June 12, 2018 11:23 PM
> To: edk2-devel@lists.01.org
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Gao, Liming <liming.gao@intel.com>; Ni,
> Ruiyu <ruiyu.ni@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Leif
> Lindholm <leif.lindholm@linaro.org>; Justen, Jordan L
> <jordan.l.justen@intel.com>; Andrew Fish <afish@apple.com>; Zeng, Star
> <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>; Laszlo Ersek
> <lersek@redhat.com>; Zenith432 <zenith432@users.sourceforge.net>; Shi,
> Steven <steven.shi@intel.com>
> Subject: [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code
> 
> The GCC toolchain uses PIE mode when building code for X64, because it
> is the most efficient in size: it uses relative references where
> possible, but still uses 64-bit quantities for absolute symbol
> references, which is optimal for executables that need to be converted
> to PE/COFF using GenFw.
> 
> Enabling PIE mode has a couple of side effects though, primarily caused
> by the fact that the primary application area of GCC is to build programs
> for userland. GCC will assume that ELF symbols should be preemptible (which
> makes sense for PIC but not for PIE, but this simply seems to be the result
> of code being shared between the two modes), and it will attempt to keep
> absolute references close to each other so that dynamic relocations that
> trigger CoW for text pages have the smallest possible footprint.
> 
> These side effects can be mititgated by overriding the visibility of all
> symbol definitions *and* symbol references, using a special #pragma. This
> will inform the compiler that symbol preemption and dynamic relocations
> are not a concern, and that all symbol references can be emitted as direct
> relative references rather than relative references to a GOT entry containing
> the absolute address. Unsurprisingly, this leads to better and smaller code.
> 
> Unfortunately, we have not been able to set this override when LTO is in
> effect, because the LTO code generator infers from the hidden visibility
> of all symbols that none of the code is reachable, and discards it all,
> leading to corrupt, empty binaries.
> 
> We can work around this by overriding the visibility for symbols that are
> module entry points. So implement this for all occcurrences of the symbol
> '_ModuleEntryPoint', and enable 'hidden' visibility in LTO builds as well.
> 
> Note that all the changes in this series resolve to no-ops if USING_LTO
> is not #defined.
> 
> Code can be found here:
> https://github.com/ardbiesheuvel/edk2/tree/x64-lto-visibility
> 
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Hao Wu <hao.a.wu@intel.com>
> Cc: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Andrew Fish <afish@apple.com>
> Cc: Star Zeng <star.zeng@intel.com>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Zenith432 <zenith432@users.sourceforge.net>
> Cc: "Shi, Steven" <steven.shi@intel.com>
> 
> Ard Biesheuvel (11):
>   MdePkg/ProcessorBind.h: define macro to decorate module entry points
>   DuetPkg: annotate module entry points with EFI_ENTRYPOINT
>   EdkCompatibilityPkg: annotate module entry points with EFI_ENTRYPOINT
>   EmbeddedPkg: annotate module entry points with EFI_ENTRYPOINT
>   EmulatorPkg: annotate module entry points with EFI_ENTRYPOINT
>   IntelFrameWorkPkg: annotate module entry points with EFI_ENTRYPOINT
>   MdeModulePkg: annotate module entry points with EFI_ENTRYPOINT
>   MdePkg: annotate module entry points with EFI_ENTRYPOINT
>   Nt32Pkg: annotate module entry points with EFI_ENTRYPOINT
>   UefiCpuPkg: annotate module entry points with EFI_ENTRYPOINT
>   MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity
>     override
> 
>  DuetPkg/DxeIpl/DxeInit.c                         |  1 +
>  DuetPkg/EfiLdr/EfiLoader.c                       |  1 +
>  .../EntryPoints/EdkIIGlueDxeDriverEntryPoint.c   |  1 +
>  .../EntryPoints/EdkIIGluePeimEntryPoint.c        |  1 +
>  .../EntryPoints/EdkIIGlueSmmDriverEntryPoint.c   |  1 +
>  .../Library/EdkIIGlueDxeSmmDriverEntryPoint.h    |  1 +
>  .../Include/Library/EdkIIGluePeimEntryPoint.h    |  1 +
>  .../Library/EdkIIGlueUefiDriverEntryPoint.h      |  1 +
>  EmbeddedPkg/TemplateSec/TemplateSec.c            |  1 +
>  EmulatorPkg/Sec/Sec.c                            |  1 +
>  .../DxeSmmDriverEntryPoint/DriverEntryPoint.c    |  1 +
>  MdeModulePkg/Universal/CapsulePei/X64/X64Entry.c |  1 +
>  MdePkg/Include/Base.h                            |  7 +++++++
>  MdePkg/Include/Library/DxeCoreEntryPoint.h       |  1 +
>  MdePkg/Include/Library/PeiCoreEntryPoint.h       |  1 +
>  MdePkg/Include/Library/PeimEntryPoint.h          |  1 +
>  .../Include/Library/UefiApplicationEntryPoint.h  |  1 +
>  MdePkg/Include/Library/UefiDriverEntryPoint.h    |  1 +
>  MdePkg/Include/X64/ProcessorBind.h               | 16 +++++++++++-----
>  .../DxeCoreEntryPoint/DxeCoreEntryPoint.c        |  1 +
>  .../PeiCoreEntryPoint/PeiCoreEntryPoint.c        |  1 +
>  MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c   |  1 +
>  .../ApplicationEntryPoint.c                      |  1 +
>  .../UefiDriverEntryPoint/DriverEntryPoint.c      |  1 +
>  Nt32Pkg/Sec/SecMain.c                            |  1 +
>  .../PlatformSecLibNull/PlatformSecLibNull.c      |  1 +
>  26 files changed, 42 insertions(+), 5 deletions(-)
> 
> --
> 2.17.1



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-06-13  2:08 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-06-12 15:22 [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Ard Biesheuvel
2018-06-12 15:22 ` [RFC PATCH 01/11] MdePkg/ProcessorBind.h: define macro to decorate module entry points Ard Biesheuvel
2018-06-12 15:22 ` [RFC PATCH 02/11] DuetPkg: annotate module entry points with EFI_ENTRYPOINT Ard Biesheuvel
2018-06-12 15:22 ` [RFC PATCH 03/11] EdkCompatibilityPkg: " Ard Biesheuvel
2018-06-12 15:22 ` [RFC PATCH 04/11] EmbeddedPkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 05/11] EmulatorPkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 06/11] IntelFrameWorkPkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 07/11] MdeModulePkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 08/11] MdePkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 09/11] Nt32Pkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 10/11] UefiCpuPkg: " Ard Biesheuvel
2018-06-12 15:23 ` [RFC PATCH 11/11] MdePkg/ProcessorBind.h X64: drop non-LTO limitation on visiblity override Ard Biesheuvel
2018-06-12 18:33 ` [RFC PATCH 00/11] GCC/X64: use hidden visibility for LTO PIE code Laszlo Ersek
2018-06-12 18:58   ` Ard Biesheuvel
2018-06-13  2:08 ` Shi, Steven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox