我正在尝试链接 GDB 参考手册中的 Overlay 示例。该示例针对 d10v 处理器(对它不熟悉),但我想通过编译 x86_64 或 i386 架构的示例来证明调试器可以处理覆盖。
我尝试将以下部分导入链接器脚本。我首先使用从 StackOverflow 学到的技术提取了链接描述文件。
$> gcc a.c -Wl,-verbose
我修改了这个链接器脚本,添加了 .ovly0{0-3} 和 .data0{0-3} 部分,如下所示:
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
"elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/usr/local/x86_64-unknown-linux-gnu/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/x86_64-unknown-linux-gnu/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.ovly0 0x1001000 : AT (0x408000) { foo.o(.text) }
.ovly1 0x1001000 : AT (0x409000) { bar.o(.text) }
.ovly2 0x1002000 : AT (0x40a000) { baz.o(.text) }
.ovly3 0x1002000 : AT (0x40b000) { grbx.o(.text) }
.data00 0x2001000 : AT (0x40c000) { foo.o(.data) }
.data01 0x2001000 : AT (0x40d000) { bar.o(.data) }
.data02 0x2002000 : AT (0x40e000) { baz.o(.data) }
.data03 0x2002000 : AT (0x40f000) { grbx.o(.data) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
*(.rela.ifunc)
}
.rela.plt :
{
*(.rela.plt)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.init :
{
KEEP (*(.init))
}
.plt : { *(.plt) *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.fini :
{
KEEP (*(.fini))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array))
KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array))
KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.got : { *(.got) *(.igot) }
. = DATA_SEGMENT_RELRO_END (24, .);
.got.plt : { *(.got.plt) *(.igot.plt) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
_ovly_table = .;
LONG(ABSOLUTE(ADDR(.ovly0)));
LONG(SIZEOF(.ovly0));
LONG(LOADADDR(.ovly0));
LONG(0);
LONG(ABSOLUTE(ADDR(.ovly1)));
LONG(SIZEOF(.ovly1));
LONG(LOADADDR(.ovly1));
LONG(0);
LONG(ABSOLUTE(ADDR(.ovly2)));
LONG(SIZEOF(.ovly2));
LONG(LOADADDR(.ovly2));
LONG(0);
LONG(ABSOLUTE(ADDR(.ovly3)));
LONG(SIZEOF(.ovly3));
LONG(LOADADDR(.ovly3));
LONG(0);
LONG(ABSOLUTE(ADDR(.data00)));
LONG(SIZEOF(.data00));
LONG(LOADADDR(.data00));
LONG(0);
LONG(ABSOLUTE(ADDR(.data01)));
LONG(SIZEOF(.data01));
LONG(LOADADDR(.data01));
LONG(0);
LONG(ABSOLUTE(ADDR(.data02)));
LONG(SIZEOF(.data02));
LONG(LOADADDR(.data02));
LONG(0);
LONG(ABSOLUTE(ADDR(.data03)));
LONG(SIZEOF(.data03));
LONG(LOADADDR(.data03));
LONG(0);
_novlys = .;
LONG((_novlys - _ovly_table) / 16);
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
__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 ? 64 / 8 : 1);
}
.lbss :
{
*(.dynlbss)
*(.lbss .lbss.* .gnu.linkonce.lb.*)
*(LARGE_COMMON)
}
. = ALIGN(64 / 8);
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
}
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.ldata .ldata.* .gnu.linkonce.l.*)
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
. = ALIGN(64 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_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) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
该脚本的相关部分如下:
.ovly0 0x1001000 : AT (0x408000) { foo.o(.text) }
.ovly1 0x1001000 : AT (0x409000) { bar.o(.text) }
.ovly2 0x1002000 : AT (0x40a000) { baz.o(.text) }
.ovly3 0x1002000 : AT (0x40b000) { grbx.o(.text) }
.data00 0x2001000 : AT (0x40c000) { foo.o(.data) }
.data01 0x2001000 : AT (0x40d000) { bar.o(.data) }
.data02 0x2002000 : AT (0x40e000) { baz.o(.data) }
.data03 0x2002000 : AT (0x40f000) { grbx.o(.data) }
当我使用此脚本编译程序时,我最终会得到一个运行的可执行对象,但在尝试加载覆盖时会出现 SEGFAULT 。有趣的是,OBJDUMP
输出似乎是正确的,两个函数 'foo' 和 'bar' 都被赋予了相同的 VMA 地址(0x1001000)并且每个都有其分配的加载地址。
这是 OBJDUMP 的相关部分:
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400318 0000000000400318 00000318 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 0000000000400334 0000000000400334 00000334 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 0000000000400354 0000000000400354 00000354 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .hash 00000030 0000000000400378 0000000000400378 00000378 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 00000000004003a8 00000000004003a8 000003a8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 000000a8 00000000004003c8 00000000004003c8 000003c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 00000050 0000000000400470 0000000000400470 00000470 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 0000000e 00000000004004c0 00000000004004c0 000004c0 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000020 00000000004004d0 00000000004004d0 000004d0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .ovly0 0000002a 0000000001001000 0000000000408000 00001000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .ovly1 0000002a 0000000001001000 0000000000409000 00201000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .ovly2 0000002a 0000000001002000 000000000040a000 00202000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .ovly3 0000002a 0000000001002000 000000000040b000 00402000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .data00 00000004 0000000002001000 000000000040c000 00601000 2**2
CONTENTS, ALLOC, LOAD, DATA
14 .data01 00000004 0000000002001000 000000000040d000 00801000 2**2
CONTENTS, ALLOC, LOAD, DATA
15 .data02 00000004 0000000002002000 000000000040e000 00802000 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .data03 00000004 0000000002002000 000000000040f000 00a02000 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .rela.dyn 00000018 0000000002002008 000000000040f008 00a02008 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .rela.plt 00000078 0000000002002020 000000000040f020 00a02020 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
19 .init 00000018 0000000002002098 000000000040f098 00a02098 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
20 .plt 00000060 00000000020020b0 000000000040f0b0 00a020b0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
21 .text 00000558 0000000002002110 000000000040f110 00a02110 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
22 .fini 0000000e 0000000002002668 000000000040f668 00a02668 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
23 .rodata 00000086 0000000002002678 000000000040f678 00a02678 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
24 .eh_frame_hdr 0000007c 0000000002002700 000000000040f700 00a02700 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
25 .eh_frame 000001e4 0000000002002780 000000000040f780 00a02780 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
26 .ctors 00000010 0000000002202e18 000000000060fe18 00c02e18 2**3
CONTENTS, ALLOC, LOAD, DATA
27 .dtors 00000010 0000000002202e28 000000000060fe28 00c02e28 2**3
CONTENTS, ALLOC, LOAD, DATA
28 .jcr 00000008 0000000002202e38 000000000060fe38 00c02e38 2**3
CONTENTS, ALLOC, LOAD, DATA
29 .dynamic 000001a0 0000000002202e40 000000000060fe40 00c02e40 2**3
CONTENTS, ALLOC, LOAD, DATA
30 .got 00000008 0000000002202fe0 000000000060ffe0 00c02fe0 2**3
CONTENTS, ALLOC, LOAD, DATA
31 .got.plt 00000040 0000000002202fe8 000000000060ffe8 00c02fe8 2**3
CONTENTS, ALLOC, LOAD, DATA
32 .data 00000094 0000000002203028 0000000000610028 00c03028 2**3
CONTENTS, ALLOC, LOAD, DATA
33 .bss 00000010 00000000022030c0 00000000006100c0 00c030bc 2**3
ALLOC
34 .comment 00000048 0000000000000000 0000000000000000 00c030bc 2**0
CONTENTS, READONLY
35 .debug_aranges 00000120 0000000000000000 0000000000000000 00c03104 2**0
CONTENTS, READONLY, DEBUGGING
36 .debug_pubnames 000000c7 0000000000000000 0000000000000000 00c03224 2**0
CONTENTS, READONLY, DEBUGGING
37 .debug_info 000004eb 0000000000000000 0000000000000000 00c032eb 2**0
CONTENTS, READONLY, DEBUGGING
38 .debug_abbrev 000002d6 0000000000000000 0000000000000000 00c037d6 2**0
CONTENTS, READONLY, DEBUGGING
39 .debug_line 00000551 0000000000000000 0000000000000000 00c03aac 2**0
CONTENTS, READONLY, DEBUGGING
40 .debug_str 0000016e 0000000000000000 0000000000000000 00c03ffd 2**0
CONTENTS, READONLY, DEBUGGING
41 .debug_loc 00000344 0000000000000000 0000000000000000 00c0416b 2**0
CONTENTS, READONLY, DEBUGGING
42 .debug_macinfo 0000f019 0000000000000000 0000000000000000 00c044af 2**0
CONTENTS, READONLY, DEBUGGING
我真的很想知道是否有人使用过链接器的 Overlay 功能,如果有,是否有人能够对此进行演示?我需要这个用于我正在开发的嵌入式调试器。
我将不胜感激在这方面的任何帮助。
谢谢,
muman613