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。