Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linker MIPS、ELF和部分链接_Linker_Shared Libraries_Mips_Elf_Binutils - Fatal编程技术网

Linker MIPS、ELF和部分链接

Linker MIPS、ELF和部分链接,linker,shared-libraries,mips,elf,binutils,Linker,Shared Libraries,Mips,Elf,Binutils,我有一个大型软件项目,其构建过程非常复杂,其工作原理如下: 50: 8f9e0000 lw s8,0(gp) 50: R_MIPS_GOT16 $SYMBOLNAME 54: 8fd9001c lw t9,28(s8) 58: 0320f809 jalr t9 5c: 00a02021 move a0,a1 编译单个源文件 使用ld-

我有一个大型软件项目,其构建过程非常复杂,其工作原理如下:

50:   8f9e0000        lw      s8,0(gp)
                      50: R_MIPS_GOT16        $SYMBOLNAME
54:   8fd9001c        lw      t9,28(s8)
58:   0320f809        jalr    t9
5c:   00a02021        move    a0,a1
  • 编译单个源文件
  • 使用
    ld-r
    将每个模块的对象文件部分链接到另一个.o中
  • 使用
    objcopy-G
    隐藏每个模块中的专用符号
  • 再次使用
    ld-r
    将模块对象部分链接在一起
  • 将模块链接到一个共享对象中
  • 步骤3是允许不导出到项目其余部分的模块专用全局变量所必需的

    这一切都与ARM和IA32配合得很好。不幸的是,现在我必须在mips上工作(特别是针对Android的mipsel linux gnu)。MIPS共享对象ABI比其他平台上的要复杂得多,而且不起作用

    发生的情况是,步骤5因以下错误而失败:

    CALL16 reloc at 0x1234 not against global symbol
    
    这似乎是因为编译器生成CALL16重定位来调用另一个编译单元中的函数,但CALL16只允许您调用全局符号——而且由于步骤3,我们尝试调用的一些符号不再是全局的

    在这一点上,我可以看到几个可能的选择:

    • 在步骤2,说服链接器将CALL16重定位解析为正常的编译单元内部PC相对调用
    • 同上,但在步骤4或5
    • 告诉编译器不要为编译单元间函数调用生成CALL16重定位
    • 其他的
    由于外部要求,禁用步骤3恐怕不是一个选项

    我真正想做的是生成绝对代码,在加载时将其修补到正确的地址;它更小、更快、更简单,而且我们不需要在进程之间共享库。不幸的是,Android的
    dlopen()
    似乎不支持这一点

    目前我的能力已经超出了我的能力范围。有人有什么建议吗

    这是gcc 4.4.5(来自Emdebian),binutils 2.20.1。目标BFD是elf32 Tradlemips。主机操作系统是Linux,我正在为Android进行交叉编译

    附录

    我也从第4步收到类似的警告

    $MODULE.o: Can't find matching LO16 reloc against `$SYMBOLNAME' for R_MIPS_GOT16 at 0x18 in section `.text.$SYMBOLNAME'
    
    查看步骤4输入的反汇编,我可以看到编译器生成的代码如下所示:

    50:   8f9e0000        lw      s8,0(gp)
                          50: R_MIPS_GOT16        $SYMBOLNAME
    54:   8fd9001c        lw      t9,28(s8)
    58:   0320f809        jalr    t9
    5c:   00a02021        move    a0,a1
    
    GOT16不等于地址的高半部,而低半部应该紧跟着LO16吗?但是代码看起来像是在做一个GET间接寻址。这让我困惑。我不知道这是否与我之前的问题有关,或者是另一个问题,或者根本不是问题

    更新

    显然,MIPS根本不支持隐藏的全局符号

    我们通过弄乱应该隐藏的符号的名称来绕过它,这样就没有人能分辨出它们是什么。这在很大程度上推动了外部需求,但我通过指出这是获得可交付产品的唯一途径来推销管理层


    这太可怕了(还涉及到一些非常讨厌的makefile工作),所以我希望有一个更好的解决方案,如果有人有一个…

    我不确定您遇到的具体问题。binutils中的GOT、LO16/HI16内容存在很多错误和问题。我认为大多数已经在您使用的版本中修复,除非您针对的是MIPS16(您似乎没有这样做)。LO16实际上只有在那里才是必要的,除了MIPS16之外,因为您有32位寄存器,所以要从GOT中提取完整的26位偏移量。LO16是不需要的,但仍然是一些ABI/API正式要求的,但它被篡改为最多一个警告(如果您正在使用它,您可以尝试在该阶段删除-Werror)。老实说,我只了解这一部分的基本情况,对于你的其他情况,我有一些建议,如果没有答案的话(考虑到你的设置的复杂性,很难确定)

    在MIPS(以及我熟悉的大多数程序集)中,您有三个基本的可见性级别:本地、全局和弱。此外,您还有用于共享对象的comm。当然,GNU喜欢让事情变得更复杂,增加更多。gas提供了受保护、隐藏和内部(最低限度,很难跟上所有扩展)。有了所有这些,手动设置可见性的步骤似乎是不必要的

    如果您可以删除变量的中间全局性,那么它应该可以删除您需要使它们成为非全局性的变量,这只能简化您以后遇到的任何GET问题

    总体问题有点令人困惑。我不确定你所说的隐藏的全局符号是什么意思,这有点矛盾(当然,可移植性和特定的项目会带来疯狂的问题和限制)。您似乎希望在某个阶段使用跨部件单元符号,但不希望在以后的阶段使用跨部件单元符号。在不使用GNU扩展的情况下(在我的书中最好避免),您可能希望用comm和/或weakglobals替换步骤1-2中的globals。您可以始终使用预处理器技巧来避免在阶段中使用多个子单元(虽然很难看,但这是此级别的可移植代码)

    你真的有一个1)子模块2)子模块->模块3-5)模块->共享库的设置。简化这不会有什么坏处。您总是可以在2)或3-5)处插入C级接口,只是为了找到GCC将为您的体系结构生成的组件,并将其用作将可见性分解为干净接口的基础


    希望我能给你一个量身定做的解决方案,但如果没有你的整个项目,这是不可能的。我可以保证,虽然MIPS位置(特别是工具链)有问题,但可见性选项(特别是在使用gas、libbfd和gcc时)是相同的

    你的头发太老了。2.23中的一些变更集可能会解决您的问题,例如“隐藏没有PLT的符号,也不获取引用”