使用汇编

时间:2016-12-26 12:21:14

标签: assembly ld arm64 relocation

这是我在AArch64面临的问题的简化版本:

我已将此宏继续转储到某个部分。

#define GEN_DATA(_type) \
    .pushsection .mydata_##_type, "aw"; \
    .ifndef start; \
    start:; \
    .endif; \
    .word 1; \
    .reloc end_loc, R_AARCH64_ABS64, .; \
    .popsection

我最终想在这样的结构中捕获相似类型的开头和结尾:

    .pushsection .head, "aw"
    .quad start
    end_loc:
    .quad 0
    .popsection

我可以使用start符号跟踪该部分的开头位置。我事先并不知道GEN_DATA()会在构建中有多少次调用,因此我无法定义end。我也不知道会使用多少_type个部分,因此无法放置保护符号脚本。因此,我决定留下end_loc的重定位条目,以便链接器最终将修复整个部分结束的位置。是的,同一个end_loc会有多个重定位条目,但由于它们是绝对的重新定位,我认为它们不会发生冲突。

我有预感,但在最后的二进制文件中,end_loc正在修复错误的地址。我会把它归咎于多个重定位条目,但奇怪的是,如果我还添加一个虚拟的额外重定位条目,一切都没问题 - 即。我将上面的结构修改为:

#define GEN_DATA(_type) \
    .pushsection .mydata_##_type, "aw"; \
    .ifndef start; \
    start:; \
    .endif; \
    .word 1; \
    .reloc end_loc, R_AARCH64_ABS64, .; \
    .reloc dummy_loc, R_AARCH64_ABS64, .; \
    .popsection

    .pushsection .head, "aw"
    .quad start
    end_loc:
    .quad 0
    dummy_loc:
    .quad 0
    .popsection

所以我想知道:

  • 为什么end_loc错误地修复了?多个绝对重定位条目有什么问题,如果有的话?是不是链接器会按顺序通过它们,最后一个是否生效?

  • 为什么简单地添加虚拟重定位会使一切正常?

基本上,发生了什么?!

最后,我可以尝试其他方法吗?

编辑:我现在已将示例代码推送到Git repository。使用makemake broken=1查看反汇编。需要$PATH中的Linaro AArch64 tool chain

1 个答案:

答案 0 :(得分:0)

我不知道重定位发生了什么,但是你正在尝试完成的最简单的方法是使用链接描述文件。这样,您就可以将所有.mydata_XXX_type部分组合在一起,并为分组部分的开头和结尾提供符号。像这样:

SECTIONS
{
    .mydata :
    {
        start   = .;
        *(.mydata*);
        end_loc = .;
    }
}

您将使用这样的程序集文件:

    .macro gen_data, type
    .pushsection .mydata_\()\type\()_type, "aw"
    .word   1
    .popsection
    .endm

    .text
    gen_data foo
    gen_data bar
    gen_data baz

    .section .head, "aw"
    .quad   start
    .quad   end_loc

(我使用汇编程序宏而不是C宏,因为它们更容易使用。)你可以使用上面这两个文件:

    as -o test.o test.s
    ld -o test test.o test.ld

如果您知道所有可能的“类型”部分,那么您可以在不使用链接描述文件的情况下依赖于链接器按其首次遇到它们的顺序放置未知部分的事实。例如:

    .section .mydata_start, "aw"
start:
    .section .mydata_foo_type, "aw"
    .section .mydata_bar_type, "aw"
    .section .mydata_baz_type, "aw"
    .section .mydata_end, "aw"
end_loc:

    .macro gen_data, type
    .ifndef .mydata_\()\type\()_type
    .error  "gen_data invoked with unknown type '\type\()'"
    .endif
    .pushsection .mydata_\()\type\()_type, "aw"
    .word   1
    .popsection
    .endm

    .text
    gen_data foo
    gen_data bar
    gen_data baz
    # gen_data unk

    .section .head, "aw"
    .quad   start
    .quad   end_loc

如果您使用宏有多个汇编程序文件,请确保所有汇编程序文件在开头都包含上面显示的.section指令,因此它们在链接器命令行中出现的顺序无关紧要。

请注意,这两个解决方案都解决了您的宏的问题,如果碰巧第一次按顺序出现在链接器中,则可能会在.mydata_XXX_type部分之间放置其他未知部分。