[PATCH v2 00/10] Introduce strub: machine-independent stack scrubbing
Alexandre Oliva
oliva@adacore.com
Fri Jul 29 06:16:41 GMT 2022
This patch adds the strub attribute for function and variable types,
command-line options, passes and adjustments to implement it,
documentation, and tests.
Stack scrubbing is implemented in a machine-independent way: functions
with strub enabled are modified so that they take an extra stack
watermark argument, that they update with their stack use, and the
caller can then zero it out once it regains control, whether by return
or exception. There are two ways to go about it: at-calls, that
modifies the visible interface (signature) of the function, and
internal, in which the body is moved to a clone, the clone undergoes
the interface change, and the function becomes a wrapper, preserving
its original interface, that calls the clone and then clears the stack
used by it.
Variables can also be annotated with the strub attribute, so that
functions that read from them get stack scrubbing enabled implicitly,
whether at-calls, for functions only usable within a translation unit,
or internal, for functions whose interfaces must not be modified.
There is a strict mode, in which functions that have their stack
scrubbed can only call other functions with stack-scrubbing
interfaces, or those explicitly marked as callable from strub
contexts, so that an entire call chain gets scrubbing, at once or
piecemeal depending on optimization levels. In the default mode,
relaxed, this requirement is not enforced by the compiler.
The implementation adds two IPA passes, one that assigns strub modes
early on, another that modifies interfaces and adds calls to the
builtins that jointly implement stack scrubbing. Another builtin,
that obtains the stack pointer, is added for use in the implementation
of the builtins, whether expanded inline or called in libgcc.
There are new command-line options to change operation modes and to
force the feature disabled; it is enabled by default, but it has no
effect and is implicitly disabled if the strub attribute is never
used. There are also options meant to use for testing the feature,
enabling different strubbing modes for all (viable) functions.
I'm going to split up the very large patch into separate posts:
1:documentation, tests (2:C/C++ torture, 3:C/C++ non-torture, 4:C++
and Ada), 5:builtins and runtime, 6:attributes, 7:interfaces and
adjustments, and ipa-strub.cc fragments (8:strub modes, 9:strub mode
assignment pass, and 10:strub pass proper).
This is an refreshed and updated version of the patch posted in Sept
last year. It was regstrapped on x86_64-linux-gnu, bootstrapped with a
patchlet that enables -fstrub=all by default (with a fix for a warning
exposed by it). Earlier, essentially the same change has undergone
significant testing, with and without -fstrub=all on multiple embedded
platforms. Ok to install?
for gcc/ChangeLog
* Makefile.in (OBJS): Add ipa-strub.o.
* builtins.def (BUILT_IN_STACK_ADDRESS): New.
(BUILT_IN___STRUB_ENTER): New.
(BUILT_IN___STRUB_UPDATE): New.
(BUILT_IN___STRUB_LEAVE): New.
* builtins.cc: Include ipa-strub.h.
(STACK_STOPS, STACK_UNSIGNED): Define.
(expand_builtin_stack_address): New.
(expand_builtin_strub_enter): New.
(expand_builtin_strub_update): New.
(expand_builtin_strub_leave): New.
(expand_bulitin): Call them.
* common.opt (fstrub=*): New options.
* doc/extend.texi (strub): New type attribute.
(__builtin_stack_address): New function.
(Stack Scrubbing): New section.
* doc/invoke.texi (-fstrub=*): New options.
(-fdump-ipa-*): New passes.
* ipa-inline.cc: Include ipa-strub.h.
(can_inline_edge_p): Test strub_inlinable_to_p.
* ipa-split.cc: Include ipa-strub.h.
(execute_split_functions): Test strub_splittable_p.
* ipa-strub.cc, ipa-strub.h: New.
* passes.def: Add strub_mode and strub passes.
* tree-cfg.cc (gimple_verify_flow_info): Note on debug stmts.
* tree-pass.h (make_pass_ipa_strub_mode): Declare.
(make_pass_ipa_strub): Declare.
(make_pass_ipa_function_and_variable_visibility): Fix
formatting.
* tree-ssa-ccp.cc (optimize_stack_restore): Keep restores
before strub leave.
* multiple_target.cc (pass_target_clone::gate): Test seen_error.
* attribs.cc: Include ipa-strub.h.
(decl_attributes): Support applying attributes to function
type, rather than pointer type, at handler's request.
(comp_type_attributes): Combine strub_comptypes and target
comp_type results.
for gcc/c-family/ChangeLog
* c-attribs.cc: Include ipa-strub.h.
(handle_strub_attribute): New.
(c_common_attribute_table): Add strub.
for gcc/ada/ChangeLog
* gcc-interface/trans.cc: Include ipa-strub.h.
(gigi): Make internal decls for targets of compiler-generated
calls strub-callable too.
(build_raise_check): Likewise.
* gcc-interface/utils.cc: Include ipa-strub.h.
(handle_strub_attribute): New.
(gnat_internal_attribute_table): Add strub.
for gcc/testsuite/ChangeLog
* c-c++-common/strub-O0.c: New.
* c-c++-common/strub-O1.c: New.
* c-c++-common/strub-O2.c: New.
* c-c++-common/strub-O2fni.c: New.
* c-c++-common/strub-O3.c: New.
* c-c++-common/strub-O3fni.c: New.
* c-c++-common/strub-Og.c: New.
* c-c++-common/strub-Os.c: New.
* c-c++-common/strub-all1.c: New.
* c-c++-common/strub-all2.c: New.
* c-c++-common/strub-apply1.c: New.
* c-c++-common/strub-apply2.c: New.
* c-c++-common/strub-apply3.c: New.
* c-c++-common/strub-apply4.c: New.
* c-c++-common/strub-at-calls1.c: New.
* c-c++-common/strub-at-calls2.c: New.
* c-c++-common/strub-defer-O1.c: New.
* c-c++-common/strub-defer-O2.c: New.
* c-c++-common/strub-defer-O3.c: New.
* c-c++-common/strub-defer-Os.c: New.
* c-c++-common/strub-internal1.c: New.
* c-c++-common/strub-internal2.c: New.
* c-c++-common/strub-parms1.c: New.
* c-c++-common/strub-parms2.c: New.
* c-c++-common/strub-parms3.c: New.
* c-c++-common/strub-relaxed1.c: New.
* c-c++-common/strub-relaxed2.c: New.
* c-c++-common/strub-short-O0-exc.c: New.
* c-c++-common/strub-short-O0.c: New.
* c-c++-common/strub-short-O1.c: New.
* c-c++-common/strub-short-O2.c: New.
* c-c++-common/strub-short-O3.c: New.
* c-c++-common/strub-short-Os.c: New.
* c-c++-common/strub-strict1.c: New.
* c-c++-common/strub-strict2.c: New.
* c-c++-common/strub-tail-O1.c: New.
* c-c++-common/strub-tail-O2.c: New.
* c-c++-common/torture/strub-callable1.c: New.
* c-c++-common/torture/strub-callable2.c: New.
* c-c++-common/torture/strub-const1.c: New.
* c-c++-common/torture/strub-const2.c: New.
* c-c++-common/torture/strub-const3.c: New.
* c-c++-common/torture/strub-const4.c: New.
* c-c++-common/torture/strub-data1.c: New.
* c-c++-common/torture/strub-data2.c: New.
* c-c++-common/torture/strub-data3.c: New.
* c-c++-common/torture/strub-data4.c: New.
* c-c++-common/torture/strub-data5.c: New.
* c-c++-common/torture/strub-indcall1.c: New.
* c-c++-common/torture/strub-indcall2.c: New.
* c-c++-common/torture/strub-indcall3.c: New.
* c-c++-common/torture/strub-inlinable1.c: New.
* c-c++-common/torture/strub-inlinable2.c: New.
* c-c++-common/torture/strub-ptrfn1.c: New.
* c-c++-common/torture/strub-ptrfn2.c: New.
* c-c++-common/torture/strub-ptrfn3.c: New.
* c-c++-common/torture/strub-ptrfn4.c: New.
* c-c++-common/torture/strub-pure1.c: New.
* c-c++-common/torture/strub-pure2.c: New.
* c-c++-common/torture/strub-pure3.c: New.
* c-c++-common/torture/strub-pure4.c: New.
* c-c++-common/torture/strub-run1.c: New.
* c-c++-common/torture/strub-run2.c: New.
* c-c++-common/torture/strub-run3.c: New.
* c-c++-common/torture/strub-run4.c: New.
* c-c++-common/torture/strub-run4c.c: New.
* c-c++-common/torture/strub-run4d.c: New.
* c-c++-common/torture/strub-run4i.c: New.
* g++.dg/strub-run1.C: New.
* g++.dg/torture/strub-init1.C: New.
* g++.dg/torture/strub-init2.C: New.
* g++.dg/torture/strub-init3.C: New.
* gnat.dg/strub_attr.adb, gnat.dg/strub_attr.ads: New.
* gnat.dg/strub_ind.adb, gnat.dg/strub_ind.ads: New.
for libgcc/ChangeLog
* Makefile.in (LIB2ADD): Add strub.c.
* libgcc2.h (__strub_enter, __strub_update, __strub_leave):
Declare.
* strub.c: New.
---
gcc/Makefile.in | 1
gcc/ada/gcc-interface/trans.cc | 18
gcc/ada/gcc-interface/utils.cc | 73
gcc/attribs.cc | 40
gcc/builtins.cc | 273 ++
gcc/builtins.def | 4
gcc/c-family/c-attribs.cc | 82
gcc/common.opt | 29
gcc/doc/extend.texi | 307 ++
gcc/doc/invoke.texi | 60
gcc/ipa-inline.cc | 6
gcc/ipa-split.cc | 7
gcc/ipa-strub.cc | 3489 ++++++++++++++++++++
gcc/ipa-strub.h | 45
gcc/multiple_target.cc | 2
gcc/passes.def | 2
gcc/testsuite/c-c++-common/strub-O0.c | 14
gcc/testsuite/c-c++-common/strub-O1.c | 15
gcc/testsuite/c-c++-common/strub-O2.c | 16
gcc/testsuite/c-c++-common/strub-O2fni.c | 15
gcc/testsuite/c-c++-common/strub-O3.c | 12
gcc/testsuite/c-c++-common/strub-O3fni.c | 15
gcc/testsuite/c-c++-common/strub-Og.c | 16
gcc/testsuite/c-c++-common/strub-Os.c | 18
gcc/testsuite/c-c++-common/strub-all1.c | 32
gcc/testsuite/c-c++-common/strub-all2.c | 24
gcc/testsuite/c-c++-common/strub-apply1.c | 15
gcc/testsuite/c-c++-common/strub-apply2.c | 12
gcc/testsuite/c-c++-common/strub-apply3.c | 8
gcc/testsuite/c-c++-common/strub-apply4.c | 21
gcc/testsuite/c-c++-common/strub-at-calls1.c | 30
gcc/testsuite/c-c++-common/strub-at-calls2.c | 23
gcc/testsuite/c-c++-common/strub-defer-O1.c | 7
gcc/testsuite/c-c++-common/strub-defer-O2.c | 8
gcc/testsuite/c-c++-common/strub-defer-O3.c | 97 +
gcc/testsuite/c-c++-common/strub-defer-Os.c | 7
gcc/testsuite/c-c++-common/strub-internal1.c | 31
gcc/testsuite/c-c++-common/strub-internal2.c | 21
gcc/testsuite/c-c++-common/strub-parms1.c | 48
gcc/testsuite/c-c++-common/strub-parms2.c | 36
gcc/testsuite/c-c++-common/strub-parms3.c | 58
gcc/testsuite/c-c++-common/strub-relaxed1.c | 18
gcc/testsuite/c-c++-common/strub-relaxed2.c | 14
gcc/testsuite/c-c++-common/strub-short-O0-exc.c | 10
gcc/testsuite/c-c++-common/strub-short-O0.c | 10
gcc/testsuite/c-c++-common/strub-short-O1.c | 10
gcc/testsuite/c-c++-common/strub-short-O2.c | 10
gcc/testsuite/c-c++-common/strub-short-O3.c | 12
gcc/testsuite/c-c++-common/strub-short-Os.c | 12
gcc/testsuite/c-c++-common/strub-strict1.c | 36
gcc/testsuite/c-c++-common/strub-strict2.c | 25
gcc/testsuite/c-c++-common/strub-tail-O1.c | 8
gcc/testsuite/c-c++-common/strub-tail-O2.c | 14
gcc/testsuite/c-c++-common/strub-var1.c | 24
.../c-c++-common/torture/strub-callable1.c | 9
.../c-c++-common/torture/strub-callable2.c | 264 ++
gcc/testsuite/c-c++-common/torture/strub-const1.c | 18
gcc/testsuite/c-c++-common/torture/strub-const2.c | 22
gcc/testsuite/c-c++-common/torture/strub-const3.c | 13
gcc/testsuite/c-c++-common/torture/strub-const4.c | 17
gcc/testsuite/c-c++-common/torture/strub-data1.c | 13
gcc/testsuite/c-c++-common/torture/strub-data2.c | 14
gcc/testsuite/c-c++-common/torture/strub-data3.c | 14
gcc/testsuite/c-c++-common/torture/strub-data4.c | 14
gcc/testsuite/c-c++-common/torture/strub-data5.c | 15
.../c-c++-common/torture/strub-indcall1.c | 14
.../c-c++-common/torture/strub-indcall2.c | 14
.../c-c++-common/torture/strub-indcall3.c | 14
.../c-c++-common/torture/strub-inlinable1.c | 16
.../c-c++-common/torture/strub-inlinable2.c | 7
gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c | 10
gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c | 55
gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c | 50
gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c | 43
gcc/testsuite/c-c++-common/torture/strub-pure1.c | 18
gcc/testsuite/c-c++-common/torture/strub-pure2.c | 22
gcc/testsuite/c-c++-common/torture/strub-pure3.c | 13
gcc/testsuite/c-c++-common/torture/strub-pure4.c | 17
gcc/testsuite/c-c++-common/torture/strub-run1.c | 90 +
gcc/testsuite/c-c++-common/torture/strub-run2.c | 79
gcc/testsuite/c-c++-common/torture/strub-run3.c | 75
gcc/testsuite/c-c++-common/torture/strub-run4.c | 101 +
gcc/testsuite/c-c++-common/torture/strub-run4c.c | 5
gcc/testsuite/c-c++-common/torture/strub-run4d.c | 7
gcc/testsuite/c-c++-common/torture/strub-run4i.c | 5
gcc/testsuite/g++.dg/strub-run1.C | 19
gcc/testsuite/g++.dg/torture/strub-init1.C | 13
gcc/testsuite/g++.dg/torture/strub-init2.C | 14
gcc/testsuite/g++.dg/torture/strub-init3.C | 13
gcc/testsuite/gnat.dg/strub_access.adb | 21
gcc/testsuite/gnat.dg/strub_access1.adb | 16
gcc/testsuite/gnat.dg/strub_attr.adb | 37
gcc/testsuite/gnat.dg/strub_attr.ads | 12
gcc/testsuite/gnat.dg/strub_disp.adb | 64
gcc/testsuite/gnat.dg/strub_disp1.adb | 79
gcc/testsuite/gnat.dg/strub_ind.adb | 33
gcc/testsuite/gnat.dg/strub_ind.ads | 17
gcc/testsuite/gnat.dg/strub_ind1.adb | 41
gcc/testsuite/gnat.dg/strub_ind1.ads | 17
gcc/testsuite/gnat.dg/strub_ind2.adb | 34
gcc/testsuite/gnat.dg/strub_ind2.ads | 17
gcc/testsuite/gnat.dg/strub_intf.adb | 93 +
gcc/testsuite/gnat.dg/strub_intf1.adb | 86
gcc/testsuite/gnat.dg/strub_intf2.adb | 55
gcc/testsuite/gnat.dg/strub_renm.adb | 21
gcc/testsuite/gnat.dg/strub_renm1.adb | 32
gcc/testsuite/gnat.dg/strub_renm2.adb | 32
gcc/testsuite/gnat.dg/strub_var.adb | 16
gcc/testsuite/gnat.dg/strub_var1.adb | 20
gcc/tree-cfg.cc | 1
gcc/tree-pass.h | 5
gcc/tree-ssa-ccp.cc | 4
libgcc/Makefile.in | 3
libgcc/libgcc2.h | 4
libgcc/strub.c | 112 +
115 files changed, 7227 insertions(+), 12 deletions(-)
create mode 100644 gcc/ipa-strub.cc
create mode 100644 gcc/ipa-strub.h
create mode 100644 gcc/testsuite/c-c++-common/strub-O0.c
create mode 100644 gcc/testsuite/c-c++-common/strub-O1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-O2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-O2fni.c
create mode 100644 gcc/testsuite/c-c++-common/strub-O3.c
create mode 100644 gcc/testsuite/c-c++-common/strub-O3fni.c
create mode 100644 gcc/testsuite/c-c++-common/strub-Og.c
create mode 100644 gcc/testsuite/c-c++-common/strub-Os.c
create mode 100644 gcc/testsuite/c-c++-common/strub-all1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-all2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-apply1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-apply2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-apply3.c
create mode 100644 gcc/testsuite/c-c++-common/strub-apply4.c
create mode 100644 gcc/testsuite/c-c++-common/strub-at-calls1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-at-calls2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-defer-O1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-defer-O2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-defer-O3.c
create mode 100644 gcc/testsuite/c-c++-common/strub-defer-Os.c
create mode 100644 gcc/testsuite/c-c++-common/strub-internal1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-internal2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-parms1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-parms2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-parms3.c
create mode 100644 gcc/testsuite/c-c++-common/strub-relaxed1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-relaxed2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-O0-exc.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-O0.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-O1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-O2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-O3.c
create mode 100644 gcc/testsuite/c-c++-common/strub-short-Os.c
create mode 100644 gcc/testsuite/c-c++-common/strub-strict1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-strict2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-tail-O1.c
create mode 100644 gcc/testsuite/c-c++-common/strub-tail-O2.c
create mode 100644 gcc/testsuite/c-c++-common/strub-var1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-callable1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-callable2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-const1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-const2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-const3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-const4.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-data1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-data2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-data3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-data4.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-data5.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-indcall1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-indcall2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-indcall3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-pure1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-pure2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-pure3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-pure4.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run1.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run2.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run3.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run4.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run4c.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run4d.c
create mode 100644 gcc/testsuite/c-c++-common/torture/strub-run4i.c
create mode 100644 gcc/testsuite/g++.dg/strub-run1.C
create mode 100644 gcc/testsuite/g++.dg/torture/strub-init1.C
create mode 100644 gcc/testsuite/g++.dg/torture/strub-init2.C
create mode 100644 gcc/testsuite/g++.dg/torture/strub-init3.C
create mode 100644 gcc/testsuite/gnat.dg/strub_access.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_access1.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_attr.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_attr.ads
create mode 100644 gcc/testsuite/gnat.dg/strub_disp.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_disp1.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_ind.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_ind.ads
create mode 100644 gcc/testsuite/gnat.dg/strub_ind1.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_ind1.ads
create mode 100644 gcc/testsuite/gnat.dg/strub_ind2.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_ind2.ads
create mode 100644 gcc/testsuite/gnat.dg/strub_intf.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_intf1.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_intf2.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_renm.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_renm1.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_renm2.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_var.adb
create mode 100644 gcc/testsuite/gnat.dg/strub_var1.adb
create mode 100644 libgcc/strub.c
--
Alexandre Oliva, happy hacker https://FSFLA.org/blogs/lxo/
Free Software Activist GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts. Ask me about <https://stallmansupport.org>
More information about the Gcc-patches
mailing list