區別
常用的可執行文件包含兩類:原始二進制文件(bin)和可加載執行的二進制文件,在linux中可加載執行的二進制文件為elf文件。
BIN文件是直接的二進制文件,內部沒有地址標記。bin文件內部數據按照代碼段或者數據段的物理空間地址來排列。一般用編程器燒寫時從00開始,而如果下載運行,則下載到編譯時的地址即可。
在Linux OS上,為了運行可執行文件,他們是遵循ELF格式的,通常gcc -o test test.c,生成的test文件就是ELF格式的。執行elf文件時內核會使用加載器來解析elf文件並執行。
ELF文件格式是一個開放標准,各種UNIX系統的可執行文件都采用ELF格式,它有三種不同的類型:
-
可重定位的目標文件(Relocatable,或者Object File)
-
可執行文件(Executable)
-
共享庫(Shared Object,或者Shared Library)
$ file sum.o sub.o test.o libsub.so test sum.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped sub.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped test.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped libsub.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped test: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not stripped 結果很清楚的告訴我們他們都屬於哪一個類別。比方 sum.o 是應用在x86架構上的可重定位文件。這個結果也間接的告訴我們,x86是小端模式(LSB)的32位結構。
那對於 file 命令來說,它又能如何知道這些信息?答案是在ELF對象文件的最前面有一個ELF文件頭,里面記載了所適用的處理器、對象文件類型等各種信息。
ELF格式提供了兩種不同的視角,鏈接器把ELF文件看成是Section的集合,而加載器把ELF文件看成是Segment的集合。
在Embedded中,如果上電開始運行,沒有OS系統,如果將ELF格式的文件燒寫進去, 包含一些ELF文件的符號表字符表之類的section,運行碰到這些,就會導致失敗,如果用objcopy生成純粹的二進制文件,去除掉符號表之類的 section,只將代碼段數據段保留下來,程序就可以一步一步運行。elf文件里面包含了符號表等。BIN文件是將elf文件中的代碼段,數據段,還有一些自定義的段抽取出來做成的一個內存的鏡像。並且elf文件中代碼段數據段的位置並不是它實際的物理位置,實際物理位置是在表中標記出來的。
文件的內容
1. BIN文件是 raw binary 文件,這種文件只包含機器碼。2. ELF文件除了機器碼外,還包含其它額外的信息,如段的加載地址,運行地址,重定位表,符號表等。
所以ELF文件的體積比對應的BIN文件要大。
文件的執行
1. 執行raw binary很簡單,只需要將程序加載到其起始地址,就可以執行;FILE *fp = fopen("vmlinux.bin", "rb"); fread(VMLINUX_START, 1, VMLINUX_SIZE, fp); ((void (*)(void))VMLINUX_START)();
uboot和Linux kernel啟動的時候是沒有ELF Loader的,所以燒在flash上的文件只能是raw binary格式的,即鏡像文件image。
文件的轉換
1. 通過gcc編譯出來的是elf文件2. 通過objcpy可以把elf文件轉換為bin文件
CC=ppc-gcc LD=ppc-ld OBJCOPY=ppc-objcopy $(CC) -g $(CFLAG) -c boot.S #先將boot.S文件生成boot.o $(LD) -g -Bstatic -T$(LDFILE) \ -Ttext 0x12345600 boot.o \ --start-group -Map boot.map -o boot.elf #再將boot.o生成boot.elf $(OBJCOPY) -O binary -R .note -R .comment -S boot.elf boot.bin #接着將 boot.elf 轉換為 boot.bin #使用 -O binary (或--out-target=binary) 輸出為原始的二進制文件 #使用 -R .note (或--remove-section) 輸出文件中不要.note這個section,縮小了文件尺寸 #使用 -S (或 --strip-all) 輸出文件中不要重定位信息和符號信息,縮小了文件尺寸
u-boot ELF文件可用來調試
u-boot.bin BIN文件用來燒在Flash上
編譯linux生成:
vmlinux ELF文件可用來調試
vmlinux.bin BIN文件,沒直接用過
zImage/vmlinuz/bzimage
將vmlinux.bin壓縮,並加上一段解壓代碼得到的,不可和bootloader共存?
uImage
uboot專用的內核鏡像,在zImage前加了一個64字節的頭,描述內核版本、加載地址、生成時間,文件大小等等。 其0x40后的內容和zImage一樣。
它是由uboot的工具mkImage生成的。
uImage相對於zImage的優點在於:uImage可以和uboot共存。
文件的調試
1. 我們調試一般都是使用elf文件,比如: nm elf文件 #得到符號表
objdump -D elf文件 #反匯編,且匯編代碼與源碼混排
objdump -b binary -m powerpc uboot.bin
此外還有工具:readelf,objcopy,ldd,file等。