【问题标题】:Relocation truncated to fit: R_X86_64_32重定位被截断以适应:R_X86_64_32
【发布时间】:2014-08-14 17:46:32
【问题描述】:

我有一个C 驱动程序文件,它声明了一个extern 函数,以便在我的asm 文件中使用它。我在 Windows 7 x64 机器上。

我使用以下命令将asm 文件与NASM 组装在一起:

nasm avxmain.asm -f win64 -o avxmain.o

然后我像这样编译C文件:

gcc avxdriver.c -c -m64 -o avxdriver.o

把这一切联系在一起,我跑了:

gcc avxdriver.o avxmain.o -o final

这是我得到的错误:

avxmain.o:G:\Desktop\CPSC240:(.text+0x50): 重定位截断为 适合:R_X86_64_32 对 `.bss'

avxmain.o:G:\Desktop\CPSC240:(.text+0xb9): 重定位截断为 适合:R_X86_64_32 对 `.data'

avxmain.o:G:\Desktop\CPSC240:(.text+0xc2): 重定位截断为 适合:R_X86_64_32 对 `.data'

avxmain.o:G:\Desktop\CPSC240:(.text+0x14e):重定位截断为 适合:R_X86_64_32 对 `.bss'

collect2:错误:ld 返回 1 退出 状态


avxdriver.c文件:

#include <stdio.h>
#include <stdint.h>

extern double avxdemo();

int main()
{
    double return_code = -99.9;
    printf("%s","This program will test for the presence of AVX (Advanced Vector Extensions) also known as state component number 2.\n");

    return_code = avxdemo();

    printf("%s %1.12lf\n","The value returned to the driver is ", return_code);
    printf("%s","The driver program will next send a zero to the operating system.  Enjoy your programming.\n");
    return 0;
}

avxmain.asm文件:

http://pastebin.com/CfnjbpXM

因为教授提供的cmets,所以放在这里很长。


我已尝试运行 -fPIC-mcmodel=medium 选项。我仍然遇到同样的错误。 我完全迷茫和困惑,因为这是我应该为我的班级运行的示例项目。这个主题对我来说是全新的。我花了大约半天的时间来搜索这些错误并尝试不同的东西。我只需要指出正确的方向。

【问题讨论】:

  • 你在asm代码中试过default rel吗?
  • @harold 你能解释一下那是什么吗?我仍然是汇编编程的新手,但正在逐步学习它。
  • 基本上相当于在任何地方使用[rel label]使用使用[label]

标签: c gcc assembly extern


【解决方案1】:

问题是一般 x64 指令不允许在其编码中直接使用 64 位地址。有两种解决方法:

  1. 使用movabs rax, symbolNameHere指令将rax设置为地址,然后使用[rax]访问该地址的数据。

  2. 使用[rel symbolNameHere]作为操作数;这将创建一个对symbolNameHere 的相对于 PC 的引用。它被编码为 32 位有符号偏移量,与执行该指令时 rip 的任何值不同。

方法 1 允许您在指令中编码绝对地址,而方法 2 是较小的代码(您可以随时使用lea rax, [rel symbolNameHere] 来获得与方法 1 相同的效果)。

【讨论】:

  • 我应该在哪里进行这些更改?抱歉,我还是 Assembly 的新手。
  • 通常,您只需离开编译器输出引用的任何行。但是因为消息直到链接时间才会出现,所以它们不显示行号。对于初学者,您可以尝试用我的建议替换所有内存引用([] 括号之间的任何内容)。
  • 我讨厌无法理解某人所说的内容,但老实说,我对所有的行话感到迷茫。如果您能指出asm 文件的行号以及我需要具体进行哪些更改,我们将不胜感激。这个作业本应帮助我开始使用汇编编程,但到目前为止它只是一场噩梦。
  • 尝试第 115、156、162 和 311 行。
  • 我现在收到 5 个类似这样的错误:115: error: symbol rip' undefined,每个错误对应于您和 Ross Ridge 建议更改的行号。
【解决方案2】:

您应该在avxmain.o 上使用objdump -d 来找出链接器抱怨的语句。但是很清楚哪些指令是问题所在:

xrstor     [backuparea]
vmovupd ymm0, [testdata]  
vmovupd ymm1, [testdata+32] 
xsave      [backuparea] 

正如 Drew McGowen 所解释的,问题在于 64 位指令集无法将这些地址编码为指令中的 64 位值。相反,它们变为 32 位有符号位移,这些位移经过有符号扩展至 64 位以创建有效地址。显然,Windows 在从0xFFFFF88`00000000 开始的地址范围内加载 64 位驱动程序,截断的 32 位位移不会将符号扩展回正确的值。

您应该能够像 Drew McGowen 建议的那样使用 RIP 相对寻址来解决该问题。在这种情况下,汇编器应该生成链接器不会抱怨的 PC 相对(RIP 相对)重定位:

xrstor     [rel backuparea]
vmovupd ymm0, [rel testdata]  
vmovupd ymm1, [rel + testdata+32] 
xsave      [rel backuparea] 

【讨论】:

  • 我已经更新了我的答案,其中包含有关 Windows 在何处加载 64 位驱动程序的正确信息。
猜你喜欢
  • 2014-08-13
  • 1970-01-01
  • 2013-12-25
  • 2016-05-01
  • 2016-04-03
  • 2018-04-06
  • 2020-05-23
  • 2015-10-20
相关资源
最近更新 更多