如何在 linux amd64 上找到当前线程的 TLS 段?
How to find TLS segments of the current thread on linux amd64?
我正在寻找一种方法来找出 linux、amd64 上当前线程的 TLS 段的内存地址。适用于 OSX.
的解决方案的奖励积分
研究了各种语言运行时或 GC(如 boehm),但到目前为止无法通过多层抽象来支持所有类型的系统。任何帮助表示赞赏。
在 Linux 上,线程特定段是通过 arch_prtcl(ARCH_SET_FS, <addr>)
调用设置的。您可以通过 arch_prctl(ARCH_GET_FS, ...)
.
查看当前线程中设置的内容
Bonus point for a solution that works on OSX.
OSX 是一个完全不同的 OS,并且使用完全不同的机制来支持 TLS。
你看过我和 Martin 在 druntime 中提出的解决方案了吗?
我们在那里所做的归结为扫描类型为 PT_TLS
的段的相应 dl_phdr_info
中的段(通过使用 dl_iterate_phdr
查找正确的段获得),以及存储其模块 ID 和大小。
然后,您可以通过调用 __tls_get_addr
偏移量 0 和模块 ID(某些拱门上有偏移量)来获取当前线程地址范围的开始,并通过简单地添加结束你确定的尺寸。如果你不需要支持共享库,你也可以简单地在 x86 上使用 fs
/gs
(如果你想 link 静态可执行文件可能需要)。
这适用于 Linux 和 FreeBSD(可能还有其他 ELF 平台),但不适用于 OS X。到目前为止,我能想到的最好的是:
void _d_dyld_getTLSRange(void* arbitraryTLSSymbol, void** start, size_t* size) {
dyld_enumerate_tlv_storage(
^(enum dyld_tlv_states state, const dyld_tlv_info *info) {
assert(state == dyld_tlv_state_allocated);
if (info->tlv_addr <= arbitraryTLSSymbol &&
arbitraryTLSSymbol < (info->tlv_addr + info->tlv_size)
) {
// Found the range we are looking for.
*start = info->tlv_addr;
*size = info->tlv_size;
}
}
);
}
</pre>
目前在 LDC 的 druntime 中使用的原始实现并不能很好地处理共享库,而且 dyld_enumerate_tlv_storage
来自 dyld_priv.h
,这可能会也可能不会成为 App Store 发布的问题。
我正在寻找一种方法来找出 linux、amd64 上当前线程的 TLS 段的内存地址。适用于 OSX.
的解决方案的奖励积分研究了各种语言运行时或 GC(如 boehm),但到目前为止无法通过多层抽象来支持所有类型的系统。任何帮助表示赞赏。
在 Linux 上,线程特定段是通过 arch_prtcl(ARCH_SET_FS, <addr>)
调用设置的。您可以通过 arch_prctl(ARCH_GET_FS, ...)
.
Bonus point for a solution that works on OSX.
OSX 是一个完全不同的 OS,并且使用完全不同的机制来支持 TLS。
你看过我和 Martin 在 druntime 中提出的解决方案了吗?
我们在那里所做的归结为扫描类型为 PT_TLS
的段的相应 dl_phdr_info
中的段(通过使用 dl_iterate_phdr
查找正确的段获得),以及存储其模块 ID 和大小。
然后,您可以通过调用 __tls_get_addr
偏移量 0 和模块 ID(某些拱门上有偏移量)来获取当前线程地址范围的开始,并通过简单地添加结束你确定的尺寸。如果你不需要支持共享库,你也可以简单地在 x86 上使用 fs
/gs
(如果你想 link 静态可执行文件可能需要)。
这适用于 Linux 和 FreeBSD(可能还有其他 ELF 平台),但不适用于 OS X。到目前为止,我能想到的最好的是:
void _d_dyld_getTLSRange(void* arbitraryTLSSymbol, void** start, size_t* size) { dyld_enumerate_tlv_storage( ^(enum dyld_tlv_states state, const dyld_tlv_info *info) { assert(state == dyld_tlv_state_allocated); if (info->tlv_addr <= arbitraryTLSSymbol && arbitraryTLSSymbol < (info->tlv_addr + info->tlv_size) ) { // Found the range we are looking for. *start = info->tlv_addr; *size = info->tlv_size; } } ); } </pre>
目前在 LDC 的 druntime 中使用的原始实现并不能很好地处理共享库,而且
dyld_enumerate_tlv_storage
来自dyld_priv.h
,这可能会也可能不会成为 App Store 发布的问题。