【发布时间】:2021-04-22 07:31:04
【问题描述】:
我使用GDB 跟踪glibc-2.27。在sysdeps/unix/sysv/linux/getsysstats.c中的178行,有一个thread local storage访问,如下图:
while (l < re && isspace (*l))
IIUC,isspace() 似乎访问了 table mapping ASCII 字符到符号类型,以快速确定当前字符是否为空格。这张表似乎是TLS。相关拆解如下:
0x7f8f9ef480de <__GI___get_nprocs+318> mov 0x2cbd1b(%rip),%rax # 0x7f8f9f213e00
0x7f8f9ef480e5 <__GI___get_nprocs+325> mov %fs:(%rax),%rdi
rax 包含0xffffffffffffff98,IIUC 表示表的地址,对于每个线程,使用以下等式计算:@987654333 @。当我使用这个等式查找每个线程的表地址时,它们都返回相同值0x00007f8f9732b82c。如下所示:
(gdb) thread apply all x/2x $fs_base + 0xffffffffffffff98
Thread 47 (Thread 22457.22471):
0x7f8f75dfc698: 0x9732b82c 0x00007f8f
Thread 46 (Thread 22457.22470):
0x7f8f768fd698: 0x9732b82c 0x00007f8f
Thread 45 (Thread 22457.22469):
0x7f8f773fe698: 0x9732b82c 0x00007f8f
Thread 44 (Thread 22457.22468):
0x7f8f77eff698: 0x9732b82c 0x00007f8f
Thread 43 (Thread 22457.22467):
0x7f8f80a53698: 0x9732b82c 0x00007f8f
Thread 37 (Thread 22457.22465):
0x7f8f81c55698: 0x9732b82c 0x00007f8f
Thread 36 (Thread 22457.22464):
0x7f8f82456698: 0x9732b82c 0x00007f8f
Thread 35 (Thread 22457.22463):
0x7f8f8e6b0698: 0x9732b82c 0x00007f8f
Thread 34 (Thread 22457.22461):
0x7f8f8f480698: 0x9732b82c 0x00007f8f
Thread 33 (Thread 22457.22460):
0x7f8f94824698: 0x9732b82c 0x00007f8f
Thread 32 (Thread 22457.22459):
0x7f8f9649f698: 0x9732b82c 0x00007f8f
Thread 31 (Thread 22457.22458):
0x7f8f96ea0698: 0x9732b82c 0x00007f8f
Thread 30 (Thread 22457.22457):
0x7f8fa2570a18: 0x9732b82c 0x00007f8f
Thread 29 (Thread 22457.22466):
0x7f8f81454698: 0x9732b82c 0x00007f8f
我认为TLS 是每个线程专有的,但是在这里,所有线程使用相同强>变量0x00007f8f9732b82c。为什么会这样?似乎链接器识别变量是read-only 并且节省一些空间?
【问题讨论】:
-
验证
fs_base在每个线程中给出不同的值。我认为 gdb 可能会在thread apply之前替换$fs_base,因此它对所有线程使用当前线程的值。手动切换线程并检查。 -
我查过了。它们是不同的。你所说的对
$fs是正确的,not$fs_base(在GDB 8中引入以解决问题)。
标签: assembly linker gdb glibc thread-local-storage