objcopy 是 GNU Binutils 套件核心工具,用於**目標文件間的內容複製與格式轉換**。基於 BFD (Binary File Descriptor) 庫,支援 50+ 種目標格式 (ELF、COFF、a.out、S-record、Intel Hex、Binary 等)。
| 任務 | 命令範例 | 關鍵選項 |
|---|---|---|
| ELF → 純二進制 | objcopy -O binary app.elf app.bin | -O binary |
| ELF → S-record (燒錄) | objcopy -O srec app.elf app.srec | -O srec |
| ELF → Intel Hex | objcopy -O ihex app.elf app.hex | -O ihex |
| 去除符號/調試資訊 | objcopy -S -g app.elf app_stripped.elf | -S -g |
| 僅保留特定段 | objcopy -j .text -j .data -O binary app.elf firmware.bin | -j section |
| 移除特定段 | objcopy -R .comment -R .note app.elf | -R section |
| 重定位段地址 | objcopy --change-section-address .text=0x8000 app.elf | --change-section-address |
| 添加二進制資源段 | objcopy --add-section .mydata=data.bin app.elf | --add-section |
| 格式轉換 (ELF32→ELF64) | objcopy -O elf64-x86-64 app32.elf app64.elf | -O bfdname |
# 1. 編譯鏈接生成 ELF
arm-none-eabi-gcc -mcpu=cortex-m4 -T linker.ld -o app.elf src/*.c
# 2. 提取 .text .data .rodata 生成二進制
arm-none-eabi-objcopy -O binary \
-j .text -j .data -j .rodata -j .vectors \
app.elf app.bin
# 3. 驗證
arm-none-eabi-objdump -h app.elf
ls -l app.bin
注意:Binary 格式**不包含**符號表、重定位資訊、段屬性。起始地址為被複製段的最小虛擬地址 (VMA)。燒錄器需知晓載入地址 (通常來自鏈接腳本
ENTRY或向量表)。
# 去除所有符號與調試資訊
objcopy -S -g --strip-unneeded app.elf app.release.elf
# 進一步:僅保留必要段
objcopy -R .comment -R .note -R .note.gnu.build-id \
-R .eh_frame -R .eh_frame_hdr \
app.release.elf app.minimal.elf
# 將圖片/字體/配置文件嵌入為只讀數據段
objcopy --add-section .firmware_logo=logo.png \
--set-section-flags .firmware_logo=readonly,data \
--change-section-vma .firmware_logo=0x08020000 \
app.elf app_with_logo.elf
C 代碼中訪問:
extern const unsigned char _binary_firmware_logo_start[];
extern const unsigned char _binary_firmware_logo_end[];
size_t logo_size = _binary_firmware_logo_end - _binary_firmware_logo_start;
# 1. 分別編譯
arm-none-eabi-gcc -T boot.ld -o boot.elf boot/*.c
arm-none-eabi-gcc -T app.ld -o app.elf app/*.c
# 2. 提取二進制
arm-none-eabi-objcopy -O binary -j .text -j .data boot.elf boot.bin
arm-none-eabi-objcopy -O binary -j .text -j .data -j .rodata app.elf app.bin
# 3. 合併 (假設 Bootloader 佔 32KB,App 從 0x08008000 開始)
cat boot.bin app.bin > full_image.bin
# 或使用 objcopy 精確控制地址
objcopy -I binary -O binary --pad-to=0x8000 --gap-fill=0xFF boot.bin boot_padded.bin
cat boot_padded.bin app.bin > full_image.bin
-K symbol / --keep-symbol:僅保留指定符號 (可多次使用)-N symbol / --strip-symbol:移除指定符號-L symbol / --localize-symbol:將全局符號設為局部 (隱藏)-W symbol / --weaken-symbol:將符號標記為弱符號-x / --discard-all:移除所有非全局符號-X / --discard-locals:移除編譯器生成的局部符號 (以 L 或 . 開頭)--set-section-flags .name=alloc,load,readonly,data,contents--change-section-vma .name=0xADDR:修改虛擬地址 (VMA)--change-section-lma .name=0xADDR:修改載入地址 (LMA)--change-section-address .name=0xADDR:同時修改 VMA/LMA--gap-fill=0xFF:段間隙填充值 (燒錄常用 0xFF/0x00)--pad-to=0x10000:輸出文件填充至指定地址--set-start=0xADDR:設定入口點地址--adjust-start=0xOFFSET:調整入口點偏移| 問題 | 原因 | 解決 |
|---|---|---|
| Binary 輸出檔案大小異常大 | 段間隙被填充、VMA 不連續 | 使用 --gap-fill=0 --pad-to=0 或調整鏈接腳本 |
| 符號在 Binary 中丟失 | Binary 格式不保存符號 | 保留 ELF 供調試,僅發布 Binary |
| 交叉編譯 objcopy 無法識別目標格式 | BFD 未支援該架構/格式組合 | 確認 objcopy --help 列表、更新 Binutils |
| --add-section 後段不可讀 | 未設定 alloc/load/readonly flags | 加上 --set-section-flags .sec=alloc,load,readonly,data |
| 工具 | 核心功能 | 典型用途 |
|---|---|---|
| objcopy | 複製、轉換、修改目標文件 | 格式轉換、裁剪、嵌入資源、地址調整 |
| objdump | 反組裝、顯示段/符號/重定位 | 代碼審計、調試、檢查指令編碼 |
| readelf | 解析 ELF 結構 (程序頭、段頭、符號表) | ELF 結構分析、動態鏈接檢查、ABI 驗證 |