GNU链接器简介-3
该篇文章是基于对 The GNU linker的翻译,并添加了部分自己的理解。
1 SECTIONS Command
The SECTIONS command tells the linker how to map input sections into output sections, and how to place the output sections in memory.
SECTIONS命令告诉链接器如何将输入段映射到输出段,以及如何将输出段放置在内存中。
The format of the SECTIONS command is:
SECTIONS命令的格式是:
SECTIONS
{
sections-command
sections-command
…
}
Each sections-command may of be one of the following:
每个部分命令可以使一下之一:
- an ENTRY command (see Entry command)
- an ENTRY command(参考Entry 命令)
- a symbol assignment (see Assigning Values to Symbols)
- 符号赋值(参考符号赋值)
- an output section description
- 输出部分描述
- an overlay description
- 覆盖层描述
The ENTRY command and symbol assignments are permitted inside the SECTIONS command for convenience in using the location counter in those commands. This can also make the linker script easier to understand because you can use those commands at meaningful points in the layout of the output file.
在SECTIONS命令中允许使用ENTRY命令和符号赋值,以便在这些命令中方便地使用位置计数器。这也可以使链接器脚本更容易理解,因为你可以在输出文件布局中有意义的点使用这些命令。
Output section descriptions and overlay descriptions are described below.
输出部分描述和叠加描述如下所述。
If you do not use a SECTIONS command in your linker script, the linker will place each input section into an identically named output section in the order that the sections are first encountered in the input files. If all input sections are present in the first file, for example, the order of sections in the output file will match the order in the first input file. The first section will be at address zero.
如果你在链接器脚本中不使用SECTIONS命令,链接器会按照输入文件中首次遇到的顺序,将每个输入段放置到同名的输出段中。例如,如果所有输入段都存在于第一个文件中,那么输出文件中的段顺序将与第一个输入文件中的顺序相匹配。第一个段将位于地址零。
- Output Section Description
- 输出段描述
- Output Section Name
- 输出段名字
- Output Section Address
- 输出段地址
- Input Section Description
- 输入段描述
- Output Section Data
- 输出段数据
- Output Section Keywords
- 输出部分关键词
- Output Section Discarding
- 输出段丢弃
- Output Section Attributes
- 输出段属性
- Overlay Description
- 叠加说明
1.1 Output Section Description
The full description of an output section looks like this:
一个输出部分的完整描述如下:
section [address] [(type)] :
[AT(lma)]
[ALIGN(section_align) | ALIGN_WITH_INPUT]
[SUBALIGN(subsection_align)]
[constraint]
{
output-section-command
output-section-command
…
} [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp] [,]
Most output sections do not use most of the optional section attributes.
大多数输出部分不使用大部分可选段的属性。
The whitespace around section is required, so that the section name is unambiguous. The colon and the curly braces are also required. The comma at the end may be required if a fillexp is used and the next sections-command looks like a continuation of the expression. The line breaks and other white space are optional.
节周围的空白是必需的,这样节的名称才是明确的。冒号和大括号也是必需的。如果使用了fillexp并且下一个sections-command看起来像是表达式的延续,那么表达式末尾的逗号可能是必需的。换行和其他空白是可选的。
Each output-section-command may be one of the following:
每个输出部分命令可以是以下之一:
- a symbol assignment (see Assigning Values to Symbols)
- 符号赋值(请参考符号赋值)
- an input section description (see Input Section Description)
- 输入段的描述(请参考输入段描述)
- data values to include directly (see Output Section Data)
- 直接包含的数据值(见输出段数据)
- a special output section keyword (see Output Section Keywords)
- 一个输出段的关键词(请参考输出段关键字)
2.2 Output Section Name
The name of the output section is section. section must meet the constraints of your output format. In formats which only support a limited number of sections, such as a.out, the name must be one of the names supported by the format (a.out, for example, allows only ‘.text’, ‘.data’ or ‘.bss’). If the output format supports any number of sections, but with numbers and not names (as is the case for Oasys), the name should be supplied as a quoted numeric string. A section name may consist of any sequence of characters, but a name which contains any unusual characters such as commas must be quoted.
输出部分的名称是section
。section
必须满足你的输出格式的约束。在只支持有限数量部分的格式中,例如a.out,名称必须是格式支持的名称之一(例如,a.out只允许'.text'
、'.data'
或'.bss'
)。如果输出格式支持任意数量的部分,但使用数字而不是名称(如Oasys的情况),则应将名称作为带引号的数字字符串提供。部分名称可以由任何字符序列组成,但是如果名称包含任何不寻常的字符,如逗号,则必须加上引号。
The output section name ‘/DISCARD/’ is special; Output Section Discarding.
输出部分名称‘/DISCARD/’
是特殊的;
1.3 Output Section Address
The address is an expression for the VMA (the virtual memory address) of the output section. This address is optional, but if it is provided then the output address will be set exactly as specified.
地址是对输出段的虚拟内存地址(VMA)的表达。这个地址是可选的,但如果提供了这个地址,输出地址将会被精确地设置为指定的值。
If the output address is not specified then one will be chosen for the section, based on the heuristic below. This address will be adjusted to fit the alignment requirement of the output section. The alignment requirement is the strictest alignment of any input section contained within the output section.
如果未指定输出地址,则将根据下面的启发式方法为该部分选择一个地址。该地址将根据输出部分的对齐要求进行调整。对齐要求是输出部分中包含的任何输入部分的最严格对齐要求。
The output section address heuristic is as follows:
输出部分地址启发式如下:
- If an output memory region is set for the section then it is added to this region and its address will be the next free address in that region.
- 如果为该段设置了输出内存区域,则它将被添加到该区域中,其地址将是该区域中下一个可用的地址。
- If the MEMORY command has been used to create a list of memory regions then the first region which has attributes compatible with
the section is selected to contain it. The section’s output address will be the next free address in that region; MEMORY Command.
如果已经使用MEMORY命令创建了一个内存区域列表,那么会选择第一个与该段属性兼容的区域来包含它。该段的输出地址将是该区域中下一个空闲地址; - If no memory regions were specified, or none match the section then the output address will be based on the current value of the
location counter.
如果没有指定内存区域,或者没有与该部分匹配的区域,那么输出地址将基于位置计数器的当前值。
For example:
.text . : { *(.text) }
and
.text : { *(.text) }
are subtly different. The first will set the address of the ‘.text’ output section to the current value of the location counter. The second will set it to the current value of the location counter aligned to the strictest alignment of any of the ‘.text’ input sections.
它们微妙地不同。第一个会将'.text'
输出段的地址设置为位置计数器的当前值。第二个会将其设置为位置计数器的当前值,该值与任何'.text'
输入段中最严格的对齐方式对齐。
The address may be an arbitrary expression; Expressions in Linker Scripts. For example, if you want to align the section on a 0x10 byte boundary, so that the lowest four bits of the section address are zero, you could do something like this:
地址可以是任意表达式;链接脚本中的表达式。例如,如果要在 0x10 字节边界对齐分段,使分段地址的最低四位为零,可以这样做:
.text ALIGN(0x10) : { *(.text) }
This works because ALIGN returns the current location counter aligned upward to the specified value.
这是因为ALIGN函数将当前的位置计数器向上对齐到指定的值。
Specifying address for a section will change the value of the location counter, provided that the section is non-empty. (Empty sections are ignored).
指定一个节的地址会改变位置计数器的值,前提是该节非空。(空节会被忽略)。
1.4 Input Section Description
The most common output section command is an input section description.
最常见的输出部分命令是一个输入段描述。
The input section description is the most basic linker script operation. You use output sections to tell the linker how to lay out your program in memory. You use input section descriptions to tell the linker how to map the input files into your memory layout.
输入段描述是最基本的链接器脚本操作。您使用输出部段来告诉链接器如何在内存中布局您的程序。您使用输入部分描述来告诉链接器如何将输入文件映射到您的内存布局中。
- Input Section Basics
- 输入段基础
- Input Section Wildcard Patterns
- 输入段通配符模式
- Input Section for Common Symbols
- 常见符号输入段
- Input Section and Garbage Collection
- 输入段和垃圾回收机制
- Input Section Example
- 输入段样例
1.4.1 Input Section Basics
An input section description consists of a file name optionally followed by a list of section names in parentheses.
输入段描述由一个文件名组成,可选地后面跟着一对括号内的部分名称列表。
The file name and the section name may be wildcard patterns, which we describe further below (see Input Section Wildcard Patterns).
文件名和段名可以是通配符模式,我们将在下文进一步介绍(请参阅输入段通配符模式)。
The most common input section description is to include all input sections with a particular name in the output section. For example, to include all input ‘.text’ sections, you would write:
最常见的输入段描述是将所有具有特定名称的输入段包含在输出段中。例如,要包含所有的输入“.text”
部分,你应该这样写:
*(.text)
Here the ‘*’ is a wildcard which matches any file name. To exclude a list of files from matching the file name wildcard, EXCLUDE_FILE may be used to match all files except the ones specified in the EXCLUDE_FILE list. For example:
这里的‘*’
是一个通配符,可以匹配任何文件名。要排除一系列文件不被文件名通配符匹配,可以使用EXCLUDE FILE来匹配除了EXCLUDE FILE列表中指定的文件之外的所有文件。例如:
EXCLUDE_FILE (*crtend.o *otherfile.o) *(.ctors)
will cause all .ctors sections from all files except crtend.o and otherfile.o to be included. The EXCLUDE_FILE can also be placed inside the section list, for example:
将导致所有文件(除了‘crtend.o’和‘otherfile.o’)的所有.ctors
段被包含。EXCLUDE FILE也可以放在段列表中,例如:
*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors)
The result of this is identically to the previous example. Supporting two syntaxes for EXCLUDE_FILE is useful if the section list contains more than one section, as described below.
这个结果与前一个示例完全相同。如果部分列表包含多个部分,如下面所述,支持EXCLUDE FILE的两种语法是有用的。
There are two ways to include more than one section:
有两种方式可以包含不止一个部分:
*(.text .rdata)
*(.text) *(.rdata)
The difference between these is the order in which the ‘.text’ and ‘.rdata’ input sections will appear in the output section. In the first example, they will be intermingled, appearing in the same order as they are found in the linker input. In the second example, all ‘.text’ input sections will appear first, followed by all ‘.rdata’ input sections.
这些之间的区别在于‘.text’
和‘.rdata’
输入段在输出段中出现的顺序。在第一个例子中,它们将被混合在一起,按照它们在链接器输入中找到的顺序出现。在第二个例子中,所有的‘.text’
输入段将首先出现,然后是所有的‘.rdata’
输入段。
When using EXCLUDE_FILE with more than one section, if the exclusion is within the section list then the exclusion only applies to the immediately following section, for example:
当使用EXCLUDE FILE命令并指定多个部分时,如果排除项在部分列表内,则排除仅适用于紧随其后的部分,例如:
*(EXCLUDE_FILE (*somefile.o) .text .rdata)
will cause all ‘.text’ sections from all files except somefile.o to be included, while all ‘.rdata’ sections from all files, including somefile.o, will be included. To exclude the ‘.rdata’ sections from somefile.o the example could be modified to:
将导致除了'somefile.o'
之外的所有文件中的'.text'
部分被包含,同时包括'somefile.o'
在内的所有文件的'.rdata'
部分也将被包含。要排除'somefile.o'
中的'.rdata'
部分,示例可以修改为:
*(EXCLUDE_FILE (*somefile.o) .text EXCLUDE_FILE (*somefile.o) .rdata)
Alternatively, placing the EXCLUDE_FILE outside of the section list, before the input file selection, will cause the exclusion to apply for all sections. Thus the previous example can be rewritten as:
或者,将排除文件放置在部分列表之外,在输入文件选择之前,将导致排除适用于所有部分。因此,前面的例子可以重写为:
EXCLUDE_FILE (*somefile.o) *(.text .rdata)
You can specify a file name to include sections from a particular file. You would do this if one or more of your files contain special data that needs to be at a particular location in memory. For example:
你可以指定一个文件名来包含来自特定文件的部分。如果你的一个或多个文件包含需要位于内存中特定位置的特殊数据,你会这样做。例如:
data.o(.data)
To refine the sections that are included based on the section flags of an input section, INPUT_SECTION_FLAGS may be used.
为了根据输入段的段标志细化包含的段部分,可以使用输入段标志。
Here is a simple example for using Section header flags for ELF sections:
这里有一个使用ELF节区标志的简单示例:
SECTIONS {
.text : { INPUT_SECTION_FLAGS (SHF_MERGE & SHF_STRINGS) *(.text) }
.text2 : { INPUT_SECTION_FLAGS (!SHF_WRITE) *(.text) }
}
In this example, the output section ‘.text’ will be comprised of any input section matching the name *(.text) whose section header flags SHF_MERGE and SHF_STRINGS are set. The output section ‘.text2’ will be comprised of any input section matching the name *(.text) whose section header flag SHF_WRITE is clear.
在这个例子中,输出部分“.text”
将由任何匹配名称*(.text)
且其节头标志SHF_MERGE
和SHF_STRINGS
被设置的输入部分组成。输出部分“.text2”
将由任何匹配名称*(.text)
且其节头标志SHF_WRITE
未设置的输入部分组成。
You can also specify files within archives by writing a pattern matching the archive, a colon, then the pattern matching the file, with no whitespace around the colon.
您也可以通过写一个匹配存档的模式,后面跟一个冒号,然后是匹配文件的模式,冒号周围不要有空格,来指定存档内的文件。
‘archive:file’
matches file within archive
存档的匹配文件
‘archive:’
matches the whole archive
匹配整个的归档
‘:file’
matches file but not one in an archive
匹配文件但不匹配存档中的一个
Either one or both of ‘archive’ and ‘file’ can contain shell wildcards. On DOS based file systems, the linker will assume that a single letter followed by a colon is a drive specifier, so ‘c:myfile.o’ is a simple file specification, not ‘myfile.o’ within an archive called ‘c’. ‘archive:file’ filespecs may also be used within an EXCLUDE_FILE list, but may not appear in other linker script contexts. For instance, you cannot extract a file from an archive by using ‘archive:file’ in an INPUT command.
“archive”
和“file”
中的任意一个或两者都可以包含shell通配符。在基于DOS的文件系统中,链接器会假定一个单独的字母后跟一个冒号是一个驱动器标识符,因此“c:myfile.o”
是一个简单的文件规范,而不是在名为“c”
的存档中的“myfile.o”
。也可以在EXCLUDE_FILE
列表中使用“archive:file”
文件规范,但它们可能不会出现在其他链接器脚本上下文中。例如,你不能通过在INPUT命令中使用“archive:file”
来从存档中提取文件。
If you use a file name without a list of sections, then all sections in the input file will be included in the output section. This is not commonly done, but it may by useful on occasion. For example:
如果你使用一个没有段列表的文件名,那么输入文件中的所有部分都将被包含在输出部分中。这不是通常的做法,但偶尔可能会有用。例如:
data.o
When you use a file name which is not an ‘archive:file’ specifier and does not contain any wild card characters, the linker will first see if you also specified the file name on the linker command line or in an INPUT command. If you did not, the linker will attempt to open the file as an input file, as though it appeared on the command line. Note that this differs from an INPUT command, because the linker will not search for the file in the archive search path.
当你使用一个不是“archive:file”
指定符且不包含任何通配符的文件名时,链接器首先会检查你是否也在链接器命令行或在INPUT命令中指定了该文件名。如果你没有这样做,链接器将尝试将该文件作为输入文件打开,就好像它出现在命令行上一样。请注意,这与INPUT命令不同,因为链接器不会在归档搜索路径中搜索该文件。
1.4.2 Input Section Wildcard Patterns
In an input section description, either the file name or the section name or both may be wildcard patterns.
在输入段描述中,文件名或部分名称或两者都可能是通配符模式。
The file name of ‘*’ seen in many examples is a simple wildcard pattern for the file name.
在许多示例中看到的‘*’
文件名是一个简单的文件名通配符模式。
The wildcard patterns are like those used by the Unix shell.
通配符模式类似于Unix shell所使用的模式。
- ‘*’
matches any number of characters 匹配任意数量的字符
- ‘?’
matches any single character 匹配一个单一的字符
- ‘[chars]’
matches a single instance of any of the chars; the ‘-’ character may be used to specify a range of characters, as in ‘[a-z]’ to match any lower case letter
匹配任意单个字符;可以使用‘-’
字符来指定一系列字符,如‘[a-z]’
来匹配任何小写字母。
- ‘\’
quotes the following character 引用以下字符
File name wildcard patterns only match files which are explicitly specified on the command line or in an INPUT command. The linker does not search directories to expand wildcards.
文件名通配符模式仅匹配在命令行或在INPUT命令中明确指定的文件。链接器不会搜索目录来扩展通配符。
If a file name matches more than one wildcard pattern, or if a file name appears explicitly and is also matched by a wildcard pattern, the linker will use the first match in the linker script. For example, this sequence of input section descriptions is probably in error, because the data.o rule will not be used:
如果文件名匹配多个通配符模式,或者文件名明确出现并且也被通配符模式匹配,链接器将使用链接器脚本中的第一个匹配项。例如,以下输入段描述序列可能有误,因为‘data.o’
规则将不会被使用:
.data : { *(.data) }
.data1 : { data.o(.data) }
Normally, the linker will place files and sections matched by wildcards in the order in which they are seen during the link. You can change this by using the SORT_BY_NAME keyword, which appears before a wildcard pattern in parentheses (e.g., SORT_BY_NAME(.text*)). When the SORT_BY_NAME keyword is used, the linker will sort the files or sections into ascending order by name before placing them in the output file.
通常情况下,链接器会按照在链接过程中遇到的顺序将匹配通配符的文件和段放置。你可以通过使用SORT_BY_NAME
关键字来改变这一顺序,该关键字出现在括号内的通配符模式之前(例如,SORT_BY_NAME(.text*)
)。当使用SORT_BY_NAME
关键字时,链接器会在将文件或段放入输出文件之前,按名称的升序对它们进行排序。
SORT_BY_ALIGNMENT is similar to SORT_BY_NAME. SORT_BY_ALIGNMENT will sort sections into descending order of alignment before placing them in the output file. Placing larger alignments before smaller alignments can reduce the amount of padding needed.
SORT_BY_ALIGNMENT
类似于 SORT_BY_NAME
。SORT_BY_ALIGNMENT
会先将部分按照对齐度降序排序,然后再将它们放入输出文件中。将较大的对齐度放在前面可以减少所需的填充量。
SORT_BY_INIT_PRIORITY is also similar to SORT_BY_NAME. SORT_BY_INIT_PRIORITY will sort sections into ascending numerical order of the GCC init_priority attribute encoded in the section name before placing them in the output file. In .init_array.NNNNN and .fini_array.NNNNN, NNNNN is the init_priority. In .ctors.NNNNN and .dtors.NNNNN, NNNNN is 65535 minus the init_priority.
SORT_BY_INIT_PRIORITY 与 SORT_BY_NAME 类似。SORT_BY_INIT_PRIORITY 会根据节名称中编码的 GCC 初始化优先级属性将节排序为升序数值顺序,然后再将它们放置到输出文件中。在 .init_array.NNNNN
和 .fini_array.NNNNN
中,NNNNN
是初始化优先级。在 .ctors.NNNNN
和 .dtors.NNNNN
中,NNNNN
是 65535
减去初始化优先级。
SORT is an alias for SORT_BY_NAME.
SORT
是SORT_BY_NAME
的别名。
When there are nested section sorting commands in linker script, there can be at most 1 level of nesting for section sorting commands.
当链接脚本中有嵌套的段排序命令时,段排序命令最多只能嵌套1层。
- SORT_BY_NAME (SORT_BY_ALIGNMENT (wildcard section pattern)). It will sort the input sections by name first, then by alignment if two sections have the same name.
SORT_BY_NAME (SORT_BY_ALIGNMENT (通配符部分模式))
. 它会首先按名称对输入部分进行排序,如果两个部分名称相同,则按对齐方式排序。 - SORT_BY_ALIGNMENT (SORT_BY_NAME (wildcard section pattern)). It will sort the input sections by alignment first, then by name if two sections have the same alignment.
SORT_BY_ALIGNMENT (SORT_BY_NAME (通配符部分模式))
。它会首先按对齐方式对输入的部分进行排序,如果两个部分对齐方式相同,则按名称排序。 - SORT_BY_NAME (SORT_BY_NAME (wildcard section pattern)) is treated the same as SORT_BY_NAME (wildcard section pattern).
SORT_BY_NAME (SORT_BY_NAME (wildcard section pattern))
被视为与SORT_BY_NAME (wildcard section pattern)
相同。 - SORT_BY_ALIGNMENT (SORT_BY_ALIGNMENT (wildcard section pattern)) is treated the same as SORT_BY_ALIGNMENT (wildcard section pattern).
SORT_BY_ALIGNMENT (SORT_BY_ALIGNMENT (通配符部分模式))
被视为与SORT_BY_ALIGNMENT (通配符部分模式)
相同。 - All other nested section sorting commands are invalid.
所有其他嵌套的节排序命令都是无效的。
When both command-line section sorting option and linker script section sorting command are used, section sorting command always takes precedence over the command-line option.
当同时使用命令行部分排序选项和链接器脚本部分排序命令时,部分排序命令总是优先于命令行选项。
If the section sorting command in linker script isn’t nested, the command-line option will make the section sorting command to be treated as nested sorting command.
如果链接脚本中的段排序命令没有嵌套,那么命令行选项将使段排序命令被视为嵌套排序命令。
- SORT_BY_NAME (wildcard section pattern ) with --sort-sections alignment is equivalent to SORT_BY_NAME SORT_BY_ALIGNMENT (wildcard section pattern)).
SORT_BY_NAME(通配符部分模式)
与‘--sort-sections alignment’
等效于SORT_BY_NAME(SORT_BY_ALIGNMENT(通配符部分模式))
。 SORT_BY_ALIGNMENT (wildcard section pattern)
with--sort-section
name is equivalent toSORT_BY_ALIGNMENT (SORT_BY_NAME (wildcard section pattern))
.
SORT_BY_ALIGNMENT (通配符部分模式)
与‘--sort-section name’
等价于SORT_BY_ALIGNMENT (SORT_BY_NAME (通配符部分模式))
。
If the section sorting command in linker script is nested, the command-line option will be ignored.
如果链接器脚本中的段排序命令是嵌套的,那么命令行选项将被忽略。
SORT_NONE disables section sorting by ignoring the command-line section sorting option.
SORT_NONE 禁用通过忽略命令行部分排序选项来实现的部分排序。
If you ever get confused about where input sections are going, use the ‘-M’ linker option to generate a map file. The map file shows precisely how input sections are mapped to output sections.
如果你对输入部分的去向感到困惑,可以使用‘-M’
链接器选项生成一个映射文件。映射文件会精确显示输入部分是如何映射到输出部分的。
This example shows how wildcard patterns might be used to partition files. This linker script directs the linker to place all ‘.text’ sections in ‘.text’ and all ‘.bss’ sections in ‘.bss’. The linker will place the ‘.data’ section from all files beginning with an upper case character in ‘.DATA’; for all other files, the linker will place the ‘.data’ section in ‘.data’.
本例展示了如何使用通配符模式来分割文件。此链接脚本指示链接程序将所有“.text ”
部分放入“.text”
,将所有“.bss ”
部分放入“.bss”
。链接器将把所有文件中以大写字母开头的“.data ”
部分放在“.DATA ”
中;对于所有其他文件,链接器将把“.data ”
部分放在“.data ”
中。
SECTIONS {
.text : { *(.text) }
.DATA : { [A-Z]*(.data) }
.data : { *(.data) }
.bss : { *(.bss) }
}
1.4.3 Input Section for Common Symbols
A special notation is needed for common symbols, because in many object file formats common symbols do not have a particular input section. The linker treats common symbols as though they are in an input section named ‘COMMON’.
需要一种特殊的符号表示法来表示常见的符号,因为在许多目标文件格式中,常见的符号并没有特定的输入段。链接器将常见的符号视为它们位于一个名为‘COMMON’
的输入段中。
You may use file names with the ‘COMMON’ section just as with any other input sections. You can use this to place common symbols from a particular input file in one section while common symbols from other input files are placed in another section.
你可以像使用任何其他输入部分一样使用带有“COMMON”
部分的文件名。你可以用这个方法将特定输入文件中的通用符号放在一个部分,而将其他输入文件中的通用符号放在另一个部分。
In most cases, common symbols in input files will be placed in the ‘.bss’ section in the output file. For example:
在大多数情况下,输入文件中的常见符号会被放置在输出文件的‘.bss’
部分。例如:
.bss { *(.bss) *(COMMON) }
Some object file formats have more than one type of common symbol. For example, the MIPS ELF object file format distinguishes standard common symbols and small common symbols. In this case, the linker will use a different special section name for other types of common symbols. In the case of MIPS ELF, the linker uses ‘COMMON’ for standard common symbols and ‘.scommon’ for small common symbols. This permits you to map the different types of common symbols into memory at different locations.
一些目标文件格式具有多种类型的常见符号。例如,MIPS ELF目标文件格式区分标准常见符号和小型常见符号。在这种情况下,链接器将为其他类型的常见符号使用不同的特殊节名称。在MIPS ELF的情况下,链接器使用'COMMON'
用于标准常见符号,使用'.scommon'
用于小型常见符号。这允许你将不同类型的常见符号映射到内存的不同位置。
You will sometimes see ‘[COMMON]’ in old linker scripts. This notation is now considered obsolete. It is equivalent to ‘*(COMMON)’.
在旧的链接脚本中,你有时会看到‘[COMMON]’
这样的标记。这种表示法现在被认为是过时的。它等同于‘*(COMMON)’
。
1.4.4 Input Section and Garbage Collection
When link-time garbage collection is in use (‘–gc-sections’), it is often useful to mark sections that should not be eliminated. This is accomplished by surrounding an input section’s wildcard entry with KEEP(), as in KEEP((.init)) or KEEP(SORT_BY_NAME()(.ctors)).
当使用链接时垃圾收集(‘--gc-sections’)
时,通常很有用标记不应该被消除的节。这可以通过用KEEP()
包围输入节的通配符条目来实现,例如KEEP(*(.init))
或KEEP(SORT_BY_NAME(*)(.ctors))
。
1.4.5 Input Section Example
The following example is a complete linker script. It tells the linker to read all of the sections from file all.o and place them at the start of output section ‘outputa’ which starts at location ‘0x10000’. All of section ‘.input1’ from file foo.o follows immediately, in the same output section. All of section ‘.input2’ from foo.o goes into output section ‘outputb’, followed by section ‘.input1’ from foo1.o. All of the remaining ‘.input1’ and ‘.input2’ sections from any files are written to output section ‘outputc’.
以下示例是一个完整的链接器脚本。它指示链接器读取文件‘all.o’
中的所有节,并将它们放置在输出节‘outputa’
的开始处,该节从位置‘0x10000’
开始。紧接着,文件‘foo.o’
中的所有‘.input1’
节紧随其后,位于同一个输出节中。来自‘foo.o’
的所有‘.input2’
节被放入输出节‘outputb’
,后面跟着来自‘foo1.o’
的‘.input1’
节。任何文件中剩余的‘.input1’
和‘.input2’
节都被写入输出节‘outputc’
。
SECTIONS {
outputa 0x10000 :
{
all.o
foo.o (.input1)
}
outputb :
{
foo.o (.input2)
foo1.o (.input1)
}
outputc :
{
*(.input1)
*(.input2)
}
}
If an output section’s name is the same as the input section’s name and is representable as a C identifier, then the linker will automatically see PROVIDE two symbols: __start_SECNAME and __stop_SECNAME, where SECNAME is the name of the section. These indicate the start address and end address of the output section respectively. Note: most section names are not representable as C identifiers because they contain a ‘.’
character.
如果输出段的名称与输入段的名称相同,并且可以表示为C标识符,那么链接器将自动识别两个符号:__start_SECNAME
和__stop_SECNAME
,其中SECNAME是该段的名称。这些分别表示输出段的起始地址和结束地址。注意:大多数段名称不能表示为C标识符,因为它们包含一个'.'
字符。
1.5 Output Section Data
You can include explicit bytes of data in an output section by using BYTE, SHORT, LONG, QUAD, or SQUAD as an output section command. Each keyword is followed by an expression in parentheses providing the value to store (see Expressions in Linker Scripts). The value of the expression is stored at the current value of the location counter.
您可以通过使用BYTE、SHORT、LONG、QUAD或SQUAD作为输出段的命令,将明确的数据字节包含在输出段中。每个关键字后面都跟着一个括号内的表达式,提供要存储的值(请参阅链接器脚本中的表达式)。表达式的值存储在位置计数器的当前值处。
The BYTE, SHORT, LONG, and QUAD commands store one, two, four, and eight bytes (respectively). After storing the bytes, the location counter is incremented by the number of bytes stored.
BYTE, SHORT, LONG 和 QUAD 命令分别存储一个、两个、四个和八个字节。存储完字节后,位置计数器会根据存储的字节数增加相应的数值。
For example, this will store the byte 1 followed by the four byte value of the symbol ‘addr’:
例如,这将存储一个字节1,后面跟着符号‘addr’的四个字节值:
BYTE(1)
LONG(addr)
When using a 64 bit host or target, QUAD and SQUAD are the same; they both store an 8 byte, or 64 bit, value. When both host and target are 32 bits, an expression is computed as 32 bits. In this case QUAD stores a 32 bit value zero extended to 64 bits, and SQUAD stores a 32 bit value sign extended to 64 bits.
当使用64位主机或目标机时,QUAD和SQUAD是相同的;它们都存储一个8字节或64位的值。当主机和目标都是32位时,表达式被计算为32位。在这种情况下,QUAD存储一个扩展到64位的32位值(零扩展),而SQUAD存储一个符号扩展到64位的32位值。
If the object file format of the output file has an explicit endianness, which is the normal case, the value will be stored in that endianness. When the object file format does not have an explicit endianness, as is true of, for example, S-records, the value will be stored in the endianness of the first input object file.
如果输出文件的对象文件格式具有明确的字节序(通常是这种情况),则值将按照该字节序存储。当对象文件格式没有明确的字节序时,例如,S-records,值将按照第一个输入对象文件的字节序存储。
Note—these commands only work inside a section description and not between them, so the following will produce an error from the linker:
注意——这些命令只在段描述内部有效,而不能在它们之间使用,因此以下内容将导致链接器产生错误:
SECTIONS { .text : { *(.text) } LONG(1) .data : { *(.data) } }
whereas this will work:
然而这将会起作用:
SECTIONS { .text : { *(.text) ; LONG(1) } .data : { *(.data) } }
You may use the FILL command to set the fill pattern for the current section. It is followed by an expression in parentheses. Any otherwise unspecified regions of memory within the section (for example, gaps left due to the required alignment of input sections) are filled with the value of the expression, repeated as necessary. A FILL statement covers memory locations after the point at which it occurs in the section definition; by including more than one FILL statement, you can have different fill patterns in different parts of an output section.
你可以使用FILL命令来设置当前段的填充模式。它后面跟着一个括号内的表达式。段内任何未明确指定的内存区域(例如,由于输入段所需的对齐而留下的间隙)都会用表达式的值填充,必要时重复该值。FILL语句覆盖了在节定义中出现该语句之后的内存位置;通过包含多个FILL语句,你可以在输出节的不同部分设置不同的填充模式。
This example shows how to fill unspecified regions of memory with the value ‘0x90’:
这个例子展示了如何用值‘0x90’
填充内存中未指定的区域:
FILL(0x90909090)
The FILL command is similar to the ‘=fillexp’ output section attribute, but it only affects the part of the section following the FILL command, rather than the entire section. If both are used, the FILL command takes precedence. See Output Section Fill, for details on the fill expression.
FILL
命令类似于‘=fillexp’
输出部分属性,但它只影响FILL
命令之后的部分,而不是整个部分。如果两者都使用,FILL
命令优先。有关填充表达式的详细信息,请参阅输出段填充。
1.6 Output Section Keywords
There are a couple of keywords which can appear as output section commands.
有几个关键词可以作为输出段的命令出现。
- CREATE_OBJECT_SYMBOLS
The command tells the linker to create a symbol for each input file. The name of each symbol will be the name of the corresponding input file. The section of each symbol will be the output section in which the CREATE_OBJECT_SYMBOLS command appears.
该命令指示链接器为每个输入文件创建一个符号。每个符号的名称将是相应输入文件的名称。每个符号的部分将是CREATE_OBJECT_SYMBOLS
命令出现的输出部分。
This is conventional for the a.out object file format. It is not normally used for any other object file format.
这是a.out
对象文件格式的常规做法。它通常不用于其他任何对象文件格式。
- CONSTRUCTORS
When linking using the a.out object file format, the linker uses an unusual set construct to support C++ global constructors and destructors. When linking object file formats which do not support arbitrary sections, such as ECOFF and XCOFF, the linker will automatically recognize C++ global constructors and destructors by name. For these object file formats, the CONSTRUCTORS command tells the linker to place constructor information in the output section where the CONSTRUCTORS command appears. The CONSTRUCTORS command is ignored for other object file formats.
当使用a.out对象文件格式进行链接时,链接器使用了一种不寻常的构造集来支持C++全局构造函数和析构函数。当链接不支持任意节的对象文件格式,如ECOFF
和XCOFF
时,链接器将通过名称自动识别C++全局构造函数和析构函数。对于这些对象文件格式,CONSTRUCTORS
命令告诉链接器将构造函数信息放置在CONSTRUCTORS
命令出现的输出节中。对于其他对象文件格式,CONSTRUCTORS
命令将被忽略。
The symbol __CTOR_LIST__
marks the start of the global constructors, and the symbol __CTOR_END__
marks the end. Similarly, __DTOR_LIST__
and __DTOR_END__
mark the start and end of the global destructors. The first word in the list is the number of entries, followed by the address of each constructor or destructor, followed by a zero word. The compiler must arrange to actually run the code. For these object file formats GNU C++ normally calls constructors from a subroutine __main; a call to __main is automatically inserted into the startup code for main. GNU C++ normally runs destructors either by using atexit, or directly from the function exit.
符号__CTOR_LIST__
标志着全局构造函数的开始,而符号__CTOR_END__
标志着结束。同样地,__DTOR_LIST__
和__DTOR_END__
分别标志着全局析构函数的开始和结束。列表中的第一个词是条目数量,后面跟着每个构造函数或析构函数的地址,最后是一个零字。编译器必须安排实际运行代码。对于这些目标文件格式,GNU C++通常通过一个名为__main
的子程序调用构造函数;在main
的启动代码中自动插入对__main
的调用。GNU C++通常通过使用atexit
或者直接从函数exit
中运行析构函数。
For object file formats such as COFF or ELF which support arbitrary section names, GNU C++ will normally arrange to put the addresses of global constructors and destructors into the .ctors and .dtors sections. Placing the following sequence into your linker script will build the sort of table which the GNU C++ runtime code expects to see.
对于支持任意节名的对象文件格式,如COFF
或ELF
,GNU C++通常会安排将全局构造函数和析构函数的地址放入.ctors
和.dtors
节中。在你的链接脚本中加入以下序列,将构建出GNU C++运行时代码所期望看到的那种表。
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
If you are using the GNU C++ support for initialization priority, which provides some control over the order in which global constructors are run, you must sort the constructors at link time to ensure that they are executed in the correct order. When using the CONSTRUCTORS command, use ‘SORT_BY_NAME(CONSTRUCTORS)’ instead. When using the .ctors and .dtors sections, use ‘(SORT_BY_NAME(.ctors))’ and ‘(SORT_BY_NAME(.dtors))’ instead of just ‘(.ctors)’ and ‘(.dtors)’.
如果你正在使用GNU C++支持的初始化优先级,它提供了一些控制全局构造函数运行顺序的功能,你必须在链接时对构造函数进行排序,以确保它们按照正确的顺序执行。当使用CONSTRUCTORS
命令时,使用‘SORT_BY_NAME(CONSTRUCTORS)’
代替。当使用.ctors
和.dtors
段时,使用‘*(SORT_BY_NAME(.ctors))
’和‘*(SORT_BY_NAME(.dtors))
’代替仅仅‘*(.ctors)
’和‘*(.dtors)
’。
Normally the compiler and linker will handle these issues automatically, and you will not need to concern yourself with them. However, you may need to consider this if you are using C++ and writing your own linker scripts.
通常编译器和链接器会自动处理这些问题,你不需要担心它们。然而,如果你正在使用C++并且编写自己的链接器脚本,你可能需要考虑这个问题。
1.7 Output Section Discarding
The linker will not normally create output sections with no contents. This is for convenience when referring to input sections that may or may not be present in any of the input files. For example:
链接器通常不会创建没有内容的输出段。这样做是为了方便引用可能存在于任何输入文件中或不存在的输入段。
例如:
.foo : { *(.foo) }
will only create a ‘.foo’ section in the output file if there is a ‘.foo’ section in at least one input file, and if the input sections are not all empty. Other link script directives that allocate space in an output section will also create the output section. So too will assignments to dot even if the assignment does not create space, except for ‘. = 0’, ‘. = . + 0’, ‘. = sym’, ‘. = . + sym’ and ‘. = ALIGN (. != 0, expr, 1)’ when ‘sym’ is an absolute symbol of value 0 defined in the script. This allows you to force output of an empty section with ‘. = .’.
只有当至少有一个输入文件中存在“.foo”
节,并且输入节不全为空时,链接脚本才会在输出文件中创建一个“.foo”
节。其他在输出节中分配空间的链接脚本指令也会创建输出节。对点(dot)
的赋值也会创建输出节,即使赋值不创建空间,但以下情况除外:‘.= 0’
、‘.= . + 0’
、‘.= sym’
、‘.= . + sym’
以及当‘sym’
是在脚本中定义的值为0的绝对符号时的‘.= ALIGN (. != 0, expr, 1)’
。这允许你使用‘.= .’
强制输出一个空节。
The linker will ignore address assignments (see Output Section Address) on discarded output sections, except when the linker script defines symbols in the output section. In that case the linker will obey the address assignments, possibly advancing dot even though the section is discarded.
链接器将忽略被丢弃的输出段上的地址分配(请参阅输出部分地址),除非链接器脚本在输出部分中定义了符号。在这种情况下,链接器将遵守地址分配,即使该部分已被丢弃,也可能将点向前推进。
The special output section name ‘/DISCARD/’ may be used to discard input sections. Any input sections which are assigned to an output section named ‘/DISCARD/’ are not included in the output file.
特殊的输出部分名称“/DISCARD/”
可用于丢弃输入部分。任何分配给名为“/DISCARD/”
的输出部分的输入部分都不会包含在输出文件中。
This can be used to discard input sections marked with the ELF flag SHF_GNU_RETAIN, which would otherwise have been saved from linker garbage collection.
这可以用来丢弃标有 ELF 标志 SHF_GNU_RETAIN
的输入部分,否则这些部分就可以从链接器垃圾收集中保存下来。
Note, sections that match the ‘/DISCARD/’ output section will be discarded even if they are in an ELF section group which has other members which are not being discarded. This is deliberate. Discarding takes precedence over grouping.
请注意,与“/DISCARD/”
输出部分相匹配的部分将被丢弃,即使它们位于 ELF 段组中,而该部分组中还有其他未被丢弃的成员。这是有意为之。丢弃优先于分组。
1.8 Output Section Attributes
We showed above that the full description of an output section looked like this:
我们上面展示了输出部分的完整描述如下:
section [address] [(type)] :
[AT(lma)]
[ALIGN(section_align) | ALIGN_WITH_INPUT]
[SUBALIGN(subsection_align)]
[constraint]
{
output-section-command
output-section-command
…
} [>region] [AT>lma_region] [:phdr :phdr …] [=fillexp]
We’ve already described section, address, and output-section-command. In this section we will describe the remaining section attributes.
我们已经描述了节(section)、地址(address)和输出节命令(output-section-command)。在本节中,我们将描述剩余的节属性。
- Output Section Type
- Output Section LMA
- Forced Output Alignment
- Forced Input Alignment
- Output Section Constraint
- Output Section Region
- Output Section Phdr
- Output Section Fill
1.8.1 Output Section Type
Each output section may have a type. The type is a keyword in parentheses. The following types are defined:
每个输出部分可能有一个类型。类型是在括号中的关键词。以下是定义的类型:
- NOLOAD The section should be marked as not loadable, so that it will not be loaded into memory when the program is run.
该部分应标记为不可加载,以便在程序运行时不会加载到内存中。 - READONLY The section should be marked as read-only.
该部分应标记为只读。 - DSECT
- COPY
- INFO
- OVERLAY These type names are supported for backward compatibility, and are rarely used. They all have the same effect: the section should be marked as not allocatable, so that no memory is allocated for the section when the program is run.
这些类型名称是为了向后兼容性而支持的,很少使用。它们都有相同的效果:应该将该部分标记为不可分配,这样当程序运行时,就不会为该部分分配任何内存。 - TYPE = type Set the section type to the integer type. When generating an ELF output file, type names SHT_PROGBITS, SHT_STRTAB, SHT_NOTE, SHT_NOBITS, SHT_INIT_ARRAY, SHT_FINI_ARRAY, and SHT_PREINIT_ARRAY are also allowed for type. It is the user’s responsibility to ensure that any special requirements of the section type are met.
将部分类型设置为整数类型。在生成 ELF 输出文件时,还允许使用SHT_PROGBITS
、SHT_STRTAB
、SHT_NOTE
、SHT_NOBITS
、SHT_INIT_ARRAY
、SHT_FINI_ARRAY
和SHT_PREINIT_ARRAY
等类型名称。用户有责任确保满足章节类型的任何特殊要求。
Note - the TYPE only is used if some or all of the contents of the section do not have an implicit type of their own. So for example:
注意:只有在部分或全部内容本身没有隐式类型时,才会使用 TYPE
。例如
.foo . TYPE = SHT_PROGBITS { *(.bar) }
will set the type of section ‘.foo’ to the type of the section ‘.bar’ in the input files, which may not be the SHT_PROGBITS type. Whereas:
会将“.foo ”
部分的类型设置为输入文件中“.bar ”
部分的类型,而“.bar ”
部分可能不是 SHT_PROGBITS
类型。而
.foo . TYPE = SHT_PROGBITS { BYTE(1) }
will set the type of ‘.foo’ to SHT_PROGBBITS. If it is necessary to override the type of incoming sections and force the output section type then an extra piece of untyped data will be needed:
将把“.foo ”
的类型设置为 SHT_PROGBBITS
。如果需要覆盖输入节的类型并强制输出节的类型,则需要额外的非类型数据:
.foo . TYPE = SHT_PROGBITS { BYTE(1); *(.bar) }
- READONLY ( TYPE = type )
This form of the syntax combines the READONLY type with the type specified by type.
这种语法形式结合了 READONLY
类型和 type 指定的类型。
The linker normally sets the attributes of an output section based on the input sections which map into it. You can override this by using the section type. For example, in the script sample below, the ‘ROM’ section is addressed at memory location ‘0’ and does not need to be loaded when the program is run.
链接器通常会根据映射到输出段的输入段来设置输出段的属性。你可以通过使用部分类型来覆盖这一点。例如,在下面的脚本示例中,“ROM ”
部分的地址位于内存位置 “0”
,程序运行时无需加载。
SECTIONS {
ROM 0 (NOLOAD) : { … }
…
}
1.8.2 Output Section LMA
Every section has a virtual address (VMA) and a load address (LMA); see Basic Linker Script Concepts. The virtual address is specified by the see Output Section Address described earlier. The load address is specified by the AT or AT> keywords. Specifying a load address is optional.
每个部分都有一个虚拟地址 (VMA)
和一个加载地址 (LMA)
;请参阅链接器脚本基本概念。虚拟地址由前面描述的输出段地址指定。加载地址由 AT
或 AT>
关键字指定。指定加载地址是可选的。
The AT keyword takes an expression as an argument. This specifies the exact load address of the section. The AT> keyword takes the name of a memory region as an argument. See MEMORY Command. The load address of the section is set to the next free address in the region, aligned to the section’s alignment requirements.
AT
关键字的参数是一个表达式。该表达式指定段的确切加载地址
。AT>
关键字将内存区域的名称作为参数。请参阅 MEMORY
命令。段的加载地址将设置为该区域的下一个空闲地址,并按照段的对齐要求对齐。
- If neither AT nor AT> is specified for an allocatable section, the linker will use the following heuristic to determine the load address:
如果没有为可分配区段指定AT
或AT>
,链接程序将使用以下启发式方法确定加载地址: - If the section has a specific VMA address, then this is used as the LMA address as well.
如果区段有特定的 VMA 地址,则该地址也将用作 LMA 地址。 - If the section is not allocatable then its LMA is set to its VMA.
如果段不可分配,则其 LMA 设置为其 VMA。 - Otherwise if a memory region can be found that is compatible with the current section, and this region contains at least one section, then the LMA is set so the difference between the VMA and LMA is the same as the difference between the VMA and LMA of the last section in the located region.
否则,如果能找到与当前区段兼容的内存区域,且该区域至少包含一个区段,则设置LMA
,使VMA
与LMA
之间的差值与定位区域中最后一个区段的VMA
与LMA
之间的差值相同。 - If no memory regions have been declared then a default region that covers the entire address space is used in the previous step.
如果没有声明内存区域,则在上一步中使用覆盖整个地址空间的默认区域。 - If no suitable region could be found, or there was no previous section then the LMA is set equal to the VMA.
如果找不到合适的区域,或者没有前一个区段,则LMA
设置为等于VMA
。
This feature is designed to make it easy to build a ROM image. For example, the following linker script creates three output sections: one called ‘.text’, which starts at 0x1000, one called ‘.mdata’, which is loaded at the end of the ‘.text’ section even though its VMA is 0x2000, and one called ‘.bss’ to hold uninitialized data at address 0x3000. The symbol _data is defined with the value 0x2000, which shows that the location counter holds the VMA value, not the LMA value.
该功能旨在简化 ROM 映像的制作。例如,下面的链接器脚本创建了三个输出部分:一个名为“.text”
,起始地址为 0x1000
;一个名为“.mdata”
,加载到“.text ”
部分的末尾,尽管其 VMA
为 0x2000
;一个名为“.bss”
,用于保存未初始化的数据,地址为 0x3000
。符号 _data
的定义值为 0x2000
,这表明位置计数器保存的是 VMA
值,而不是 LMA
值。
SECTIONS
{
.text 0x1000 : { *(.text) _etext = . ; }
.mdata 0x2000 :
AT ( ADDR (.text) + SIZEOF (.text) )
{ _data = . ; *(.data); _edata = . ; }
.bss 0x3000 :
{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;}
}
The run-time initialization code for use with a program generated with this linker script would include something like the following, to copy the initialized data from the ROM image to its runtime address. Notice how this code takes advantage of the symbols defined by the linker script.
使用此链接器脚本生成的程序的运行时初始化代码将包括如下内容,将初始化数据从 ROM 映像复制到运行时地址。注意这段代码是如何利用链接器脚本定义的符号的。
extern char _etext, _data, _edata, _bstart, _bend;
char *src = &_etext;
char *dst = &_data;
/* ROM has data at end of text; copy it. */
while (dst < &_edata)
*dst++ = *src++;
/* Zero bss. */
for (dst = &_bstart; dst< &_bend; dst++)
*dst = 0;
1.8.3 Forced Output Alignment
You can increase an output section’s alignment by using ALIGN. As an alternative you can enforce that the difference between the VMA and LMA remains intact throughout this output section with the ALIGN_WITH_INPUT attribute.
您可以使用 ALIGN
增加输出部分的对齐方式。另外,您还可以使用 ALIGN_WITH_INPUT
属性强制 VMA
和 LMA
之间的差异在整个输出部分保持不变。
1.8.4 Forced Input Alignment
You can force input section alignment within an output section by using SUBALIGN. The value specified overrides any alignment given by input sections, whether larger or smaller.
您可以使用 SUBALIGN
在输出部分中强制输入段对齐。指定的值会覆盖输入段提供的任何对齐方式,无论其大小。
1.8.5 Output Section Constraint
You can specify that an output section should only be created if all of its input sections are read-only or all of its input sections are read-write by using the keyword ONLY_IF_RO and ONLY_IF_RW respectively.
您可以分别使用关键字 ONLY_IF_RO
和 ONLY_IF_RW
,指定只有在输出段的所有输入段都是只读或所有输入段都是读写时,才创建输出部分。
1.8.6 Output Section Region
You can assign a section to a previously defined region of memory by using ‘>region’. See MEMORY Command.
您可以使用“>区域 ”
将某个部分分配给先前定义的内存区域。请参阅 MEMORY
命令。
Here is a simple example:
下面是一个简单的示例:
MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 }
SECTIONS { ROM : { *(.text) } >rom }
1.8.7 Output Section Phdr
You can assign a section to a previously defined program segment by using ‘:phdr’. See PHDRS Command. If a section is assigned to one or more segments, then all subsequent allocated sections will be assigned to those segments as well, unless they use an explicitly :phdr modifier. You can use :NONE to tell the linker to not put the section in any segment at all.
您可以使用“:phdr ”
将一个部分分配给先前定义的程序段。请参阅 PHDRS
命令。如果一个程序段被分配到一个或多个程序段,那么所有后续分配的程序段也将被分配到这些程序段,除非它们明确使用 :phdr
修饰符。您可以使用 :NONE
命令告诉链接器不要将该段放在任何段中。
Here is a simple example:
下面是一个简单的示例:
PHDRS { text PT_LOAD ; }
SECTIONS { .text : { *(.text) } :text }
1.8.8 Output Section Fill
You can set the fill pattern for an entire section by using ‘=fillexp’. fillexp is an expression (see Expressions in Linker Scripts). Any otherwise unspecified regions of memory within the output section (for example, gaps left due to the required alignment of input sections) will be filled with the value, repeated as necessary. If the fill expression is a simple hex number, ie. a string of hex digit starting with ‘0x’ and without a trailing ‘k’ or ‘M’, then an arbitrarily long sequence of hex digits can be used to specify the fill pattern; Leading zeros become part of the pattern too. For all other cases, including extra parentheses or a unary +, the fill pattern is the four least significant bytes of the value of the expression. In all cases, the number is big-endian.
您可以使用“=fillexp ”
设置整个部分的填充模式。fillexp 是一个表达式(请参阅链接脚本中的表达式)。输出部分中任何未指定的内存区域(例如,由于输入段需要对齐而留下的间隙)都将用该值填充,必要时还会重复。如果填充表达式是一个简单的十六进制数,即以 “0x ”开头的十六进制数字字符串,且没有尾部的 “k ”或 “M”,那么可以使用任意长的十六进制数字序列来指定填充模式;前导零也会成为模式的一部分。在所有其他情况下,包括额外的括号或一元 +,填充模式是表达式值的四个最小有效字节。在所有情况下,数字都是大端模式。
You can also change the fill value with a FILL command in the output section commands; (see Output Section Data).
您还可以使用输出段命令中的 FILL 命令更改填充值(请参阅输出部分数据)。
Here is a simple example:
下面是一个简单的示例:
SECTIONS { .text : { *(.text) } =0x90909090 }
1.9 Overlay Description
An overlay description provides an easy way to describe sections which are to be loaded as part of a single memory image but are to be run at the same memory address. At run time, some sort of overlay manager will copy the overlaid sections in and out of the runtime memory address as required, perhaps by simply manipulating addressing bits. This approach can be useful, for example, when a certain region of memory is faster than another.
覆盖描述提供了一种简便的方法来描述作为单个内存映像的一部分加载但在同一内存地址运行的部分。在运行时,某种覆盖管理器会根据需要将覆盖部分复制到运行时内存地址中或从运行时内存地址中复制出来,也许只需操作寻址位即可。例如,当某个内存区域的运行速度比另一个内存区域快时,这种方法就非常有用。
Overlays are described using the OVERLAY command. The OVERLAY command is used within a SECTIONS command, like an output section description. The full syntax of the OVERLAY command is as follows:
叠加使用 OVERLAY
命令进行描述。OVERLAY
命令在 SECTIONS
命令中使用,就像输出段描述一样。OVERLAY
命令的完整语法如下:
OVERLAY [start] : [NOCROSSREFS] [AT ( ldaddr )]
{
secname1
{
output-section-command
output-section-command
…
} [:phdr…] [=fill]
secname2
{
output-section-command
output-section-command
…
} [:phdr…] [=fill]
…
} [>region] [:phdr…] [=fill] [,]
Everything is optional except OVERLAY (a keyword), and each section must have a name (secname1 and secname2 above). The section definitions within the OVERLAY construct are identical to those within the general SECTIONS construct (see SECTIONS Command), except that no addresses and no memory regions may be defined for sections within an OVERLAY.
除了 OVERLAY(关键字)外,其他都是可选的,每个部分都必须有一个名称(上面的 secname1 和 secname2)。OVERLAY 结构中的部分定义与一般 SECTIONS 结构中的部分定义相同(参见 SECTIONS 命令),但 OVERLAY 结构中的部分不能定义地址和内存区域。
The comma at the end may be required if a fill is used and the next sections-command looks like a continuation of the expression.
如果使用了填充,且下一个章节命令看起来像是表达式的延续,则可能需要在末尾使用逗号。
The sections are all defined with the same starting address. The load addresses of the sections are arranged such that they are consecutive in memory starting at the load address used for the OVERLAY as a whole (as with normal section definitions, the load address is optional, and defaults to the start address; the start address is also optional, and defaults to the current value of the location counter).
所有分段都以相同的起始地址定义。各部分的加载地址是这样安排的:从整个 OVERLAY 使用的加载地址开始,它们在内存中是连续的(与正常的部分定义一样,加载地址是可选的,默认为起始地址;起始地址也是可选的,默认为位置计数器的当前值)。
If the NOCROSSREFS keyword is used, and there are any references among the sections, the linker will report an error. Since the sections all run at the same address, it normally does not make sense for one section to refer directly to another. See NOCROSSREFS.
如果使用了 NOCROSSREFS
关键字,且各部分之间存在任何引用,链接器将报错。由于各部分都在同一地址运行,因此一个部分直接引用另一个部分通常是不合理的。参见 NOCROSSREFS
。
For each section within the OVERLAY, the linker automatically provides two symbols. The symbol __load_start_secname is defined as the starting load address of the section. The symbol __load_stop_secname is defined as the final load address of the section. Any characters within secname which are not legal within C identifiers are removed. C (or assembler) code may use these symbols to move the overlaid sections around as necessary.
对于 OVERLAY
中的每个部分,链接器都会自动提供两个符号。符号 __load_start_secname
被定义为该部分的起始加载地址。符号 __load_stop_secname
被定义为该部分的最终加载地址。secname
中任何不符合 C 语言标识符的字符都将被删除。C 语言(或汇编语言)代码可根据需要使用这些符号移动重叠部分。
At the end of the overlay, the value of the location counter is set to the start address of the overlay plus the size of the largest section.
在叠加结束时,位置计数器的值将被设置为叠加的起始地址加上最大部分的大小。
Here is an example. Remember that this would appear inside a SECTIONS construct.
下面是一个示例。请记住,这将出现在 SECTIONS
结构中。
OVERLAY 0x1000 : AT (0x4000)
{
.text0 { o1/*.o(.text) }
.text1 { o2/*.o(.text) }
}
This will define both ‘.text0’ and ‘.text1’ to start at address 0x1000. ‘.text0’ will be loaded at address 0x4000, and ‘.text1’ will be loaded immediately after ‘.text0’. The following symbols will be defined if referenced: __load_start_text0, __load_stop_text0, __load_start_text1, __load_stop_text1.
这样,“.text0 ”
和“.text1 ”
都将从地址 0x1000
开始。.text0 “
将加载到地址 0x4000,”.text1 “
将紧接着”.text0 "
加载。如果引用,将定义以下符号: __load_start_text0
、__load_stop_text0
、__load_start_text1
、__load_stop_text1
。
C code to copy overlay .text1 into the overlay area might look like the following.
将覆载 .text1
复制到覆载区域的 C 代码可能如下所示。
extern char __load_start_text1, __load_stop_text1;
memcpy ((char *) 0x1000, &__load_start_text1,
&__load_stop_text1 - &__load_start_text1);
Note that the OVERLAY command is just syntactic sugar, since everything it does can be done using the more basic commands. The above example could have been written identically as follows.
请注意,OVERLAY 命令只是语法糖,因为它所做的一切都可以用更基本的命令来完成。上面的示例可以写成下面的样子。
.text0 0x1000 : AT (0x4000) { o1/*.o(.text) }
PROVIDE (__load_start_text0 = LOADADDR (.text0));
PROVIDE (__load_stop_text0 = LOADADDR (.text0) + SIZEOF (.text0));
.text1 0x1000 : AT (0x4000 + SIZEOF (.text0)) { o2/*.o(.text) }
PROVIDE (__load_start_text1 = LOADADDR (.text1));
PROVIDE (__load_stop_text1 = LOADADDR (.text1) + SIZEOF (.text1));
. = 0x1000 + MAX (SIZEOF (.text0), SIZEOF (.text1));
2 MEMORY Command
The linker’s default configuration permits allocation of all available memory. You can override this by using the MEMORY command.
The MEMORY command describes the location and size of blocks of memory in the target. You can use it to describe which memory regions may be used by the linker, and which memory regions it must avoid. You can then assign sections to particular memory regions. The linker will set section addresses based on the memory regions, and will warn about regions that become too full. The linker will not shuffle sections around to fit into the available regions.
A linker script may contain many uses of the MEMORY command, however, all memory blocks defined are treated as if they were specified inside a single MEMORY command. The syntax for MEMORY is:
MEMORY
{
name [(attr)] : ORIGIN = origin, LENGTH = len
…
}
The name is a name used in the linker script to refer to the region. The region name has no meaning outside of the linker script. Region names are stored in a separate name space, and will not conflict with symbol names, file names, or section names. Each memory region must have a distinct name within the MEMORY command. However you can add later alias names to existing memory regions with the Assign alias names to memory regions command.
The attr string is an optional list of attributes that specify whether to use a particular memory region for an input section which is not explicitly mapped in the linker script. As described in SECTIONS Command, if you do not specify an output section for some input section, the linker will create an output section with the same name as the input section. If you define region attributes, the linker will use them to select the memory region for the output section that it creates.
The attr string must consist only of the following characters:
‘R’
Read-only section
‘W’
Read/write section
‘X’
Executable section
‘A’
Allocatable section
‘I’
Initialized section
‘L’
Same as ‘I’
‘!’
Invert the sense of any of the attributes that follow
If an unmapped section matches any of the listed attributes other than ‘!’, it will be placed in the memory region. The ‘!’ attribute reverses the test for the characters that follow, so that an unmapped section will be placed in the memory region only if it does not match any of the attributes listed afterwards. Thus an attribute string of ‘RW!X’ will match any unmapped section that has either or both of the ‘R’ and ‘W’ attributes, but only as long as the section does not also have the ‘X’ attribute.
The origin is an numerical expression for the start address of the memory region. The expression must evaluate to a constant and it cannot involve any symbols. The keyword ORIGIN may be abbreviated to org or o (but not, for example, ORG).
The len is an expression for the size in bytes of the memory region. As with the origin expression, the expression must be numerical only and must evaluate to a constant. The keyword LENGTH may be abbreviated to len or l.
In the following example, we specify that there are two memory regions available for allocation: one starting at ‘0’ for 256 kilobytes, and the other starting at ‘0x40000000’ for four megabytes. The linker will place into the ‘rom’ memory region every section which is not explicitly mapped into a memory region, and is either read-only or executable. The linker will place other sections which are not explicitly mapped into a memory region into the ‘ram’ memory region.
MEMORY
{
rom (rx) : ORIGIN = 0, LENGTH = 256K
ram (!rx) : org = 0x40000000, l = 4M
}
Once you define a memory region, you can direct the linker to place specific output sections into that memory region by using the ‘>region’ output section attribute. For example, if you have a memory region named ‘mem’, you would use ‘>mem’ in the output section definition. See Output Section Region. If no address was specified for the output section, the linker will set the address to the next available address within the memory region. If the combined output sections directed to a memory region are too large for the region, the linker will issue an error message.
It is possible to access the origin and length of a memory in an expression via the ORIGIN(memory) and LENGTH(memory) functions:
_fstack = ORIGIN(ram) + LENGTH(ram) - 4;
3 PHDRS Command
The ELF object file format uses program headers, also knows as segments. The program headers describe how the program should be loaded into memory. You can print them out by using the objdump program with the ‘-p’ option.
When you run an ELF program on a native ELF system, the system loader reads the program headers in order to figure out how to load the program. This will only work if the program headers are set correctly. This manual does not describe the details of how the system loader interprets program headers; for more information, see the ELF ABI.
The linker will create reasonable program headers by default. However, in some cases, you may need to specify the program headers more precisely. You may use the PHDRS command for this purpose. When the linker sees the PHDRS command in the linker script, it will not create any program headers other than the ones specified.
The linker only pays attention to the PHDRS command when generating an ELF output file. In other cases, the linker will simply ignore PHDRS.
This is the syntax of the PHDRS command. The words PHDRS, FILEHDR, AT, and FLAGS are keywords.
PHDRS
{
name type [ FILEHDR ] [ PHDRS ] [ AT ( address ) ]
[ FLAGS ( flags ) ] ;
}
The name is used only for reference in the SECTIONS command of the linker script. It is not put into the output file. Program header names are stored in a separate name space, and will not conflict with symbol names, file names, or section names. Each program header must have a distinct name. The headers are processed in order and it is usual for them to map to sections in ascending load address order.
Certain program header types describe segments of memory which the system loader will load from the file. In the linker script, you specify the contents of these segments by placing allocatable output sections in the segments. You use the ‘:phdr’ output section attribute to place a section in a particular segment. See Output Section Phdr.
It is normal to put certain sections in more than one segment. This merely implies that one segment of memory contains another. You may repeat ‘:phdr’, using it once for each segment which should contain the section.
If you place a section in one or more segments using ‘:phdr’, then the linker will place all subsequent allocatable sections which do not specify ‘:phdr’ in the same segments. This is for convenience, since generally a whole set of contiguous sections will be placed in a single segment. You can use :NONE to override the default segment and tell the linker to not put the section in any segment at all.
You may use the FILEHDR and PHDRS keywords after the program header type to further describe the contents of the segment. The FILEHDR keyword means that the segment should include the ELF file header. The PHDRS keyword means that the segment should include the ELF program headers themselves. If applied to a loadable segment (PT_LOAD), all prior loadable segments must have one of these keywords.
The type may be one of the following. The numbers indicate the value of the keyword.
PT_NULL (0)
Indicates an unused program header.
PT_LOAD (1)
Indicates that this program header describes a segment to be loaded from the file.
PT_DYNAMIC (2)
Indicates a segment where dynamic linking information can be found.
PT_INTERP (3)
Indicates a segment where the name of the program interpreter may be found.
PT_NOTE (4)
Indicates a segment holding note information.
PT_SHLIB (5)
A reserved program header type, defined but not specified by the ELF ABI.
PT_PHDR (6)
Indicates a segment where the program headers may be found.
PT_TLS (7)
Indicates a segment containing thread local storage.
expression
An expression giving the numeric type of the program header. This may be used for types not defined above.
You can specify that a segment should be loaded at a particular address in memory by using an AT expression. This is identical to the AT command used as an output section attribute (see Output Section LMA). The AT command for a program header overrides the output section attribute.
The linker will normally set the segment flags based on the sections which comprise the segment. You may use the FLAGS keyword to explicitly specify the segment flags. The value of flags must be an integer. It is used to set the p_flags field of the program header.
Here is an example of PHDRS. This shows a typical set of program headers used on a native ELF system.
PHDRS
{
headers PT_PHDR PHDRS ;
interp PT_INTERP ;
text PT_LOAD FILEHDR PHDRS ;
data PT_LOAD ;
dynamic PT_DYNAMIC ;
}
SECTIONS
{
. = SIZEOF_HEADERS;
.interp : { *(.interp) } :text :interp
.text : { *(.text) } :text
.rodata : { *(.rodata) } /* defaults to :text */
…
. = . + 0x1000; /* move to a new page in memory */
.data : { *(.data) } :data
.dynamic : { *(.dynamic) } :data :dynamic
…
}