Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit a warning if inline assembly with a clobber list is used inside a naked function. #29015

Open
goussepi opened this issue Jul 21, 2016 · 5 comments
Labels
bugzilla Issues migrated from bugzilla llvm:regalloc

Comments

@goussepi
Copy link
Collaborator

Bugzilla Link 28641
Version trunk
OS Windows NT
CC @eugenis,@pogo59,@rnk

Extended Description

Having inline assembly with a clobber list in a function marked naked seems dangerous as this will alter the stack but only at -O0 in the case below, higher optimisations level are fine.

eg:
$ clang --version
clang version 3.9.0 @​r276109
Target: x86_64-unknown-linux-gnu

#include <stdlib.h>

attribute((naked, noinline)) int foo(size_t)
{
asm volatile (
"ret" : : : "rdi"
);
}

$ clang -O0 -S test.cpp

BB#0: # %entry

    movq    %rdi, -16(%rbp)         # 8-byte Spill <- Stack altered
    #APP
    retq
    #NO_APP
@rnk
Copy link
Collaborator

rnk commented Jul 21, 2016

Alternatively we could avoid generating code around inline asm if it appears in a naked function.

@goussepi
Copy link
Collaborator Author

Alternatively we could avoid generating code around inline asm if it appears
in a naked function.

Yes, I think it depends whether clobbered list are meant to be supported inside naked functions, or are their behaviour undefined?

This gcc documentation https://gcc.gnu.org/onlinedocs/gcc/ARM-Function-Attributes.html#ARM-Function-Attributes seems to suggest that only "basic asm" is allowed in a naked function, clobbered list are considered "extended asm" I think.

Does it mean we could emit an undefined behaviour warning whenever a non "basic asm" statement is found in a naked function?

@eugenis
Copy link
Contributor

eugenis commented Dec 22, 2016

FTR, we've got a use for simple input arguments in inline asm in naked functions, like this:

define void @​f() #​0 {
entry:
call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(void ()* @​f.cfi)
unreachable
}

attributes #​0 = { naked }

We use this to emit CFI jumptables, see https://reviews.llvm.org/D28012 for more context. Without the input argument, we'd have to do asm name mangling in IR transform pass, which is ugly and wrong.

Btw, win32 backend is not happy about any assembly in a naked function right now.

target triple = "x86_64-pc-windows-msvc"

define void @​f() #​0 {
entry:
call void asm "nop", ""()
unreachable
}

attributes #​0 = { naked }

include/llvm/CodeGen/MachineFunction.h:452: bool llvm::MachineFunction::hasWinCFI() const: Assertion `HasWinCFI.hasValue() && "HasWinCFI not set yet!"' failed.

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 15, 2018

It looks like the register spill instruction is nothing to do with the inline assembler statement register clobber list. The extra instruction is a spill of a function input argument:

Consider the source:
attribute((naked, noinline)) void foo(SIZE_T x, SIZE_T y, SIZE_T z)
{
asm volatile (
"ret" : : :
);
}

It produces the following assembler:
foo: # @​foo

%bb.0: # %entry

    #APP
    retq
    #NO_APP
    movq    %rsi, -8(%rbp)          # 8-byte Spill
    movq    %rdi, -16(%rbp)         # 8-byte Spill
    movq    %rdx, -24(%rbp)         # 8-byte Spill

As can be seen the spilled registers are the function input arguments.

It happens only if the clang uses Fast registry allocator, which produces spill to the stack frame instruction for every function input argument. Other registry allocators in similar situation, mark those registers as "dead", replace them with "KILL %%reg" instructions and no machine instructions will be produced for them during the instruction selection phase.
So, the question is, what is a best way to fix the issue?
Disable spill instruction generation for "naked" function? Produce a warning message?

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 26, 2018

potential fix on Phabricator:
https://reviews.llvm.org/D43542

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla llvm:regalloc
Projects
None yet
Development

No branches or pull requests

4 participants