[llvm-bugs] [Bug 24556] New: naked functions with parameters are impossible to use correctly

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Aug 24 10:26:13 PDT 2015


https://llvm.org/bugs/show_bug.cgi?id=24556

            Bug ID: 24556
           Summary: naked functions with parameters are impossible to use
                    correctly
           Product: clang
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: froydnj at gmail.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

The following testcase is a cut-down version of real code from Firefox:

struct siginfo_t;

// Shortened to act as an example.
struct sigaction {
  void (*sa_sigaction)(int, siginfo_t*, void*);
};

extern void SetSignalHandler(int sig, struct sigaction*);

// Some (old) Linux kernels on ARM have a bug where a signal handler
// can be called without clearing the IT bits in CPSR first. The result
// is that the first few instructions of the handler could be skipped,
// ultimately resulting in crashes. To workaround this bug, the handler
// on ARM is a trampoline that starts with enough NOP instructions, so
// that even if the IT bits are not cleared, only the NOP instructions
// will be skipped over.

template <void (*H)(int, siginfo_t*, void*)>
__attribute__((naked)) void
SignalTrampoline(int aSignal, siginfo_t* aInfo, void* aContext)
{
  asm volatile (
    "nop; nop; nop; nop"
    : : : "memory");

  // Because the assembler may generate additional insturctions below, we
  // need to ensure NOPs are inserted first by separating them out above.

  asm volatile (
    "bx %0"
    :
    : "r"(H)
#ifndef __clang__
      , "l"(aSignal), "l"(aInfo), "l"(aContext)
#endif
    : "memory");
}

extern void MySignalHandler(int, siginfo_t*, void*);

void
f()
{
  struct sigaction sa;
  sa.sa_sigaction = SignalTrampoline<MySignalHandler>;
  SetSignalHandler(0, &sa);
}

The #ifndef __clang__ is needed because clang doesn't permit references to
local variables in naked functions.  But then there's no way to communicate the
dependence that the asm statement has on the function's parameters.  The
generated assembly (-O2 -fno-exceptions -fno-rtti) looks like:

    .fnstart
@ BB#0:
    ldr    r0, .LCPI1_0
    ldr    r1, .LCPI1_1
    @APP
    mov    r0, r0
    mov    r0, r0
    mov    r0, r0
    mov    r0, r0
    @NO_APP
.LPC1_0:
    add    r0, pc, r0
    ldr    r0, [r1, r0]
    @APP
    bx    r0
    @NO_APP
    .align    2
@ BB#1:
.LCPI1_0:
    .long    _GLOBAL_OFFSET_TABLE_-(.LPC1_0+8)
.LCPI1_1:
    .long    _Z15MySignalHandleriP9siginfo_tPv(GOT)
.Lfunc_end1:

Both small sequences of code prior to the @APP directives clobber the argument
registers, which is undesirable.  (This sample also exhibits undesirable
behavior in that part of the load of the function address to jump to is moved
above the first asm statement.  But one thing at a time.)

GCC, AFAICT, gets this correct.  (I haven't checked GCC trunk, but the Android
NDK compilers and the arm-none-eabi cross compiler on my Linux distribution
generate code that does the right thing here.)

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150824/2cbdb107/attachment.html>


More information about the llvm-bugs mailing list