title: the lds file of the Linux
refer to <>, and translating it as following part.
OUTPUT_ARCH(arm)
/***************************************************************************
OUTPUT_ARCH(bfdarch)
Specify a particular output machine architecture, bfdarch. The argument is one of
the names used by the BFD library. You can see the architecture of an object file
by using the objdump program with the -f option.
(译)
OUTPUT_ARCH(bfdarch)
指定的一个特定的输出机器体系,bfdarch。参数名被BFD库所使用。你能够使用带有-f选项的
objdump程序来查看object文件的体系结构。
***************************************************************************/
ENTRY(stext)
/***************************************************************************
Setting the Entry Point
The first instruction to execute in a program is called the entry point. You can use the
ENTRY linker script command to set the entry point. The argument is a symbol name:
ENTRY (symbol)
There are several ways to set the entry point. The linker will set the entry point by
trying each of the following methods in order, and stopping when one of them
succeeds:
1) The -e entry command-line option;
2) The ENTRY (symbol) command in a linker script;
3) The value of the symbol, start, if defined;
4) The address of the first byte of the .text section, if present;
5) The address, 0.
(译)
设置入口点
程序第一个指令的执行被叫做入口点。你能够使用ENTRY连接器脚本命令去设置入口点。参数是一个
符号名:
ENTRY (symbol)
有几种方法去设置入口点。连接器将设置入口点,通过顺序的尝试下面的方法和当一旦有成功找到就
立即停止:
1) 通过命令行参数-e entry传递入口点。
2) 通过在链接脚本设置ENTRY (symbol)。
3) 符号值,start, 如果定义了。
4) 如果存在.text段,那么就默认是.text段第一字节的地址。
5) 如果上面都找不到,那么默认是地址 0 。
***************************************************************************/
jiffies = jiffies_64;
/***************************************************************************
(1)Assigning Values to Symbols
You may assign a value to a symbol in a linker script. This will define the symbol as a
global symbol. The following documentation discusses such assignments in more
detail.
1) “Simple Assignments” on page 35
2) “PROVIDE Keyword” on page 36
(1.1)Simple Assignments
You may assign to a symbol using any of the C assignment operators:
symbol = expression ;
symbol += expression ;
symbol -= expression ;
symbol *= expression ;
symbol /= expression ;
symbol <<= expression ;
symbol >>= expression ;
symbol &= expression ;
symbol |= expression ;
1) The first case will define symbol to the value of expression. In the other cases,
symbol must already be defined, and the value will be accordingly adjusted.
2) The special . symbol name indicates the location counter. You may only use this
within a SECTIONS command.
3) The semicolon after expression is required.
4) See “Expressions in Linker Scripts” on page 55.
5) You may write symbol assignments as commands in their own right, or as
statements within a SECTIONS command, or as part of an output section
description in a SECTIONS command.
6) The section of the symbol will be set from the section of the expression; for more
information, see “Expressions in Linker Scripts” on page 55.
7) The following is an example showing the three different places that symbol
assignments may be used:
floating_point = 0;
SECTIONS
{
.text :
{
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 4;
.data : { *(.data) }
}
In the previous example, the floating_point symbol will be defined as zero. The
_etext symbol will be defined as the address following the last .text input section.
The symbol _bdata will be defined as the address following the .text output section
aligned upward to a 4 byte boundary.
(1.2)PROVIDE Keyword
In some cases, it is desirable for a linker script to define a symbol only if it is
referenced and is not defined by any object included in the link. For example,
traditional linkers defined the symbol etext. However, ANSI C requires that the user
be able to use etext as a function name without encountering an error. The PROVIDE
keyword may be used to define a symbol, such as etext, only if it is referenced but
not defined. The syntax is PROVIDE(symbol = expression).
Here is an example of using PROVIDE to define etext:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
In the previou***ample, if the program defines _etext, the linker will give a multiple
definition error. If, on the other hand, the program defines etext, the linker will
silently use the definition in the program. If the program references etext but does not
define it, the linker will use the definition in the linker script.
(译)
(1)符号赋值
你可以在链接脚本里赋值给一个符号变量。这将定义这个符号为全局的符号。下面的文档更详细的讨论这样的赋值:
(1.1) “简单赋值“
(1.2) “PROVIDE关键字”
(1.1)简单赋值
你可以使用任何的C赋值操作赋值给一个符号:
symbol = expression ;
symbol += expression ;
symbol -= expression ;
symbol *= expression ;
symbol /= expression ;
symbol <<= expression ;
symbol >>= expression ;
symbol &= expression ;
symbol |= expression ;
1) 第一种情况将定义符号为表达式的值。在另一种情况,符号必须已经被定义,和这个值将相应的被改变。
2) 特殊的 . 符号名指示了本地计数器。你可以仅仅在SECTIONS命令里使用它。
3) 表达式后面的分号是必须的。
4) 查看55页的 “Expressions in Linker Scripts”。
5) 你可以在它们自己的权限里写一个符号赋值语句作为命令,或者在一个SECTIONS命令里作为语句,或者在一个SECTIONS命令里
作为输出段描述的一部分。
6) 符号段将从表达式段被设置,更详细的信息,参见55页的“Expressions in Linker Scripts”。
7) 下面例子示范了三个不同地方,符号赋值可以被使用到:
floating_point = 0;
SECTIONS
{
.text :
{
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 4;
.data : { *(.data) }
}
在前面的例子,floating_point符号将被定义为0. 符号_etext将被定义为紧跟输入段.text的最后地址。
符号 _bdata将被定义为紧跟输出段.text的最后地址。赋值将是向上4字节边界对齐。
(1.2) PROVIDE 关键字
在某些情况,渴望连接器定义一个符号,仅仅是如果它被引用到,和没有被链接器里包含的任何object文件里定义到。
例如,传统的连接器定义符号etext。然而,ANSI C在没有遇到错误的时候需要用户能够使用etext作为一个函数名。
关键字PROVIDE 可以常被用来定义一个符号,例如etext,仅仅如果它被引用到,但没被定义。
语法PROVIDE(symbol = expression).
这里是一个使用PROVIDE的例子去定义了etext:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
在前面的例子里, 如果程序定义了 _etext, 链接器将给出一多个定义的错误信息。如果,另一方面,
程序定义了etext,连接器将在程序里默认的使用这个定义。如果程序引用引用etext,但没有定义它,
连接器将在连接器脚本里使用这个定义。
***************************************************************************/
SECTIONS
{
. = 0xC0008000;
.init : { /* Init code and data */
_stext = .;
_sinittext = .;
*(.init.text)
/***************************************************************************
section (“section-name”)
Normally, the compiler places the code it generates in the text section.
Sometimes, however, you need additional sections, or you need certain particular
functions to appear in special sections. The section attribute specifies that a
function lives in a particular section. For example, the following declaration puts
the function, foobar, in the bar section.
extern void foobar (void) __attribute__ \
((section (“bar”)));
Some file formats do not support arbitrary sections so the section attribute is not
available on all platforms. If you need to map the entire contents of a module to a
particular section, consider using the facilities of the linker instead.
(译)(注:这里小片段是引用gcc编译器说明文档的,因为这些产生的段名称需要编译器支持)
段 (“段名”)
一般地,编译器放置它自己产生的代码到text段。有时候,然而,你需要附加的段,或者你需要某个特殊函数出现
在特殊的段里。段属性attribute指示了一个函数被放置在特定的段里。例如,下面的声明把函数foobar放置在bar段。
extern void foobar (void) __attribute__ \
((section (“bar”)));
有些文件格式不支持任意段,这样段属性在所有的平台都不起作用。如果你需要映射模块的整个内容到一个特殊的段,
考虑使用连接器机制来代替。
***************************************************************************/
_einittext = .;
__proc_info_begin = .;
*(.proc.info)
__proc_info_end = .;
__arch_info_begin = .;
*(.arch.info)
__arch_info_end = .;
__tagtable_begin = .;
*(.taglist)
__tagtable_end = .;
. = ALIGN(16);
/***************************************************************************
Builtin Functions
The linker script language includes the following builtin functions for use in linker
script expressions.
ABSOLUTE(exp)
Return the absolute (non-relocatable, as opposed to non-negative) value of the exp
expression. Primarily useful to assign an absolute value to a symbol within a
section definition, where symbol values are normally section relative. See
“Expressions in Linker Scripts” on page 55.
ADDR(section)
Return the absolute address (the VMA) of the named section. Your script must
previously have defined the location of that section. In the following example,
symbol_1 and symbol_2 are assigned identical values:
SECTIONS { ...
.output1 :
{
start_of_output_1 = ABSOLUTE(.);
...
}
.output :
{
symbol_1 = ADDR(.output1);
symbol_2 = start_of_output_1;
}
...
}
ALIGN(exp)
Return the location counter (.) aligned to the next exp boundary. exp must be an
expression whose value is a power of two. This is equivalent to:
(. + exp - 1) & ~(exp - 1)
ALIGN does not change the value of the location counter, it just does arithmetic on
it. Here is an example which aligns the output .data section to the next 0x2000
byte boundary after the preceding section and sets a variable within the section to
the next 0x8000 boundary after the input sections:
SECTIONS { ...
.data ALIGN(0x2000): {
*(.data)
variable = ALIGN(0x8000);
}
...
}
The first use of ALIGN in this example specifies the location of a section because it is
used as the optional ADDRESS attribute of a section definition. The second use of ALIGN
is to define the value of a symbol. The builtin function NEXT is closely related to
ALIGN. See “Output Section Address” on page 39.
BLOCK(exp)
This is a synonym for ALIGN, for compatibility with older linker scripts. It is most
often seen when setting the address of an output section.
DEFINED(symbol)
Return 1 if symbol is in the linker global symbol table and is defined, otherwise
return 0. You can use this function to provide default values for symbols. For
example, the following script fragment shows how to set a global symbol begin to
the first location in the .text section, but if a symbol called begin already
existed, its value is preserved:
SECTIONS{ ...
.text : {
begin = DEFINED(begin) ? begin : . ;
...
}
...
}
LOADADDR(section)
Return the absolute LMA of the named SECTION. This is normally the same as ADDR,
but it may be different if the AT attribute is used in the output section definition.
MAX(exp1, exp2)
Returns the maximum of exp1 and exp2.
MIN(exp1, exp2)
Returns the minimum of exp1 and exp2.
NEXT(exp)
Return the next unallocated address that is a multiple of exp. This function is
closely related to ALIGN(exp); unless you use the MEMORY command to define
discontinuous memory for the output file, the two functions are equivalent.
SIZEOF(section)
Return the size in bytes of the named section, if that section has been allocated.
If the section has not been allocated when this is evaluated, the linker will report
an error. See “PHDRS Command” on page 50. In the following example,
symbol_1 and symbol_2 are assigned identical values:
SECTIONS{ ...
.output {
.start = . ;
...
SIZEOF_HEADERS
Return the size in bytes of the output file’s headers. This is information which
appears at the start of the output file. You can use this number when setting the
start address of the first section, if you choose, to facilitate paging.
When producing an ELF output file, if the linker script uses the SIZEOF_HEADERS
builtin function, the linker must compute the number of program headers before it
has determined all the section addresses and sizes. If the linker later discovers that
it needs additional program headers, it will report an “not enough room for
program headers” error . To avoid this error, you must avoid using the
SIZEOF_HEADERS function, or you must rework your linker script to avoid forcing
the linker to use additional program headers, or you must define the program
headers yourself using the PHDRS command (see “PHDRS Command” on page
50).
(译)
内建函数
连接器脚本语言包含下面的内建函数,提供给连接器脚本表达式使用。
ABSOLUTE(exp)
返回一个绝对的(不可重定位的,与non-negative相对立) 表达式的值。主要用在一个段定义里赋值
一个绝对值给符号,这个符号值与正规段相关。参见55页“Expressions in Linker Scripts”。
ADDR(section)
返回一个命名段的绝对地址(the VMA)。 你的脚本必须预先地在本地定义那个段。在下面的例子里,
symbol_1 和 symbol_2 被赋值为一值:
SECTIONS { ...
.output1 :
{
start_of_output_1 = ABSOLUTE(.);
...
}
.output :
{
symbol_1 = ADDR(.output1);
symbol_2 = start_of_output_1;
}
...
}
ALIGN(exp)
返回一个本地计数器(.) ,这数值与下一个exp边界对齐。exp必须是一个值是2的指数的表达式。这相当于:
(. + exp - 1) & ~(exp - 1)
ALIGN不会改变本地计数器的值,只是使用它计算。这里是一个例子,它使输出段.data在前一个段之后对齐到下一个0x2000
字节边界,和在这个段里设置一个变量,这变量对齐在输入端之后的下一个0x8000的边界:
SECTIONS { ...
.data ALIGN(0x2000): {
*(.data)
variable = ALIGN(0x8000);
}
...
}
在这个例子中,第一个ALIGN指定了一个段的位置,因为它被用来作为一个可选的段定义的ADDRESS属性。第二个ALIGN使用是
定义一个符号值。内建函数NEXT跟ALIGN密切相关。参见“Output Section Address”。
BLOCK(exp)
这是一个ALIGN的近义词,为了兼容老式的链接脚本。它常常在设定输出段地址时候能看到。
DEFINED(symbol)
返回1,如果符号在连接器全局符号表里存在并定义了。否则返回0.你能够使用这个函数去提供该符号的默认值。例如,下面的脚本片段
示范了如何去设置一个全局符号begin为.text段的第一个位置,但是如果begin符号已经存在,它的值将被保留。
SECTIONS{ ...
.text : {
begin = DEFINED(begin) ? begin : . ;
...
}
...
}
LOADADDR(section)
返回一个绝对的已命名段的LMA。这是常规地跟ADDR一样,但它可以不同,当AT属性在输出段定义里被使用到
MAX(exp1, exp2)
返回exp1和exp2中的最大值。
MIN(exp1, exp2)
返回exp1和exp2中的最小值。
NEXT(exp)
返回下一个没被分配的地址,这地址是exp的倍数。这函数与ALIGN(exp)密切相关;除非你 使用MEMORY命令去为
输出文件定义不连续的内存,否则这两个函数是是相同的。
SIZEOF(section)
如果那段已经被分配,返回命名段的字节数。当这个被评估时,如果这段还没被分配,连接器将报告一个错误。
参见50页"PHDRS Command”。在如下的例子,symbol_1和symbol_2被赋唯一值:
SECTIONS{ ...
.output {
.start = . ;
...
SIZEOF_HEADERS
返回输出文件头部的字节数。这些信息出现在输出文件的开始处。当设置第一个段的开始地址时,你能够使用这个数字,
如果你选择了加速分页。当产生一个ELF输出文件时,如果链接器脚本使用SIZEOF_HEADERS内建函数,连接器必须在它
算出所有段地址和长度之前计算程序头部的数值。如果连接器后来发现它需要附加程序头,它将报告一个“not enough room for
program headers”错误。为了避免这样的错误,你必须避免使用SIZEOF_HEADERS函数,或者你必须修改你的连接器脚本去避免强制
连接器去使用附加程序头,或者你必须使用PHDRS命令去定义你自己的程序头。(参见50页“PHDRS Command”)。
***************************************************************************/
__setup_start = .;
*(.init.setup)
__setup_end = .;
__early_begin = .;
*(__early_param)
__early_end = .;
__initcall_start = .;
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
__initcall_end = .;
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
__security_initcall_start = .;
*(.security_initcall.init)
__security_initcall_end = .;
. = ALIGN(32);
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
__initramfs_end = .;
. = ALIGN(64);
__per_cpu_start = .;
*(.data.percpu)
__per_cpu_end = .;
__init_begin = _stext;
*(.init.data)
. = ALIGN(4096);
__init_end = .;
}
/DISCARD/ : { /* Exit code and data */
*(.exit.text)
*(.exit.data)
*(.exitcall.exit)
}
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(.text)
__sched_text_start = .; *(.sched.text) __sched_text_end = .;
__lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.got) /* Global offset table */
}
. = ALIGN(16);
__ex_table : { /* Exception table */
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
}
.rodata : AT(ADDR(.rodata) - 0) { *(.rodata) *(.rodata.*) *(__vermagic) } .rodata1 : AT(ADDR(.rodata1) - 0) { *(.rodata1) } .pci_fixup : AT(ADDR(.pci_fixup) - 0) { __start_pci_fixups_early = .; *(.pci_fixup_early) __end_pci_fixups_early = .; __start_pci_fixups_header = .; *(.pci_fixup_header) __end_pci_fixups_header = .; __start_pci_fixups_final = .; *(.pci_fixup_final) __end_pci_fixups_final = .; __start_pci_fixups_enable = .; *(.pci_fixup_enable) __end_pci_fixups_enable = .; } __ksymtab : AT(ADDR(__ksymtab) - 0) { __start___ksymtab = .; *(__ksymtab) __stop___ksymtab = .; } __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - 0) { __start___ksymtab_gpl = .; *(__ksymtab_gpl) __stop___ksymtab_gpl = .; } __kcrctab : AT(ADDR(__kcrctab) - 0) { __start___kcrctab = .; *(__kcrctab) __stop___kcrctab = .; } __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - 0) { __start___kcrctab_gpl = .; *(__kcrctab_gpl) __stop___kcrctab_gpl = .; } __ksymtab_strings : AT(ADDR(__ksymtab_strings) - 0) { *(__ksymtab_strings) } __param : AT(ADDR(__param) - 0) { __start___param = .; *(__param) __stop___param = .; }
_etext = .; /* End of text and rodata section */
. = ALIGN(8192);
__data_loc = .;
.data : AT(__data_loc) {
__data_start = .; /* address in memory */
/*
* first, the init task union, aligned
* to an 8192 byte boundary.
*/
*(.init.task)
. = ALIGN(4096);
__nosave_begin = .;
*(.data.nosave)
. = ALIGN(4096);
__nosave_end = .;
/*
* then the cacheline aligned data
*/
. = ALIGN(32);
*(.data.cacheline_aligned)
/*
* and the usual data section
*/
*(.data)
CONSTRUCTORS
_edata = .;
}
.bss : {
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
_end = .;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
/* those must never be empty */
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
you can use the objdump tool to show all the header infomation, as below:
[root@localhost kernel-2.6.13]# objdump -h vmlinux
vmlinux: file format elf32-little
Sections:
Idx Name Size VMA LMA File off Algn
0 .init 00024000 c0008000 c0008000 00008000 2**5
CONTENTS, ALLOC, LOAD, CODE
1 .text 002693e4 c002c000 c002c000 0002c000 2**8
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 __ex_table 00000a50 c02953f0 c02953f0 002953f0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .pci_fixup 00000000 c0295e40 c0295e40 00331e40 2**0
CONTENTS
4 __ksymtab 00004380 c0295e40 c0295e40 00295e40 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 __ksymtab_gpl 000007d8 c029a1c0 c029a1c0 0029a1c0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 __kcrctab 00000000 c029a998 c029a998 00331e40 2**0
CONTENTS
7 __kcrctab_gpl 00000000 c029a998 c029a998 00331e40 2**0
CONTENTS
8 __ksymtab_strings 0000a884 c029a998 c029a998 0029a998 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 __param 0000071c c02a521c c02a521c 002a521c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .data 0008be40 c02a6000 c02a6000 002a6000 2**5
CONTENTS, ALLOC, LOAD, DATA
11 .bss 0006fa3c c0331e40 c0331e40 00331e40 2**5
ALLOC
12 .comment 000028b6 00000000 00000000 00331e40 2**0
CONTENTS, READONLY
阅读(1297) | 评论(0) | 转发(0) |