简体   繁体   English

使用自定义 linker 脚本构建裸机应用程序时如何链接数学库

[英]how to link math library when building bare metal application with custom linker script

I am building a RISC-V cpu core, and i am trying to build some C code for it.我正在构建一个 RISC-V cpu 内核,并且我正在尝试为它构建一些 C 代码。 I have some basic code compiling and linking the way i want and working just fine, for example this:我有一些基本的代码编译和链接我想要的方式并且工作得很好,例如:

asm("li sp, 0x390");
asm("li s0, 0x390");
asm("li ra, 0");

int main(void){
        char *memptr = 0 ;
        int sum = 0;
        for(int i = 0; i < 8; i++)
                *(memptr + i) = i;
        for(int i = 0; i < 8; i++)
                       sum += *(memptr + i);
        *((int*)0xC) = sum;

        asm("lw x31, 0xc(x0)");


}

and compile/link with these commands:并使用以下命令编译/链接:

riscv64-unknown-elf-gcc -nostartfiles -nostdlib -mno-relax -march=rv32i -mabi=ilp32 -c main.c
riscv64-unknown-elf-ld -nostartfiles -nostdlib -march=rv32i -melf32lriscv -o main -T link.ld main.o

my linker script is the following:我的 linker 脚本如下:

OUTPUT_ARCH( "riscv" )
ENTRY(main)

MEMORY
{
        progmem (rx) : ORIGIN = 0x10000000, LENGTH = 8K
        ram (!rx) : ORIGIN = 0x20000000, LENGTH = 64K
}

SECTIONS
{
        .text : {
                main.o(.text)
        } > progmem


        .data : {
                main.o(.rodata)
                main.o(.data)
                main.o(.sdata)
                main.o(.bss)
        } > ram
}

With this setup, i get the results i want no problem.通过这个设置,我得到了我想要的结果,没有问题。 I get my text section (which i put in the program memory), and i get the data section with all of the subsections put in there and load it straight into ram (it works for what im doing right now).我得到了我的文本部分(我把它放在程序内存中),我得到了包含所有子部分的数据部分,并将它直接加载到内存中(它适用于我现在正在做的事情)。

The problems begin when i try to use floating point addition:当我尝试使用浮点加法时,问题就开始了:

asm("li sp, 0x390");
asm("li s0, 0x390");
asm("li ra, 0");

float a = 1.7;
float b = 0.7;

int main(void){
        int *memptr = (int*)0x8;
        float c = a - b;

}

trying to link after compilation results in this error:编译后尝试链接会导致此错误:

riscv64-unknown-elf-ld -nostartfiles -march=rv32i -melf32lriscv -o main -T link.ld main.o
riscv64-unknown-elf-ld: main.o: in function `main':
main.c:(.text+0x3c): undefined reference to `__subsf3'

I can see in the assembly file (using gcc -S option) that there is an instruction call __subsf3 , but there is no such label anywhere in the.text section.我可以在汇编文件(使用 gcc -S 选项)中看到有一条指令调用 __subsf3 ,但在.text 部分的任何地方都没有这样的 label 。 I believe i have to somehow link the math library for this to work, so i have tried adding #include "math.h" , and then adding various flags to the ld command like "-lc", "-lgcc", "-lm", but it results in these errors:我相信我必须以某种方式链接数学库才能使其工作,所以我尝试添加#include "math.h" ,然后向ld命令添加各种标志,如 "-lc"、"-lgcc"、"- lm",但会导致以下错误:

riscv64-unknown-elf-ld: cannot find -lc
riscv64-unknown-elf-ld: cannot find -lgcc
riscv64-unknown-elf-ld: cannot find -lm

By trial and error i have managed to come up with this通过反复试验,我设法想出了这个

riscv64-unknown-elf-gcc -nostartfiles -mno-relax -march=rv32i -mabi=ilp32 -Wl,-emain -lm main.c -o main

which almost does what i want, but does not use my link script.这几乎可以满足我的要求,但不使用我的链接脚本。 if i add -Wl,link.ld then it again doesnt work, giving out errors:如果我添加-Wl,link.ld然后它再次不起作用,给出错误:

/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o:(.sdata+0x0): multiple definition of `a'; /tmp/cc0LmWB4.o:(.sdata+0x0): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o:(.sdata+0x4): multiple definition of `b'; /tmp/cc0LmWB4.o:(.sdata+0x4): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o: in function `main':
main.c:(.text+0xc): multiple definition of `main'; /tmp/cc0LmWB4.o:main.c:(.text+0xc): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: error: no memory region specified for loadable section `.sdata'
collect2: error: ld returned 1 exit status

I would really appreciate if someone could explain me what im doing wrong, and how i should actually go about building the code using the floating point math above for bare metal RISC-V, and get ld to add the math functions in my.text section.如果有人能解释我做错了什么,我真的很感激,我应该如何使用上面的浮点数学为裸机 RISC-V 构建代码,并让 ld 在 my.text 部分添加数学函数.

The problem is that gcc is not a linker it is a compiler, but in the gnu world gcc knows where it is (from a directory and relative paths perspective). 问题是gcc不是一个链接器它是一个编译器,但在gnu世界中,gcc知道它在哪里(从目录和相对路径的角度来看)。 Ld is a linker but doesnt know where it is (typical use case (by design) it relies on gcc to pass the library path to it) so... Ld是一个链接器,但不知道它在哪里(典型的用例(按设计)它依赖于gcc将库路径传递给它)所以......

bootstrap.s bootstrap.s

.globl _start
_start:
    lui x2,0x20010
    jal notmain
    j .

notmain.c notmain.c

unsigned int abcd = 5;

float fun ( float a, float b)
{
    return(a+b);
}

int notmain ( void )
{
    return(0);
}

memmap MEMMAP

MEMORY
{
    rom : ORIGIN = 0x10000000, LENGTH = 8K
    ram : ORIGIN = 0x20000000, LENGTH = 64K
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
    .data : { *(.data*) } > ram
}

One way: 单程:

riscv32-none-elf-as --warn -march=rv32i -mabi=ilp32 bootstrap.s -o bootstrap.o
riscv32-none-elf-gcc -Wall -march=rv32i -mabi=ilp32 -O2 -nostdlib -nostartfiles -ffreestanding  -c notmain.c -o notmain.o
riscv32-none-elf-ld -T memmap bootstrap.o notmain.o -lgcc -L /opt/gnuriscv32/lib/gcc/riscv32-none-elf/9.1.0/rv32i/ilp32 -o notmain.elf
riscv32-none-elf-objcopy notmain.elf -O binary notmain.bin 
riscv32-none-elf-objdump -D notmain.elf > notmain.list

gives

10000000 <_start>:
10000000:   20010137            lui x2,0x20010
10000004:   020000ef            jal x1,10000024 <notmain>
10000008:   0000006f            j   10000008 <_start+0x8>

1000000c <fun>:
1000000c:   ff010113            addi    x2,x2,-16 # 2000fff0 <abcd+0xfff0>
10000010:   00112623            sw  x1,12(x2)
10000014:   018000ef            jal x1,1000002c <__addsf3>
10000018:   00c12083            lw  x1,12(x2)
1000001c:   01010113            addi    x2,x2,16
10000020:   00008067            ret

10000024 <notmain>:
10000024:   00000513            li  x10,0
10000028:   00008067            ret

1000002c <__addsf3>:
1000002c:   008006b7            lui x13,0x800
10000030:   ff010113            addi    x2,x2,-16
10000034:   01755713            srli    x14,x10,0x17

...


20000000 <abcd>:
20000000:   0005
    ...

equally distasteful: 同样令人反感:

riscv32-none-elf-as --warn -march=rv32i -mabi=ilp32 bootstrap.s -o bootstrap.o
riscv32-none-elf-gcc -Wall -march=rv32i -mabi=ilp32 -O2 -nostdlib -nostartfiles -ffreestanding  -c notmain.c -o notmain.o
riscv32-none-elf-gcc -Wall -march=rv32i -mabi=ilp32 -O2 -nostdlib -nostartfiles -ffreestanding  -Xlinker -T -Xlinker memmap bootstrap.o notmain.o -lgcc -o notmain.elf
riscv32-none-elf-objcopy notmain.elf -O binary notmain.bin 
riscv32-none-elf-objdump -D notmain.elf > notmain.list

gives

10000000 <_start>:
10000000:   20010137            lui x2,0x20010
10000004:   020000ef            jal x1,10000024 <notmain>
10000008:   0000006f            j   10000008 <_start+0x8>

1000000c <fun>:
1000000c:   ff010113            addi    x2,x2,-16 # 2000fff0 <abcd+0xfff0>
10000010:   00112623            sw  x1,12(x2)
10000014:   018000ef            jal x1,1000002c <__addsf3>
10000018:   00c12083            lw  x1,12(x2)
1000001c:   01010113            addi    x2,x2,16
10000020:   00008067            ret

10000024 <notmain>:
10000024:   00000513            li  x10,0
10000028:   00008067            ret

1000002c <__addsf3>:
1000002c:   008006b7            lui x13,0x800
10000030:   ff010113            addi    x2,x2,-16

...


20000000 <abcd>:
20000000:   0005

the gcc solution is less painful as you dont have to hardcode a library path. gcc解决方案不那么痛苦,因为你不必硬编码库路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM