-1

我正在尝试链接 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

4

1 回答 1

-1

首先,我必须承认我没有彻底检查您的链接器脚本 - 也许您可以尝试简化它,并提供一个仍然包含您的问题的最小链接器脚本?

也就是说,根据http://www.scoberlin.de/content/media/http/informatik/gcc_docs/ld_3.html#SEC36, OVERLAY 命令只是一个方便的命令。也许这对你有帮助?

叠加说明

覆盖描述提供了一种简单的方法来描述要作为单个内存映像的一部分加载但要在相同内存地址上运行的部分。在运行时,某种覆盖管理器将根据需要将覆盖的部分复制进和复制出运行时内存地址,可能通过简单地操作寻址位。这种方法很有用,例如,当某个内存区域比另一个更快时。

使用 OVERLAY 命令描述叠加。OVERLAY 命令在 SECTIONS 命令中使用,就像输出节描述一样。OVERLAY 命令的完整语法如下:

请注意,OVERLAY 命令只是语法糖,因为它所做的一切都可以使用更基本的命令来完成。上面的例子可以写成如下。

于 2013-10-16T08:27:09.413 回答