什么是_dl_lookup_symbol_x?-C++评测
What is _dl_lookup_symbol_x ? - C++ Profiling
我正在使用valgrind/callgrind来评测我的服务器代码以进行一些优化。callgrind向我报告的两个最常用的调用(使用kcachegrind查看)是_dl_lookup_symbol_x和do_lookup_x。然而,我不知道这两种都是什么,似乎也找不到任何关于它们的文档。
有人能告诉我这两个函数在哪里使用以及它们的作用吗?
_dl_lookup_symbol_x
是glibc运行库中的一个内部函数。如果您浏览glibc的源代码,您会在_dl_lookup_symbol_x
定义上方找到以下注释:
/* Search loaded objects' symbol tables for a definition of the symbol
UNDEF_NAME, perhaps with a requested version for the symbol.
do_lookup_x
仅仅是在_dl_lookup_symbol_x
函数内调用的辅助函数。
我不是glibc内部的专家,但据我所知,_dl_lookup_symbol_x
在程序加载的共享库中查找符号(如函数)。
我不知道为什么在你的评测中经常调用这些函数,但至少现在你对它们的作用有了一些了解。你的评测应该告诉你哪些函数负责如此频繁地调用_dl_lookup_symbol_x
。
请注意,当程序首次启动时,_dl_lookup_symbol_x
被多次调用是正常的,因为运行时会计算出具有给定名称的共享库函数的地址。如果你正在分析一个非常短命的程序,那么你会发现大部分时间都花在了内部"内务管理"功能上,而不是你自己的代码上,这并不奇怪。
dl_lookup_symbol从_dl_fixup调用,后者从_dl_runtime_resolve_sse 调用
在gdb中,如果您中断了第一个函数调用,任何调用,然后在延迟链接中(这是使用gcc时的默认设置),函数的地址实际上不会被解析,直到该调用几乎返回到main。进程用来解析函数地址的函数之一是dl_lookup_symbol,因此对于每个使用延迟链接的程序调用的每个函数,几乎所有程序都应该看到一次。
源代码:
#include <stdio.h>
#include <string.h>
int main (void)
{
size_t a = strlen("Hello");
printf("%s is %d lettersn", "Hello", a);
if (a != sizeof("Hello") - 1)
{
perror("What?");
}
size_t b = strlen("Bye");
printf("%s is %d lettersn", "Bye", b);
if (b != sizeof("Bye") - 1)
{
perror("What?");
}
return 0;
}
去gdb:
(gdb) disas
Dump of assembler code for function main:
0x0000555555554700 <+0>: push rbp
0x0000555555554701 <+1>: mov rbp,rsp
0x0000555555554704 <+4>: sub rsp,0x10
0x0000555555554708 <+8>: mov QWORD PTR [rbp-0x8],0x5
0x0000555555554710 <+16>: mov rax,QWORD PTR [rbp-0x8]
0x0000555555554714 <+20>: mov rdx,rax
0x0000555555554717 <+23>: lea rsi,[rip+0xf6] # 0x555555554814
0x000055555555471e <+30>: lea rdi,[rip+0xf5] # 0x55555555481a
0x0000555555554725 <+37>: mov eax,0x0
=> 0x000055555555472a <+42>: call 0x5555555545a0 <printf@plt>
0x000055555555472f <+47>: cmp QWORD PTR [rbp-0x8],0x5
0x0000555555554734 <+52>: je 0x555555554742 <main+66>
0x0000555555554736 <+54>: lea rdi,[rip+0xef] # 0x55555555482c
0x000055555555473d <+61>: call 0x5555555545b0 <perror@plt>
0x0000555555554742 <+66>: mov QWORD PTR [rbp-0x10],0x3
0x000055555555474a <+74>: mov rax,QWORD PTR [rbp-0x10]
0x000055555555474e <+78>: mov rdx,rax
0x0000555555554751 <+81>: lea rsi,[rip+0xda] # 0x555555554832
0x0000555555554758 <+88>: lea rdi,[rip+0xbb] # 0x55555555481a
0x000055555555475f <+95>: mov eax,0x0
0x0000555555554764 <+100>: call 0x5555555545a0 <printf@plt>
0x0000555555554769 <+105>: cmp QWORD PTR [rbp-0x10],0x3
0x000055555555476e <+110>: je 0x55555555477c <main+124>
0x0000555555554770 <+112>: lea rdi,[rip+0xb5] # 0x55555555482c
0x0000555555554777 <+119>: call 0x5555555545b0 <perror@plt>
0x000055555555477c <+124>: mov eax,0x0
0x0000555555554781 <+129>: leave
0x0000555555554782 <+130>: ret
在进入printf之后,以下是懒惰链接的神奇结果在完成后显示的地方。在这里,我只是展示了当我完成这一步时,程序会遍历,但一旦printf被解决,如果我在上执行
0x00005555555545a0 <+0>: jmp QWORD PTR [rip+0x200a72]
程序将直接进入printf。因此,下一次调用函数时,jmp QWORD PTR[rip+0x200a72]将直接转到printf。在这一点之后,直到函数返回main的所有代码都只是printf地址的解析,并且只在第一次调用函数时发生
(gdb) disas
Dump of assembler code for function printf@plt:
=> 0x00005555555545a0 <+0>: jmp QWORD PTR [rip+0x200a72] # 0x555555755018
0x00005555555545a6 <+6>: push 0x0
0x00005555555545ab <+11>: jmp 0x555555554590
(gdb) disas
Dump of assembler code for function printf@plt:
=> 0x00005555555545a0 <+0>: jmp QWORD PTR [rip+0x200a72] # 0x555555755018
0x00005555555545a6 <+6>: push 0x0
0x00005555555545ab <+11>: jmp 0x555555554590
End of assembler dump.
(gdb) stepi
0x00005555555545a6 in printf@plt ()
(gdb) disas
Dump of assembler code for function printf@plt:
0x00005555555545a0 <+0>: jmp QWORD PTR [rip+0x200a72] # 0x555555755018
=> 0x00005555555545a6 <+6>: push 0x0
0x00005555555545ab <+11>: jmp 0x555555554590
End of assembler dump.
(gdb) stepi
0x00005555555545ab in printf@plt ()
(gdb) disas
Dump of assembler code for function printf@plt:
0x00005555555545a0 <+0>: jmp QWORD PTR [rip+0x200a72] # 0x555555755018
0x00005555555545a6 <+6>: push 0x0
=> 0x00005555555545ab <+11>: jmp 0x555555554590
介入。不知道gdb为什么不接收这些,它们只是.plt表中的指令。是的,地址不一样,我的系统在我们启动之前就给所有东西添加了0x555555554000
(gdb) stepi
0x0000555555554590 in ?? ()
(gdb) disas
No function contains program counter for selected frame.
(gdb) stepi
0x0000555555554596 in ?? ()
(gdb) disas
No function contains program counter for selected frame.
,证明:
$ gdb -q ./simpletest
Reading symbols from ./simpletest...done.
(gdb) break _start
Breakpoint 1 at 0x5d0
(gdb) run
Starting program: /flerb/flerb/flerb/simpletest
Breakpoint 1, 0x00005555555545d0 in _start ()
(gdb)
来自objdump:
Disassembly of section .plt:
0000000000000590 <.plt>:
590: ff 35 72 0a 20 00 push QWORD PTR [rip+0x200a72] # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
596: ff 25 74 0a 20 00 jmp QWORD PTR [rip+0x200a74] # 201010 <_GLOBAL_OFFSET_TABLE_+0x10>
59c: 0f 1f 40 00 nop DWORD PTR [rax+0x0]
gdb
(gdb) stepi
_dl_runtime_resolve_sse () at ../sysdeps/x86_64/dl-trampoline.h:164
164 ../sysdeps/x86_64/dl-trampoline.h: No such file or directory.
嘿,_dl_runtime_resolve_sse,我们越来越近了。下面的可能看起来很难看。事实并非如此。它只是保存寄存器,以便在中途调用0x00007ffff7def11a <+154>: call 0x7ffff7de7970 <_dl_fixup>
时可以使用它需要的任何寄存器,这才是真正的神奇之处。在0x00007ffff7def1b0<304>:bnd jmp r11将带我们打印这一次,程序为这个特定函数执行这段代码,因为这是程序为这个特殊函数执行这一代码的唯一一次。
(gdb) disas
Dump of assembler code for function _dl_runtime_resolve_sse:
=> 0x00007ffff7def080 <+0>: push rbx
0x00007ffff7def081 <+1>: mov rbx,rsp
0x00007ffff7def084 <+4>: and rsp,0xfffffffffffffff0
0x00007ffff7def088 <+8>: sub rsp,0x100
0x00007ffff7def08f <+15>: mov QWORD PTR [rsp+0xc0],rax
0x00007ffff7def097 <+23>: mov QWORD PTR [rsp+0xc8],rcx
0x00007ffff7def09f <+31>: mov QWORD PTR [rsp+0xd0],rdx
0x00007ffff7def0a7 <+39>: mov QWORD PTR [rsp+0xd8],rsi
0x00007ffff7def0af <+47>: mov QWORD PTR [rsp+0xe0],rdi
0x00007ffff7def0b7 <+55>: mov QWORD PTR [rsp+0xe8],r8
0x00007ffff7def0bf <+63>: mov QWORD PTR [rsp+0xf0],r9
0x00007ffff7def0c7 <+71>: movaps XMMWORD PTR [rsp],xmm0
0x00007ffff7def0cb <+75>: movaps XMMWORD PTR [rsp+0x10],xmm1
0x00007ffff7def0d0 <+80>: movaps XMMWORD PTR [rsp+0x20],xmm2
0x00007ffff7def0d5 <+85>: movaps XMMWORD PTR [rsp+0x30],xmm3
0x00007ffff7def0da <+90>: movaps XMMWORD PTR [rsp+0x40],xmm4
0x00007ffff7def0df <+95>: movaps XMMWORD PTR [rsp+0x50],xmm5
0x00007ffff7def0e4 <+100>: movaps XMMWORD PTR [rsp+0x60],xmm6
0x00007ffff7def0e9 <+105>: movaps XMMWORD PTR [rsp+0x70],xmm7
0x00007ffff7def0ee <+110>: bndmov [rsp+0x80],bnd0
0x00007ffff7def0f7 <+119>: bndmov [rsp+0x90],bnd1
0x00007ffff7def100 <+128>: bndmov [rsp+0xa0],bnd2
0x00007ffff7def109 <+137>: bndmov [rsp+0xb0],bnd3
0x00007ffff7def112 <+146>: mov rsi,QWORD PTR [rbx+0x10]
0x00007ffff7def116 <+150>: mov rdi,QWORD PTR [rbx+0x8]
0x00007ffff7def11a <+154>: call 0x7ffff7de7970 <_dl_fixup>
0x00007ffff7def11f <+159>: mov r11,rax
0x00007ffff7def122 <+162>: bndmov bnd3,[rsp+0xb0]
0x00007ffff7def12b <+171>: bndmov bnd2,[rsp+0xa0]
0x00007ffff7def134 <+180>: bndmov bnd1,[rsp+0x90]
0x00007ffff7def13d <+189>: bndmov bnd0,[rsp+0x80]
0x00007ffff7def146 <+198>: mov r9,QWORD PTR [rsp+0xf0]
0x00007ffff7def14e <+206>: mov r8,QWORD PTR [rsp+0xe8]
0x00007ffff7def156 <+214>: mov rdi,QWORD PTR [rsp+0xe0]
0x00007ffff7def15e <+222>: mov rsi,QWORD PTR [rsp+0xd8]
0x00007ffff7def166 <+230>: mov rdx,QWORD PTR [rsp+0xd0]
0x00007ffff7def16e <+238>: mov rcx,QWORD PTR [rsp+0xc8]
0x00007ffff7def176 <+246>: mov rax,QWORD PTR [rsp+0xc0]
0x00007ffff7def17e <+254>: movaps xmm0,XMMWORD PTR [rsp]
0x00007ffff7def182 <+258>: movaps xmm1,XMMWORD PTR [rsp+0x10]
0x00007ffff7def187 <+263>: movaps xmm2,XMMWORD PTR [rsp+0x20]
0x00007ffff7def18c <+268>: movaps xmm3,XMMWORD PTR [rsp+0x30]
0x00007ffff7def191 <+273>: movaps xmm4,XMMWORD PTR [rsp+0x40]
0x00007ffff7def196 <+278>: movaps xmm5,XMMWORD PTR [rsp+0x50]
0x00007ffff7def19b <+283>: movaps xmm6,XMMWORD PTR [rsp+0x60]
0x00007ffff7def1a0 <+288>: movaps xmm7,XMMWORD PTR [rsp+0x70]
0x00007ffff7def1a5 <+293>: mov rsp,rbx
0x00007ffff7def1a8 <+296>: mov rbx,QWORD PTR [rsp]
0x00007ffff7def1ac <+300>: add rsp,0x18
0x00007ffff7def1b0 <+304>: bnd jmp r11
End of assembler dump.
最后的bnd jmp r11将带我们打印f。
最后,我们进入_dl_fixup,在这里我特别指出了对_dl_lookup_symbol 的调用
(gdb) break *0x7ffff7def11a
Note: breakpoint 5 also set at pc 0x7ffff7def11a.
Breakpoint 8 at 0x7ffff7def11a: file ../sysdeps/x86_64/dl-trampoline.h, line 212.
(gdb) cont
Continuing.
Breakpoint 5, _dl_runtime_resolve_sse () at ../sysdeps/x86_64/dl-trampoline.h:212
212 in ../sysdeps/x86_64/dl-trampoline.h
(gdb) stepi
_dl_fixup (l=0x7ffff7ffe168, reloc_arg=0) at ../elf/dl-runtime.c:66
66 ../elf/dl-runtime.c: No such file or directory.
(gdb) disas
Dump of assembler code for function _dl_fixup:
=> 0x00007ffff7de7970 <+0>: push rbx
0x00007ffff7de7971 <+1>: mov r10,rdi
0x00007ffff7de7974 <+4>: mov esi,esi
0x00007ffff7de7976 <+6>: lea rdx,[rsi+rsi*2]
0x00007ffff7de797a <+10>: sub rsp,0x10
0x00007ffff7de797e <+14>: mov rax,QWORD PTR [rdi+0x68]
0x00007ffff7de7982 <+18>: mov rdi,QWORD PTR [rax+0x8]
0x00007ffff7de7986 <+22>: mov rax,QWORD PTR [r10+0xf8]
0x00007ffff7de798d <+29>: mov rax,QWORD PTR [rax+0x8]
0x00007ffff7de7991 <+33>: lea r8,[rax+rdx*8]
0x00007ffff7de7995 <+37>: mov rax,QWORD PTR [r10+0x70]
0x00007ffff7de7999 <+41>: mov rcx,QWORD PTR [r8+0x8]
0x00007ffff7de799d <+45>: mov rax,QWORD PTR [rax+0x8]
0x00007ffff7de79a1 <+49>: mov rdx,rcx
0x00007ffff7de79a4 <+52>: shr rdx,0x20
0x00007ffff7de79a8 <+56>: lea rsi,[rdx+rdx*2]
0x00007ffff7de79ac <+60>: lea rsi,[rax+rsi*8]
0x00007ffff7de79b0 <+64>: mov rax,QWORD PTR [r10]
0x00007ffff7de79b3 <+67>: mov QWORD PTR [rsp+0x8],rsi
0x00007ffff7de79b8 <+72>: mov rbx,rax
0x00007ffff7de79bb <+75>: add rbx,QWORD PTR [r8]
0x00007ffff7de79be <+78>: cmp ecx,0x7
0x00007ffff7de79c1 <+81>: jne 0x7ffff7de7b17 <_dl_fixup+423>
0x00007ffff7de79c7 <+87>: test BYTE PTR [rsi+0x5],0x3
0x00007ffff7de79cb <+91>: jne 0x7ffff7de7a67 <_dl_fixup+247>
0x00007ffff7de79d1 <+97>: mov rax,QWORD PTR [r10+0x1c8]
0x00007ffff7de79d8 <+104>: test rax,rax
0x00007ffff7de79db <+107>: je 0x7ffff7de7a90 <_dl_fixup+288>
0x00007ffff7de79e1 <+113>: mov rax,QWORD PTR [rax+0x8]
0x00007ffff7de79e5 <+117>: movzx eax,WORD PTR [rax+rdx*2]
0x00007ffff7de79e9 <+121>: and eax,0x7fff
0x00007ffff7de79ee <+126>: lea rdx,[rax+rax*2]
0x00007ffff7de79f2 <+130>: mov rax,QWORD PTR [r10+0x2e0]
0x00007ffff7de79f9 <+137>: lea r8,[rax+rdx*8]
0x00007ffff7de79fd <+141>: mov eax,0x0
0x00007ffff7de7a02 <+146>: mov r9d,DWORD PTR [r8+0x8]
0x00007ffff7de7a06 <+150>: test r9d,r9d
0x00007ffff7de7a09 <+153>: cmove r8,rax
0x00007ffff7de7a0d <+157>: mov edx,DWORD PTR fs:0x18
0x00007ffff7de7a15 <+165>: test edx,edx
0x00007ffff7de7a17 <+167>: mov eax,0x1
0x00007ffff7de7a1c <+172>: jne 0x7ffff7de7ab0 <_dl_fixup+320>
0x00007ffff7de7a22 <+178>: mov esi,DWORD PTR [rsi]
0x00007ffff7de7a24 <+180>: mov rcx,QWORD PTR [r10+0x380]
0x00007ffff7de7a2b <+187>: lea rdx,[rsp+0x8]
0x00007ffff7de7a30 <+192>: push 0x0
0x00007ffff7de7a32 <+194>: push rax
0x00007ffff7de7a33 <+195>: mov r9d,0x1
0x00007ffff7de7a39 <+201>: add rdi,rsi
0x00007ffff7de7a3c <+204>: mov rsi,r10
0x00007ffff7de7a3f <+207>: call 0x7ffff7de2d10 <_dl_lookup_symbol_x>
0x00007ffff7de7a44 <+212>: mov r8,rax
0x00007ffff7de7a47 <+215>: mov eax,DWORD PTR fs:0x18
0x00007ffff7de7a4f <+223>: test eax,eax
0x00007ffff7de7a51 <+225>: pop rcx
0x00007ffff7de7a52 <+226>: pop rsi
0x00007ffff7de7a53 <+227>: jne 0x7ffff7de7ad0 <_dl_fixup+352>
0x00007ffff7de7a55 <+229>: mov rsi,QWORD PTR [rsp+0x8]
0x00007ffff7de7a5a <+234>: test rsi,rsi
0x00007ffff7de7a5d <+237>: je 0x7ffff7de7aa0 <_dl_fixup+304>
0x00007ffff7de7a5f <+239>: test r8,r8
0x00007ffff7de7a62 <+242>: je 0x7ffff7de7aa8 <_dl_fixup+312>
0x00007ffff7de7a64 <+244>: mov rax,QWORD PTR [r8]
0x00007ffff7de7a67 <+247>: movzx edx,BYTE PTR [rsi+0x4]
0x00007ffff7de7a6b <+251>: add rax,QWORD PTR [rsi+0x8]
0x00007ffff7de7a6f <+255>: and edx,0xf
0x00007ffff7de7a72 <+258>: cmp dl,0xa
0x00007ffff7de7a75 <+261>: je 0x7ffff7de7b10 <_dl_fixup+416>
0x00007ffff7de7a7b <+267>: mov edx,DWORD PTR [rip+0x215267] # 0x7ffff7ffcce8 <_rtld_global_ro+72>
0x00007ffff7de7a81 <+273>: test edx,edx
0x00007ffff7de7a83 <+275>: jne 0x7ffff7de7a88 <_dl_fixup+280>
0x00007ffff7de7a85 <+277>: mov QWORD PTR [rbx],rax
0x00007ffff7de7a88 <+280>: add rsp,0x10
0x00007ffff7de7a8c <+284>: pop rbx
0x00007ffff7de7a8d <+285>: ret
0x00007ffff7de7a8e <+286>: xchg ax,ax
0x00007ffff7de7a90 <+288>: xor r8d,r8d
0x00007ffff7de7a93 <+291>: jmp 0x7ffff7de7a0d <_dl_fixup+157>
0x00007ffff7de7a98 <+296>: nop DWORD PTR [rax+rax*1+0x0]
0x00007ffff7de7aa0 <+304>: xor eax,eax
0x00007ffff7de7aa2 <+306>: jmp 0x7ffff7de7a7b <_dl_fixup+267>
0x00007ffff7de7aa4 <+308>: nop DWORD PTR [rax+0x0]
0x00007ffff7de7aa8 <+312>: xor eax,eax
0x00007ffff7de7aaa <+314>: jmp 0x7ffff7de7a67 <_dl_fixup+247>
0x00007ffff7de7aac <+316>: nop DWORD PTR [rax+0x0]
0x00007ffff7de7ab0 <+320>: mov DWORD PTR fs:0x1c,0x1
0x00007ffff7de7abc <+332>: mov eax,0x5
0x00007ffff7de7ac1 <+337>: jmp 0x7ffff7de7a22 <_dl_fixup+178>
0x00007ffff7de7ac6 <+342>: nop WORD PTR cs:[rax+rax*1+0x0]
0x00007ffff7de7ad0 <+352>: xor eax,eax
0x00007ffff7de7ad2 <+354>: xchg DWORD PTR fs:0x1c,eax
0x00007ffff7de7ada <+362>: cmp eax,0x2
0x00007ffff7de7add <+365>: jne 0x7ffff7de7a55 <_dl_fixup+229>
0x00007ffff7de7ae3 <+371>: mov rdi,QWORD PTR fs:0x10
0x00007ffff7de7aec <+380>: xor r10d,r10d
0x00007ffff7de7aef <+383>: add rdi,0x1c
0x00007ffff7de7af3 <+387>: mov edx,0x1
0x00007ffff7de7af8 <+392>: mov esi,0x81
0x00007ffff7de7afd <+397>: mov eax,0xca
0x00007ffff7de7b02 <+402>: syscall
0x00007ffff7de7b04 <+404>: jmp 0x7ffff7de7a55 <_dl_fixup+229>
0x00007ffff7de7b09 <+409>: nop DWORD PTR [rax+0x0]
0x00007ffff7de7b10 <+416>: call rax
0x00007ffff7de7b12 <+418>: jmp 0x7ffff7de7a7b <_dl_fixup+267>
0x00007ffff7de7b17 <+423>: lea rcx,[rip+0x10862] # 0x7ffff7df8380 <__PRETTY_FUNCTION__.10645>
0x00007ffff7de7b1e <+430>: lea rsi,[rip+0xea8f] # 0x7ffff7df65b4
0x00007ffff7de7b25 <+437>: lea rdi,[rip+0x1081c] # 0x7ffff7df8348
0x00007ffff7de7b2c <+444>: mov edx,0x4f
0x00007ffff7de7b31 <+449>: call 0x7ffff7df1210 <__GI___assert_fail>
End of assembler dump.
这是这段旅程的终点。dllookup_symbol函数用于解析elf文件和处理符号,这就是pfm发生的地方。
- 使用nvprof进行评测时没有GPU活动
- 为可选的评测代码执行进行高效设计
- 什么是_dl_lookup_symbol_x?-C++评测
- Visual Studio 2013评测Cinder项目时,没有显示任何函数调用
- 协助C++程序评测
- 使用clock()评测C++线程
- 使用库对基于g++的应用程序进行c++评测
- 获取评测函数持续时间的时间(以毫秒为单位)
- Windows中单个C++函数的简单评测
- 评测:一行代码的自身时间与总时间
- 实现行级评测
- 如何在g++/std::mutex下评测锁争用
- C++评测和优化
- 设计模式-C++对象生命周期评测
- 如何诊断/评测瞬时性能命中,C++
- if语句-如何在C++中评测if
- C++中的免费评测