首页 > 解决方案 > -O2 函数作用域静态 TLS 上的 LLD 错误不能用于使用 -fPIC 重新编译符号

问题描述

我正在使用 LLVM 的 LLD8 来替换 GNU-LD 以提高链接速度。但是当我制作.so文件时,发布模式出现了一个奇怪的错误。精简后,我用一个简单的例子重现了这个问题

测试.h:

#ifndef TEST_H
#define TEST_H

inline int func(){
  static __thread int i = 1;
  return i;
}

void handle();

#endif

测试.cpp

#include <iostream>
#include <stdio.h>
#include "test.h"

void handle() {
  std::cout << func() << std::endl;
}

主文件

#include "test.h"

void x(){
  handle();
}

在我的项目中从 make V=1 stdout 复制的 cmds 之后,我将这些 cmds 保存到脚本中并编译我的示例文件

编译库:

$dpath/bin/g++ -DLT_OBJDIR=\".libs/\" -I. -I$dpath/include/ -w -std=gnu++11 -g -O2 -D_GLIBCXX_USE_CXX11_ABI=0 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -Wall -Werror -Wextra -Wunused-parameter -Wformat -Wconversion -Wno-deprecated -Wno-invalid-offsetof -finline-functions -fno-strict-aliasing -mtune=core2 -Wno-psabi -Wno-sign-compare -Wno-literal-suffix -DGCC_52 -DUSE_POSIX_FALLOCATE -DSUPPORT_SSE4_2 -DHAVE_SCHED_GETCPU -DHAVE_REALTIME_COARSE -DHAVE_FALLOCATE -c test.cpp  -fPIC -DPIC -o .libs/test.o

链接库

ar cru .libs/lib.a .libs/test.o
ranlib .libs/lib.a

编译文件

$dpath/bin/g++ -DLT_OBJDIR=\".libs/\" -I. -I$dpath/include -std=gnu++11 -g -O2 -D_GLIBCXX_USE_CXX11_ABI=0 -D_NO_EXCEPTION -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -DNDEBUG -Wall -Werror -Wextra -Wunused-parameter -Wformat -Wconversion -Wno-deprecated -Wno-invalid-offsetof -finline-functions -fno-strict-aliasing -mtune=core2 -Wno-psabi -Wno-sign-compare -Wno-literal-suffix -DGCC_52 -DUSE_POSIX_FALLOCATE -DSUPPORT_SSE4_2 -DHAVE_SCHED_GETCPU -DHAVE_REALTIME_COARSE -DHAVE_FALLOCATE -c main.cpp  -fPIC -DPIC -o .libs/main.o

链接所以

$dpath/bin/ld.lld -shared -nostdlib .libs/main.o -l:lib.a -L./.libs -L/usr/lib64 -L$glib/gcc/x86_64-unknown-linux-gnu/5.2.0 -L$glib/gcc -L$glib/../lib64 -L$glib -L$dpath/lib/libstdc++.so --allow-shlib-undefined -soname server.so.0 -o ./server.so.0.0.0

最后我得到了这个错误

ld.lld: error: can't create dynamic relocation R_X86_64_DTPOFF32 against symbol: func()::i in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in ./.libs/lib.a(test.o)
>>> referenced by test.cpp:6
>>>               test.o:(handle()) in archive ./.libs/lib.a

如您所见,我已经在我的 cmds 中传递了 -fPIC,所以我将 -znotext 传递给 lld 但我又遇到了另一个错误

ld.lld: error: relocation R_X86_64_DTPOFF32 cannot be used against symbol func()::i; recompile with -fPIC
>>> defined in ./.libs/lib.a(test.o)
>>> referenced by test.cpp:6`enter code here`
>>>               test.o:(handle()) in archive ./.libs/lib.a

此错误仅在我以发布模式编译项目时报告,当我删除 -O2 时,它链接良好。但是当我使用在调试模式下链接的 so/bin 来运行测试用例时,我在使用函数作用域静态 tls 的代码周围得到了很多无异常的核心转储。

标签: c++llvmldthread-locallld

解决方案


推荐阅读