diff options
Diffstat (limited to 'packages/gcc/8.5.0')
7 files changed, 937 insertions, 0 deletions
diff --git a/packages/gcc/8.5.0/0026-aarch64-Explicitly-handle-frames-with-no-saved-regis.patch b/packages/gcc/8.5.0/0026-aarch64-Explicitly-handle-frames-with-no-saved-regis.patch new file mode 100644 index 00000000..7e32ce8e --- /dev/null +++ b/packages/gcc/8.5.0/0026-aarch64-Explicitly-handle-frames-with-no-saved-regis.patch @@ -0,0 +1,43 @@ +From f9e1c86b3397faa8dee4bbaeaf8b56492e3a63df Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Fri, 16 Jun 2023 17:00:51 +0100 +Subject: [PATCH 26/32] aarch64: Explicitly handle frames with no saved + registers + +If a frame has no saved registers, it can be allocated in one go. +There is no need to treat the areas below and above the saved +registers as separate. + +This is a no-op as thing stand, since a leaf function will have +no outgoing arguments, and so all the frame will be above where +the saved registers normally go. + +gcc/ + * config/aarch64/aarch64.c (aarch64_layout_frame): Explicitly + allocate the frame in one go if there are no saved registers. +--- + gcc/config/aarch64/aarch64.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c +index 4ad73220337f..ed9e2a28f914 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -4215,9 +4215,11 @@ aarch64_layout_frame (void) + max_push_offset = 256; + + HOST_WIDE_INT const_size, const_fp_offset; +- if (cfun->machine->frame.frame_size.is_constant (&const_size) +- && const_size < max_push_offset +- && known_eq (crtl->outgoing_args_size, 0)) ++ if (cfun->machine->frame.saved_regs_size == 0) ++ cfun->machine->frame.initial_adjust = cfun->machine->frame.frame_size; ++ else if (cfun->machine->frame.frame_size.is_constant (&const_size) ++ && const_size < max_push_offset ++ && known_eq (crtl->outgoing_args_size, 0)) + { + /* Simple, small frame with no outgoing arguments: + stp reg1, reg2, [sp, -frame_size]! +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0027-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch b/packages/gcc/8.5.0/0027-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch new file mode 100644 index 00000000..f9ee88d6 --- /dev/null +++ b/packages/gcc/8.5.0/0027-aarch64-Add-bytes_below_hard_fp-to-frame-info.patch @@ -0,0 +1,165 @@ +From b4780c8d6cbd3fc8f2997dd7dcd360b3039c6690 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Fri, 16 Jun 2023 16:55:12 +0100 +Subject: [PATCH 27/32] aarch64: Add bytes_below_hard_fp to frame info + +The frame layout code currently hard-codes the assumption that +the number of bytes below the saved registers is equal to the +size of the outgoing arguments. This patch abstracts that +value into a new field of aarch64_frame. + +gcc/ + * config/aarch64/aarch64.h (aarch64_frame::bytes_below_hard_fp): New + field. + * config/aarch64/aarch64.c (aarch64_layout_frame): Initialize it, + and use it instead of crtl->outgoing_args_size. + (aarch64_get_separate_components): Use bytes_below_hard_fp instead + of outgoing_args_size. + (aarch64_process_components): Likewise. +--- + gcc/config/aarch64/aarch64.c | 40 ++++++++++++++++++++---------------- + gcc/config/aarch64/aarch64.h | 6 +++++- + 2 files changed, 27 insertions(+), 19 deletions(-) + +diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c +index ed9e2a28f914..996c898888cd 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -4136,6 +4136,8 @@ aarch64_layout_frame (void) + last_fp_reg = regno; + } + ++ cfun->machine->frame.bytes_below_hard_fp = crtl->outgoing_args_size; ++ + if (cfun->machine->frame.emit_frame_chain) + { + /* FP and LR are placed in the linkage record. */ +@@ -4195,11 +4197,11 @@ aarch64_layout_frame (void) + STACK_BOUNDARY / BITS_PER_UNIT); + + /* Both these values are already aligned. */ +- gcc_assert (multiple_p (crtl->outgoing_args_size, ++ gcc_assert (multiple_p (cfun->machine->frame.bytes_below_hard_fp, + STACK_BOUNDARY / BITS_PER_UNIT)); + cfun->machine->frame.frame_size + = (cfun->machine->frame.hard_fp_offset +- + crtl->outgoing_args_size); ++ + cfun->machine->frame.bytes_below_hard_fp); + + cfun->machine->frame.locals_offset = cfun->machine->frame.saved_varargs_size; + +@@ -4219,23 +4221,23 @@ aarch64_layout_frame (void) + cfun->machine->frame.initial_adjust = cfun->machine->frame.frame_size; + else if (cfun->machine->frame.frame_size.is_constant (&const_size) + && const_size < max_push_offset +- && known_eq (crtl->outgoing_args_size, 0)) ++ && known_eq (cfun->machine->frame.bytes_below_hard_fp, 0)) + { +- /* Simple, small frame with no outgoing arguments: ++ /* Simple, small frame with no data below the saved registers. + stp reg1, reg2, [sp, -frame_size]! + stp reg3, reg4, [sp, 16] */ + cfun->machine->frame.callee_adjust = const_size; + } +- else if (known_lt (crtl->outgoing_args_size ++ else if (known_lt (cfun->machine->frame.bytes_below_hard_fp + + cfun->machine->frame.saved_regs_size, 512) + && !(cfun->calls_alloca + && known_lt (cfun->machine->frame.hard_fp_offset, + max_push_offset))) + { +- /* Frame with small outgoing arguments: ++ /* Frame with small area below the saved registers: + sub sp, sp, frame_size +- stp reg1, reg2, [sp, outgoing_args_size] +- stp reg3, reg4, [sp, outgoing_args_size + 16] */ ++ stp reg1, reg2, [sp, bytes_below_hard_fp] ++ stp reg3, reg4, [sp, bytes_below_hard_fp + 16] */ + cfun->machine->frame.initial_adjust = cfun->machine->frame.frame_size; + cfun->machine->frame.callee_offset + = cfun->machine->frame.frame_size - cfun->machine->frame.hard_fp_offset; +@@ -4243,22 +4245,23 @@ aarch64_layout_frame (void) + else if (cfun->machine->frame.hard_fp_offset.is_constant (&const_fp_offset) + && const_fp_offset < max_push_offset) + { +- /* Frame with large outgoing arguments but a small local area: ++ /* Frame with large area below the saved registers, but with a ++ small area above: + stp reg1, reg2, [sp, -hard_fp_offset]! + stp reg3, reg4, [sp, 16] +- sub sp, sp, outgoing_args_size */ ++ sub sp, sp, bytes_below_hard_fp */ + cfun->machine->frame.callee_adjust = const_fp_offset; + cfun->machine->frame.final_adjust + = cfun->machine->frame.frame_size - cfun->machine->frame.callee_adjust; + } + else + { +- /* Frame with large local area and outgoing arguments using frame pointer: ++ /* General case: + sub sp, sp, hard_fp_offset + stp x29, x30, [sp, 0] + add x29, sp, 0 + stp reg3, reg4, [sp, 16] +- sub sp, sp, outgoing_args_size */ ++ sub sp, sp, bytes_below_hard_fp */ + cfun->machine->frame.initial_adjust = cfun->machine->frame.hard_fp_offset; + cfun->machine->frame.final_adjust + = cfun->machine->frame.frame_size - cfun->machine->frame.initial_adjust; +@@ -4666,9 +4669,11 @@ aarch64_get_separate_components (void) + if (aarch64_register_saved_on_entry (regno)) + { + poly_int64 offset = cfun->machine->frame.reg_offset[regno]; ++ ++ /* Get the offset relative to the register we'll use. */ + if (!frame_pointer_needed) +- offset += cfun->machine->frame.frame_size +- - cfun->machine->frame.hard_fp_offset; ++ offset += cfun->machine->frame.bytes_below_hard_fp; ++ + /* Check that we can access the stack slot of the register with one + direct load with no adjustments needed. */ + if (offset_12bit_unsigned_scaled_p (DImode, offset)) +@@ -4786,8 +4791,8 @@ aarch64_process_components (sbitmap components, bool prologue_p) + rtx reg = gen_rtx_REG (mode, regno); + poly_int64 offset = cfun->machine->frame.reg_offset[regno]; + if (!frame_pointer_needed) +- offset += cfun->machine->frame.frame_size +- - cfun->machine->frame.hard_fp_offset; ++ offset += cfun->machine->frame.bytes_below_hard_fp; ++ + rtx addr = plus_constant (Pmode, ptr_reg, offset); + rtx mem = gen_frame_mem (mode, addr); + +@@ -4828,8 +4833,7 @@ aarch64_process_components (sbitmap components, bool prologue_p) + /* REGNO2 can be saved/restored in a pair with REGNO. */ + rtx reg2 = gen_rtx_REG (mode, regno2); + if (!frame_pointer_needed) +- offset2 += cfun->machine->frame.frame_size +- - cfun->machine->frame.hard_fp_offset; ++ offset2 += cfun->machine->frame.bytes_below_hard_fp; + rtx addr2 = plus_constant (Pmode, ptr_reg, offset2); + rtx mem2 = gen_frame_mem (mode, addr2); + rtx set2 = prologue_p ? gen_rtx_SET (mem2, reg2) +diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h +index f4d27fa64580..cac7a57ed475 100644 +--- a/gcc/config/aarch64/aarch64.h ++++ b/gcc/config/aarch64/aarch64.h +@@ -647,9 +647,13 @@ struct GTY (()) aarch64_frame + HOST_WIDE_INT saved_varargs_size; + + /* The size of the saved callee-save int/FP registers. */ +- + HOST_WIDE_INT saved_regs_size; + ++ /* The number of bytes between the bottom of the static frame (the bottom ++ of the outgoing arguments) and the hard frame pointer. This value is ++ always a multiple of STACK_BOUNDARY. */ ++ poly_int64 bytes_below_hard_fp; ++ + /* Offset from the base of the frame (incomming SP) to the + top of the locals area. This value is always a multiple of + STACK_BOUNDARY. */ +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0028-aarch64-Rename-locals_offset-to-bytes_above_locals.patch b/packages/gcc/8.5.0/0028-aarch64-Rename-locals_offset-to-bytes_above_locals.patch new file mode 100644 index 00000000..c96071e2 --- /dev/null +++ b/packages/gcc/8.5.0/0028-aarch64-Rename-locals_offset-to-bytes_above_locals.patch @@ -0,0 +1,94 @@ +From 746f8815cf7efc16c6973420e74b2560b82a644c Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Tue, 27 Jun 2023 11:25:40 +0100 +Subject: [PATCH 28/32] aarch64: Rename locals_offset to bytes_above_locals +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +locals_offset was described as: + + /* Offset from the base of the frame (incomming SP) to the + top of the locals area. This value is always a multiple of + STACK_BOUNDARY. */ + +This is implicitly an “upside down” view of the frame: the incoming +SP is at offset 0, and anything N bytes below the incoming SP is at +offset N (rather than -N). + +However, reg_offset instead uses a “right way up” view; that is, +it views offsets in address terms. Something above X is at a +positive offset from X and something below X is at a negative +offset from X. + +Also, even on FRAME_GROWS_DOWNWARD targets like AArch64, +target-independent code views offsets in address terms too: +locals are allocated at negative offsets to virtual_stack_vars. + +It seems confusing to have *_offset fields of the same structure +using different polarities like this. This patch tries to avoid +that by renaming locals_offset to bytes_above_locals. + +gcc/ + * config/aarch64/aarch64.h (aarch64_frame::locals_offset): Rename to... + (aarch64_frame::bytes_above_locals): ...this. + * config/aarch64/aarch64.c (aarch64_layout_frame) + (aarch64_initial_elimination_offset): Update accordingly. +--- + gcc/config/aarch64/aarch64.c | 9 +++++---- + gcc/config/aarch64/aarch64.h | 6 +++--- + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c +index 996c898888cd..32a9857cb111 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -4203,7 +4203,8 @@ aarch64_layout_frame (void) + = (cfun->machine->frame.hard_fp_offset + + cfun->machine->frame.bytes_below_hard_fp); + +- cfun->machine->frame.locals_offset = cfun->machine->frame.saved_varargs_size; ++ cfun->machine->frame.bytes_above_locals ++ = cfun->machine->frame.saved_varargs_size; + + cfun->machine->frame.initial_adjust = 0; + cfun->machine->frame.final_adjust = 0; +@@ -7628,14 +7629,14 @@ aarch64_initial_elimination_offset (unsigned from, unsigned to) + + if (from == FRAME_POINTER_REGNUM) + return cfun->machine->frame.hard_fp_offset +- - cfun->machine->frame.locals_offset; ++ - cfun->machine->frame.bytes_above_locals; + } + + if (to == STACK_POINTER_REGNUM) + { + if (from == FRAME_POINTER_REGNUM) +- return cfun->machine->frame.frame_size +- - cfun->machine->frame.locals_offset; ++ return cfun->machine->frame.frame_size ++ - cfun->machine->frame.bytes_above_locals; + } + + return cfun->machine->frame.frame_size; +diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h +index cac7a57ed475..eb69e38bd537 100644 +--- a/gcc/config/aarch64/aarch64.h ++++ b/gcc/config/aarch64/aarch64.h +@@ -654,10 +654,10 @@ struct GTY (()) aarch64_frame + always a multiple of STACK_BOUNDARY. */ + poly_int64 bytes_below_hard_fp; + +- /* Offset from the base of the frame (incomming SP) to the +- top of the locals area. This value is always a multiple of ++ /* The number of bytes between the top of the locals area and the top ++ of the frame (the incomming SP). This value is always a multiple of + STACK_BOUNDARY. */ +- poly_int64 locals_offset; ++ poly_int64 bytes_above_locals; + + /* Offset from the base of the frame (incomming SP) to the + hard_frame_pointer. This value is always a multiple of +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0029-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch b/packages/gcc/8.5.0/0029-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch new file mode 100644 index 00000000..385b7594 --- /dev/null +++ b/packages/gcc/8.5.0/0029-aarch64-Rename-hard_fp_offset-to-bytes_above_hard_fp.patch @@ -0,0 +1,130 @@ +From 8711ad4ae2c4c9fa693bab65a6a2fe0b191f7678 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Tue, 27 Jun 2023 11:28:11 +0100 +Subject: [PATCH 29/32] aarch64: Rename hard_fp_offset to bytes_above_hard_fp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Similarly to the previous locals_offset patch, hard_fp_offset +was described as: + + /* Offset from the base of the frame (incomming SP) to the + hard_frame_pointer. This value is always a multiple of + STACK_BOUNDARY. */ + poly_int64 hard_fp_offset; + +which again took an “upside-down” view: higher offsets meant lower +addresses. This patch renames the field to bytes_above_hard_fp instead. + +gcc/ + * config/aarch64/aarch64.h (aarch64_frame::hard_fp_offset): Rename + to... + (aarch64_frame::bytes_above_hard_fp): ...this. + * config/aarch64/aarch64.c (aarch64_layout_frame) + (aarch64_expand_prologue): Update accordingly. + (aarch64_initial_elimination_offset): Likewise. +--- + gcc/config/aarch64/aarch64.c | 21 +++++++++++---------- + gcc/config/aarch64/aarch64.h | 6 +++--- + 2 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c +index 32a9857cb111..861e928ebdc2 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -4191,7 +4191,7 @@ aarch64_layout_frame (void) + HOST_WIDE_INT varargs_and_saved_regs_size + = offset + cfun->machine->frame.saved_varargs_size; + +- cfun->machine->frame.hard_fp_offset ++ cfun->machine->frame.bytes_above_hard_fp + = aligned_upper_bound (varargs_and_saved_regs_size + + get_frame_size (), + STACK_BOUNDARY / BITS_PER_UNIT); +@@ -4200,7 +4200,7 @@ aarch64_layout_frame (void) + gcc_assert (multiple_p (cfun->machine->frame.bytes_below_hard_fp, + STACK_BOUNDARY / BITS_PER_UNIT)); + cfun->machine->frame.frame_size +- = (cfun->machine->frame.hard_fp_offset ++ = (cfun->machine->frame.bytes_above_hard_fp + + cfun->machine->frame.bytes_below_hard_fp); + + cfun->machine->frame.bytes_above_locals +@@ -4232,7 +4232,7 @@ aarch64_layout_frame (void) + else if (known_lt (cfun->machine->frame.bytes_below_hard_fp + + cfun->machine->frame.saved_regs_size, 512) + && !(cfun->calls_alloca +- && known_lt (cfun->machine->frame.hard_fp_offset, ++ && known_lt (cfun->machine->frame.bytes_above_hard_fp, + max_push_offset))) + { + /* Frame with small area below the saved registers: +@@ -4241,14 +4241,14 @@ aarch64_layout_frame (void) + stp reg3, reg4, [sp, bytes_below_hard_fp + 16] */ + cfun->machine->frame.initial_adjust = cfun->machine->frame.frame_size; + cfun->machine->frame.callee_offset +- = cfun->machine->frame.frame_size - cfun->machine->frame.hard_fp_offset; ++ = cfun->machine->frame.frame_size - cfun->machine->frame.bytes_above_hard_fp; + } +- else if (cfun->machine->frame.hard_fp_offset.is_constant (&const_fp_offset) ++ else if (cfun->machine->frame.bytes_above_hard_fp.is_constant (&const_fp_offset) + && const_fp_offset < max_push_offset) + { + /* Frame with large area below the saved registers, but with a + small area above: +- stp reg1, reg2, [sp, -hard_fp_offset]! ++ stp reg1, reg2, [sp, -bytes_above_hard_fp]! + stp reg3, reg4, [sp, 16] + sub sp, sp, bytes_below_hard_fp */ + cfun->machine->frame.callee_adjust = const_fp_offset; +@@ -4258,12 +4258,13 @@ aarch64_layout_frame (void) + else + { + /* General case: +- sub sp, sp, hard_fp_offset ++ sub sp, sp, bytes_above_hard_fp + stp x29, x30, [sp, 0] + add x29, sp, 0 + stp reg3, reg4, [sp, 16] + sub sp, sp, bytes_below_hard_fp */ +- cfun->machine->frame.initial_adjust = cfun->machine->frame.hard_fp_offset; ++ cfun->machine->frame.initial_adjust ++ = cfun->machine->frame.bytes_above_hard_fp; + cfun->machine->frame.final_adjust + = cfun->machine->frame.frame_size - cfun->machine->frame.initial_adjust; + } +@@ -7625,10 +7626,10 @@ aarch64_initial_elimination_offset (unsigned from, unsigned to) + if (to == HARD_FRAME_POINTER_REGNUM) + { + if (from == ARG_POINTER_REGNUM) +- return cfun->machine->frame.hard_fp_offset; ++ return cfun->machine->frame.bytes_above_hard_fp; + + if (from == FRAME_POINTER_REGNUM) +- return cfun->machine->frame.hard_fp_offset ++ return cfun->machine->frame.bytes_above_hard_fp + - cfun->machine->frame.bytes_above_locals; + } + +diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h +index eb69e38bd537..55ef6ae08a54 100644 +--- a/gcc/config/aarch64/aarch64.h ++++ b/gcc/config/aarch64/aarch64.h +@@ -659,10 +659,10 @@ struct GTY (()) aarch64_frame + STACK_BOUNDARY. */ + poly_int64 bytes_above_locals; + +- /* Offset from the base of the frame (incomming SP) to the +- hard_frame_pointer. This value is always a multiple of ++ /* The number of bytes between the hard_frame_pointer and the top of ++ the frame (the incomming SP). This value is always a multiple of + STACK_BOUNDARY. */ +- poly_int64 hard_fp_offset; ++ poly_int64 bytes_above_hard_fp; + + /* The size of the frame. This value is the offset from base of the + frame (incomming SP) to the stack_pointer. This value is always +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0030-aarch64-Tweak-frame_size-comment.patch b/packages/gcc/8.5.0/0030-aarch64-Tweak-frame_size-comment.patch new file mode 100644 index 00000000..129a7179 --- /dev/null +++ b/packages/gcc/8.5.0/0030-aarch64-Tweak-frame_size-comment.patch @@ -0,0 +1,35 @@ +From d1cfa6a4f7c148000b9cd591479accf001fc739b Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Thu, 22 Jun 2023 22:26:30 +0100 +Subject: [PATCH 30/32] aarch64: Tweak frame_size comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes another case in which a value was described with +an “upside-down” view. + +gcc/ + * config/aarch64/aarch64.h (aarch64_frame::frame_size): Tweak comment. +--- + gcc/config/aarch64/aarch64.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h +index 55ef6ae08a54..fbcfb9891b73 100644 +--- a/gcc/config/aarch64/aarch64.h ++++ b/gcc/config/aarch64/aarch64.h +@@ -664,8 +664,8 @@ struct GTY (()) aarch64_frame + STACK_BOUNDARY. */ + poly_int64 bytes_above_hard_fp; + +- /* The size of the frame. This value is the offset from base of the +- frame (incomming SP) to the stack_pointer. This value is always ++ /* The size of the frame, i.e. the number of bytes between the bottom ++ of the outgoing arguments and the incoming SP. This value is always + a multiple of STACK_BOUNDARY. */ + poly_int64 frame_size; + +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0031-Backport-check-function-bodies-support.patch b/packages/gcc/8.5.0/0031-Backport-check-function-bodies-support.patch new file mode 100644 index 00000000..ba96f85e --- /dev/null +++ b/packages/gcc/8.5.0/0031-Backport-check-function-bodies-support.patch @@ -0,0 +1,211 @@ +From 30455227307a5b078d8d857f337d931191c2d9f0 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Tue, 15 Aug 2023 19:05:30 +0100 +Subject: [PATCH 31/32] Backport check-function-bodies support + +--- + gcc/testsuite/lib/scanasm.exp | 191 ++++++++++++++++++++++++++++++++++ + 1 file changed, 191 insertions(+) + +diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp +index e653b1e7597e..191d38686cd3 100644 +--- a/gcc/testsuite/lib/scanasm.exp ++++ b/gcc/testsuite/lib/scanasm.exp +@@ -542,3 +542,194 @@ proc scan-lto-assembler { args } { + verbose "output_file: $output_file" + dg-scan "scan-assembler" 1 $testcase $output_file $args + } ++ ++# Read assembly file FILENAME and store a mapping from function names ++# to function bodies in array RESULT. FILENAME has already been uploaded ++# locally where necessary and is known to exist. ++ ++proc parse_function_bodies { filename result } { ++ upvar $result up_result ++ ++ # Regexp for the start of a function definition (name in \1). ++ set label {^([a-zA-Z_]\S+):$} ++ ++ # Regexp for the end of a function definition. ++ set terminator {^\s*\.size} ++ ++ # Regexp for lines that aren't interesting. ++ set fluff {^\s*(?:\.|//|@|$)} ++ ++ set fd [open $filename r] ++ set in_function 0 ++ while { [gets $fd line] >= 0 } { ++ if { [regexp $label $line dummy function_name] } { ++ set in_function 1 ++ set function_body "" ++ } elseif { $in_function } { ++ if { [regexp $terminator $line] } { ++ set up_result($function_name) $function_body ++ set in_function 0 ++ } elseif { ![regexp $fluff $line] } { ++ append function_body $line "\n" ++ } ++ } ++ } ++ close $fd ++} ++ ++# FUNCTIONS is an array that maps function names to function bodies. ++# Return true if it contains a definition of function NAME and if ++# that definition matches BODY_REGEXP. ++ ++proc check_function_body { functions name body_regexp } { ++ upvar $functions up_functions ++ ++ if { ![info exists up_functions($name)] } { ++ return 0 ++ } ++ set fn_res [regexp "^$body_regexp\$" $up_functions($name)] ++ if { !$fn_res } { ++ verbose -log "body: $body_regexp" ++ verbose -log "against: $up_functions($name)" ++ } ++ return $fn_res ++} ++ ++# Check the implementations of functions against expected output. Used as: ++# ++# { dg-do { check-function-bodies PREFIX TERMINATOR[ OPTION[ SELECTOR]] } } ++# ++# See sourcebuild.texi for details. ++ ++proc check-function-bodies { args } { ++ if { [llength $args] < 2 } { ++ error "too few arguments to check-function-bodies" ++ } ++ if { [llength $args] > 4 } { ++ error "too many arguments to check-function-bodies" ++ } ++ ++ if { [llength $args] >= 3 } { ++ set required_flags [lindex $args 2] ++ ++ upvar 2 dg-extra-tool-flags extra_tool_flags ++ set flags $extra_tool_flags ++ ++ global torture_current_flags ++ if { [info exists torture_current_flags] } { ++ append flags " " $torture_current_flags ++ } ++ foreach required_flag $required_flags { ++ switch -- $required_flag { ++ target - ++ xfail { ++ error "misplaced $required_flag in check-function-bodies" ++ } ++ } ++ } ++ foreach required_flag $required_flags { ++ if { ![regexp " $required_flag " $flags] } { ++ return ++ } ++ } ++ } ++ ++ set xfail_all 0 ++ if { [llength $args] >= 4 } { ++ switch [dg-process-target [lindex $args 3]] { ++ "S" { } ++ "N" { return } ++ "F" { set xfail_all 1 } ++ "P" { } ++ } ++ } ++ ++ set testcase [testname-for-summary] ++ # The name might include a list of options; extract the file name. ++ set filename [lindex $testcase 0] ++ ++ global srcdir ++ set input_filename "$srcdir/$filename" ++ set output_filename "[file rootname [file tail $filename]].s" ++ ++ set prefix [lindex $args 0] ++ set prefix_len [string length $prefix] ++ set terminator [lindex $args 1] ++ if { [string equal $terminator ""] } { ++ set terminator "*/" ++ } ++ set terminator_len [string length $terminator] ++ ++ set have_bodies 0 ++ if { [is_remote host] } { ++ remote_upload host "$filename" ++ } ++ if { [file exists $output_filename] } { ++ parse_function_bodies $output_filename functions ++ set have_bodies 1 ++ } else { ++ verbose -log "$testcase: output file does not exist" ++ } ++ ++ set count 0 ++ set function_regexp "" ++ set label {^(\S+):$} ++ ++ set lineno 1 ++ set fd [open $input_filename r] ++ set in_function 0 ++ while { [gets $fd line] >= 0 } { ++ if { [string equal -length $prefix_len $line $prefix] } { ++ set line [string trim [string range $line $prefix_len end]] ++ if { !$in_function } { ++ if { [regexp "^(.*?\\S)\\s+{(.*)}\$" $line dummy \ ++ line selector] } { ++ set selector [dg-process-target $selector] ++ } else { ++ set selector "P" ++ } ++ if { ![regexp $label $line dummy function_name] } { ++ close $fd ++ error "check-function-bodies: line $lineno does not have a function label" ++ } ++ set in_function 1 ++ set function_regexp "" ++ } elseif { [string equal $line "("] } { ++ append function_regexp "(?:" ++ } elseif { [string equal $line "|"] } { ++ append function_regexp "|" ++ } elseif { [string equal $line ")"] } { ++ append function_regexp ")" ++ } elseif { [string equal $line "..."] } { ++ append function_regexp ".*" ++ } else { ++ append function_regexp "\t" $line "\n" ++ } ++ } elseif { [string equal -length $terminator_len $line $terminator] } { ++ if { ![string equal $selector "N"] } { ++ if { $xfail_all || [string equal $selector "F"] } { ++ setup_xfail "*-*-*" ++ } ++ set testname "$testcase check-function-bodies $function_name" ++ if { !$have_bodies } { ++ unresolved $testname ++ } elseif { [check_function_body functions $function_name \ ++ $function_regexp] } { ++ pass $testname ++ } else { ++ fail $testname ++ } ++ } ++ set in_function 0 ++ incr count ++ } ++ incr lineno ++ } ++ close $fd ++ if { $in_function } { ++ error "check-function-bodies: missing \"$terminator\"" ++ } ++ if { $count == 0 } { ++ error "check-function-bodies: no matches found" ++ } ++} +-- +2.42.0 + diff --git a/packages/gcc/8.5.0/0032-aarch64-Make-stack-smash-canary-protect-saved-regist.patch b/packages/gcc/8.5.0/0032-aarch64-Make-stack-smash-canary-protect-saved-regist.patch new file mode 100644 index 00000000..b074c42d --- /dev/null +++ b/packages/gcc/8.5.0/0032-aarch64-Make-stack-smash-canary-protect-saved-regist.patch @@ -0,0 +1,259 @@ +From ee9111b567ddcd2f1b16da4f38b69b1b979df9ef Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Thu, 15 Jun 2023 19:16:52 +0100 +Subject: [PATCH 32/32] aarch64: Make stack smash canary protect saved + registers + +AArch64 normally puts the saved registers near the bottom of the frame, +immediately above any dynamic allocations. But this means that a +stack-smash attack on those dynamic allocations could overwrite the +saved registers without needing to reach as far as the stack smash +canary. + +The same thing could also happen for variable-sized arguments that are +passed by value, since those are allocated before a call and popped on +return. + +This patch avoids that by putting the locals (and thus the canary) below +the saved registers when stack smash protection is active. + +The patch fixes CVE-2023-4039. + +gcc/ + * config/aarch64/aarch64.c (aarch64_save_regs_above_locals_p): + New function. + (aarch64_layout_frame): Use it to decide whether locals should + go above or below the saved registers. + (aarch64_expand_prologue): Update stack layout comment. + Emit a stack tie after the final adjustment. + +gcc/testsuite/ + * gcc.target/aarch64/stack-protector-8.c: New test. + * gcc.target/aarch64/stack-protector-9.c: Likewise. +--- + gcc/config/aarch64/aarch64.c | 46 ++++++++++++-- + .../gcc.target/aarch64/stack-protector-8.c | 62 +++++++++++++++++++ + .../gcc.target/aarch64/stack-protector-9.c | 33 ++++++++++ + 3 files changed, 137 insertions(+), 4 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-protector-8.c + create mode 100644 gcc/testsuite/gcc.target/aarch64/stack-protector-9.c + +diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c +index 861e928ebdc2..5c0e3fd484da 100644 +--- a/gcc/config/aarch64/aarch64.c ++++ b/gcc/config/aarch64/aarch64.c +@@ -4078,6 +4078,20 @@ aarch64_output_probe_stack_range (rtx reg1, rtx reg2) + return ""; + } + ++/* Return true if the current function should save registers above ++ the locals area, rather than below it. */ ++ ++static bool ++aarch64_save_regs_above_locals_p () ++{ ++ /* When using stack smash protection, make sure that the canary slot ++ comes between the locals and the saved registers. Otherwise, ++ it would be possible for a carefully sized smash attack to change ++ the saved registers (particularly LR and FP) without reaching the ++ canary. */ ++ return crtl->stack_protect_guard; ++} ++ + /* Mark the registers that need to be saved by the callee and calculate + the size of the callee-saved registers area and frame record (both FP + and LR may be omitted). */ +@@ -4138,6 +4152,16 @@ aarch64_layout_frame (void) + + cfun->machine->frame.bytes_below_hard_fp = crtl->outgoing_args_size; + ++ bool regs_at_top_p = aarch64_save_regs_above_locals_p (); ++ ++ if (regs_at_top_p) ++ { ++ cfun->machine->frame.bytes_below_hard_fp += get_frame_size (); ++ cfun->machine->frame.bytes_below_hard_fp ++ = aligned_upper_bound (cfun->machine->frame.bytes_below_hard_fp, ++ STACK_BOUNDARY / BITS_PER_UNIT); ++ } ++ + if (cfun->machine->frame.emit_frame_chain) + { + /* FP and LR are placed in the linkage record. */ +@@ -4191,9 +4215,11 @@ aarch64_layout_frame (void) + HOST_WIDE_INT varargs_and_saved_regs_size + = offset + cfun->machine->frame.saved_varargs_size; + ++ cfun->machine->frame.bytes_above_hard_fp = varargs_and_saved_regs_size; ++ if (!regs_at_top_p) ++ cfun->machine->frame.bytes_above_hard_fp += get_frame_size (); + cfun->machine->frame.bytes_above_hard_fp +- = aligned_upper_bound (varargs_and_saved_regs_size +- + get_frame_size (), ++ = aligned_upper_bound (cfun->machine->frame.bytes_above_hard_fp, + STACK_BOUNDARY / BITS_PER_UNIT); + + /* Both these values are already aligned. */ +@@ -4205,6 +4231,9 @@ aarch64_layout_frame (void) + + cfun->machine->frame.bytes_above_locals + = cfun->machine->frame.saved_varargs_size; ++ if (regs_at_top_p) ++ cfun->machine->frame.bytes_above_locals ++ += cfun->machine->frame.saved_regs_size; + + cfun->machine->frame.initial_adjust = 0; + cfun->machine->frame.final_adjust = 0; +@@ -4912,10 +4941,10 @@ aarch64_add_cfa_expression (rtx_insn *insn, unsigned int reg, + | for register varargs | + | | + +-------------------------------+ +- | local variables | <-- frame_pointer_rtx ++ | local variables (1) | <-- frame_pointer_rtx + | | + +-------------------------------+ +- | padding0 | \ ++ | padding (1) | \ + +-------------------------------+ | + | callee-saved registers | | frame.saved_regs_size + +-------------------------------+ | +@@ -4923,6 +4952,10 @@ aarch64_add_cfa_expression (rtx_insn *insn, unsigned int reg, + +-------------------------------+ | + | FP' | / <- hard_frame_pointer_rtx (aligned) + +-------------------------------+ ++ | local variables (2) | ++ +-------------------------------+ ++ | padding (2) | ++ +-------------------------------+ + | dynamic allocation | + +-------------------------------+ + | padding | +@@ -4932,6 +4965,9 @@ aarch64_add_cfa_expression (rtx_insn *insn, unsigned int reg, + +-------------------------------+ + | | <-- stack_pointer_rtx (aligned) + ++ The regions marked (1) and (2) are mutually exclusive. (2) is used ++ when aarch64_save_regs_above_locals_p is true. ++ + Dynamic stack allocations via alloca() decrease stack_pointer_rtx + but leave frame_pointer_rtx and hard_frame_pointer_rtx + unchanged. */ +@@ -5042,6 +5078,8 @@ aarch64_expand_prologue (void) + aarch64_save_callee_saves (DFmode, callee_offset, V0_REGNUM, V31_REGNUM, + callee_adjust != 0 || emit_frame_chain); + aarch64_sub_sp (ip1_rtx, ip0_rtx, final_adjust, !frame_pointer_needed); ++ if (emit_frame_chain && maybe_ne (final_adjust, 0)) ++ emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx)); + } + + /* Return TRUE if we can use a simple_return insn. +diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c +new file mode 100644 +index 000000000000..b808735762fd +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-8.c +@@ -0,0 +1,62 @@ ++/* { dg-options " -O -fstack-protector-strong" } */ ++/* { dg-final { check-function-bodies "**" "" } } */ ++ ++void g(void *); ++ ++/* ++** test1: ++** sub sp, sp, #304 ++** stp x29, x30, \[sp, #?272\] ++** add x29, sp, #?272 ++** str (x[0-9]+), \[sp, #?288\] ++** ... ++** ldr (x[0-9]+), \[\1\] ++** str \2, \[sp, #?264\] ++** mov \2, *0 ++** add x0, sp, #?8 ++** bl g ++** ... ++** ldr x[0-9]+, \[\1\] ++** ... ++** bne .* ++** ... ++** ldr \1, \[sp, #?288\] ++** ldp x29, x30, \[sp, #?272\] ++** add sp, sp, #?304 ++** ret ++** bl __stack_chk_fail ++*/ ++int test1() { ++ int y[0x40]; ++ g(y); ++ return 1; ++} ++ ++/* ++** test2: ++** stp x29, x30, \[sp, #?-32\]! ++** mov x29, sp ++** str (x[0-9]+), \[sp, #?16\] ++** sub sp, sp, #1040 ++** ... ++** ldr (x[0-9]+), \[\1\] ++** str \2, \[sp, #?1032\] ++** mov \2, *0 ++** add x0, sp, #?8 ++** bl g ++** ... ++** ldr x[0-9]+, \[\1\] ++** ... ++** bne .* ++** ... ++** add sp, sp, #?1040 ++** ldr \1, \[sp, #?16\] ++** ldp x29, x30, \[sp\], #?32 ++** ret ++** bl __stack_chk_fail ++*/ ++int test2() { ++ int y[0x100]; ++ g(y); ++ return 1; ++} +diff --git a/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c b/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c +new file mode 100644 +index 000000000000..58f322aa480a +--- /dev/null ++++ b/gcc/testsuite/gcc.target/aarch64/stack-protector-9.c +@@ -0,0 +1,33 @@ ++/* { dg-options "-O2 -mcpu=neoverse-v1 -fstack-protector-all" } */ ++/* { dg-final { check-function-bodies "**" "" } } */ ++ ++/* ++** main: ++** ... ++** stp x29, x30, \[sp, #?-[0-9]+\]! ++** ... ++** sub sp, sp, #[0-9]+ ++** ... ++** str x[0-9]+, \[x29, #?-8\] ++** ... ++*/ ++int f(const char *); ++void g(void *); ++int main(int argc, char* argv[]) ++{ ++ int a; ++ int b; ++ char c[2+f(argv[1])]; ++ int d[0x100]; ++ char y; ++ ++ y=42; a=4; b=10; ++ c[0] = 'h'; c[1] = '\0'; ++ ++ c[f(argv[2])] = '\0'; ++ ++ __builtin_printf("%d %d\n%s\n", a, b, c); ++ g(d); ++ ++ return 0; ++} +-- +2.42.0 + |