Arm的鏈接工具
Linker Guide PDF
一、鏈接器概述
Armlinkの功能
-
鏈接ARM代碼和Thumb®代碼。
-
生成 interworking veneers,以便在需要時在ARM代碼和Thumb®代碼之間切換。
-
根據需要生成range extension veneers,以擴展分支指令的範圍。
-
根據所鏈接對象的構建屬性,自動選擇要鏈接的適當標準C或c++庫變體。
-
允許使用 acommand-line 選項或 .sct 文件指定代碼和數據在系統內存映射中的位置。
-
執行RW數據壓縮以最小化ROM大小。
-
刪除未使用的部分,以減小輸出Image的大小。
-
控制輸出文件中調試信息的生成。
-
生成一個靜態調用圖(.map),並列出堆棧使用情況。
-
控制輸出圖像中符號表的內容。
-
顯示輸出中的代碼和數據的大小。
-
使用鏈接器反饋來刪除單個未使用的函數。
Armlinkの輸入文件
armlink可以從支持ARM ELF的工具鏈中接受一個或多個目標文件
可選地,以下文件可作爲armlink的輸入:
• One or more libraries created by the librarian, armar.
• A symbol definitions file.
• A scatter file.
• A steering file
Armlinkの輸出文件
armlink的輸出可以是:
•ELF可執行映像。
•一個部分鏈接的ELF對象,可在後續鏈接步驟中用作輸入。
Linker command-line options
Options that control library files and paths 控制庫文件和路徑的選項
• --libpath=pathlist.
• --library_type=lib.
• --scanlib, --no_scanlib.
• --thumb2_library, --no_thumb2_library.
• --userlibpath=pathlist.
Options that control the linking of object files 控制對象文件鏈接的選項
• --match=crossmangled.
• --strict.
• --strict_ph, --no_strict_ph.
• --strict_relocations, --no_strict_relocations.
• --unresolved=symbol.
Options that control the output 控制輸出的選項
• --combreloc, --no_combreloc.
• --ldpartial.
• --output=filename.
• --partial.
• --reloc.
Options to specify the image memory map 指定image內存映射的選項
• --predefine="string".
• --ro_base=address.
• --ropi.
• --rosplit.
• --rw_base=address.
• --rwpi.
• --scatter=filename.
• --split.
• --zi_base=address.
Options that control debug information in an image 控制image中的調試信息的選項
• --bestdebug, --no_bestdebug.
• --compress_debug, --no_compress_debug.
• --debug, --no_debug.
• --eager_load_debug, --no_eager_load_debug.
• --emit_debug_overlay_relocs.
• --emit_debug_overlay_section.
• --emit_non_debug_relocs.
Options that control the content of an image 控制image內容的選項
• --any_contingency.
• --any_placement=algorithm.
• --any_sort_order=order.
• --api, --no_api.
• --arm_only.
• --autoat, --no_autoat.
• --blx_arm_thumb, --no_blx_arm_thumb.
• --blx_thumb_arm, --no_blx_thumb_arm.
• --branchnop, --no_branchnop.
• --comment_section, --no_comment_section.
• --cpp_compat.
• --cppinit, --no_cppinit.
• --cpu=name.
• --datacompressor=opt.
• --edit=file_list.
• --emit_relocs.
• --entry=location.
• --exceptions, --no_exceptions.
• --exceptions_tables=action.
• --filtercomment, --no_filtercomment.
• --fini=symbol.
• --first=section_id.
• --force_explicit_attr.
• --fpu=name.
• --init=symbol.
• --inline, --no_inline.
• --inline_type=type.
• --keep=section_id.
• --largeregions, --no_largeregions.
• --last=section_id.
• --locals, --no_locals.
• --max_er_extension=size.
• --max_visibility=type.
• --merge, --no_merge.
• --muldefweak, --no_muldefweak.
• --override_visibility.
• --pad=num.
• --paged.
• --pagesize=pagesize.
• --ref_cpp_init, --no_ref_cpp_init.
• --remove, --no_remove.
• --sort=algorithm.
• --startup=symbol, --no_startup.
• --strict_flags, --no_strict_flags.
• --tailreorder, --no_tailreorder.
• --tiebreaker=option.
• --undefined=symbol.
• --undefined_and_export=symbol.
• --use_definition_visibility.
• --vfemode=mode.
Options that control veneer generation 控制 veneer 生成的選項
• --crosser_veneershare, --no_crosser_veneershare.
• --inlineveneer, --no_inlineveneer.
• --max_veneer_passes=value.
• --piveneer, --no_piveneer.
• --veneerinject,--no_veneerinject.
• --veneer_inject_type=type.
• --veneer_pool_size=size.
• --veneershare, --no_veneershare.
Options that control byte addressing mode 控制字節尋址模式的選項
• --be8.
• --be32.
Optionscontrol extraction and presentation of image information 控制image信息的提取和表示的選項
• --callgraph, --no_callgraph.
• --callgraph_file=filename.
• --callgraph_output=fmt.
• --callgraph_subset=symbol[,symbol,…].
• --cgfile=type.
• --cgsymbol=type.
• --cgundefined=type.
• --feedback=filename.
• --feedback_image=option.
• --feedback_type=type.
• --info=topic[,topic,...].
• --info_lib_prefix=opt.
• --list_mapping_symbols, --no_list_mapping_symbols.
• --load_addr_map_info, --no_load_addr_map_info.
• --mangled, --unmangled.
• --map, --no_map.
• --section_index_display=type.
• --symbols, --no_symbols.
• --symdefs=filename.
• --xref, --no_xref.
• --xrefdbg, --no_xrefdbg.
• --xref{from|to}=object(section).
Options that control diagnostic messages 控制診斷消息的選項
• --diag_error=tag[,tag,…].
• --diag_remark=tag[,tag,…].
• --diag_style=arm|ide|gnu.
• --diag_suppress=tag[,tag,…].
• --diag_warning=tag[,tag,…].
• --errors=filename.
• --list=filename.
• --remarks.
• --show_full_path.
• --show_parent_lib.
• --show_sec_idx.
• --strict_enum_size, --no_strict_enum_size.
• --strict_symbols, --no_strict_symbols.
• --strict_visibility, --no_strict_visibility.
• --strict_wchar_size, --no_strict_wchar_size.
• --verbose.
Options that control alignment in legacy images 控制legacy images對齊的選項
• --legacyalign, --no_legacyalign.
License related options
• --licretry.
• --liclinger.
Miscellaneous options 雜項選項
• --cpu=list.
• --fpu=list.
• --help.
• input-file-list.
• --show_cmdline.
• --version_number.
• --via=filename.
• --vsn.
當使用鏈接器構造一個可執行的圖像時:
•解析輸入對象文件之間的符號引用。
•從庫中提取對象模塊,以滿足不滿足的符號引用。
•刪除未使用的部分。
•消除重複的公共組和公共代碼、數據和調試部分。
•根據輸入部分的屬性和名稱對其進行排序,並將具有相似屬性和名稱的部分合併到相鄰的塊中。
•根據所提供的分組和位置信息,將對象片段組織到內存區域。
•爲可重定位值分配地址。
•生成可執行映像。
二、armlink支持的鏈接模型
linking model是一組命令行選項和內存映射,它們控制鏈接器的行爲。
Bare-metal linking model
在傳統的嵌入式應用場景,整個程序,可能包括一個實時操作系統(RTOS),一次性全部連接。
-
使用分散文件或命令行選項識別可以重新定位或與位置無關的區域。
-
識別可以使用 steering file 導入和導出的符號。
You can use the following options with this model:
• --edit=file_list.
• --scatter=file.
You can use the following options when scatter-loading is not used:
• --reloc.
• --ro_base=address.
• --ropi.
• --rosplit.
• --rw_base=address.
• --rwpi.
• --split.
• --xo_base=address.
• --zi_base.
--xo_base cannot be used with --ropi or --rwpi
Partial linking model
-
生成一個輸出文件,該文件可以用作後續鏈接步驟的輸入。
-
消除調試部分的重複副本。
-
將符號表合併爲一個。
-
未解析的引用未解析。
-
合併公共數據(COMDAT)組。
-
生成一個對象文件,該文件可以用作後續鏈接步驟的輸入。
如果鏈接器在輸入文件中找到多個入口點,它將生成一個錯誤,因爲單個輸出文件只能有一個入口點。
三、Image 結構與生成
3.1 The structure of an ARM ELF image
ARM ELF圖像包含節section、區域region和段segment,每個鏈接階段都有不同的圖像視圖。
ELF對象文件視圖(鏈接器輸入)
ELF對象文件視圖包含輸入部分。ELF對象文件可以是:
-
一個可以重定位的文件,包含適合與其他對象文件鏈接的代碼和數據,以創建可執行文件或共享對象文件。
-
一個包含代碼和數據的共享對象文件。
鏈接器視圖
鏈接器對程序的地址空間有兩個視圖,當存在重疊的、位置無關的和可重定位的程序片段(代碼或數據)時,它們變得不同:
-
程序片段的加載地址是鏈接器期望外部代理(如程序加載器、動態鏈接器或調試器)從ELF文件中複製該片段的目標地址。這可能不是片段執行的地址。
-
程序片段的執行地址是鏈接器期望該片段在參與程序執行時駐留的目標地址。如果一個片段是位置無關的或可重定位的,那麼它的執行地址在執行期間可能會發生變化。
ELF圖像文件視圖(鏈接器輸出)
ELF圖像文件視圖包括程序段和輸出部分:
-
一個加載區域對應於一個程序段。
-
執行區域包含以下一個或多個輸出部分:
RO部分。
RW部分。
XO部分。
子部分。
一個或多個執行區域組成一個加載區域。
使用armlink,程序段的最大大小爲2GB。
Input section
輸入部分是輸入對象文件中的一個單獨部分。它包含代碼、初始化的數據,或者描述未初始化的內存片段,或者在執行映像之前必須將其設置爲零。這些屬性由諸如RO、RW、XO和等屬性表示子。armlink使用這些屬性將輸入部分分組爲更大的構建塊(稱爲輸出部分和區域)。
Output section
輸出部分是一組有相同的RO、RW、XO或ZI屬性的輸入部分,並且由鏈接器連續地放置在內存中。輸出部分有與其組成輸入部分相同的屬性。在輸出部分中,輸入部分根據部分放置規則進行排序。
Region
根據內容和具有不同屬性的節的數量,一個區域最多包含四個輸出節。默認情況下,區域中的輸出部分根據其屬性進行排序。首先是任何XO輸出部分,然後是RO輸出部分,然後是RW輸出部分,最後是ZI輸出部分。區域通常映射到物理內存設備,如ROM、RAM或外設。可以使用分散加載更改輸出部分的順序。
Program segment
程序段對應於一個加載區域,幷包含執行區域。程序段包含文本和數據等信息。
圖像的加載視圖和執行視圖
Image入口點
Image中的入口點是加載到PC指針中的位置。它是程序執行開始的位置。雖然在一個圖像中可以有多個入口點,但是在鏈接時只能指定一個入口點。
並不是每個ELF文件都必須有一個入口點。不允許在一個ELF文件中包含多個入口點。
初始入口點 Initial entry point
圖像的初始入口點是存儲在ELF頭文件中的單個值。對於 由操作系統或引導加載程序加載 到RAM中的程序,加載程序 通過將控制權轉移 到映像中的初始入口點來啓動映像執行。一個圖像只能有一個初始入口點。初始入口點可以是入口指令(ENTRY directive)設置的入口點之一,但不是必需的。
作爲“初始入口點”必須滿足以下條件:
-
圖像入口點必須始終位於執行區域內。
-
執行區域不能覆蓋其他執行區域,必須是根執行區域 (也就是說,加載地址與執行地址相同)。
-
如果不使用 --entry選項指定初始入口點,則:
如果輸入對象只包含entry指令設置的一個入口點,鏈接器將該入口點用作圖像的初始入口點。
如果使用entry指令指定了多個入口點 或 沒有使用入口指令沒有指定入口點 則鏈接器生成的圖像不包含初始入口點。
入口指令設置的入口點 Entry points set by the ENTRY directive
可以爲圖像選擇許多可能的入口點之一。一個圖像只能有一個入口點。
使用匯編程序文件中的 --entry指令在對象中創建入口點。在嵌入式系統中,這個指令的典型用法是標記通過處理器異常向量(如RESET、IRQ和FIQ)輸入的代碼。
該指令用ENTRY關鍵字標記輸出代碼部分,該關鍵字指示鏈接器在執行未使用的部分消除時不要刪除該部分。對於C和c++程序,C庫中的__main()函數也是一個入口點。
如果加載程序要使用嵌入式映像,則必須在標頭中指定一個初始入口點。使用 --entry命令行選項選擇入口點。
默認的Section安放順序
默認情況下,鏈接器在執行區域內以特定的順序放置輸入部分。
1. 按照以下屬性(優先級a最高):
a. Read-only code.
b. Read-only data.
c. Read-write code.
d. Read-write data.
e. Zero-initialized data.
2. 如果它們具有相同的屬性,則按輸入節名稱。名稱被認爲是區分大小寫的,並使用ASCII字符排序序列按字母順序進行比較。
3.如果它們具有相同的屬性和節名,則使用tie-breaker。默認情況下,這是armlink處理該節的順序。當然,也可以使用 FIRST 或 LAST 執行區域屬性覆蓋此屬性。
這些規則意味着具有相同屬性和庫中包含的名稱的輸入部分的位置取決於鏈接器處理對象的順序。當命令行上出現許多庫時,這很難預測。--tiebreaker=cmdline選項使用基於命令行上出現的節的順序的更可預測的順序。
每個輸入節的基本地址由鏈接器定義的排序順序決定,並在包含它的輸出節中正確對齊。
鏈接器爲執行區域中的每個屬性生成一個輸出部分:
-
如果執行區域只包含XO sections,則生成一個XO section。
-
如果執行區域包含RO 代碼或數據,則生成一個RO section。
-
如果執行區域包含RW 代碼或數據, 則生成一個RW section。
-
如果執行區域包含zero-initialized數據, 則生成一個ZI section。