如何解决RISC-V程序中的分段错误

问题描述 投票:0回答:1
// factorial.c

#include <stdio.h>

// Function to calculate factorial
unsigned long long factorial(unsigned int n) {
    if (n == 0)
        return 1;
    else
        return n * factorial(n - 1);
}

int main() {
    // Calculate factorial of 10
    unsigned long long result = factorial(10);

    // Print the result
    printf("Factorial of 10 = %llu\n", result);

    return 0;
}

使用带有优化和分析标志的 RISC-V GCC 编译器编译程序。 使用 Spike RISC-V 模拟器执行该程序。 执行期间遇到分段错误。

vindhya@latitude-7390:~$ nano factorial.c
vindhya@latitude-7390:~$ /home/latitude-7390/rvv64/bin/riscv64-unknown-elf-gcc -O2 -pg factorial.c -o factorial
vindhya@latitude-7390:~$ /home/vindhya/riscv-vector/riscv-isa-sim/build/spike /home/latitude-7390/rvv64/bin/riscv64-unknown-elf/bin/pk ./factorial
z  0000000000000000 ra 00000000000101d4 sp 0000003fff7ffff0 gp 000000000001b018
tp 0000000000000000 t0 0000000000010818 t1 000000000000000f t2 0000000000000000
s0 0000000000000000 s1 0000000000000000 a0 00000000000101d4 a1 0000003ffffffb58
a2 0000000000000000 a3 0000000000000010 a4 000000000001a680 a5 0000000000000000
a6 000000000000001f a7 0000000000000000 s2 0000000000000000 s3 0000000000000000
s4 0000000000000000 s5 0000000000000000 s6 0000000000000000 s7 0000000000000000
s8 0000000000000000 s9 0000000000000000 sA 0000000000000000 sB 0000000000000000
t3 0000000000000000 t4 0000000000000000 t5 0000000000000000 t6 0000000000000000
pc 00000000000101cc va/inst 0000003fff7ffff8 sr 8000000200006020
User store segfault @ 0x0000003fff7ffff8
segmentation-fault profiling simulator riscv spike
1个回答
0
投票

您的设置/意图中可能存在许多问题:

  1. 尖峰模拟器运行静态构建的应用程序二进制文件,但您没有为 GCC 提供

    -static
    选项,如下所示:

    $ riscv64-unknown-elf-gcc -O2 -pg -static -o factorial factorial.c
    

    这可能是您的代码出现段错误的原因 - 当在尖峰上运行时,它会蜿蜒进入一些不受支持的动态链接加载路径。

    顺便说一句,尝试使用非静态编译的程序运行最新版本的 Spike 会产生:

    ~/Work/repos/spike/test
    ❯ spike pk factorial
    not a statically linked ELF program
    

    查看该消息的Spike git 历史记录会产生:

    ~/Work/repos/spike/repos/riscv-pk master
    ❯ git log -S 'not a statically linked ELF program'   
    commit 099c99482f7ac032bf04caad13a9ca1da7ce58ed
    Date:   Tue Oct 1 12:13:28 2019 +0100
    
    Only accept statically linked binaries (#176)
    

    这是大约 2019 年的提交,因此我假设您正在运行一个相当旧的模拟器版本。运行最新版本会更好。

  2. 奇怪的是你的工具链根本允许你的程序链接。

    问题是,用于裸机开发的 RISC-V 工具链(例如您似乎使用的 riscv64-unknown-elf 工具链)是为了选择性地链接“更简单”的 C 库(例如 newlib 或 picolibc)而构建的。

    现在 GCC 的“-pg”分析选项生成引用“_mcount”符号的代码。 RISC-V 的 newlib 或 picolibc 不提供此符号。然而,它是由 glibc 为 RISC-V 提供的,但那是针对 Linux 用户空间程序的 - 而不是裸机程序。

    例如,在我的设置中,尝试编译你的程序会给我:

    ❯ riscv64-unknown-elf-gcc -O2 -pg -static -o factorial factorial.c
    ~/Work/repos/spike/toolchain/riscv64-unknown-elf/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/bin/ld: /tmp/ccbz7QsX.o: in function `factorial':
    factorial.c:(.text+0xa): undefined reference to `_mcount'
    ~/Work/repos/spike/toolchain/riscv64-unknown-elf/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/bin/ld: /tmp/ccbz7QsX.o: in function    `main':
    factorial.c:(.text.startup+0x6): undefined reference to `_mcount'
    collect2: error: ld returned 1 exit status
    

    但是,如果我使用 glibc 链接工具链,链接会成功并且程序运行正确 - 这通常用于构建 Linux 用户空间程序:

    ~/Work/repos/spike/test
    ❯ riscv64-linux-gnu-gcc -O2 -pg -static -o factorial factorial.c
    
    ~/Work/repos/spike/test
    ❯ spike pk factorial
    Factorial of 10 = 3628800
    

    因此,我只能得出结论,您的工具链要么没有正确构建,要么已经过时,甚至可能有错误。

  3. 鉴于上述情况,堆栈指针值和相关的 va/inst 参考值显得奇数。要使该程序与“-pg”一起使用,您需要一个 Linux RISC-V 工具链和使用“-static”构建的 Factorial.c。

    如果你这样做,spike最终会使用一个虚拟地址位于

    0xffffffc000xxxxxx
    区域的堆栈。

  4. 最终,使用 GCC 的“-pg”进行分析并不适合在具有功能 ISA 模拟器(例如不模拟微架构现实的 spike)的裸机环境中使用。您可能打算在 Linux 下的某个周期精确的目标平台上构建和运行程序?

无论如何,我的建议是:

  1. 从最近的 RISC-V Linux 工具链上游构建开始,也许使用优秀的 crosstool-ng 框架
  2. 以及最近的上游构建 spikepk
  3. 注意静态构建你的程序

祝一切顺利。

© www.soinside.com 2019 - 2024. All rights reserved.