[Adding Josh in CC]

> On Thu, Sep 12, 2024 at 06:09:53PM +0200, Jose E. Marchesi via Gcc wrote:
>> - "noreturn" and jump tables run-time hints
>> 
>>   It has been expressed on the kernel side the desire of having the C 
>> compiler
>>   emit run-time hints marking functions that are not supposed to return and
>>   also to provide annotations on jump tables.  This is for the benefit of
>>   objtool in arm64, see references below.
>> 
>>   Goal of the discussion:
>> 
>>   Collect and assess the requirements of these features, discuss their
>>   pertinence and the way it could be best implemented.  The outcome of the
>>   discussion will then be used to continue the discussion with the clang/llvm
>>   and kernel hackers at LPC.
>> 
>>   References:
>>   
>> https://lore.kernel.org/linux-arm-kernel/yylmhuxtuanza...@hirez.programming.kicks-ass.net/
>
> What I was suggesting is something like (completely untested, GPL v2.0+ in
> case you'd like to use anything from that):
> #include "gcc-common.h"
>
> __visible int plugin_is_GPL_compatible;
>
> static struct plugin_info mark_noreturn_plugin_info = {
>         .version        = PLUGIN_VERSION,
>         .help           = "mark noreturn plugin\n",
> };
>
> static unsigned int mark_noreturn_execute(void)
> {
>       if (flags_from_decl_or_type(current_function_decl) & ECF_NORETURN) {
>               const char *name = 
> IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(current_function_decl));
>               name = targetm.strip_name_encoding(name);
>               name = concat("__noreturn_function.", name, NULL);
>               tree decl = build_decl(UNKNOWN_LOCATION, FUNCTION_DECL,
>                                      get_identifier(name), 
> TREE_TYPE(current_function_decl));
>               DECL_ARTIFICIAL(decl) = 1;
>               TREE_PUBLIC(decl) = 0;
>               DECL_WEAK(decl) = DECL_WEAK(current_function_decl);
>               assemble_alias(current_function_decl, decl);
>       }
>       return 0;
> }
>
> #define PASS_NAME mark_noreturn
>
> #define NO_GATE
>
> #include "gcc-generate-gimple-pass.h"
>
> __visible int plugin_init(struct plugin_name_args *plugin_info, struct 
> plugin_gcc_version *version)
> {
>       int i;
>       const char * const plugin_name = plugin_info->base_name;
>       const int argc = plugin_info->argc;
>       const struct plugin_argument * const argv = plugin_info->argv;
>       bool enable = true;
>
>       PASS_INFO(mark_noreturn, "optimized", 0, PASS_POS_INSERT_BEFORE);
>
>       if (!plugin_default_version_check(version, &gcc_version)) {
>               error(G_("incompatible gcc/plugin versions"));
>               return 1;
>       }
>
>       for (i = 0; i < argc; ++i) {
>               if (!strcmp(argv[i].key, "no-mark-noreturn")) {
>                       enable = false;
>                       continue;
>               }
>               error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, 
> argv[i].key);
>       }
>
>       register_callback(plugin_name, PLUGIN_INFO, NULL, 
> &mark_noreturn_plugin_info);
>
>       if (!enable)
>               return 0;
>
> #if BUILDING_GCC_VERSION < 6000
>       register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, 
> &mark_noreturn_pass_info);
> #endif
>
>       return 0;
> }
>
> Basically just create a __noreturn_function.foobarbaz alias to foobarbaz
> function if that function is noreturn.  Haven't investigated if all Linux
> kernel arches will be happy with . in the name, other options are $ or
> _ or conditionally one of them e.g. based on 
> NO_DOT_IN_LABEL/NO_DOLLAR_IN_LABEL
> macros.
>
>> - Struct layout randomization (-frandomize-struct-layout) and debug info
>> 
>>   The GCC plugin hooks in a way that emitted debug info doesn't match with 
>> the
>>   resulting randomized structs.  It works in clang because it generates DWARF
>>   later in the compilation process.
>> 
>>   References:
>> 
>>   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84052
>>   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116457
>> 
>>   Goal of the discussion:
>> 
>>   Determine how to best fix this in the plugin, or by using a different
>>   approach.  The outcome of the discussion will then be used to continue the
>>   discussion with the clang/llvm and kernel hackers at LPC.
>> 
>> - Userland stack unwinding from within the Linux kernel
>> 
>>   There are reasons for wanting to unwind both userland and kernel
>>   stacks from within the kernel.  Currently the kernel can unwind kernel
>>   stacks based on ORC (which is revese-engineered from kernel compiled
>>   objects by objtool) and userland stacks provided stack frame pointers
>>   are present.  SFrame is a format similar to ORC, but general enough to
>>   be used in userspace, and there is an on-going effort to introduce a
>>   SFrame based unwinder in the kernel.  This will require some glibc
>>   support as well.
>> 
>>   References:
>> 
>>   First prototype (V1) from Josh Poimboeuf:
>>   https://lkml.kernel.org/lkml/cover.1699487758.git.jpoim...@kernel.org/
>
> As discussed, either submit a patch to add another plugin callback event
> after a new structure is almost ready to be finalized but debug info hasn't
> been emitted yet, or there is also not so complicated option of reordering
> the already registered debug info to match how the FIELD_DECLs have been
> actually reordered.
>
> As for marking of the start and end of jump tables (though, of course, only
> when they are actually emitted, switch lowering can use many different ways
> of lowering the switches or combination thereof), I'd think a GCC plugin
> registering an RTL pass which is run before "final" (or so), walks the
> RTL and adds CODE_LABEL with some prefix and consecutively increased counter
> before and after the JUMP_TABLE_DATA insns.
>
>       Jakub

Reply via email to