裸函数中的非 ASM 语句

问题描述 投票:0回答:1

我正在尝试创建一个包含自定义序言/尾声的类,该类应由其他“消费者”类的方法使用。

它应该类似于以下示例。 (请记住,这些示例序言/尾声主体只是用于说明目的的占位符。当然,它们将以纯汇编形式编写)

class foo
{
    public:

    static inline void prologue(void) __attribute__ ((always_inline))
    {
        asm("nop");
    }
    

    static inline void epilogue(void) __attribute__ ((always_inline))
    {
        asm("nop");
    }

};

现在,在包含使用这些自定义序言/尾声的方法的“消费者”类中,我使用如下所示的 bare 属性。 (请记住,此示例方法主体结构才是最重要的。应在序言/尾声之间放置更多代码,但对于此说明来说不是必需的)

class bar
{
    public:
    static void method()  __attribute__ ((naked))
    {
        foo::prologue();
        //more cpp instructions shall go here
        foo::epilogue();
    }
};

我面临的问题是 clang 编译器不允许在裸函数中调用像

foo::prologue()
这样的标准 Cpp 代码,并返回以下错误

<source>:23:9: error: non-ASM statement in naked function is not supported
   23 |         foo::prologue();
      |         ^

有趣的是,GCC 似乎允许这样做。

我错过了什么吗?有没有其他优雅的方法来做到这一点?

godbolt 测试可以在这里找到:https://godbolt.org/z/YfnvfEM3f

c++ assembly inline-assembly clang++
1个回答
0
投票

本质上,naked函数不允许使用C++语句,因为你没有任何堆栈、寄存器或地址的设置。

作为解决方法,您可以将函数作为 ARM 指令的 extern C 符号调用,您可以将其传递到裸函数的 ASM.inside 中。

class foo {
public:
    static inline void prologue(void) __attribute__((always_inline)) {
        asm("nop");
    }

    static inline void epilogue(void) __attribute__((always_inline)) {
        asm("nop");
    }
};

extern "C" void foo_prologue_wrapper() {
    foo::prologue();
}

extern "C" void foo_epilogue_wrapper() {
    foo::epilogue();
}

extern "C" void foo_otherfunctioncall(){
    //code the rest here
    return;
}

class bar {
public:
    static void method() __attribute__((naked)) {
        asm volatile(
            "bl foo_prologue_wrapper\n"  
            "bl foo_otherfunctioncall\n"
            "bl foo_epilogue_wrapper\n"  
            "ret\n"                      
        );
    }
};

int main(void) {
    bar::method();
    return 0;
}

有了这个,你应该能够在“foo_otherfunctioncall”函数中访问你的C++。

#include <vector>

extern "C" void foo_otherfunctioncall(){
    std::vector<int> a;
    return;
}

它确实编译成这样:

foo_prologue_wrapper:
        nop
        ret

foo_epilogue_wrapper:
        nop
        ret

foo_otherfunctioncall:
        sub     sp, sp, #48
        stp     x29, x30, [sp, #32]
        add     x29, sp, #32
        add     x0, sp, #8
        str     x0, [sp]
        bl      std::vector<int, std::allocator<int>>::vector() [base object constructor]
        ldr     x0, [sp]
        bl      std::vector<int, std::allocator<int>>::~vector() [base object destructor]
        ldp     x29, x30, [sp, #32]
        add     sp, sp, #48
        ret

main:
        sub     sp, sp, #32
        stp     x29, x30, [sp, #16]
        add     x29, sp, #16
        mov     w8, wzr
        str     w8, [sp, #8]
        stur    wzr, [x29, #-4]
        bl      bar::method()
        ldr     w0, [sp, #8]
        ldp     x29, x30, [sp, #16]
        add     sp, sp, #32
        ret

bar::method():
        bl      foo_prologue_wrapper
        bl      foo_otherfunctioncall
        bl      foo_epilogue_wrapper
        ret

__clang_call_terminate:
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      __cxa_begin_catch
        bl      std::terminate()

DW.ref.__gxx_personality_v0:
        .xword  __gxx_personality_v0
© www.soinside.com 2019 - 2024. All rights reserved.