❶ 請問arm-linux-gcc和arm-linux-ld還有arm-linux-obj之間是什麼關系
arm-linux-ld 是連接器,它把一些目標和歸檔文件結合在一起,重定位數據,並連接符號引用。通常,建立一個新編譯程序的最後一步就是調用ld。
arm-linux-gcc -wall -O2 -c -o $@ $<
-o 只激活預處理,編譯,和匯編,也就是他只把程序做成obj文件
-Wall 指定產生全部的警告信息
-O2 編譯器對程序提供的編譯優化選項,在編譯的時候使用該選項,可以使生成的執行文件的執行效率提高
-c 表示只要求編譯器進行編譯,而不要進行鏈接,生成以源文件的文件名命名但把其後綴由 .c 或 .cc 變成 .o 的目標文件
-S 只激活預處理和編譯,就是指把文件編譯成為匯編代碼
arm-linux-ld 直接指定代碼段,數據段,BSS段的起始地址
-Tbss ADDRESS Set address of .bss section
-Tdata ADDRESS Set address of .data section
-Ttext ADDRESS Set address of .text section
示例:
${CROSS}ld -Ttext=0x33000000 led.o -o led.elf
使用連接腳本設置地址:
arm-linux-ld -Tbeep.lds start.o beep.o -o beep.elf
其中beep.lds 為連接腳本如下:
arm-linux-obj被用來復制一個目標文件的內容到另一個文件中,可用於不同源文件的之間的格式轉換
示例:
arm-linux-obj –o binary –S elf_file bin_file
常用的選項:
input-file , outflie
輸入和輸出文件,如果沒有outfile,則輸出文件名為輸入文件名
2.-l bfdname或—input-target=bfdname
用來指明源文件的格式,bfdname是BFD庫中描述的標准格式名,如果沒指明,則arm-linux-obj自己分析
3.-O bfdname 輸出的格式
4.-F bfdname 同時指明源文件,目的文件的格式
5.-R sectionname 從輸出文件中刪除掉所有名為sectionname的段
6.-S 不從源文件中復制重定位信息和符號信息到目標文件中
7.-g 不從源文件中復制調試符號到目標文件中
arm-linux-objmp
查看目標文件(.o文件)和庫文件(.a文件)信息
arm-linux-objmp -D -m arm beep.elf > beep.dis
-D 顯示文件中所有匯編信息
-m machine
指定反匯編目標文件時使用的架構,當待反匯編文件本身沒有描述架構信息的時候(比如S-records),這個選項很有用。可以用-i選項列出這里能夠指定的架構.
[guowenxue@localhost asm_c_buzzer]$ cat beep.lds
/***********************************************************************
* File: beep.lds
* Version: 1.0.0
* Copyright: 2011 (c) Guo Wenxue <[email protected]>
* Description: Cross tool link text, refer to u-boot.lds
* ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
*
**********************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
. = 0x33000000;
.text : {
*(.text)
*(.rodata)
}
.data ALIGN(4): {
*(.data)
}
.bss ALIGN(4): {
*(.bss)
}
}
[guowenxue@localhost asm_c_buzzer]$ cat makefile
# ***********************************************************************
# * File: makefile
# * Version: 1.0.0
# * Copyright: 2011 (c) Guo Wenxue <[email protected]>
# * Description: Makefile used to cross compile the ASM and C source code
# * ChangeLog: 1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
CROSS = /opt/buildroot-2011.02/arm920t/usr/bin/arm-linux-
CFLAGS =
beep.bin: start.S beep.c
arm-linux-gcc $(CFLAGS) -c -o start.o start.S
arm-linux-gcc $(CFLAGS) -c -o beep.o beep.c
arm-linux-ld -Tbeep.lds start.o beep.o -o beep.elf
arm-linux-obj -O binary -S beep.elf beep.bin
rm -f *.elf *.o
install:
cp beep.bin ~/winxp -f --reply=yes
clean:
rm -f *.elf *.o
rm -f beep.bin
❷ 用make指令後不能成功,出現以下提示,應該怎麼解決 make: arm-linux-ld: Command not found
環境變數問題,你arm-linux-ld沒有找到
❸ arm-linux/bin/ld.real:找不到 -lts
在交叉編譯器的inlcude目錄下有asm/page.h文件,將其中的PAGE_SIZE PAGE_MASK相關
❹ /arm-linux/bin/ld: cannot find -lfreetype
你是在進行arm linux的移植嗎?錯誤很明顯 顯示找不到freetype庫
我移植過一些東西 也報找不到freetype庫
你直接下載一個freetype源代碼 然後交叉編譯過 將生成的arm庫放到你的LD_LIBRARY_PATH路徑下就可以了,或者你已經編譯好了freetype庫 但是你的路徑不對,你可以直接將其放置到你的LD_LIBRARY_PATH路徑目錄下,或者將freetype庫路徑添加到LD_LIBRARY_PATH都可以
不懂再問
❺ 使用arm-linux-ld時出錯,求解
你的 -Ttext=30000000 是十進制的,應該在前面加上0x 變成十六進制 -Ttext=0x30000000 ,試試吧
❻ 編程貓讓程序跳轉到起始位置
在開始的時候設置起始代碼段。
1,首先,進入目錄LINK,運行make生成arm-linux-ld選項為「-Ttext 0x00000000」的反匯編碼ttt.s。
然後,修改Makefile:將第4、7行的「#」去掉,在第3、6行前加上「#」,運行make生成arm-linux-ld選項為「-Ttext 0x30000000」的反匯編碼ttt2.s,link.s程序中用到兩種跳轉方法:b跳轉指令、直接向pc寄存器賦值。
然後,先把在不同「-Ttext」選項下,生成的可執行文件的反匯編碼列出來,再詳細分析這兩種不同指令帶來的差異。
然後,讓第一張圖片從最左面開始,滾動方向是從左向右,而且讓第一張圖片和最後一張圖片要連接在一起,現在是一個滾動完成之後,圖片又從最右邊開始向左滾動。
然後,在應用程序中,棧和堆的起始地址是有約定的。但是內核本身沒有另外一個更高層的程序來管理內核的地址空間,所以內核空間的棧的組織,和應用程序有所不同。內核的棧如果溢出時,不能像應用程序那樣產生一個page fault,然後分配新的地址空間,繼續使用。內核的棧如果溢出,沒有人知道,除非溢出的地方影響了運行,讓程序crash。
後,堆的空間的擴大靠brk()系統調用,而內核的內存使用,get_free_pages來實現的(雖然上層封裝了kmalloc和vmalloc),這個基本上是自己管理自己,由於Linux內核還不支持自己的swapping,所以內核如果找不到可用的頁框了,也就沒辦法了。
❼ 如何建立Linux下的ARM交叉編譯環境
這個過程如下
1. 下載源文件、補丁和建立編譯的目錄
2. 建立內核頭文件
3. 建立二進制工具(binutils)
4. 建立初始編譯器(bootstrap gcc)
5. 建立c庫(glibc)
6. 建立全套編譯器(full gcc)
下載源文件、補丁和建立編譯的目錄
1. 選定軟體版本號
選擇軟體版本號時,先看看glibc源代碼中的INSTALL文件。那裡列舉了該版本的glibc編譯時所需的binutils 和gcc的版本號。例如在 glibc-2.2.3/INSTALL 文件中推薦 gcc 用 2.95以上,binutils 用 2.10.1 以上版本。
我選的各個軟體的版本是:
linux-2.4.21+rmk2
binutils-2.10.1
gcc-2.95.3
glibc-2.2.3
glibc-linuxthreads-2.2.3
如果你選的glibc的版本號低於2.2,你還要下載一個叫glibc-crypt的文件,例如glibc-crypt-2.1.tar.gz。 Linux 內核你可以從www.kernel.org 或它的鏡像下載。
Binutils、gcc和glibc你可以從FSF的FTP站點ftp://ftp.gun.org/gnu/ 或它的鏡像去下載。在編譯glibc時,要用到 Linux 內核中的 include 目錄的內核頭文件。如果你發現有變數沒有定義而導致編譯失敗,你就改變你的內核版本號。例如我開始用linux-2.4.25+vrs2,編譯glibc-2.2.3 時報 BUS_ISA 沒定義,後來發現在 2.4.23 開始它的名字被改為 CTL_BUS_ISA。如果你沒有完全的把握保證你改的內核改完全了,就不要動內核,而是把你的 Linux 內核的版本號降低或升高,來適應 glibc。
Gcc 的版本號,推薦用 gcc-2.95 以上的。太老的版本編譯可能會出問題。Gcc-2.95.3 是一個比較穩定的版本,也是內核開發人員推薦用的一個 gcc 版本。
如果你發現無法編譯過去,有可能是你選用的軟體中有的加入了一些新的特性而其他所選軟體不支持的原因,就相應降低該軟體的版本號。例如我開始用 gcc-3.3.2,發現編譯不過,報 as、ld 等版本太老,我就把 gcc 降為 2.95.3。太新的版本大多沒經過大量的測試,建議不要選用。
2. 建立工作目錄
首先,我們建立幾個用來工作的目錄:
在你的用戶目錄,我用的是用戶liang,因此用戶目錄為 /home/liang,先建立一個項目目錄embedded。
$pwd
/home/liang
$mkdir embedded
再在這個項目目錄 embedded 下建立三個目錄 build-tools、kernel 和 tools。
build-tools-用來存放你下載的 binutils、gcc 和 glibc 的源代碼和用來編譯這些源代碼的目錄。
kernel-用來存放你的內核源代碼和內核補丁。
tools-用來存放編譯好的交叉編譯工具和庫文件。
$cd embedded
$mkdir build-tools kernel tools
執行完後目錄結構如下:
$ls embedded
build-tools kernel tools
3. 輸出和環境變數
我們輸出如下的環境變數方便我們編譯。
$export PRJROOT=/home/liang/embedded
$export TARGET=arm-linux
$export PREFIX=$PRJROOT/tools
$export TARGET_PREFIX=$PREFIX/$TARGET
$export PATH=$PREFIX/bin:$PATH
如果你不慣用環境變數的,你可以直接用絕對或相對路徑。我如果不用環境變數,一般都用絕對路徑,相對路徑有時會失敗。環境變數也可以定義在.bashrc文件中,這樣當你logout或換了控制台時,就不用老是export這些變數了。
體系結構和你的TAEGET變數的對應如下表
你可以在通過glibc下的config.sub腳本來知道,你的TARGET變數是否被支持,例如:
$./config.sub arm-linux
arm-unknown-linux-gnu
在我的環境中,config.sub 在 glibc-2.2.3/scripts 目錄下。
網上還有一些 HOWTO 可以參考,ARM 體系結構的《The GNU Toolchain for ARM Target HOWTO》,PowerPC 體系結構的《Linux for PowerPC Embedded Systems HOWTO》等。對TARGET的選取可能有幫助。
4. 建立編譯目錄
為了把源碼和編譯時生成的文件分開,一般的編譯工作不在的源碼目錄中,要另建一個目錄來專門用於編譯。用以下的命令來建立編譯你下載的binutils、gcc和glibc的源代碼的目錄。
$cd $PRJROOT/build-tools
$mkdir build-binutils build-boot-gcc build-gcc build-glibc gcc-patch
build-binutils-編譯binutils的目錄
build-boot-gcc-編譯gcc 啟動部分的目錄
build-glibc-編譯glibc的目錄
build-gcc-編譯gcc 全部的目錄
gcc-patch-放gcc的補丁的目錄
gcc-2.95.3 的補丁有 gcc-2.95.3-2.patch、gcc-2.95.3-no-fixinc.patch 和gcc-2.95.3-returntype-fix.patch,可以從 http://www.linuxfromscratch.org/ 下載到這些補丁。
再將你下載的 binutils-2.10.1、gcc-2.95.3、glibc-2.2.3 和 glibc-linuxthreads-2.2.3 的源代碼放入 build-tools 目錄中
看一下你的 build-tools 目錄,有以下內容:
$ls
binutils-2.10.1.tar.bz2 build-gcc gcc-patch
build-binutls build-glibc glibc-2.2.3.tar.gz
build-boot-gcc gcc-2.95.3.tar.gz glibc-linuxthreads-2.2.3.tar.gz
建立內核頭文件
把你從 www.kernel.org 下載的內核源代碼放入 $PRJROOT /kernel 目錄
進入你的 kernel 目錄:
$cd $PRJROOT /kernel
解開內核源代碼
$tar -xzvf linux-2.4.21.tar.gz
或
$tar -xjvf linux-2.4.21.tar.bz2
小於 2.4.19 的內核版本解開會生成一個 linux 目錄,沒帶版本號,就將其改名。
$mv linux linux-2.4.x
給 Linux 內核打上你的補丁
$cd linux-2.4.21
$patch -p1 < ../patch-2.4.21-rmk2
編譯內核生成頭文件
$make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
你也可以用 config 和 xconfig 來代替 menuconfig,但這樣用可能會沒有設置某些配置文件選項和沒有生成下面編譯所需的頭文件。推薦大家用 make menuconfig,這也是內核開發人員用的最多的配置方法。配置完退出並保存,檢查一下的內核目錄中的 include/linux/version.h 和 include/linux/autoconf.h 文件是不是生成了,這是編譯 glibc 是要用到的,version.h 和 autoconf.h 文件的存在,也說明了你生成了正確的頭文件。
還要建立幾個正確的鏈接
$cd include
$ln -s asm-arm asm
$cd asm
$ln -s arch-epxa arch
$ln -s proc-armv proc
接下來為你的交叉編譯環境建立你的內核頭文件的鏈接
$mkdir -p $TARGET_PREFIX/include
$ln -s $PRJROOT/kernel/linux-2.4.21/include/linux $TARGET_PREFIX/include/linux
$in -s $PRJROOT/kernel/linux-2.4.21/include/asm-arm $TARGET_PREFIX/include/asm
也可以把 Linux 內核頭文件拷貝過來用
$mkdir -p $TARGET_PREFIX/include
$cp -r $PRJROOT/kernel/linux-2.4.21/include/linux $TARGET_PREFIX/include
$cp -r $PRJROOT/kernel/linux-2.4.21/include/asm-arm $TARGET_PREFIX/include
建立二進制工具(binutils)
binutils是一些二進制工具的集合,其中包含了我們常用到的as和ld。
首先,我們解壓我們下載的binutils源文件。
$cd $PRJROOT/build-tools
$tar -xvjf binutils-2.10.1.tar.bz2
然後進入build-binutils目錄配置和編譯binutils。
$cd build-binutils
$../binutils-2.10.1/configure --target=$TARGET --prefix=$PREFIX
--target 選項是指出我們生成的是 arm-linux 的工具,--prefix 是指出我們可執行文件安裝的位置。
會出現很多 check,最後產生 Makefile 文件。
有了 Makefile 後,我們來編譯並安裝 binutils,命令很簡單。
$make
$make install
看一下我們 $PREFIX/bin 下的生成的文件
$ls $PREFIX/bin
arm-linux-addr2line arm-linux-gasp arm-linux-objmp arm-linux-strings
arm-linux-ar arm-linux-ld arm-linux-ranlib arm-linux-strip
arm-linux-as arm-linux-nm arm-linux-readelf
arm-linux-c++filt arm-linux-obj arm-linux-size
我們來解釋一下上面生成的可執行文件都是用來干什麼的
add2line - 將你要找的地址轉成文件和行號,它要使用 debug 信息。
Ar-產生、修改和解開一個存檔文件
As-gnu 的匯編器
C++filt-C++ 和 java 中有一種重載函數,所用的重載函數最後會被編譯轉化成匯編的標號,c++filt 就是實現這種反向的轉化,根據標號得到函數名。
Gasp-gnu 匯編器預編譯器。
Ld-gnu 的連接器
Nm-列出目標文件的符號和對應的地址
Obj-將某種格式的目標文件轉化成另外格式的目標文件
Objmp-顯示目標文件的信息
Ranlib-為一個存檔文件產生一個索引,並將這個索引存入存檔文件中
Readelf-顯示 elf 格式的目標文件的信息
Size-顯示目標文件各個節的大小和目標文件的大小
Strings-列印出目標文件中可以列印的字元串,有個默認的長度,為4
Strip-剝掉目標文件的所有的符號信息
建立初始編譯器(bootstrap gcc)
首先進入 build-tools 目錄,將下載 gcc 源代碼解壓
$cd $PRJROOT/build-tools
$tar -xvzf gcc-2.95.3.tar.gz
然後進入 gcc-2.95.3 目錄給 gcc 打上補丁
$cd gcc-2.95.3
$patch -p1< ../gcc-patch/gcc-2.95.3.-2.patch
$patch -p1< ../gcc-patch/gcc-2.95.3.-no-fixinc.patch
$patch -p1< ../gcc-patch/gcc-2.95.3-returntype-fix.patch
echo timestamp > gcc/cstamp-h.in
在我們編譯並安裝 gcc 前,我們先要改一個文件 $PRJROOT/gcc/config/arm/t-linux,把
TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC
這一行改為
TARGET_LIBGCC2-CFLAGS = -fomit-frame-pointer -fPIC -Dinhibit_libc -D__gthr_posix_h
你如果沒定義 -Dinhibit,編譯時將會報如下的錯誤
http://www.cnblogs.com/gcc-2.95.3/gcc/libgcc2.c:41: stdlib.h: No such file or directory
http://www.cnblogs.com/gcc-2.95.3/gcc/libgcc2.c:42: unistd.h: No such file or directory
make[3]: *** [libgcc2.a] Error 1
make[2]: *** [stmp-multilib-sub] Error 2
make[1]: *** [stmp-multilib] Error 1
make: *** [all-gcc] Error 2
❽ linux如何編譯arm-2440的led跑馬燈程序不是編譯驅動程序
這是一個很簡單的問題。使用ads生成二進制文件的時候會直接可執行的二進制文件的頭去掉。如程序的執行地址,鏈接地址等等信息被去掉。但是在linux上你使用的arm-linux-gcc編譯過後產生的只是linux 系統的可執行二進制文件,它能夠被linux 內核所識別。但是他們不能直接作為裸板程序直接被開發板所執行。除了使用arm-linux-gcc 以外還要使用兩個命名arm-linux-ld 和 arm-linux-obj 才能生成能直接被裸板執行的代碼
原文地址:http://www.ebhou.com/post/armtest.html
今天在空間看到一個關於arm裸板代碼的問題。這個問題對於老鳥來說都是簡單得不能再簡單的問題了。可是當時確把我給難住了,以前學習的時候沒有少些過裸板代碼。自己的電腦上至今還保留著lcd,觸摸屏和 音效卡的裸板驅動。才1年多點時間盡然自己只知道分三不,編譯、鏈接、去掉elf頭。而具體的步驟盡然只知道gcc 另外兩部的命名盡然不知道參數是什麼。慚愧啊!
今天保留過程於此。
做備忘只用,如果能夠幫助到任何人那就不虛此寫啊。
看過編譯原理的人都知道我們一句簡單的arm-linux-gcc 到達做了哪些工作。他並不是簡單的把我們的原文件編譯成我們可執行的二進制文件,在這個過程中他其實至少做了兩部工作。「編譯」和鏈接「當然這其中包含了很多關於編譯原理的至少,由於本人才疏學淺說以也只能夠簡單的把他說成編譯和鏈接了。如果需要跟深入的理解請查找相關」編譯原理的書籍吧「
這里我們先介紹一下常用的gcc命令.
1.arm-linux-gcc -v 查看gcc 版本號
2.arm-linux-nm 查看一個.o文件所需要的庫。
3.arm-linux-ld 鏈接命令
3.arm-linux-gcc 編譯命令
4 arm-linux-objmp -h test 查看符號
-d 反匯編
5 arm-linux-as ls.S -o ls.o 將匯編原文件編譯成.o文件
6 arm-linux-obj -I elf32-littlearm -O binary test test.bin 去掉二進制文件elf頭。
現在我們來寫一個arm裸板的LED閃燈程序 非常簡單的。
源代碼 led_test.c
void main()
{
int i=0;
volatile long *GPKCON0 = 0x7F008800;
volatile long *GPKDAT = 0x7F008808;
volatile long *GPKPUD = 0x7F00880C;
*GPKCON0 &= ~(0XFFFF <<16);
*GPKCON0 |= (0X1111 <<16);
while(1){
*GPKDAT &= ~(0XF <<4);
i=0xfffff;
while(i--)
;
*GPKDAT |= (0XF <<4);
i=0xfffff;
while(i--)
;
}
}
每隔大概3秒鍾的時間LED閃爍一次。非常簡單的一個程序。這里沒有使用定時器啊 什麼的知識簡單的做循環來延時。注意 關於LED 的GPIO相關寄存器地址根據你自己的實際情況來。
編譯過程
1 編譯
arm-linux-gcc -c -march=armv4 test.c -o test.o
2.鏈接 http://www.ebhou.com/post/armtest.html
❾ linux下編譯出錯arm-linux-ld: warning: cannot find entry symbol _start
這個看著不像是鏈接庫的問題,默認的鏈接腳本需要" _start "標號作為程序入口,你的匯編代碼里是不是沒有出現這個標號?
❿ 利用arm-linux-gcc編譯時出現collect2: ld returned 1 exit status 錯誤:具體步驟如下:
我看上面寫的是 /armlinux/app/mylib這個路徑,下面指定庫路徑的時候就成了/armlinux/ex/mylib了,是不是路徑不對啊,你生成的.so文件是不是在/armlinux/app/mylib這個裡面了。