简体   繁体   English

这是GCC /链接器错误吗? (共享库中名为“错误”的变量)

[英]Is this is a GCC/linker bug? (variable named 'error' inside shared library)

I've probably encountered a bug in GCC or linker that happens when there's a global variable named 'error' in a shared library loaded at run-time. 我可能在GCC或链接器中遇到了一个错误,该错误发生在在运行时加载的共享库中有一个名为“错误”的全局变量时。 At first glance it looks like there's something else in the text segment named 'error' that shadows this variable. 乍一看,似乎在文本段中有名为“错误”的其他内容遮盖了此变量。

foo.c: foo.c的:

#include <stdio.h>

const char *error = "error";
const char *error2 = "error2";

void bar(void)
{
    printf("%p\n", error2);
    printf("%p\n", error);
    printf("%s\n", error2);
    printf("%s\n", error);
}

main.c: main.c中:

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>

int main(int argc, char **argv) 
{
   void *lib_handle;
   void (*fn)(void);
   char *err;

   lib_handle = dlopen("./libfoo.so", RTLD_LAZY);
   if (!lib_handle) 
   {
      fprintf(stderr, "%s\n", dlerror());
      exit(1);
   }

   fn = dlsym(lib_handle, "bar");
   if ((err = dlerror()) != NULL)  
   {
      fprintf(stderr, "%s\n", err);
      exit(1);
   }

   (*fn)();

   dlclose(lib_handle);
   return 0;
}

Compilation and run output: 编译并运行输出:

gcc -g -Wall -pedantic -fpic -O0 -c foo.c -o foo.o
gcc -shared -o libfoo.so  foo.o
gcc main.c -Wall -fpic -o main -ldl
./main
0x7f62bc42c82b
0xfb8953f589555441
error2
Segmentation fault (core dumped)

Is this a toolchain bug? 这是一个工具链错误吗? If so, what could cause this and where should it be reported? 如果是这样,可能是什么原因引起的,应在哪里报告?

I believe that is as designed, a symbol already loaded will take precedence. 我相信按照设计,已加载的符号将具有优先权。 eg if there's any error/error2 (or bar) symbol already loaded, the same named symbols from your shared library will not be relocated. 例如,如果已经加载了任何错误/错误2(或条形)符号,则不会重定位共享库中相同名称的符号。 do eg nm -D /lib/libc.so.6 |grep error. 例如执行nm -D /lib/libc.so.6 | grep错误。 Your code will refer to the error symbol there, whatever that is. 您的代码将引用那里的错误符号,无论是什么。

However, 然而,

$nm -D /lib/libc.so.6 |grep error`
42471670 W error

This shows that glibc defines an error symbol, but it's weakly defined. 这表明glibc定义了一个error符号,但是定义很弱。

This means that if your code, at link time, defines the same symbol, yours will override any weakly defined symbols. 这意味着,如果您的代码在链接时定义了相同的符号,则您的代码将覆盖所有弱定义的符号。 But that does not happen when you dynamically load a library. 但是,当您动态加载库时,不会发生这种情况。 That behavior can be overridden by setting the environment variable LD_DYNAMIC_WEAK - see man ld.so for more info. 这种行为可以通过设置环境变量来覆盖LD_DYNAMIC_WEAK看到的- 男人ld.so获取更多信息。

So if you run your program like so: 因此,如果您像这样运行程序:

 $ LD_DYNAMIC_WEAK=true ./main

it will work 它会工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM