Problem
try 运行这个代码
if (!dlopen("../lib/libMy.so", RTLD_NOW)) {
std::cout << dlerror() << std::endl;
return 1;
}
导致了TLS(线程本地存储)错误:
无法在静态TLS块中分配内存
Solution
转储线程本地存储部分.tbss
(静态和非静态非初始化线程本地变量)显示Tls_ErrorStruct
大小为600字节(0x258),Tls_tv
大小为1600字节(0x640),总计为2200个TLS字节:
$ objdump -C -t ../lib/libMy.so | grep -F '.tbss'
00000000000008e8 l .tbss 0000000000000008 runtime.tlsg
0000000000000010 l .tbss 0000000000000001 __tls_guard
0000000000000688 l .tbss 0000000000000001 __tls_guard
...
0000000000000690 g .tbss 0000000000000258 Tls_ErrorStruct
...
0000000000000018 g .tbss 0000000000000640 Tls_tv
为了修复块错误,这thread_local
个变量被减少到约600字节.第dlopen
章成功了
Note
判断需要多少线程本地存储(TLS)0x0008f0
$ readelf -Wl ../lib/libMy.so
Elf file type is DYN (Shared object file)
Entry point 0x0
There are 10 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x48ada8 0x48ada8 R 0x1000
LOAD 0x48b000 0x000000000048b000 0x000000000048b000 0xdab271 0xdab271 R E 0x1000
LOAD 0x1237000 0x0000000001237000 0x0000000001237000 0x2c0564 0x2c0564 R 0x1000
LOAD 0x14f76a0 0x00000000014f86a0 0x00000000014f86a0 0xd16172 0xd6ec50 RW 0x1000
DYNAMIC 0x20b58c0 0x00000000020b68c0 0x00000000020b68c0 0x000220 0x000220 RW 0x8
NOTE 0x000270 0x0000000000000270 0x0000000000000270 0x000088 0x000088 R 0x4
TLS 0x14f76a0 0x00000000014f86a0 0x00000000014f86a0 0x000001 0x0008f0 R 0x8
GNU_EH_FRAME 0x13fa440 0x00000000013fa440 0x00000000013fa440 0x02358c 0x02358c R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x14f76a0 0x00000000014f86a0 0x00000000014f86a0 0xbc3960 0xbc3960 R 0x1
Question
我不知道如何找到动态加载器线程本地存储块大小,但确实找到了一个可能的引用here:
/* Size of the static TLS block. Giving this initialized value
preallocates some surplus bytes in the static TLS area. */
size_t _dl_tls_static_size = 2048;
有没有一个linux工具或一些C++方法来确定最大线程本地存储块大小?