On Thu, Aug 13, 2020 at 10:39 AM Jakub Jelinek via Gcc <gcc@gcc.gnu.org> wrote:
>
> Hi!
>
> Any time somebody adds or removes an option in some *.opt file (which e.g.
> on the 10 branch after branching off 11 happened 5 times already), many
> offsets in global_options variable change.  It is true we don't guarantee
> ABI stability for plugins, but we change the most often used data structures
> on the release branches only very rarely and so the options changes are the
> most problematic for ABI stability of plugins.
>
> Annobin uses a way to remap accesses to some of the global_options.x_* by
> looking them up in the cl_options array where we have
> offsetof (struct gcc_options, x_flag_lto)
> etc. remembered, but sadly doesn't do it for all options (e.g. some flag_*
> etc. option accesses may be hidden in various macros like POINTER_SIZE),
> and more importantly some struct gcc_options offsets are not covered at all.
> E.g. there is no offsetof (struct gcc_options, x_optimize),
> offsetof (struct gcc_options, x_flag_sanitize) etc.  Those are usually:
> Variable
> int optimize
> in the *.opt files.
>
> So, couldn't our opt*.awk scripts generate another array that would either
> cover just the offsets not covered in struct cl_options that a plugin could
> use to remap struct global_options offsets at runtime, which would include
> e.g. the offsetof value and the name of the variable and perhaps sizeof for
> verification purposes?
> Or couldn't we in plugin/include/ install a modified version of options.h
> that instead of all the:
> #define flag_opts_finished global_options.x_flag_opts_finished
> will do:
> #define flag_opts_finished gcc_lookup_option (flag_opts_finished)
> where lookup_option would be a macro that does something like:
> __attribute__((__pure__))
> void *gcc_lookup_option_2 (unsigned short, const char *, unsigned short);
> template <typename T>
> T &gcc_lookup_option_1 (unsigned short offset, const char *name)
> {
>   T *ptr = static_cast <T *> (gcc_lookup_option_2 (offset, name, sizeof (T)));
>   return *ptr;
> }
> #define lookup_option(var) \
>   gcc_lookup_option_1 <decltype (global_options.x_##var)> \
>     (offsetof (struct gcc_options, x_##var), #var, \
>      sizeof (global_options.x_##var))
> where the gcc_lookup_option_2 function would lookup the variable in an
> opt*.awk generated table, containing entries like:
>   "ix86_stack_protector_guard_offset", NULL, NULL, NULL, NULL, NULL, NULL, 
> NULL,
>   "ix86_stack_protector_guard_reg", "", NULL, NULL,
>   "recip_mask", NULL, NULL, NULL,
> ...
> As struct gcc_options is around 5KB now, that table would need 5K entries,
> NULL and "" stand for no variable starts here, and "" additionally says that
> padding starts here.
> So, if no options have changed since the plugin has been built, it would be
> very cheap, it would just verify that at the given offset the table contains
> the corresponding string (i.e. non-NULL and strcmp == 0 and that the size
> matches (that size - 1 following entries are NULL and then there is
> non-NULL)). If not, it would keep looking around (one loop that looks in
> both directions in the table, so first it would check offsets -1 and +1 from
> the original, then -2 and +2, etc.
> And would gcc_unreachable () if it can't find it in the table, or can find
> it, but the size has changed.
>
> If that is unacceptable, at least having a table with variables not covered
> in struct cl_options offsets would allow the plugin to do it itself
> (basically by constructing a remapping table, original offsetof (struct 
> gcc_options, XXX)
> remaps to offset ABC (and have some value like (unsigned short) -1 to signal
> it is gone and there should be assertion failure.
>
> Thoughts on this?

I'd say we ignore this since we do not provide any ABI stability guarantees.
Instead we maybe want to "export" the genchecksum result and embed
it into plugin objects and refuse to load plugins that were not built against
the very same ABI [unless --force is given]?

Richard.

>         Jakub
>

Reply via email to