From c38348dbb59b824873b319f42b59c3edb5342b8e Mon Sep 17 00:00:00 2001 From: Adrien 'neox' Bourmault Date: Tue, 8 Aug 2023 17:40:06 +0200 Subject: [PATCH] coreboot/fam15h: fix for gcc/gnat building With newer hostcc, trying to build GCC 8.3.0 will raise an error from ld: undefined reference to `__gnat_begin_handler_v1' This commit adds a patch for GCC found on coreboot [1] correcting this error by backporting the GNAT exception handler v1 to GCC 8.3.0 allowing GNAT to be built with newer hostcc like GCC 10+. [1]https://review.coreboot.org/c/coreboot/+/42158 Signed-off-by: Adrien 'neox' Bourmault Acked-by: Denis 'GNUtoo' Carikli --- .../patches/0011-gcc-8.3.0_gnat_eh_new.patch | 232 ++++++++++++++++++ .../patches/0011-gcc-8.3.0_gnat_eh_new.patch | 232 ++++++++++++++++++ 2 files changed, 464 insertions(+) create mode 100644 resources/coreboot/fam15h_rdimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch create mode 100644 resources/coreboot/fam15h_udimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch diff --git a/resources/coreboot/fam15h_rdimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch b/resources/coreboot/fam15h_rdimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch new file mode 100644 index 0000000..443d851 --- /dev/null +++ b/resources/coreboot/fam15h_rdimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch @@ -0,0 +1,232 @@ +From c5a03de594d6bb6ea5012a6549404e4631c903c8 Mon Sep 17 00:00:00 2001 +From: Alexandre Oliva +Date: Wed, 9 Aug 2023 16:57:31 +0200 +Subject: [PATCH] crossgcc: Backport GNAT exception handler v1 patch + +Signed-off-by: Adrien Bourmault +--- + .../patches/gcc-8.3.0_gnat_eh_new.patch | 212 ++++++++++++++++++ + 1 file changed, 212 insertions(+) + create mode 100644 util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch + +diff --git a/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch +new file mode 100644 +index 00000000..75e4f18d +--- /dev/null ++++ b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch +@@ -0,0 +1,212 @@ ++diff --git a/gcc/ada/libgnat/a-exexpr.adb b/gcc/ada/libgnat/a-exexpr.adb ++index b1aa1c6e6ba..5e72fd6e3f2 100644 ++--- a/gcc/ada/libgnat/a-exexpr.adb +++++ b/gcc/ada/libgnat/a-exexpr.adb ++@@ -197,15 +197,75 @@ package body Exception_Propagation is ++ -- whose machine occurrence is Mo. The message is empty, the backtrace ++ -- is empty too and the exception identity is Foreign_Exception. ++ ++- -- Hooks called when entering/leaving an exception handler for a given ++- -- occurrence, aimed at handling the stack of active occurrences. The ++- -- calls are generated by gigi in tree_transform/N_Exception_Handler. +++ -- Hooks called when entering/leaving an exception handler for a +++ -- given occurrence. The calls are generated by gigi in +++ -- Exception_Handler_to_gnu_gcc. +++ +++ -- Begin_Handler_v1, called when entering an exception handler, +++ -- claims responsibility for the handler to release the +++ -- GCC_Exception occurrence. End_Handler_v1, called when +++ -- leaving the handler, releases the occurrence, unless the +++ -- occurrence is propagating further up, or the handler is +++ -- dynamically nested in the context of another handler that +++ -- claimed responsibility for releasing that occurrence. +++ +++ -- Responsibility is claimed by changing the Cleanup field to +++ -- Claimed_Cleanup, which enables claimed exceptions to be +++ -- recognized, and avoids accidental releases even by foreign +++ -- handlers. +++ +++ function Begin_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access) +++ return System.Address; +++ pragma Export (C, Begin_Handler_v1, "__gnat_begin_handler_v1"); +++ -- Called when entering an exception handler. Claim +++ -- responsibility for releasing GCC_Exception, by setting the +++ -- cleanup/release function to Claimed_Cleanup, and return the +++ -- address of the previous cleanup/release function. +++ +++ procedure End_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access; +++ Saved_Cleanup : System.Address; +++ Propagating_Exception : GCC_Exception_Access); +++ pragma Export (C, End_Handler_v1, "__gnat_end_handler_v1"); +++ -- Called when leaving an exception handler. Restore the +++ -- Saved_Cleanup in the GCC_Exception occurrence, and then release +++ -- it, unless it remains claimed by an enclosing handler, or +++ -- GCC_Exception and Propagating_Exception are the same +++ -- occurrence. Propagating_Exception could be either an +++ -- occurrence (re)raised within the handler of GCC_Exception, when +++ -- we're executing as an exceptional cleanup, or null, if we're +++ -- completing the handler of GCC_Exception normally. +++ +++ procedure Claimed_Cleanup +++ (Reason : Unwind_Reason_Code; +++ GCC_Exception : not null GCC_Exception_Access); +++ pragma Export (C, Claimed_Cleanup, "__gnat_claimed_cleanup"); +++ -- A do-nothing placeholder installed as GCC_Exception.Cleanup +++ -- while handling GCC_Exception, to claim responsibility for +++ -- releasing it, and to stop it from being accidentally released. +++ +++ -- The following are version 0 implementations of the version 1 +++ -- hooks above. They remain in place for compatibility with the +++ -- output of compilers that still use version 0, such as those +++ -- used during bootstrap. They are interoperable with the v1 +++ -- hooks, except that the older versions may malfunction when +++ -- handling foreign exceptions passed to Reraise_Occurrence. ++ ++ procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access); ++ pragma Export (C, Begin_Handler, "__gnat_begin_handler"); +++ -- Called when entering an exception handler translated by an old +++ -- compiler. It does nothing. ++ ++ procedure End_Handler (GCC_Exception : GCC_Exception_Access); ++ pragma Export (C, End_Handler, "__gnat_end_handler"); +++ -- Called when leaving an exception handler translated by an old +++ -- compiler. It releases GCC_Exception, unless it is null. It is +++ -- only ever null when the handler has a 'raise;' translated by a +++ -- v0-using compiler. The artificial handler variable passed to +++ -- End_Handler was set to null to tell End_Handler to refrain from +++ -- releasing the reraised exception. In v1 safer ways are used to +++ -- accomplish that. ++ ++ -------------------------------------------------------------------- ++ -- Accessors to Basic Components of a GNAT Exception Data Pointer -- ++@@ -352,6 +412,128 @@ package body Exception_Propagation is ++ end if; ++ end Setup_Current_Excep; ++ +++ ---------------------- +++ -- Begin_Handler_v1 -- +++ ---------------------- +++ +++ function Begin_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access) +++ return System.Address is +++ Saved_Cleanup : constant System.Address := GCC_Exception.Cleanup; +++ begin +++ -- Claim responsibility for releasing this exception, and stop +++ -- others from releasing it. +++ GCC_Exception.Cleanup := Claimed_Cleanup'Address; +++ return Saved_Cleanup; +++ end Begin_Handler_v1; +++ +++ -------------------- +++ -- End_Handler_v1 -- +++ -------------------- +++ +++ procedure End_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access; +++ Saved_Cleanup : System.Address; +++ Propagating_Exception : GCC_Exception_Access) is +++ begin +++ GCC_Exception.Cleanup := Saved_Cleanup; +++ -- Restore the Saved_Cleanup, so that it is either used to +++ -- release GCC_Exception below, or transferred to the next +++ -- handler of the Propagating_Exception occurrence. The +++ -- following test ensures that an occurrence is only released +++ -- once, even after reraises. +++ -- +++ -- The idea is that the GCC_Exception is not to be released +++ -- unless it had an unclaimed Cleanup when the handler started +++ -- (see Begin_Handler_v1 above), but if we propagate across its +++ -- handler a reraise of the same exception, we transfer to the +++ -- Propagating_Exception the responsibility for running the +++ -- Saved_Cleanup when its handler completes. +++ -- +++ -- This ownership transfer mechanism ensures safety, as in +++ -- single release and no dangling pointers, because there is no +++ -- way to hold on to the Machine_Occurrence of an +++ -- Exception_Occurrence: the only situations in which another +++ -- Exception_Occurrence gets the same Machine_Occurrence are +++ -- through Reraise_Occurrence, and plain reraise, and so we +++ -- have the following possibilities: +++ -- +++ -- - Reraise_Occurrence is handled within the running handler, +++ -- and so when completing the dynamically nested handler, we +++ -- must NOT release the exception. A Claimed_Cleanup upon +++ -- entry of the nested handler, installed when entering the +++ -- enclosing handler, ensures the exception will not be +++ -- released by the nested handler, but rather by the enclosing +++ -- handler. +++ -- +++ -- - Reraise_Occurrence/reraise escapes the running handler, +++ -- and we run as an exceptional cleanup for GCC_Exception. The +++ -- Saved_Cleanup was reinstalled, but since we're propagating +++ -- the same machine occurrence, we do not release it. Instead, +++ -- we transfer responsibility for releasing it to the eventual +++ -- handler of the propagating exception. +++ -- +++ -- - An unrelated exception propagates through the running +++ -- handler. We restored GCC_Exception.Saved_Cleanup above. +++ -- Since we're propagating a different exception, we proceed to +++ -- release GCC_Exception, unless Saved_Cleanup was +++ -- Claimed_Cleanup, because then we know we're not in the +++ -- outermost handler for GCC_Exception. +++ -- +++ -- - The handler completes normally, so it reinstalls the +++ -- Saved_Cleanup and runs it, unless it was Claimed_Cleanup. +++ -- If Saved_Cleanup is null, Unwind_DeleteException (currently) +++ -- has no effect, so we could skip it, but if it is ever +++ -- changed to do more in this case, we're ready for that, +++ -- calling it exactly once. +++ if Saved_Cleanup /= Claimed_Cleanup'Address +++ and then +++ Propagating_Exception /= GCC_Exception +++ then +++ declare +++ Current : constant EOA := Get_Current_Excep.all; +++ Cur_Occ : constant GCC_Exception_Access +++ := To_GCC_Exception (Current.Machine_Occurrence); +++ begin +++ -- If we are releasing the Machine_Occurrence of the current +++ -- exception, reset the access to it, so that it is no +++ -- longer accessible. +++ if Cur_Occ = GCC_Exception then +++ Current.Machine_Occurrence := System.Null_Address; +++ end if; +++ end; +++ Unwind_DeleteException (GCC_Exception); +++ end if; +++ end End_Handler_v1; +++ +++ --------------------- +++ -- Claimed_Cleanup -- +++ --------------------- +++ +++ procedure Claimed_Cleanup +++ (Reason : Unwind_Reason_Code; +++ GCC_Exception : not null GCC_Exception_Access) is +++ pragma Unreferenced (Reason); +++ pragma Unreferenced (GCC_Exception); +++ begin +++ -- This procedure should never run. If it does, it's either a +++ -- version 0 handler or a foreign handler, attempting to +++ -- release an exception while a version 1 handler that claimed +++ -- responsibility for releasing the exception remains still +++ -- active. This placeholder stops GCC_Exception from being +++ -- released by them. +++ +++ -- We could get away with just Null_Address instead, with +++ -- nearly the same effect, but with this placeholder we can +++ -- detect and report unexpected releases, and we can tell apart +++ -- a GCC_Exception without a Cleanup, from one with another +++ -- active handler, so as to still call Unwind_DeleteException +++ -- exactly once: currently, Unwind_DeleteException does nothing +++ -- when the Cleanup is null, but should it ever be changed to +++ -- do more, we'll still be safe. +++ null; +++ end Claimed_Cleanup; +++ ++ ------------------- ++ -- Begin_Handler -- ++ ------------------- +-- +2.30.2 + diff --git a/resources/coreboot/fam15h_udimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch b/resources/coreboot/fam15h_udimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch new file mode 100644 index 0000000..443d851 --- /dev/null +++ b/resources/coreboot/fam15h_udimm/patches/0011-gcc-8.3.0_gnat_eh_new.patch @@ -0,0 +1,232 @@ +From c5a03de594d6bb6ea5012a6549404e4631c903c8 Mon Sep 17 00:00:00 2001 +From: Alexandre Oliva +Date: Wed, 9 Aug 2023 16:57:31 +0200 +Subject: [PATCH] crossgcc: Backport GNAT exception handler v1 patch + +Signed-off-by: Adrien Bourmault +--- + .../patches/gcc-8.3.0_gnat_eh_new.patch | 212 ++++++++++++++++++ + 1 file changed, 212 insertions(+) + create mode 100644 util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch + +diff --git a/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch +new file mode 100644 +index 00000000..75e4f18d +--- /dev/null ++++ b/util/crossgcc/patches/gcc-8.3.0_gnat_eh_new.patch +@@ -0,0 +1,212 @@ ++diff --git a/gcc/ada/libgnat/a-exexpr.adb b/gcc/ada/libgnat/a-exexpr.adb ++index b1aa1c6e6ba..5e72fd6e3f2 100644 ++--- a/gcc/ada/libgnat/a-exexpr.adb +++++ b/gcc/ada/libgnat/a-exexpr.adb ++@@ -197,15 +197,75 @@ package body Exception_Propagation is ++ -- whose machine occurrence is Mo. The message is empty, the backtrace ++ -- is empty too and the exception identity is Foreign_Exception. ++ ++- -- Hooks called when entering/leaving an exception handler for a given ++- -- occurrence, aimed at handling the stack of active occurrences. The ++- -- calls are generated by gigi in tree_transform/N_Exception_Handler. +++ -- Hooks called when entering/leaving an exception handler for a +++ -- given occurrence. The calls are generated by gigi in +++ -- Exception_Handler_to_gnu_gcc. +++ +++ -- Begin_Handler_v1, called when entering an exception handler, +++ -- claims responsibility for the handler to release the +++ -- GCC_Exception occurrence. End_Handler_v1, called when +++ -- leaving the handler, releases the occurrence, unless the +++ -- occurrence is propagating further up, or the handler is +++ -- dynamically nested in the context of another handler that +++ -- claimed responsibility for releasing that occurrence. +++ +++ -- Responsibility is claimed by changing the Cleanup field to +++ -- Claimed_Cleanup, which enables claimed exceptions to be +++ -- recognized, and avoids accidental releases even by foreign +++ -- handlers. +++ +++ function Begin_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access) +++ return System.Address; +++ pragma Export (C, Begin_Handler_v1, "__gnat_begin_handler_v1"); +++ -- Called when entering an exception handler. Claim +++ -- responsibility for releasing GCC_Exception, by setting the +++ -- cleanup/release function to Claimed_Cleanup, and return the +++ -- address of the previous cleanup/release function. +++ +++ procedure End_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access; +++ Saved_Cleanup : System.Address; +++ Propagating_Exception : GCC_Exception_Access); +++ pragma Export (C, End_Handler_v1, "__gnat_end_handler_v1"); +++ -- Called when leaving an exception handler. Restore the +++ -- Saved_Cleanup in the GCC_Exception occurrence, and then release +++ -- it, unless it remains claimed by an enclosing handler, or +++ -- GCC_Exception and Propagating_Exception are the same +++ -- occurrence. Propagating_Exception could be either an +++ -- occurrence (re)raised within the handler of GCC_Exception, when +++ -- we're executing as an exceptional cleanup, or null, if we're +++ -- completing the handler of GCC_Exception normally. +++ +++ procedure Claimed_Cleanup +++ (Reason : Unwind_Reason_Code; +++ GCC_Exception : not null GCC_Exception_Access); +++ pragma Export (C, Claimed_Cleanup, "__gnat_claimed_cleanup"); +++ -- A do-nothing placeholder installed as GCC_Exception.Cleanup +++ -- while handling GCC_Exception, to claim responsibility for +++ -- releasing it, and to stop it from being accidentally released. +++ +++ -- The following are version 0 implementations of the version 1 +++ -- hooks above. They remain in place for compatibility with the +++ -- output of compilers that still use version 0, such as those +++ -- used during bootstrap. They are interoperable with the v1 +++ -- hooks, except that the older versions may malfunction when +++ -- handling foreign exceptions passed to Reraise_Occurrence. ++ ++ procedure Begin_Handler (GCC_Exception : not null GCC_Exception_Access); ++ pragma Export (C, Begin_Handler, "__gnat_begin_handler"); +++ -- Called when entering an exception handler translated by an old +++ -- compiler. It does nothing. ++ ++ procedure End_Handler (GCC_Exception : GCC_Exception_Access); ++ pragma Export (C, End_Handler, "__gnat_end_handler"); +++ -- Called when leaving an exception handler translated by an old +++ -- compiler. It releases GCC_Exception, unless it is null. It is +++ -- only ever null when the handler has a 'raise;' translated by a +++ -- v0-using compiler. The artificial handler variable passed to +++ -- End_Handler was set to null to tell End_Handler to refrain from +++ -- releasing the reraised exception. In v1 safer ways are used to +++ -- accomplish that. ++ ++ -------------------------------------------------------------------- ++ -- Accessors to Basic Components of a GNAT Exception Data Pointer -- ++@@ -352,6 +412,128 @@ package body Exception_Propagation is ++ end if; ++ end Setup_Current_Excep; ++ +++ ---------------------- +++ -- Begin_Handler_v1 -- +++ ---------------------- +++ +++ function Begin_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access) +++ return System.Address is +++ Saved_Cleanup : constant System.Address := GCC_Exception.Cleanup; +++ begin +++ -- Claim responsibility for releasing this exception, and stop +++ -- others from releasing it. +++ GCC_Exception.Cleanup := Claimed_Cleanup'Address; +++ return Saved_Cleanup; +++ end Begin_Handler_v1; +++ +++ -------------------- +++ -- End_Handler_v1 -- +++ -------------------- +++ +++ procedure End_Handler_v1 +++ (GCC_Exception : not null GCC_Exception_Access; +++ Saved_Cleanup : System.Address; +++ Propagating_Exception : GCC_Exception_Access) is +++ begin +++ GCC_Exception.Cleanup := Saved_Cleanup; +++ -- Restore the Saved_Cleanup, so that it is either used to +++ -- release GCC_Exception below, or transferred to the next +++ -- handler of the Propagating_Exception occurrence. The +++ -- following test ensures that an occurrence is only released +++ -- once, even after reraises. +++ -- +++ -- The idea is that the GCC_Exception is not to be released +++ -- unless it had an unclaimed Cleanup when the handler started +++ -- (see Begin_Handler_v1 above), but if we propagate across its +++ -- handler a reraise of the same exception, we transfer to the +++ -- Propagating_Exception the responsibility for running the +++ -- Saved_Cleanup when its handler completes. +++ -- +++ -- This ownership transfer mechanism ensures safety, as in +++ -- single release and no dangling pointers, because there is no +++ -- way to hold on to the Machine_Occurrence of an +++ -- Exception_Occurrence: the only situations in which another +++ -- Exception_Occurrence gets the same Machine_Occurrence are +++ -- through Reraise_Occurrence, and plain reraise, and so we +++ -- have the following possibilities: +++ -- +++ -- - Reraise_Occurrence is handled within the running handler, +++ -- and so when completing the dynamically nested handler, we +++ -- must NOT release the exception. A Claimed_Cleanup upon +++ -- entry of the nested handler, installed when entering the +++ -- enclosing handler, ensures the exception will not be +++ -- released by the nested handler, but rather by the enclosing +++ -- handler. +++ -- +++ -- - Reraise_Occurrence/reraise escapes the running handler, +++ -- and we run as an exceptional cleanup for GCC_Exception. The +++ -- Saved_Cleanup was reinstalled, but since we're propagating +++ -- the same machine occurrence, we do not release it. Instead, +++ -- we transfer responsibility for releasing it to the eventual +++ -- handler of the propagating exception. +++ -- +++ -- - An unrelated exception propagates through the running +++ -- handler. We restored GCC_Exception.Saved_Cleanup above. +++ -- Since we're propagating a different exception, we proceed to +++ -- release GCC_Exception, unless Saved_Cleanup was +++ -- Claimed_Cleanup, because then we know we're not in the +++ -- outermost handler for GCC_Exception. +++ -- +++ -- - The handler completes normally, so it reinstalls the +++ -- Saved_Cleanup and runs it, unless it was Claimed_Cleanup. +++ -- If Saved_Cleanup is null, Unwind_DeleteException (currently) +++ -- has no effect, so we could skip it, but if it is ever +++ -- changed to do more in this case, we're ready for that, +++ -- calling it exactly once. +++ if Saved_Cleanup /= Claimed_Cleanup'Address +++ and then +++ Propagating_Exception /= GCC_Exception +++ then +++ declare +++ Current : constant EOA := Get_Current_Excep.all; +++ Cur_Occ : constant GCC_Exception_Access +++ := To_GCC_Exception (Current.Machine_Occurrence); +++ begin +++ -- If we are releasing the Machine_Occurrence of the current +++ -- exception, reset the access to it, so that it is no +++ -- longer accessible. +++ if Cur_Occ = GCC_Exception then +++ Current.Machine_Occurrence := System.Null_Address; +++ end if; +++ end; +++ Unwind_DeleteException (GCC_Exception); +++ end if; +++ end End_Handler_v1; +++ +++ --------------------- +++ -- Claimed_Cleanup -- +++ --------------------- +++ +++ procedure Claimed_Cleanup +++ (Reason : Unwind_Reason_Code; +++ GCC_Exception : not null GCC_Exception_Access) is +++ pragma Unreferenced (Reason); +++ pragma Unreferenced (GCC_Exception); +++ begin +++ -- This procedure should never run. If it does, it's either a +++ -- version 0 handler or a foreign handler, attempting to +++ -- release an exception while a version 1 handler that claimed +++ -- responsibility for releasing the exception remains still +++ -- active. This placeholder stops GCC_Exception from being +++ -- released by them. +++ +++ -- We could get away with just Null_Address instead, with +++ -- nearly the same effect, but with this placeholder we can +++ -- detect and report unexpected releases, and we can tell apart +++ -- a GCC_Exception without a Cleanup, from one with another +++ -- active handler, so as to still call Unwind_DeleteException +++ -- exactly once: currently, Unwind_DeleteException does nothing +++ -- when the Cleanup is null, but should it ever be changed to +++ -- do more, we'll still be safe. +++ null; +++ end Claimed_Cleanup; +++ ++ ------------------- ++ -- Begin_Handler -- ++ ------------------- +-- +2.30.2 +