【问题标题】:GNU LD Script to catch C++ group / dynsym SectionsGNU LD 脚本来捕获 C++ 组 / dynsym 部分
【发布时间】:2018-11-17 16:56:02
【问题描述】:

我正在维护一个可以将 ELF32 可重定位文件转换为 RDOFF2 格式的工具。
为了使这个过程正常工作,我需要预先链接当前使用 ld 脚本的输入文件,如下所示:

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
FORCE_COMMON_ALLOCATION

SECTIONS {
    .text : {
            /* collect .init / .fini sections */

        PROVIDE_HIDDEN(__init_start = .);
        KEEP (*(.init))
        PROVIDE_HIDDEN(__init_end = .);

        PROVIDE_HIDDEN(__fini_start = .);
        KEEP (*(.fini))
        PROVIDE_HIDDEN(__fini_end = .);

            /* .text and .rodata */

        *(.text .text.* .gnu.linkonce.t.*)
        *(.rodata .rodata.* .gnu.linkonce.r.*)
        *(.rodata1)


            /* .init- / .fini_arrays */

        PROVIDE_HIDDEN (__preinit_array_start = .);
        KEEP (*(.preinit_array))
        PROVIDE_HIDDEN (__preinit_array_end = .);

        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);

        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP (*(SORT(.fini_array.*)))
        KEEP (*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);
    }
    .data : {
        *(.data .data.* .gnu.linkonce.d.*)
        *(.data1)

        SORT(CONSTRUCTORS)

            /* c++ ctors / dtors and exception tables */

        PROVIDE_HIDDEN (__gcc_except_table_start = .);
        *(.gcc_except_table .gcc_except_table.*)
        PROVIDE_HIDDEN (__gcc_except_table_end = .);

        PROVIDE_HIDDEN (__eh_frame_start = .);
        *(.eh_frame_hdr)
        *(.eh_frame)
        PROVIDE_HIDDEN (__eh_frame_end = .);

        PROVIDE_HIDDEN (__ctors_array_start = .);
        KEEP (*(SORT(.ctors.*)))
        KEEP (*(.ctors))
        PROVIDE_HIDDEN (__ctors_array_end = .);

        PROVIDE_HIDDEN (__dtors_array_start = .);
        KEEP (*(SORT(.dtors.*)))
        KEEP (*(.dtors))
        PROVIDE_HIDDEN (__dtors_array_end = .);
    }
    .bss  : {
        *(.dynbss)
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(COMMON)

        . = ALIGN(. != 0 ? 32 / 8 : 1);
    }
    /DISCARD/ : {
        *(.note.GNU-stack)
        *(.gnu_debuglink)
    }
}

目标是将输入文件减少为仅包含 .text.data.bss.strtab.symtab.shstrtab 部分。

虽然当前版本适用于 C 代码,但它在 C++ 中会中断,因为 g++ / ld 似乎会生成以我的一些 C++ 符号命名的 SHT_DYNSYM 类型的部分。

我的问题:如何修改提供的链接描述文件以捕捉那些杂散符号?

这是我的示例来源:

/* compile with g++ -c cxx_hello.cc */
/* generic sys write provided by syswrite_$arch.S */
void _syscall_write(int fd, const char *msg, unsigned len);

void syscall_write(int fd, const char *msg, unsigned len)
{
    _syscall_write(fd, msg, len);
}

class HelloBase
{
    public:
        HelloBase()  { syscall_write(1, "::HelloBase()\n", 14); i = 42; };
        ~HelloBase() { syscall_write(1, "::~HelloBase()\n", 15); };
        int res(void) { return i; }
    protected:
        void sayHi(void) { syscall_write(1, "Hello", 5); };
    private:
        int i;
};

class HelloDeriv : public HelloBase
{
    public:
        HelloDeriv()  { syscall_write(1, "::HelloDeriv()\n", 15); }
        ~HelloDeriv() { syscall_write(1, "::~HelloDeriv()\n", 16); }

        void greet(void) { this->sayHi(); syscall_write(1, ", World!\n", 9); }
}; 

int
_main(void)
{
    HelloDeriv hello;

    hello.greet();
    return hello.res();
}

objdump -h 的输出(仅有趣的部分):

cxx_hello.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
0 _ZN9HelloBase3resEv 00000008  00000000  00000000  00000034  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

1 _ZN9HelloBaseC2Ev 00000008  00000000  00000000  0000003c  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

2 _ZN9HelloBaseD2Ev 00000008  00000000  00000000  00000044  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

3 _ZN10HelloDerivC1Ev 00000008  00000000  00000000  0000004c  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

4 _ZN9HelloBase5sayHiEv 00000008  00000000  00000000  00000054  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

5 _ZN10HelloDeriv5greetEv 00000008  00000000  00000000  0000005c  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

6 _ZN10HelloDerivD1Ev 00000008  00000000  00000000  00000064  2**2
              CONTENTS, READONLY, EXCLUDE, GROUP, LINK_ONCE_DISCARD

7 .text         00000000  00000000  00000000  0000006c  2**2
              CONTENTS, ALLOC, LOAD, READONLY, CODE

8 .data         00000000  00000000  00000000  0000006c  2**2

              CONTENTS, ALLOC, LOAD, DATA
9 .bss          00000000  00000000  00000000  0000006c  2**2
              ALLOC

readelf -S相同的文件

There are 37 section headers, starting at offset 0x59c:

Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .group            GROUP           00000000 000034 000008 04     35  26  4
[ 2] .group            GROUP           00000000 00003c 000008 04     35  30  4
[ 3] .group            GROUP           00000000 000044 000008 04     35  31  4
[ 4] .group            GROUP           00000000 00004c 000008 04     35  33  4
[ 5] .group            GROUP           00000000 000054 000008 04     35  34  4
[ 6] .group            GROUP           00000000 00005c 000008 04     35  35  4
[ 7] .group            GROUP           00000000 000064 000008 04     35  36  4
[ 8] .text             PROGBITS        00000000 00006c 000000 00  AX  0   0  4
[ 9] .data             PROGBITS        00000000 00006c 000000 00  WA  0   0  4
[10] .bss              NOBITS          00000000 00006c 000000 00  WA  0   0  4

【问题讨论】:

  • 进一步调查(甚至是链接器来源..)没有透露任何消息:(
  • 我投票结束这个问题(自己回答这个问题感觉很愚蠢......)。最近的 gcc 版本改变了链接行为并暴露了不同的 dynsym 部分。我认为没有人能够回答这个问题。

标签: c++ c linker elf low-level


【解决方案1】:

好吧,我有一个很简单的建议,这么简单可能行不通……

据此:

http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_19.html

您可以只为要捕获的所有部分指定文件的名称 (.o)。

你可以使用通配符。

难道只有一个 * 的行会捕获所有剩余的部分吗?像这样:

.bss  : {
    *(.dynbss)
    *(.bss .bss.* .gnu.linkonce.b.*)
    *(COMMON)
    *
}

【讨论】:

  • 抱歉,这似乎在“最新”版本中被破坏了(我使用的是 ld 2.20.1)。
猜你喜欢
  • 2011-02-10
  • 2011-10-16
  • 1970-01-01
  • 2016-04-25
  • 2021-12-11
  • 2015-07-31
  • 2018-12-11
  • 2018-02-03
  • 2012-02-10
相关资源
最近更新 更多