【发布时间】:2013-01-25 21:21:29
【问题描述】:
我正在为非常小的静态链接程序实现libc 的一小部分,我认为添加 TLS 支持将是一个很好的学习体验。我使用Ulrich Drepper's TLS document 作为参考。
我设置了两个字符串来试试这个:
static __thread const char msg1[] = "TLS (1).\n"; /* 10 bytes */
static __thread const char msg2[] = "TLS (2).\n"; /* 10 bytes */
并且编译器生成以下指令来访问它们:
mov rbx, QWORD PTR fs:0x0 ; Load TLS.
lea rsi, [rbx-0x14] ; Get a pointer to 'msg1'. 20 byte offset.
lea rsi, [rbx-0xa] ; Get a pointer to 'msg2'. 10 byte offset.
假设我将 TCB 放在堆栈上的某个位置:
struct tcb {
void* self; /* Points to self. I read that this was necessary somewhere. */
int errno; /* Per-thread errno variable. */
int padding;
};
然后将 TLS 区域放在它旁边的 tls = &tcb - tls_size。然后我设置FS寄存器指向fs = tls + tls_size,并将TLS初始化镜像复制到tls。
但是,这不起作用。我已经通过将tls_image 的20 个字节写入stdout 来验证我正确定位了TLS 初始化映像。这要么让我相信我错误地放置了 TCB 和/或 TLS 区域,要么我不符合 ABI。
- 我使用
arch_prctl(2)设置FS 寄存器。我是否需要以某种方式使用set_thread_area(2)? - 我没有
dtv。我假设这不是必需的,因为我是静态链接的。
关于我做错了什么有什么想法吗?非常感谢!
【问题讨论】:
-
如果你在 Linux 上工作,你应该尝试习惯 AT&T 语法。
-
不确定你有什么问题,但看看我们在 musl 中的实现可能会有所帮助:git.musl-libc.org/cgit/musl/tree/src/env/__init_tls.c
-
@R.. 很好的参考。但我不明白
libc.tls_size = 2*sizeof(void *)+size+align+sizeof(struct pthread);和mem += sizeof(void *) * 2;中的两个空指针是干什么用的? -
好点 - 这可能应该被评论。不看代码,我怀疑它是为 dtv 准备的。
-
请注意,原则上,
__tls_get_addr也需要适用于静态链接程序,因为没有要求链接器执行 TLS 优化,并且特定的目标文件可能已使用需要它的模型构建(例如,如果使用-fPIC,通常会出现这种情况)。但是,由于只有一个 TLS 段,__tls_get_addr并不真正需要 dtv 来操作。
标签: c linux x86-64 libc thread-local-storage