分类: 嵌入式
2013-07-05 09:35:27
原文地址:ARM9 2410移植之GNU 交叉工具链 作者:cao_lianming
1 设置环境变量,准备源码及相关补丁
1.1 设置环境变量
[arm@localhost arm]#vi ~/.bashrc
export PREFIX=/usr/local/arm/3.4.4
export TARGET=arm-linux
export SYSROOT=${PREFIX}/sysroot
export ARCH=arm
export CROSS_COMPILE=${TARGET}-
export PATH=${PREFIX}/bin:$PATH
export SRC=/home/arm/dev_home/btools/tchain3.4.4
1. 2 准备源码包
1.2.1 binuils
名称:binutils-2.16.tar.gz
下载地址:
1.2.2 gcc
名称:gcc-3.4.4.tar.bz2
下载地址:
1.2.3 glibc
名称:glibc-2.3.5.tar.gz
glibc-linuxthreads-2.3.5.tar.gz
下载地址:
1.2.4 linux kernel
名称:linux-2.6.14.1.tar.gz
下载地址:
1.3 准备补丁
1.3.1 ioperm.c.diff
作用:打修正ioperm()函数.
下载地址:~coldwell/toolchain/ioperm.c.diff
1.3.2 flow.c.diff
作用:该补丁用于产生crti.o 和crtn.o 文件。
下载地址:
branch&r1=1.563.4.2&r2=1.563.4.3
1.3.3 t-linux.diff
作用:修改gcc 一处bug
下载地址:~coldwell/toolchain/t-linux.diff
1.4 编译 GNU binutils
重新以arm 用户登陆,让新设置的环境变量起作用.
[arm@localhost arm]#su arm
[arm@localhost arm]#cd ${SRC}
[arm@localhost tchain3.4.4]#tar xzvf binutils-2.16.tar.gz
[arm@localhost tchain3.4.4]#mkdir -p BUILD/binutils-2.16
[arm@localhost binutils-2.16]#cd BUILD/binutils-2.16
[arm@localhost binutils-2.16]# ../../binutils-2.16/configure --prefix=${PREFIX} --target=${TARGET} \
--with-sysroot=${SYSROOT}
[arm@localhost binutils-2.16]#make
[arm@localhost binutils-2.16]#su root
[root@localhost binutils-2.16]#make install
[root@localhost binutils-2.16]#exit
[arm@localhost binutils-2.16]#
1.5 准备内核头文件
1.5.1 使用当前平台的gcc编译内核头文件
[arm@localhost tchain3.4.4]#cd ${KERNEL}
[arm@localhost kernel]#tar xvfz linux-2.6.14.1.tar.gz
[arm@localhost kernel]#cd linux-2.6.14.1
[arm@localhost linux-2.6.14.1]#make ARCH=arm menuconfig
[arm@localhost linux-2.6.14.1]#make
1.5.2 复制内核头文件
[arm@localhost kernel]#su root
[root@localhost kernel]#mkdir -p ${SYSROOT}/usr/include
[root@localhost kernel]#cp -a include/linux ${SYSROOT}/usr/include/linux
[root@localhost kernel]#cp -a include/asm-i386 ${SYSROOT}/usr/include/asm
[root@localhost kernel]#cp -a include/asm-generic ${SYSROOT}/usr/include/asm-generic
[root@localhost kernel]#exit
[arm@localhost kernel]#
1.6 译编glibc 头文件
[arm@localhost kernel]#cd ${SRC}
[arm@localhost chain3.4.4]#tar xvfz glibc-2.3.5.tar.gz
[arm@localhost chain3.4.4]#patch -d glibc-2.3.5 -p1 < ioperm.c.diff
[arm@localhost glibc-2.3.5]#cd glibc-2.3.5
[arm@localhost glibc-2.3.5]#tar xvfz ../glibc-linuxthreads-2.3.5.tar.gz
[arm@localhost chain3.4.4]#cd ..
[arm@localhost chain3.4.4]#mkdir BUILD/glibc-2.3.5-headers
[arm@localhost chain3.4.4]#cd BUILD/glibc-2.3.5-headers
[arm@localhost glibc-2.3.5-headers]#../../glibc-2.3.5/configure --prefix=/usr --host=${TARGET} \
--enable-add-ons=linuxthreads –with-headers=${SYSROOT}/usr/include
[arm@localhost glibc-2.3.5-headers]#su root
[root@localhost glibc-2.3.5-headers]#make cross-compiling=yes install_root=${SYSROOT} install-headers
[root@localhost glibc-2.3.5-headers]#touch ${SYSROOT}/usr/include/gnu/stubs.h
[root@localhost glibc-2.3.5-headers]#touch ${SYSROOT}/usr/include/bits/stdio_lim.h
[root@localhost glibc-2.3.5-headers]#exit
[arm@localhost glibc-2.3.5-headers]#
注意: --prefix=/usr :是gcc 寻找库的搜索路径。
1.7 编译gcc 第一阶段
[arm@localhost glibc-2.3.5-headers]#cd ${SRC}
[arm@localhost chain3.4.4]#tar xjvf gcc-3.4.4.tar.bz2
[arm@localhost chain3.4.4]#patch -d gcc-3.4.4 -p1 < flow.c.diff
[arm@localhost chain3.4.4]#patch -d gcc-3.4.4 -p1 < t-linux.diff
[arm@localhost chain3.4.4]#mkdir -p BUILD/gcc-3.4.4-stage1
[arm@localhost chain3.4.4]#cd BUILD/gcc-3.4.4-stage1
[arm@localhost gcc-3.4.4-stage1]#../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} \
--enable-languages=c --with-sysroot=${SYSROOT}
注意:不能加上"--disable-shared"选项。
[arm@localhost gcc-3.4.4-stage1]#make all-gcc
[arm@localhost gcc-3.4.4-stage1]#su root
[root@localhost gcc-3.4.4-stage1]#make install-gcc
[root@localhost gcc-3.4.4-stage1]#exit
[arm@localhost gcc-3.4.4-stage1]#
1.8 编译完整的glibc
[arm@localhost gcc-3.4.4-stage1] #cd ${SRC}
[arm@localhost tchain3.4.4]#mkdir BUILD/glibc-2.3.5
[arm@localhost tchain3.4.4]#cd BUILD/glibc-2.3.5
[arm@localhost glibc-2.3.5]#BUILD_CC=gcc CC=${CROSS_COMPILE}gcc AR=${CROSS_COMPILE}ar \
RANLIB=${CROSS_COMPILE}ranlib AS=${CROSS_COMPILE}as LD=${CROSS_COMPILE}ld \
../../glibc-2.3.5/configure --prefix=/usr --build=i386-redhat-linux --host=arm-unknown-linux-gnu \
--target=arm-unknown-linux-gnu --without-__thread --enable-add-ons=linuxthreads \
--with-headers=${SYSROOT}/usr/include
说明:
--prefix: 指定安装路径。
--target: 指定目标平台。
--host: 指定当前平台。
--build: 指定编译平台。
--with-sysroot: 用于指定编译所需要的头文件,及链接库。
--enable-add-ons: 加入其它的库,如线程库等。
--enable-languages: 指定gcc 所支持的语言。
[arm@localhost glibc-2.3.5]#make
[arm@localhost glibc-2.3.5]#su root
[root@localhost glibc-2.3.5]#make install_root=${SYSROOT} install
[root@localhost glibc-2.3.5]#exit
[arm@localhost glibc-2.3.5]#
1.9 编译完整的gcc
[arm@localhost glibc-2.3.5]#cd ${SRC}
[arm@localhost tchain3.4.4]#mkdir BUILD/gcc-3.4.4
[arm@localhost tchain3.4.4]#cd BUILD/gcc-3.4.4
[arm@localhost gcc-3.4.4]#../../gcc-3.4.4/configure --prefix=${PREFIX} --target=${TARGET} \
--enable-languages=c --with-sysroot=${SYSROOT}
[arm@localhost gcc-3.4.4]#make
[arm@localhost gcc-3.4.4]#su root
[root@localhost gcc-3.4.4]#make install
[root@localhost gcc-3.4.4]#exit
[arm@localhost gcc-3.4.4]#
2 GNU交叉工具链的下载
2.1 ARM 官方网站
工具链的官方下载地址:
可以从该站点下载2.95.3, 3.0 以及3.2 工具链
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-2.95.3.tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-3.0.tar.bz2
ftp://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-3.2.tar.bz2
3 GNU 交叉工具链的介绍与使用
3.1 常用工具介绍
名称 归属 作用
arm-linux-as binutils 编译ARM 汇编程序
arm-linux-ar binutils 把多个.o 合并成一个.o 或静态库(.a)
arm-linux-ranlib binutils 为库文件建立索引,相当于arm-linux-ar -s
arm-linux-ld binutils 连接器(Linker), 把多个.o 或库文件连接成一个可执行文件
名称 归属 作用
arm-linux-objdump binutils 查看目标文件(.o)和库(.a)的信息
arm-linux-objcopy binutils 转换可执行文件的格式
arm-linux-strip binutils 去掉elf 可执行文件的信息. 使可执行文件变小
arm-linux-readelf binutils 读elf 可执行文件的信息
arm-linux-gcc gcc 编译.c 或.S 开头的C 程序或汇编程序
arm-linux-g++ gcc 编译c++程序
3.2 主要工具的使用
3.2.1 arm-linux-gcc 的使用
1. 编译C 文件,生成elf 可执行文件
h1.c 源文件
#include
void hellofirst(void)
{
printf("The first hello! \n");
}
h2.c 源文件
#include
void hellosecond(void)
{
printf("The second hello! \n");
}
hello.c 源文件
#include
void hellosecond(void);
void hellofirst(void);
int main(int argc, char *argv[])
{
hellofirst();
hellosecond();
return(0);
}
编译以上3 个文件,有如下几种方法:
方法 1:
[arm@localhost gcc]#arm-linux-gcc -c h1.c
[arm@localhost gcc]#arm-linux-gcc -c h2.c
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c h1.o h2.o
方法2:
[arm@localhost gcc]#arm-linux-gcc -c h1.c h2.c
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c h1.o h2.o
方法3:
[arm@localhost gcc]#arm-linux-gcc -c -o h1.o h1.c
[arm@localhost gcc]#arm-linux-gcc -c -o h1.o h1.c
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c h1.o h2.o
方法4:
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c h1.c h2.c
-c: 只编译不连接。
-o: 编译且连接。
2. 产生一个预处理文件
当要看一个宏在源文件中产生的结果时,比较合适。
[arm@localhost gcc]#arm-linux-gcc -E h1.i h1.c
-E: 产生一个预处理文件.
3. 产生一个动态库
动态库是在运行时需要的库。
[arm@localhost gcc]#arm-linux-gcc -c -fpic h1.c h2.c
[arm@localhost gcc]#arm-linux-gcc -shared h1.o h2.o -o hello.so
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c hello.so
把hello.so 拷贝到目标板的/lib 目录下,把可执行文件拷贝目标板的/tmp 目录下,在目标板上运 hello.
#/tmp/hello
或把hello.so 和hello 一起拷贝到/tmp 目标下,并设置LD_LIBRARY_PATH 环境变量
#export LD_LIBRARY_PATH =/tmp:$LD_LIBRARY_PATH
#/tmp/hello
3.2.2 arm-linux-ar 和 arm-linux-ranlib 的使用
静态库是在编译时需要的库。
1. 建立一个静态库
[arm@localhost gcc]#arm-linux-ar -r libhello.a h1.o h2.o
2. 为静态库建立索引
[arm@localhost gcc]#arm-linux-ar -s libhello.a
[arm@localhost gcc]#arm-linux-ranlib libhello.a
3. 由静态库产生可执行文件
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c -lhello -L./
[arm@localhost gcc]#arm-linux-gcc -o hello hello.c libhello.a
hello 文件可以直接拷贝到/tmp 目录下运行,不需libhello.a.
3.2.3 arm-linux-obj dump 的使用
1. 查看静态库或.o 文件的组成文件
[arm@localhost gcc]$ arm-linux-objdump -a libhello.a
2. 查看静态库或.o 文件的络组成部分的头部分
[arm@localhost gcc]$ arm-linux-objdump -h libhello.a
3. 把目标文件代码反汇编
[arm@localhost gcc]$ arm-linux-objdump -d libhello.a
3.2.4 arm-linux-readelf 的使用
1. 读elf 文件开始的文件头部
[arm@localhost gcc]$ arm-linux-readelf -h hello
ELF Header:
Magic: 7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: ARM
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x82b4
Start of program headers: 52 (bytes into file)
Start of section headers: 10240 (bytes into file)
Flags: 0x2, has entry point
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 25
2. 读elf 文件中所有ELF 的头部:
[arm@localhost gcc]#arm-linux-readelf -e hello
......
3. 显示整个文件的符号表
[arm@localhost gcc]#arm-linux-readelf -s hello
......
4. 显示使用的动态库
[arm@localhost gcc]#arm-linux-readelf -d hello
......
3.2.5 arm-linux-strip 的使用
1. 移除所有的符号信息
[arm@localhost gcc]#cp hello hello1
[arm@localhost gcc]#arm-linux-strip -strip-all hello
--strip-all: 是移除所有符号信息
[arm@localhost gcc]#ll
-rwxr-xr-x 1 arm root 2856 7 月 3 15:14 hello
-rwxr-xr-x 1 arm root 13682 7 月 3 15:13 hello1
被strip 后的hello 程序比原来的hello1 程序要小很多。
2. 移除调试符号信息
[arm@localhost gcc]#arm-linux-strip -g hello
[arm@localhost gcc]#ll
-rwxr-xr-x 1 arm root 4501 7 月 3 15:17 hello
-rwxr-xr-x 1 arm root 13682 7 月 3 15:13 hello1
3.2.6 arm-linux-copydump 的使用
生成可以执行的2 进制代码
[arm@localhost gcc]#arm-linux-copydump -O binary hello hello.bin
4 ARM GNU常用汇编语言介绍
4.1 ARM GNU 常用汇编伪指令介绍
1. abort
.abort: 停止汇编
.align abs-expr1, abs-expr2: 以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16 或32. 第
二个表达式值表示填充的值.
2. if...else...endif
.if
.else
.endif: 支持条件预编译
3. include
.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中.
4. comm
.comm symbol, length:在bss 段申请一段命名空间,该段空间的名称叫symbol, 长度为length. Ld 连接器在连接会
为它留出空间.
5. data
.data subsection: 说明接下来的定义归属于subsection 数据段.
6. equ
.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.
7. global
.global symbol: 定义一个全局符号, 通常是为ld 使用.
8. ascii
.ascii "string": 定义一个字符串并为之分配空间.
9. byte
.byte expressions: 定义一个字节, 并为之分配空间.
10. short
.short expressions: 定义一个短整型, 并为之分配空间.
11. int
.int expressions: 定义一个整型,并为之分配空间.
12 long
.long expressions: 定义一个长整型, 并为之分配空间.
13 word
.word expressions: 定义一个字,并为之分配空间, 4bytes.
14. macro/endm
.macro: 定义一段宏代码, .macro 表示代码的开始, .endm 表示代码的结束.
15. req
name .req register name: 为寄存器定义一个别名.
16. code
.code [16|32]: 指定指令代码产生的长度, 16 表示Thumb 指令, 32 表示ARM 指令.
17. ltorg
.ltorg: 表示当前 下的定义在归于当前段,并为之分配空间.
4.2 ARM GNU 专有符号
1. @
表示注释从当前位置到 尾的字符.
2. #
注释掉一整 .
3. ;
新行分隔符.
4.3 操作码
1. NOP
nop
空操作, 相当于MOV r0, r0
2. LDR
ldr
相当于PC 寄存器或其它寄存器的长转移.
3.ADR
adr
}