qemu riscv 用户模式 ​​C++/musl 段错误

发布于 2025-01-13 09:43:38 字数 5350 浏览 0 评论 0原文

我是 qemu 新手,并尝试在用户模式下运行 riscv 二进制文件。不确定我是否遇到了错误或只是做错了什么。我使用的系统是非常简单的 x86_64 上的 Fedora 35。

作为参考,C++ hello world 使用来自 musl.cc 的预构建工具链对 mipsel 运行良好。

$ cat hello.cc
#include <iostream>
int main() {
 std::cout << "Hello\n";
 return 0;
}
$ mipsel-linux-musl-g++ -static -g -O0 hello.cc -o hello
$ qemu-mipsel hello
Hello

对于带有 riscv 的 C 也是如此(32 或 64 似乎并不重要)。

$ cat hello.c
#include<stdio.h>
int main(int argc, char **argv) {
 printf("Hello\n");
 return 0;
}
$ riscv32-linux-musl-gcc -static -g -Og hello.c -o hello
$ qemu-riscv32 hello
Hello

但对于 C++/riscv 我遇到了段错误。

$ riscv32-linux-musl-g++ -static -g -Og hello.cc -o hello
$ qemu-riscv32 hello
Segmentation fault (core dumped)

显然来自 qemu 本身

Thread 1 "qemu-riscv32" received signal SIGSEGV, Segmentation fault.
0x00007fffe802558e in code_gen_buffer ()
(gdb) bt
#0  0x00007fffe802558e in code_gen_buffer ()
#1  0x00005555556bb44e in cpu_tb_exec (cpu=0x555555887b50, itb=<optimized out>, tb_exit=0x7fffffffd9a0) at ../accel/tcg/cpu-exec.c:353
#2  0x00005555556bc2f9 in cpu_loop_exec_tb (tb_exit=0x7fffffffd9a0, last_tb=<synthetic pointer>, tb=0x7fffe8025500 <code_gen_buffer+152787>, cpu=0x555555887b50)
    at ../accel/tcg/cpu-exec.c:812
#3  cpu_exec (cpu=cpu@entry=0x555555887b50) at ../accel/tcg/cpu-exec.c:970
#4  0x00005555555eed28 in cpu_loop (env=0x55555588fe40) at ../linux-user/riscv/cpu_loop.c:37
#5  0x00005555555e2b81 in main (argc=<optimized out>, argv=0x7fffffffe1c8, envp=<optimized out>) at ../linux-user/main.c:885

riscv64 的系统模拟模式中也会发生类似的情况。

我很高兴将此报告为 qemu bug,但似乎更有可能我只是做错了什么。我做错了什么吗?

更新:

我附加到 gdb 存根,并且段错误发生在二进制文件中的动态转换上:

(gdb) bt
#0  __cxxabiv1::__dynamic_cast (src_ptr=0x40000e19e0 <(anonymous namespace)::ctype_c>, src_type=0x40000d8808 <typeinfo for std::locale::facet>, dst_type=0x40000d9ac0 <typeinfo for std::ctype<char>>, src2dst=0)
    at ../../../../src_gcc/libstdc++-v3/libsupc++/dyncast.cc:74
#1  0x000000400005ed58 in std::has_facet<std::ctype<char> > (__loc=...) at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/locale_classes.tcc:110
#2  0x0000004000054be0 in std::basic_ios<char, std::char_traits<char> >::_M_cache_locale (this=this@entry=0x40000e0af8 <std::cout+8>, __loc=...)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/basic_ios.tcc:159
#3  0x0000004000054eaa in std::basic_ios<char, std::char_traits<char> >::init (this=this@entry=0x40000e0af8 <std::cout+8>, __sb=__sb@entry=0x40000e00d8 <__gnu_internal::buf_cout_sync>)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/basic_ios.tcc:132
#4  0x0000004000027ad2 in std::basic_ostream<char, std::char_traits<char> >::basic_ostream (__sb=<optimized out>, this=<optimized out>, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/ostream:85
#5  std::ios_base::Init::Init (this=<optimized out>) at ../../../../../src_gcc/libstdc++-v3/src/c++98/ios_init.cc:91
#6  std::ios_base::Init::Init (this=<optimized out>) at ../../../../../src_gcc/libstdc++-v3/src/c++98/ios_init.cc:78
#7  0x00000040000278c0 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/jpkenny/src/riscv64-linux-musl-cross/riscv64-linux-musl/include/c++/11.2.1/iostream:74
#8  0x00000040000278fa in _GLOBAL__sub_I_main () at hello.cc:5
#9  0x000000400008fbfa in libc_start_init ()
Backtrace stopped: frame did not save the PC

根据 gdb,这发生在最后一个 asm 指令上:

000000000007d38e <__dynamic_cast>:
   7d38e:       c55d                    beqz    a0,7d43c <__dynamic_cast+0xae>
   7d390:       00053803                ld      a6,0(a0)
   7d394:       715d                    addi    sp,sp,-80
   7d396:       fc26                    sd      s1,56(sp)
   7d398:       ff083703                ld      a4,-16(a6)
   7d39c:       ff883783                ld      a5,-8(a6)
   7d3a0:       84b6                    mv      s1,a3
   7d3a2:       972a                    add     a4,a4,a0
   7d3a4:       6314                    ld      a3,0(a4)
   7d3a6:       4805                    li      a6,1
   7d3a8:       1812                    slli    a6,a6,0x24
   7d3aa:       e802                    sd      zero,16(sp)
   7d3ac:       ec42                    sd      a6,24(sp)
   7d3ae:       e0a2                    sd      s0,64(sp)
   7d3b0:       842a                    mv      s0,a0
   7d3b2:       ff86b503                ld      a0,-8(a3)
   7d3b6:       e486                    sd      ra,72(sp)
   7d3b8:       f84a                    sd      s2,48(sp)
   7d3ba:       f44e                    sd      s3,40(sp)
   7d3bc:       f052                    sd      s4,32(sp)
   7d3be:       e402                    sd      zero,8(sp)
   7d3c0:       04f51663                bne     a0,a5,7d40c <__dynamic_cast+0x7e>
   7d3c4:       611c                    ld      a5,0(a0)

I'm new to qemu and trying to run riscv binaries in user mode. Not sure if I'm running into a bug or just doing something wrong. System I'm using is pretty straightforward Fedora 35 on x86_64.

For reference, C++ hello world works fine for mipsel using prebuilt toolchain from musl.cc.

$ cat hello.cc
#include <iostream>
int main() {
 std::cout << "Hello\n";
 return 0;
}
$ mipsel-linux-musl-g++ -static -g -O0 hello.cc -o hello
$ qemu-mipsel hello
Hello

Likewise for C with riscv (32 or 64 doesn't seem to matter).

$ cat hello.c
#include<stdio.h>
int main(int argc, char **argv) {
 printf("Hello\n");
 return 0;
}
$ riscv32-linux-musl-gcc -static -g -Og hello.c -o hello
$ qemu-riscv32 hello
Hello

But for C++/riscv I get a segfault.

$ riscv32-linux-musl-g++ -static -g -Og hello.cc -o hello
$ qemu-riscv32 hello
Segmentation fault (core dumped)

Apparently coming from qemu itself

Thread 1 "qemu-riscv32" received signal SIGSEGV, Segmentation fault.
0x00007fffe802558e in code_gen_buffer ()
(gdb) bt
#0  0x00007fffe802558e in code_gen_buffer ()
#1  0x00005555556bb44e in cpu_tb_exec (cpu=0x555555887b50, itb=<optimized out>, tb_exit=0x7fffffffd9a0) at ../accel/tcg/cpu-exec.c:353
#2  0x00005555556bc2f9 in cpu_loop_exec_tb (tb_exit=0x7fffffffd9a0, last_tb=<synthetic pointer>, tb=0x7fffe8025500 <code_gen_buffer+152787>, cpu=0x555555887b50)
    at ../accel/tcg/cpu-exec.c:812
#3  cpu_exec (cpu=cpu@entry=0x555555887b50) at ../accel/tcg/cpu-exec.c:970
#4  0x00005555555eed28 in cpu_loop (env=0x55555588fe40) at ../linux-user/riscv/cpu_loop.c:37
#5  0x00005555555e2b81 in main (argc=<optimized out>, argv=0x7fffffffe1c8, envp=<optimized out>) at ../linux-user/main.c:885

Something similar happens in system emulation mode for riscv64 as well.

I'm happy to report this as a qemu bug, but it seems more likely that I'm just doing something wrong. Am I doing something wrong?

Update:

I attached to the gdb stub and the segfault happens on a dynamic cast in the binary:

(gdb) bt
#0  __cxxabiv1::__dynamic_cast (src_ptr=0x40000e19e0 <(anonymous namespace)::ctype_c>, src_type=0x40000d8808 <typeinfo for std::locale::facet>, dst_type=0x40000d9ac0 <typeinfo for std::ctype<char>>, src2dst=0)
    at ../../../../src_gcc/libstdc++-v3/libsupc++/dyncast.cc:74
#1  0x000000400005ed58 in std::has_facet<std::ctype<char> > (__loc=...) at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/locale_classes.tcc:110
#2  0x0000004000054be0 in std::basic_ios<char, std::char_traits<char> >::_M_cache_locale (this=this@entry=0x40000e0af8 <std::cout+8>, __loc=...)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/basic_ios.tcc:159
#3  0x0000004000054eaa in std::basic_ios<char, std::char_traits<char> >::init (this=this@entry=0x40000e0af8 <std::cout+8>, __sb=__sb@entry=0x40000e00d8 <__gnu_internal::buf_cout_sync>)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/bits/basic_ios.tcc:132
#4  0x0000004000027ad2 in std::basic_ostream<char, std::char_traits<char> >::basic_ostream (__sb=<optimized out>, this=<optimized out>, __in_chrg=<optimized out>, __vtt_parm=<optimized out>)
    at /tmp/m1132/build/local/riscv64-linux-musl/obj_gcc/riscv64-linux-musl/libstdc++-v3/include/ostream:85
#5  std::ios_base::Init::Init (this=<optimized out>) at ../../../../../src_gcc/libstdc++-v3/src/c++98/ios_init.cc:91
#6  std::ios_base::Init::Init (this=<optimized out>) at ../../../../../src_gcc/libstdc++-v3/src/c++98/ios_init.cc:78
#7  0x00000040000278c0 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/jpkenny/src/riscv64-linux-musl-cross/riscv64-linux-musl/include/c++/11.2.1/iostream:74
#8  0x00000040000278fa in _GLOBAL__sub_I_main () at hello.cc:5
#9  0x000000400008fbfa in libc_start_init ()
Backtrace stopped: frame did not save the PC

According to gdb, this occurs on the last asm instruction here:

000000000007d38e <__dynamic_cast>:
   7d38e:       c55d                    beqz    a0,7d43c <__dynamic_cast+0xae>
   7d390:       00053803                ld      a6,0(a0)
   7d394:       715d                    addi    sp,sp,-80
   7d396:       fc26                    sd      s1,56(sp)
   7d398:       ff083703                ld      a4,-16(a6)
   7d39c:       ff883783                ld      a5,-8(a6)
   7d3a0:       84b6                    mv      s1,a3
   7d3a2:       972a                    add     a4,a4,a0
   7d3a4:       6314                    ld      a3,0(a4)
   7d3a6:       4805                    li      a6,1
   7d3a8:       1812                    slli    a6,a6,0x24
   7d3aa:       e802                    sd      zero,16(sp)
   7d3ac:       ec42                    sd      a6,24(sp)
   7d3ae:       e0a2                    sd      s0,64(sp)
   7d3b0:       842a                    mv      s0,a0
   7d3b2:       ff86b503                ld      a0,-8(a3)
   7d3b6:       e486                    sd      ra,72(sp)
   7d3b8:       f84a                    sd      s2,48(sp)
   7d3ba:       f44e                    sd      s3,40(sp)
   7d3bc:       f052                    sd      s4,32(sp)
   7d3be:       e402                    sd      zero,8(sp)
   7d3c0:       04f51663                bne     a0,a5,7d40c <__dynamic_cast+0x7e>
   7d3c4:       611c                    ld      a5,0(a0)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文