Re: gcc-10: kernel stack is corrupted and fails to boot

From: Linus Torvalds
Date: Wed May 13 2020 - 22:21:03 EST


On Wed, May 13, 2020 at 5:51 PM Nick Desaulniers
<ndesaulniers@xxxxxxxxxx> wrote:
>
> Are you sure LTO treats empty asm statements differently than full
> memory barriers in regards to preventing tail calls?

It had better.

At link-time, there is nothing left of an empty asm statement. So by
the time the linker runs, it only sees

call xyz
ret

in the object code. At that point, it's somewhat reasonable for any
link-time optimizer (or an optimizing assembler, for that matter) to
say "I'll just turn that sequence into a simple 'jmp xyz' instead".

Now, don't get me wrong - I'm not convinced any existing LTO does
that. But I'd also not be shocked by something like that.

In contrast, if it's a real mb(), the linker won't see just a
'call+ret" sequence. It will see something like

call xyz
mfence
ret

(ok, the mfence may actually be something else, and we'll have a label
on it and an alternatives table pointing to it, but the point is,
unlike an empty asm, there's something _there_).

Now, if the linker turns that 'call' into a 'jmp', the linker is just
plain buggy.

See the difference?

> The TL;DR of the very long thread is that
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722 is a proper fix, on
> the GCC side. Adding arbitrary empty asm statements to work around
> it? Hacks. Full memory barriers? Hacks.

BS.

A compiler person might call it a "hack". But said compiler person
will be _wrong_.

An intelligent developer knows that it will take years for compilers
to give us all the infrastructure we need, and even then the compiler
won't actually give us everything - and people will be using the old
compilers for years anyway.

That's why inline asm's exist. They are the escape from the excessive
confines of "let's wait for the compiler person to solve this for us"
- which they'll never do completely anyway.

It's a bit like unsafe C type casts and allowing people to write
"non-portable code". Some compiler people will say that it's bad, and
unsafe. Sure, it can be unsafe, but the point is that it allows you to
do things that aren't necessarily _possible_ to do in an overly
restrictive language.

Sometimes you need to break the rules.

There's a reason everybody writes library routines in "unsafe"
languages like C. Because you need those kinds of escapes in order to
actually do something like a memory allocator etc.

And that's also why we have inline asm - because the compiler will
never know everything or be able to generate code for everything
people wants to do.

And anybody that _thinks_ that the compiler will always know better
and should be in complete control shouldn't be working on compilers.
They should probably be repeating kindergarten, sitting in a corner
eating paste with their friends.

So no. Using inline asms to work around the compiler not understanding
what is going on isn't a "hack". It's the _point_ of inline asm.

Is it perfect? No. But it's not like there are many alternatives.

Linus