FreedomSDK编译过程分析

Hello工程分析

hello工程

hello工程是freedom-e-sdk中最简单的一个实例程序, 代码只有如下几行.

1
2
3
4
#include <stdio.h>
int main() {
printf("Hello, World!\n");
}

该工程编译后在freedom上执行的效果为通过串口向主机发送一串字符Hello, world!。不过大家都明白,背后的“真相”并不想看上去那么简单。如上所见的代码只能算是应用层面的代码,其底层调用了C库,启动代码等屏蔽了RISCV硬件细节的BSP层。通过符合RISCV标准的交叉编译工具转化为可以在RISCV体系结构上执行的二进制代码后才能有如此神奇的效果。下面就通过分析代码的编译过程来学习一下,其底层所依赖的文件和交叉编译工具。

工程编译与下载

hello工程的基本操作

1
2
3
4
5
6
# 清除之前的编译所产生的文件
make PROGRAM=hello TARGET=freedom-e310-arty clean
# 进行编译
make PROGRAM=hello TARGET=freedom-e310-arty software
# 上传工程到开发板
make PROGRAM=hello TARGET=freedom-e310-arty upload

使用 make software 命令对hello工程进行编译,并保存其log文件来进行分析。

编译过程分析

依赖库编译metal

1
2
3
4
5
6
7
8
9
10
11
12
cd /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/build/debug/ && \
CFLAGS="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections -I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include -O0 -g" \
/home/hatton/repos/freedom-e-sdk/freedom-metal/configure \
--host=riscv64-unknown-elf \
--prefix=/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install \
--libdir=/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug \
--disable-maintainer-mode \
--with-preconfigured \
--with-machine-name=freedom-e310-arty \
--with-machine-header=/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.h \
--with-machine-ldscript=/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.default.lds \
--with-builtin-libgloss

编译过程中产生的log比较长,拆成几部分进行分析。首先是根据make的参数执行configure文件进行一些配置,这些配置都会反映在后面的编译过程中。

从第一部分的参数可以看出,使用到了头文件 freedom-e310-arty/metal.h 以及lds文件 metal.default.lds

lds文件的作用稍后进行分析。

再往下是一些gcc的命令,现在来选择一句分析一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
riscv64-unknown-elf-gcc 
-DPACKAGE_NAME=\"freedom-metal\"
-DPACKAGE_TARNAME=\"freedom-metal\"
-DPACKAGE_VERSION=\"v0.1.2\"
-DPACKAGE_STRING=\"freedom-metal\ v0.1.2\"
-DPACKAGE_BUGREPORT=\"palmer@sifive.com\"
-DPACKAGE_URL=\"\"
-DPACKAGE=\"freedom-metal\"
-DVERSION=\"v0.1.2\"
-I.
-I/home/hatton/repos/freedom-e-sdk/freedom-metal
-lriscv_metal_
-D__METAL_MACHINE_HEADER=\"/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.h\"
-march=rv32imac
-mabi=ilp32
-mcmodel=medlow
-ffunction-sections
-fdata-sections
-I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include
-O0
-g
-MT src/drivers/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.o
-MD
-MP
-MF src/drivers/.deps/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.Tpo
-c
-o src/drivers/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.o `test -f 'src/drivers/fixed-clock.c' || echo '/home/hatton/repos/freedom-e-sdk/freedom-metal/'`src/drivers/fixed-clock.c

mv -f src/drivers/.deps/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.Tpo src/drivers/.deps/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.Po

再往下一部分就是gcc的编译过程。

-D选项可以定义一些全局的宏到源文件中。

-I <dir> 表示将 <dir> 设定为第一个查找头文件的目录,也可以说是除了默认的头文件搜索路径(如/usr/include等)外,还在在路径<dir>进行所需的头文件搜索并且搜索循序要先于默认的头文件搜索路径。

-l 用来制定程序要链接的库,-l紧接着是库名(不是库文件名),比如-ltest,表示要链接的库的名字为libtest.so -L 用来指定库文件所在的目录

-march 表示不同的架构平台。

-mabi 用来选择数据模型和浮点参数传递规则 ilp32 表示 intlong 和指针字长都是32bits且不需要浮点扩展指令,float参数和double参数都使用整数寄存器进行传递。具体可见参考文献。

-mcmodel=medlow 用于指示程序的寻址范围固定只能在-2GB到+2GB的空间内。-2GB指的是整个地址空间最高2GB地址区间。对于32位而言,整个地址空间大小也就4GB,因此该选项的任何值对于编译的结果都没有影响。

-ffunction-sections -fdata-sections 将每个函数或符号创建一个section,其中每个section名与function或data名保持一致。因为GCC链接操作是以section作为最小的处理单元,只要一个section中的某个符号被引用,该section就会被加入到可执行程序中去。使用这两个参数就可以在链接阶段使用参数-Wl,–gc-sections 指示链接器去掉不用的section,从而减少最终可执行程序的大小。

-O0 不进行优化

-g 增加文本信息,创建符号表,关闭所有优化机制,以便gdb调试

-MT 生成目标文件

-MD 生成文件关联信息到文件中

-MP 生成伪目标规则(没有任何依赖项的规则)

-MF (target) 制定依赖关系要输出的目标文件

-c 只编译不链接,仅生成目标文件,中间文件,即.o文件

-o 指定输出文件

最后就是输入的源文件,其中test -f判断文件是否存在。

test -f 'src/drivers/fixed-clock.c' || echo '/home/hatton/repos/freedom-e-sdk/freedom-metal/'src/drivers/fixed-clock.c 先尝试相对路径寻找文件,如果相对路径没有找到就尝试使用绝对路径

mv -f 指令将保存着依赖关系信息的文件更名。

相同处理的文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
src/drivers/fixed-clock.c
src/drivers/riscv,clint0.c
src/drivers/riscv,cpu.c
src/drivers/riscv,plic0.c
src/drivers/sifive,clic0.c
src/drivers/sifive,fe310-g000,hfrosc.c
src/drivers/sifive,fe310-g000,hfxosc.c
src/drivers/sifive,fe310-g000,pll.c
src/drivers/sifive,fe310-g000,prci.c
src/drivers/sifive,global-external-interrupts0.c
src/drivers/sifive,gpio-buttons.c
src/drivers/sifive,gpio-leds.c
src/drivers/sifive,gpio-switches.c
src/drivers/sifive,gpio0.c
src/drivers/sifive,local-external-interrupts0.c
src/drivers/sifive,spi0.c
src/drivers/sifive,test0.c
src/drivers/sifive,uart0.c
src/button.c
src/clock.c
src/cpu.c
src/entry.S
src/gpio.c
src/interrupt.c
src/led.c
src/pmp.c
src/shutdown.c
src/spi.c
src/switch.c
src/timer.c
src/tty.c
src/uart.c

需要注意的是,在编译hello工程时,以上文件相比 freedom-metal/src 下所有的源码文件相比缺少了 src/cache.c 和 src/drivers/sifive,fu540-c000,l2.c,这两个文件应该是freedom用不到的两个源文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rm -f libriscv__mmachine__freedom-e310-arty.a

riscv64-unknown-elf-ar cru libriscv__mmachine__freedom-e310-arty.a src/drivers/libriscv__mmachine__freedom-e310-arty_a-fixed-clock.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-riscv,clint0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-riscv,cpu.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-riscv,plic0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,clic0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,fe310-g000,hfrosc.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,fe310-g000,hfxosc.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,fe310-g000,pll.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,fe310-g000,prci.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,global-external-interrupts0.o
src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,gpio-buttons.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,gpio-leds.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,gpio-switches.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,gpio0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,local-external-interrupts0.o
src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,spi0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,test0.o src/drivers/libriscv__mmachine__freedom-e310-arty_a-sifive,uart0.o src/libriscv__mmachine__freedom-e310-arty_a-button.o
src/libriscv__mmachine__freedom-e310-arty_a-clock.o
src/libriscv__mmachine__freedom-e310-arty_a-cpu.o
src/libriscv__mmachine__freedom-e310-arty_a-entry.o
src/libriscv__mmachine__freedom-e310-arty_a-gpio.o
src/libriscv__mmachine__freedom-e310-arty_a-interrupt.o src/libriscv__mmachine__freedom-e310-arty_a-led.o
src/libriscv__mmachine__freedom-e310-arty_a-pmp.o
src/libriscv__mmachine__freedom-e310-arty_a-shutdown.o src/libriscv__mmachine__freedom-e310-arty_a-spi.o
src/libriscv__mmachine__freedom-e310-arty_a-switch.o
src/libriscv__mmachine__freedom-e310-arty_a-timer.o
src/libriscv__mmachine__freedom-e310-arty_a-tty.o
src/libriscv__mmachine__freedom-e310-arty_a-uart.o

riscv64-unknown-elf-ranlib libriscv__mmachine__freedom-e310-arty.a

在此段中,首先删除了原有的库文件 libriscv__mmachine__freedom-e310-arty.a,然后利用上述生成的所有 .o 文件重新生成了lib库。cru分别为生成 .a 文件的三个操作参数,具体可以 man ar 来查看。

ranlib 相当于执行 ar -s,为 .a 文件创建符号表。在早期的unix系统中,ar只负责将所有的 .o 文件打包成 .a 并不负责为 .a 文件创建符号表。但在链接时,符号表是需要的。因此,ar时候往往需要ranlib来创建符号表。

依赖库编译metal-gloss

1
2
3
depbase=`echo gloss/crt0.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
riscv64-unknown-elf-gcc -DPACKAGE_NAME=\"freedom-metal\" -DPACKAGE_TARNAME=\"freedom-metal\" -DPACKAGE_VERSION=\"v0.1.2\" -DPACKAGE_STRING=\"freedom-metal\ v0.1.2\" -DPACKAGE_BUGREPORT=\"palmer@sifive.com\" -DPACKAGE_URL=\"\" -DPACKAGE=\"freedom-metal\" -DVERSION=\"v0.1.2\" -I. -I/home/hatton/repos/freedom-e-sdk/freedom-metal -march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections -I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include -O0 -g -MT gloss/crt0.o -MD -MP -MF $depbase.Tpo -c -o gloss/crt0.o /home/hatton/repos/freedom-e-sdk/freedom-metal/gloss/crt0.S &&\
mv -f $depbase.Tpo $depbase.Po

首先,echo 和 sed的组合是将 echo 后面的字符串按照 sed 的规则进行替换。不过这个直接分析也是有点复杂。在terminal中执行两句可知,此语句将 gloss/xxx.o 替换为 gloss/.deps/xxx。替换后的字符串赋值给depbase。

1
2
3
4
$ echo gloss/crt0.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'
gloss/.deps/crt0
$ echo gloss/nanosleep.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'
gloss/.deps/nanosleep

随后进行的gcc编译其过程与上文中的分析相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
freedom-metal/gloss/crt0.S
freedom-metal/gloss/nanosleep.c
freedom-metal/gloss/sys_access.c
freedom-metal/gloss/sys_chdir.c
freedom-metal/gloss/sys_chmod.c
freedom-metal/gloss/sys_chown.c
freedom-metal/gloss/sys_close.c
freedom-metal/gloss/sys_execve.c
freedom-metal/gloss/sys_exit.c
freedom-metal/gloss/sys_faccessat.c
freedom-metal/gloss/sys_fork.c
freedom-metal/gloss/sys_fstat.c
freedom-metal/gloss/sys_fstatat.c
freedom-metal/gloss/sys_ftime.c
freedom-metal/gloss/sys_getcwd.c
freedom-metal/gloss/sys_getpid.c
freedom-metal/gloss/sys_gettimeofday.c
freedom-metal/gloss/sys_isatty.c
freedom-metal/gloss/sys_kill.c
freedom-metal/gloss/sys_link.c
freedom-metal/gloss/sys_lseek.c
freedom-metal/gloss/sys_lstat.c
freedom-metal/gloss/sys_open.c
freedom-metal/gloss/sys_openat.c
freedom-metal/gloss/sys_read.c
freedom-metal/gloss/sys_sbrk.c
freedom-metal/gloss/sys_stat.c
freedom-metal/gloss/sys_sysconf.c
freedom-metal/gloss/sys_times.c
freedom-metal/gloss/sys_unlink.c
freedom-metal/gloss/sys_utime.c
freedom-metal/gloss/sys_wait.c
freedom-metal/gloss/sys_write.c

相同处理的文件如下,为freedom-e-sdk/freedom-metal/gloss文件夹下的所有文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
rm -f libriscv__menv__metal.a
riscv64-unknown-elf-ar cru libriscv__menv__metal.a
gloss/crt0.o
gloss/nanosleep.o
gloss/sys_access.o
gloss/sys_chdir.o
gloss/sys_chmod.o
gloss/sys_chown.o
gloss/sys_close.o
gloss/sys_execve.o
gloss/sys_exit.o
gloss/sys_faccessat.o
gloss/sys_fork.o
gloss/sys_fstat.o
gloss/sys_fstatat.o
gloss/sys_ftime.o
gloss/sys_getcwd.o
gloss/sys_getpid.o
gloss/sys_gettimeofday.o
gloss/sys_isatty.o
gloss/sys_kill.o
gloss/sys_link.o
gloss/sys_lseek.o
gloss/sys_lstat.o
gloss/sys_open.o
gloss/sys_openat.o
gloss/sys_read.o
gloss/sys_sbrk.o
gloss/sys_stat.o
gloss/sys_sysconf.o
gloss/sys_times.o
gloss/sys_unlink.o
gloss/sys_utime.o
gloss/sys_wait.o
gloss/sys_write.o

riscv64-unknown-elf-ranlib libriscv__menv__metal.a

随后又以与上文相同的方式来生成文件libriscv__menv__metal.a

编译应用程序前的准备

1
2
3
4
cp /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.h riscv__mmachine__freedom-e310-arty.lds
touch riscv__mmachine__freedom-e310-arty.specs
cat /home/hatton/repos/freedom-e-sdk/freedom-metal/riscv__menv__metal.specs.in > riscv__menv__metal.specs
cp /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.h metal/machine/freedom-e310-arty.h

当前 make 在文件夹 ‘/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/build/debug’ 下。复制 metal.h 为 riscv__mmachine__freedom-e310-arty.lds (这个强行更名,后面没有用,文件后缀和功能也对应不上),创建 riscv__mmachin__freedom-e310-arty.specs ,将 riscv__menv__metal.specs.in 中的内容(一个空文件,里面啥也没有)输入到 riscv__menv__metal.specs 中。复制metal.hfreedom-e310-arty.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
make[2]: Entering directory '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/build/debug'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
/usr/bin/install -c -m 644 libriscv__mmachine__freedom-e310-arty.a libriscv__menv__metal.a '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
( cd '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug' && riscv64-unknown-elf-ranlib libriscv__mmachine__freedom-e310-arty.a )
( cd '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug' && riscv64-unknown-elf-ranlib libriscv__menv__metal.a )
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
/usr/bin/install -c -m 644 riscv__mmachine__freedom-e310-arty.lds '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal'
/usr/bin/install -c -m 644 /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/button.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/clock.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/compiler.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/cpu.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/gpio.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/interrupt.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/io.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/itim.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/led.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/machine.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/pmp.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/shutdown.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/spi.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/switch.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/timer.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/tty.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/uart.h '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal/drivers'
/usr/bin/install -c -m 644 /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/fixed-clock.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/riscv,clint0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/riscv,cpu.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/riscv,plic0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,clic0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,fe310-g000,hfrosc.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,fe310-g000,hfxosc.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,fe310-g000,pll.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,fe310-g000,prci.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,global-external-interrupts0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,gpio-buttons.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,gpio-leds.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,gpio-switches.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,gpio0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,local-external-interrupts0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,spi0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,test0.h /home/hatton/repos/freedom-e-sdk/freedom-metal/metal/drivers/sifive,uart0.h '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal/drivers'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal/machine'
/usr/bin/install -c -m 644 metal/machine/freedom-e310-arty.h '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include/metal/machine'
/bin/mkdir -p '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
/usr/bin/install -c -m 644 riscv__mmachine__freedom-e310-arty.specs riscv__menv__metal.specs '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug'
make[2]: Leaving directory '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/build/debug'
make[1]: Leaving directory '/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/build/debug'
date > /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/stamp
cp /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/libriscv__mmachine__freedom-e310-arty.a /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/libmetal.a
cp /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/libriscv__menv__metal.a /home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/libmetal-gloss.a
mkdir -p /home/hatton/repos/freedom-e-sdk/software/hello/debug/

install命令与cp命令相似,都可以将文件或目录拷贝到制定的路径。但是install命令可以控制目标文件的属性。参数部分-c (ignored),-m (set permission mode)644表示,(第一个6)当前文件的拥有者的权限,可读可写不可执行,(第一个4)当前文件的所属组(同组用户)权限,可读权限,(第二个4)当前文件的组外权限,可读权限。

以上log所表示的操作为:

在freedom-e310-arty 下创建文件夹 build/debug

复制 libriscv__mmachine__freedom-e310-arty.a libriscv__menv__metal.a 到 install/lib/debug 下,并创建符号表(符号表在之前已经创建过了,不知道这里再创建有什么用?)

复制 riscv__mmachine__freedom-e310-arty.lds 到 install/lib/debug 文件夹下

创建文件夹 install/includeinstall/include/metal

复制 freedom-e-sdk/freedom-metal/metal 下的头文件到 install/include/metal 文件夹下。

创建文件夹 install/include/drivers

复制 freedom-metal/metal/drivers 下的头文件到 install/include/metal/drivers 文件夹下。

创建文件夹 install/include/mechine

复制 metal/machine/freedom-e310-arty.hinstall/include/mechine 文件夹下。

创建文件夹 install/lib/debug

复制 riscv__mmachine__freedom-e310-arty.specsriscv__menv__metal.specsinstall/lib/debug 文件夹下。

输出当前日期信息到 install/lib/debug/stamp 文件中

分别复制 install/lib/debug 文件夹下的 libriscv__mmachine__freedom-e310-arty.alibriscv__menv__metal.a 并重新命名为 libmetal.alibmetal-gloss.a

创建文件夹 freedom-e-sdk/software/hello/debug

编译Hello

1
2
3
4
5
6
7
8
9
make -C /home/hatton/repos/freedom-e-sdk/software/hello hello \
AR=/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ar \
CC=/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc \
CXX=/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-g++ \
ASFLAGS="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include -O0 -g" \
CFLAGS="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections -I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include -O0 -g" \
CXXFLAGS="-march=rv32imac -mabi=ilp32 -mcmodel=medlow -ffunction-sections -fdata-sections -I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include -O0 -g" \
LDFLAGS="-Wl,--gc-sections -Wl,-Map,hello.map -nostartfiles -nostdlib -L/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/ -T/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.default.lds" \
LDLIBS="-Wl,--start-group -lc -lgcc -lmetal -lmetal-gloss -Wl,--end-group"

-Wl,–gc-sections 表示在链接是去掉没有用到的section,以减少输出文件的大小

-Wl,-Map,hello.map 表示要成成map文件hello.map

-nostartfiles 链接时不使用标准系统的启动文件

-nostdlib 链接时不适用标准相同启动文件和标准库文件,只把制定的文件传递给链接器。

-T Use script as the linker script 指定链接脚本

-Wl,–start-group

-Wl,–end-group 和 –start-group 一起解决循环依赖问题

-Wl, 后面的内容是由gcc传递给ld的。

以上同样只是一些配置信息真正的命令执行在其后。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
make[1]: Entering directory '/home/hatton/repos/freedom-e-sdk/software/hello'
/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc
-march=rv32imac
-mabi=ilp32
-mcmodel=medlow
-ffunction-sections
-fdata-sections
-I/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/include
-O0
-g
-Wl,--gc-sections
-Wl,-Map,hello.map
-nostartfiles
-nostdlib
-L/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/install/lib/debug/
-T/home/hatton/repos/freedom-e-sdk/bsp/freedom-e310-arty/metal.default.lds
hello.c
-Wl,--start-group
-lc
-lgcc
-lmetal
-lmetal-gloss
-Wl,--end-group
-o hello
make[1]: Leaving directory '/home/hatton/repos/freedom-e-sdk/software/hello'

编译 hello.c 输出hello,其中用到的库有c,gcc,metal和metal-gloss。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mv /home/hatton/repos/freedom-e-sdk/software/hello/hello.map /home/hatton/repos/freedom-e-sdk/software/hello/debug/
mv /home/hatton/repos/freedom-e-sdk/software/hello/hello /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf
touch -c /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf

/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-objdump
--source
--all-headers
--demangle
--line-numbers
--wide /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf > /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.lst

/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-size /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf
text data bss dec hex filename
15404 4112 12276 31792 7c30 /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf

/home/hatton/tools/riscv64-unknown-elf-gcc-8.2.0-2019.02.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-objcopy
-O ihex /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.elf /home/hatton/repos/freedom-e-sdk/software/hello/debug/hello.hex

touch -c xxx 表示改变文件xxx的 timestamps ,其中 -c 表示,如果该文件不存在,将不会创建与此同名的空文件。

objdump, objdump命令是Linux下的反汇编目标文件或者可执行文件的命令,它以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。

–source 同时显示源码和汇编

–all-headers 显示头文件

–line-numbers 在输出中给出行号和文件名

–wide 以多于 80 列的宽度对输出进行格式化

使用objdump 命令将hello可执行文件反汇编,结果输出到hello.lst文件中

riscv64-unknown-elf-size, size工具输出各段的大小。

objcopy 被用来复制一个目标文件的内容到另一个文件中,可以使用不同于源文件的格式来输出目的文件,即可以进行格式转换。

-O 用来制定转换的格式,-O ihex 表示生成HEX

elf文件生成为了hex文件

总结

  1. 使用freedom-e-sdk/freedom-metal/src及freedom-e-sdk/freedom-metal/src/drivers目录下的所有源文件(在本例中不包含其中的src/cache.c和src/drivers/sifive,fu540-c000,l2.c文件)创建了libmetal.a库。
  2. 使用freedom-e-sdk/freedom-metal/gloss目录下的所有源文件创建了libmetal-gloss.a库。
  3. 将前两个阶段生成的两个库libmetal.a和libmetal-gloss.a以及它们的头文件拷贝到 freedom-e-sdk/bsp/freedom-e310-arty/install 目录下。同时也将freedom-e310平台的头文件也拷贝到该目录下。
  4. 编译freedom-e-sdk/software/hello 下的 hello 工程,并指定链接上述两个库,添加相应的头文件目录。

参考

http://blog.chinaunix.net/uid-28458801-id-4512377.html

https://www.jianshu.com/p/6daa5a052e75

http://www.elecfans.com/d/694957.html

https://blog.csdn.net/qq1452008/article/details/50855810

RISC-V数据模型,-mabi=ilp32, ilp32f, ilp32d, lp64, lp64f, lp64d