libc 中的 strcmp 和 strcmp_sse 函数
strcmp and strcmp_sse functions in libc
我在 libc.so 中看到要调用的 strcmp_sse 的实际类型由函数 strcmp 本身决定。
这是代码:
strcmp:
.text:000000000007B9F0 cmp cs:__cpu_features.kind, 0
.text:000000000007B9F7 jnz short loc_7B9FE
.text:000000000007B9F9 call __init_cpu_features
.text:000000000007B9FE
.text:000000000007B9FE loc_7B9FE: ; CODE XREF: .text:000000000007B9F7j
.text:000000000007B9FE lea rax, __strcmp_sse2_unaligned
.text:000000000007BA05 test cs:__cpu_features.cpuid._eax, 10h
.text:000000000007BA0F jnz short locret_7BA2B
.text:000000000007BA11 lea rax, __strcmp_ssse3
.text:000000000007BA18 test cs:__cpu_features.cpuid._ecx, 200h
.text:000000000007BA22 jnz short locret_7BA2B
.text:000000000007BA24 lea rax, __strcmp_sse2
.text:000000000007BA2B
.text:000000000007BA2B locret_7BA2B: ; CODE XREF: .text:000000000007BA0Fj
.text:000000000007BA2B ; .text:000000000007BA22j
.text:000000000007BA2B retn
我不明白的是strcmp_sse调用函数的地址是放在rax里面的,从来没有真正调用过。因此我想知道:谁会调用 *rax?什么时候?
Linux 动态链接器支持一种名为 STT_GNU_IFUNC 的特殊符号类型。 Strcmp 可能作为 IFUNC 实现。 'Regular' 动态库中的符号只不过是从名称到地址的映射。 IFUNC 比这复杂一点:地址不容易获得,为了获得它,链接器必须从库本身执行一段代码。我们在这里看到了这样一段代码的示例。请注意,在 x86_64 ABI 中,函数 returns RAX 中的结果。
此技术通常用于根据 CPU 特征选择最佳实现。请注意,选择逻辑只运行一次;除了对 strcmp 的第一次调用外,所有调用都很快。
我在 libc.so 中看到要调用的 strcmp_sse 的实际类型由函数 strcmp 本身决定。
这是代码:
strcmp:
.text:000000000007B9F0 cmp cs:__cpu_features.kind, 0
.text:000000000007B9F7 jnz short loc_7B9FE
.text:000000000007B9F9 call __init_cpu_features
.text:000000000007B9FE
.text:000000000007B9FE loc_7B9FE: ; CODE XREF: .text:000000000007B9F7j
.text:000000000007B9FE lea rax, __strcmp_sse2_unaligned
.text:000000000007BA05 test cs:__cpu_features.cpuid._eax, 10h
.text:000000000007BA0F jnz short locret_7BA2B
.text:000000000007BA11 lea rax, __strcmp_ssse3
.text:000000000007BA18 test cs:__cpu_features.cpuid._ecx, 200h
.text:000000000007BA22 jnz short locret_7BA2B
.text:000000000007BA24 lea rax, __strcmp_sse2
.text:000000000007BA2B
.text:000000000007BA2B locret_7BA2B: ; CODE XREF: .text:000000000007BA0Fj
.text:000000000007BA2B ; .text:000000000007BA22j
.text:000000000007BA2B retn
我不明白的是strcmp_sse调用函数的地址是放在rax里面的,从来没有真正调用过。因此我想知道:谁会调用 *rax?什么时候?
Linux 动态链接器支持一种名为 STT_GNU_IFUNC 的特殊符号类型。 Strcmp 可能作为 IFUNC 实现。 'Regular' 动态库中的符号只不过是从名称到地址的映射。 IFUNC 比这复杂一点:地址不容易获得,为了获得它,链接器必须从库本身执行一段代码。我们在这里看到了这样一段代码的示例。请注意,在 x86_64 ABI 中,函数 returns RAX 中的结果。
此技术通常用于根据 CPU 特征选择最佳实现。请注意,选择逻辑只运行一次;除了对 strcmp 的第一次调用外,所有调用都很快。