脚本模型:
ENTRY(__entry)
SECTIONS
{
. = 0x0 + SIZEOF_HEADERS;
.hash : {*(.hash)}
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.dyn :
{
*(.rel.init)
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.fini)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
*(.rel.ctors)
*(.rel.dtors)
*(.rel.got)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.dynsym : { *(.dynsym) }
.entry_init : {*(.entry_init)}
__param_addr = . ;
.text xxx : AT( __param_addr + 100)@此处将会出现问题(将导致.plt以及.got覆盖.text),原因为__param_addr 为运行态当前地址,则当使用AT指明.text段加载地址为当前运行地址再加上100,但后面的.plt以及got段又使用默认的加载地址(即加载地址与运行地址相等),这样就会在链接的时候造成.text段有100字节的加载地址与.ply段重叠!
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
*(.rodata.str1.4)
*(.rodata)
} =0
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.data :
{
__data_start = . ;
*(.data .data.* .gnu.linkonce.d.*)
KEEP (*(.gnu.linkonce.d.*personality*))
SORT(CONSTRUCTORS)
}
__bss_start__ = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
__bss_end__ = .;
end = .;
_end = .;
}
要点:.textxxx : AT( __param_addr + 100)@此处将会出现问题(将导致.plt以及.got覆盖.text),原因为__param_addr 为运行态当前地址,则当使用AT指明.text段加载地址为当前运行地址再加上100,但后面的.plt以及got段又使用默认的加载地址(即加载地址与运行地址相等),这样就会在链接的时候造成.text段有100字节的加载地址与.ply段重叠!
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
*(.rodata.str1.4)
*(.rodata)
} =0
:.textxxx 为链接脚本任意命名,可在反汇编中查询到此段名称,但*(.text .stub .text.* .gnu.linkonce.t.*)中的.text段为各.o中真实的.text段内容(gcc将会默认代码段为.text,默认全局可读写变量数据为.data段,默认只读全局数据为.rodata段,默认未初始化的可读写数据为.bss段),如果在某个函数前面加上__attribute__ ((section(".MAIN_DATA"))) 则将改变函数默认的.text段,而归为新命名的.MAIN_DATA段,同理,如果在某个全局变量前面加__attribute__ ((section(".MAIN_DATA")))则该变量由原来默认的.data段变为新命名 的.MAIN_DATA段。
__param_addr = . ;的写法需要注意为 xx = , ; 而非xx=.;
z