C 如何修复本地符号';在发生共享对象错误时不能使用?

C 如何修复本地符号';在发生共享对象错误时不能使用?,c,makefile,arm,linker-errors,C,Makefile,Arm,Linker Errors,我编译c源文件失败,出现以下错误: libservices.a(protocol.o):在创建共享对象时,不能使用针对“本地符号”的重新定位R_ARM_MOVW_ABS_NC;使用-fPIC重新编译 libservices.a:添加符号时出错:错误值collect2.exe: 错误:ld返回了1个退出状态 除了在源目录中添加一个额外的文件外,我没有做任何更改,一切都很艰难。虽然我没有使用-fPIC选项,但在没有这些警告的情况下,它工作正常。由于我没有做任何文件更改,我很想知道为什么会出现这个错误

我编译c源文件失败,出现以下错误:

libservices.a(protocol.o):在创建共享对象时,不能使用针对“本地符号”的重新定位R_ARM_MOVW_ABS_NC;使用-fPIC重新编译
libservices.a:添加符号时出错:错误值collect2.exe:
错误:ld返回了1个退出状态


除了在源目录中添加一个额外的文件外,我没有做任何更改,一切都很艰难。虽然我没有使用
-fPIC
选项,但在没有这些警告的情况下,它工作正常。由于我没有做任何文件更改,我很想知道为什么会出现这个错误,这是什么意思,以及如何摆脱这个问题。非常感谢您的帮助。

这取决于您将哪些类型的文件添加到源文件夹中。 例如,如果您添加了一个新的库文件,并且该新库文件是根据-fPIC build选项生成的,那么您可能会遇到类似的情况

实际上,错误消息为您提供了足够的信息来修复它。 可以通过“-fPIC”构建选项重新编译它

  • 如果您是通过命令行进行构建,请在命令中添加附录“-fPIC” 线路
  • 如果您是通过Makefiles进行构建,请按以下方式修改Makefiles:

    CFLAGS+=-fPIC

  • 有关ARM编译器,请参阅

  • 有关GCC编译器,请参阅

您应该使用-fPIC编译。看

非PIC代码在重新定位到其他地址时需要修改。这些二进制代码和数据的修改称为重定位。有许多不同类型的重新安置。它们可能涉及将符号的绝对地址放入数据字,或修改MOVW或MOVT指令的某些位,以将常量的一部分放入指令本身。后者是你的问题

在链接可执行文件时,静态链接器将执行所有这些重定位。如果使用共享库,则动态链接器必须在可执行文件运行并动态链接到共享库时执行这些操作

动态链接器可能不支持某些类型的重定位(称为文本重定位或TEXTRELS)。这些操作包括使用实际代码修改文本段,并将值放入指令中。由于它修改了代码,共享库的这一部分将不再在进程之间共享。您应该通过-fPIC使库位置独立,因此动态链接器不需要执行文本重定位

您以前的代码可能没有导致编译器发出任何需要不受支持的重新定位的内容。然后你添加的文件中就有了这样的东西。例如,访问全局变量可以在ARM上触发此操作

int x = 1;
void foo(void) { x=42; }
汇编至:

    movw    r3, #:lower16:x
    mov     r2, #42
    movt    r3, #:upper16:x
    str     r2, [r3]
    bx      lr
x地址的下半部分和上半部分需要放在movw和movt指令中。动态链接器不支持此操作。如果代码是使用-fPIC(或-mword重定位)编译的,编译器将生成不需要这些重定位的不同输出


“protocol.o”具有不受支持的重新定位,在您进行更改之前,它不存在、未使用或没有重新定位。如果libservice.a已经存在,请记住,静态库中的代码只有在被使用时才会被包含。也许“protocol.o”没有被任何东西使用,但无论你添加了什么,都会使用它。

我在我的应用程序中添加了新的.c源文件,我没有添加任何新的库文件,在这种情况下,我不必将它们构建为独立于位置的二进制文件,不是吗,因为以前没有