2012年11月3日 星期六

使用 buildroot 建置可用於 SimpleScalar 的 ARM toolchain

0. 前言

剛好最近有人來信詢問,就順便整理先前的一些文件一下,雖然 SimpleScalar 相對於現階段 ARM 的發展而言還停留在 ARMv4 的指令集,但若是在學術用途方面的話,還算是個相當有用的工具。

但在研究初期最容易遇到的問題就是 toolchain 的問題,官方附贈的過舊,要自行建置則網路上資訊過於零散,建立出來也不見得能用...

而在這篇文章中會透過 buildroot 來建立一串基礎的 ARM toolchain ,來簡化整個建置的過程,若一般用途而言這樣的方式就夠了

另外此篇文章假設你已經有一個已經建立好的 SimpleScalar ARM 可以用了


1. 使用 buildroot 建置 ARM toolchain

buildroot 的官方網站是 http://buildroot.uclibc.org/download.html
以下操作以 2012.08 的版本為例子,其它版本操作上大同小異,但部份路徑可能會有不同,第一次建議使用相同版本操作較為保險

目前作過測試是到 gcc 4.6 都可以在 SimpleScalar ARM 上運作沒有問題

gcc 4.7 因為不支援 ARM oabi 的部份所以會有點問題 (需要對 SimpleScalar 作一些修改)

i. 抓取 buildroot

wget http://buildroot.uclibc.org/downloads/buildroot-2012.08.tar.bz2

ii. 解壓縮 buildroot

tar -jxf buildroot-2012.08.tar.bz2

iii. 組態 buildroot

打入 make menuconfig 進入選單,會有 console 版本的選單出現
make menuconfig
# 接著會進入選單
Target Architecture 按 enter 選 ARM (little endian)
Target Architecture Variant 保留 generic_arm ,simplescalar 只支援 arm v4
Target ABI 選 oabi <--這是大重點,eabi 會不能動
Toolchain 點進去可以選 gcc 跟 binutils 版本
  uClibc C library Version 選 uClibc 0.9.31.x ,太新會沒辦法用(需要用到 bx 指令, armv4 不支援)
  需要 g++ 的話在  Enable C++ support 那邊按空白打 *
  需要使用 hard floating point 則 Use software floating point by default 的 * 按空白拿掉
其它看無就不用動

選擇最下面 Save an Alternate Configuration File
你會看到有一串
/home/kito/xxxxxxx/buildroot-2012.08/.config 之類的路徑
不要改
直接按 enter
然後 exit (左右可以移動下面的按鈕)
接著 make
然後轉身去泡杯咖啡,需要一點時間下載跟建置

build 完後在 buildroot 資料夾底下的
./output/host/usr/
這個資料夾
裡面就有 arm toolchain 了

iii. 測試 buildroot

先弄一個 Hello World
echo "int main() {printf(\"hello world\");}" > hello.c
編譯 Hello World ,-static 一定要加, simplescalar 只支援 static link
./output/host/usr/bin/arm-linux-gcc hello.c -o hello -static
使用 SimpleScalar ARM 測試,前面的 path 記得自行替換成 simplescalar 的路徑
/<path-to-simplescalar>/sim-uop hello
看到下面那一沱就代表你成功了!

sim-uop: SimpleScalar/ARM Tool Set version 3.0 of November, 2000.
Copyright (c) 1994-2000 by Todd M. Austin.  All Rights Reserved.
This version of SimpleScalar is licensed for academic non-commercial use only.

sim: command line: /home/kito/simulators/simplesim-arm-v2/sim-uop hello

sim: simulation started @ Mon Oct 22 20:25:18 2012, options follow:

sim-safe: This simulator implements a functional simulator.  This
functional simulator is the simplest, most user-friendly simulator in the
simplescalar tool set.  Unlike sim-fast, this functional simulator checks
for all instruction errors, and the implementation is crafted for clarity
rather than speed.

# -config                     # load configuration from a file
# -dumpconfig                 # dump configuration to a file
# -h                    false # print help message
# -v                    false # verbose operation
# -i                    false # start in Dlite debugger
-seed                       1 # random number generator seed (0 for timer seed)
# -q                    false # initialize and terminate immediately
# -chkpt               <null> # restore EIO trace execution from <fname>
# -redir:sim           <null> # redirect simulator output to file
(non-interactive only)
# -redir:prog          <null> # redirect simulated program output to file
-nice                       0 # simulator scheduling priority
-max:inst                   0 # maximum number of inst's to execute
-trigger:inst               0 # trigger instruction

sim: ** starting functional simulation **
warning: unsupported ioctl call: ioctl(21505, ...)
warning: unsupported ioctl call: ioctl(21505, ...)
hello world
sim: ** simulation statistics **
sim_num_insn                   5276 # total number of instructions executed
sim_num_uops                   7095 # total number of UOPs executed
sim_avg_flowlen              1.3448 # uops per instruction
sim_num_refs                   1259 # total number of loads and stores executed
sim_elapsed_time                  1 # total simulation time in seconds
sim_inst_rate             5276.0000 # simulation speed (in insts/sec)
ld_text_base           0x00008094 # program text (code) segment base
ld_text_bound          0x0000c54c # program text (code) segment bound
ld_text_size                  17592 # program text (code) size in bytes
ld_data_base           0x0000c54c # program initialized data segment base
ld_data_bound          0x000177d0 # program initialized data segment bound
ld_data_size                  45700 # program init'ed `.data' and
uninit'ed `.bss' size in bytes
ld_stack_base          0xc0000000 # program stack segment base
(highest address in stack)
ld_stack_size                 16384 # program initial stack size
ld_prog_entry          0x000080b0 # program entry point (initial PC)
ld_environ_base        0xbfffc000 # program environment base address address
ld_target_big_endian              0 # target executable endian-ness,
non-zero if big endian
mem.page_count                   11 # total number of pages allocated
mem.page_mem                    44k # total size of memory pages allocated
mem.ptab_misses                  11 # total first level page table misses
mem.ptab_accesses             63794 # total page table accesses
mem.ptab_miss_rate           0.0002 # first level page table miss rate

2. 將 GCC, Bintuils 及 uClibc 拉出來重新建置

這個段落主要是給需要修改到編譯器的屠龍人士看的,如果你只是要 ARM Toolchain 或著是要修改 Simulator 的話這段可以直接略過。

i. 建立一個要放等一下所有東西的資料夾

mkdir ~/arm-linux-gcc

ii. 把整串 toolchain 拉出來

cp -a buildroot-2012.08/output/host/usr ~/arm-linux-gcc/

iii. 資料夾重新命名為 arm-linux-gcc

mv ~/arm-linux-gcc/usr ~/arm-linux-gcc/arm-linux-gcc

iv. gcc, binutils, uclibc 等 source code 拉出來

cp -a buildroot-2012.08/output/toolchain/gcc-4.5.4 ~/arm-linux-gcc/
cp -a buildroot-2012.08/output/toolchain/uClibc-0.9.31.1/ ~/arm-linux-gcc/
tar -jxf buildroot-2012.08/dl/binutils-2.21.tar.bz2 -C ~/arm-linux-gcc

v. 建立 bulid-* 資料夾準備

cd ~/arm-linux-gcc
mkdir build-gcc
mkdir build-binutils

vi. 重新 build bintuils

cd build-binutils

vii. 開啟bintuils 的 config log 看一下怎麼下

vim ~/buildroot-2012.08/output/build/host-binutils-2.21/config.log
大約在第七行會有類似的東西
  $ ./configure --prefix=/home/kito/buildroot-2012.08/output/host/usr
--sysconfdir=/home/kito/buildroot-2012.08/output/host/etc
--enable-shared --disable-static --disable-multilib --disable-werror
--target=arm-unknown-linux-uclibc --disable-shared --enable-static
--with-sysroot=/home/kito/buildroot-2012.08/output/host/usr/arm-unknown-linux-uclibc/sysroot

viii. 產生新的 configure 參數

接著把 configure 中所有路徑更新一下, 然後 --sysconfdir 可以拿掉
note : 這邊路徑用我家示範,--prefix 跟 --with-sysroot 都要改
../binutils-2.21/configure
--prefix=/home/kito/arm-linux-gcc/arm-linux-gcc --enable-shared
--disable-static --disable-multilib --disable-werror
--target=arm-unknown-linux-uclibc --disable-shared --enable-static
--with-sysroot=/home/kito/arm-linux-gcc/arm-linux-gcc
/arm-unknown-linux-uclibc/sysroot

ix. 建置並安裝 buildroot

make -j8
make install

x. 重新 build gcc

cd build-gcc

xi. 偷看 buildroot config 怎麼下

~/arm-linux-gcc/arm-linux-gcc/bin/arm-linux-gcc -v
應該會吐出下面訊息,看到 Configured with: 那一段,抄過來修改
Using built-in specs.
COLLECT_GCC=/home/kito/buildroots/buildroot-2012.08/output/host/usr/bin/arm-linux-gcc
COLLECT_LTO_WRAPPER=/home/kito/buildroots/buildroot-2012.08/output/host/usr/libexec/gcc/arm-unknown-linux-uclibc/4.5.4/lto-wrapper
Target: arm-unknown-linux-uclibc
Configured with:
/home/kito/buildroots/buildroot-2012.08/output/toolchain/gcc-4.5.4/configure
--prefix=/home/kito/buildroots/buildroot-2012.08/output/host/usr
--build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu
--target=arm-unknown-linux-uclibc --enable-languages=c
--with-sysroot=/home/kito/buildroots/buildroot-2012.08/output/host/usr/arm-unknown-linux-uclibc/sysroot
--with-build-time-tools=/home/kito/buildroots/buildroot-2012.08/output/host/usr/arm-unknown-linux-uclibc/bin
--disable-__cxa_atexit --enable-target-optspace --disable-libquadmath
--disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib
--disable-tls --enable-shared
--with-gmp=/home/kito/buildroots/buildroot-2012.08/output/host/usr
--with-mpfr=/home/kito/buildroots/buildroot-2012.08/output/host/usr
--with-mpc=/home/kito/buildroots/buildroot-2012.08/output/host/usr
--disable-nls --enable-threads --disable-decimal-float
--with-float=soft --with-abi=apcs-gnu --disable-largefile
--with-pkgversion='Buildroot 2012.08'
--with-bugurl=http://bugs.buildroot.net/
Thread model: posix
gcc version 4.5.4 (Buildroot 2012.08)

xii. 產生新的 gcc 的 configure 參數

接著把 configure 中所有路徑更新一下, 然後 --with-bugurl, --with-pkgversion 可以拿掉 build 跟 host 也可以拔掉,它會自己抓,這樣整串指令就不會太長
note1 : mpfr, gmp, mpc 如果你系統有裝的話可以使用系統的就好, 如果使用系統的話--with-gmp --with-mpfr --with-mpc 這三個可以拔掉
note2 : 這邊路徑用我家示範,--prefix --with-sysroot 跟 --with-build-time-tools= 都要改
note3 : 需要 g++ 的話,把--enable-languages=c 改成 --enable-languages=c,c++
../gcc-4.5.4/configure --prefix=/home/kito/arm-linux-gcc/arm-linux-gcc
--target=arm-unknown-linux-uclibc --enable-languages=c
--with-sysroot=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/sysroot
--with-build-time-tools=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/bin
--disable-__cxa_atexit --enable-target-optspace --disable-libquadmath
--disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib
--disable-tls --enable-shared --disable-nls --enable-threads
--disable-decimal-float --with-float=soft --with-abi=apcs-gnu
--disable-largefile

xiii. 建置 gcc !

make! 另外注意一下 gcc 4.4 不支援 make -jx 的功能
make -j8
make install

xiv. 檢查 gcc

~/arm-linux-gcc/arm-linux-gcc/bin/arm-linux-gcc -v
輸出會跟第一次很像但 Configured with: 後面已經換成新的參數,這樣就代表有覆蓋掉舊的了
Using built-in specs.
COLLECT_GCC=/home/kito/arm-linux-gcc/arm-linux-gcc/bin/arm-linux-gcc
COLLECT_LTO_WRAPPER=/home/kito/arm-linux-gcc/arm-linux-gcc/libexec/gcc/arm-unknown-linux-uclibc/4.5.4/lto-wrapper
Target: arm-unknown-linux-uclibc
Configured with: ../gcc-4.5.4/configure
--prefix=/home/kito/arm-linux-gcc/arm-linux-gcc
--target=arm-unknown-linux-uclibc --enable-languages=c
--with-sysroot=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/sysroot
--with-build-time-tools=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/bin
--disable-__cxa_atexit --enable-target-optspace --disable-libquadmath
--disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib
--disable-tls --enable-shared --disable-nls --enable-threads
--disable-decimal-float --with-float=soft --with-abi=apcs-gnu
--disable-largefile : (reconfigured) ../gcc-4.5.4/configure
--prefix=/home/kito/arm-linux-gcc/arm-linux-gcc
--target=arm-unknown-linux-uclibc --enable-languages=c,c++
--with-sysroot=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/sysroot
--with-build-time-tools=/home/kito/arm-linux-gcc/arm-linux-gcc/arm-unknown-linux-uclibc/bin
--disable-__cxa_atexit --enable-target-optspace --disable-libquadmath
--disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib
--disable-tls --enable-shared --disable-nls --enable-threads
--disable-decimal-float --with-float=soft --with-abi=apcs-gnu
--disable-largefile
Thread model: posix
gcc version 4.5.4 (GCC)

xv. 重新 build uClibc

cd ~/arm-linux-gcc/uClibc-0.9.31.1

xvi. 將 buildroot 中 linux header 複製過來

cp -a ~/buildroot-2012.08/output/toolchain/linux/ .

xvii. 更新 uClibc 組態

vim .config
# 修改以下地方
KERNEL_HEADERS="/home/kito/buildroot-2012.08/output/toolchain/linux/include"
改成
KERNEL_HEADERS="/home/kito/arm-linux-gcc/uClibc-0.9.31.1/linux/include"

RUNTIME_PREFIX="/"
改成
RUNTIME_PREFIX="/home/kito/arm-linux-gcc/arm-linux-gcc/"

DEVEL_PREFIX="/usr/"
改成
DEVEL_PREFIX="/home/kito/arm-linux-gcc/arm-linux-gcc/"

CROSS_COMPILER_PREFIX="/home/kito/buildroots/buildroot-2012.08/output/host/usr/bin/arm-unknown-linux-uclibc-"
改成
CROSS_COMPILER_PREFIX="/home/kito/arm-linux-gcc/arm-linux-gcc/bin/arm-unknown-linux-uclibc-"
# 然後存檔離開

xviii. 重新 build uClibc !

make -j8
make install

xix. 往後更動 gcc 步驟

大功告成,往後如果有更動到 gcc
uClibc 必須清掉重新 build 一次
make clean
make -j8
make install