GDB 在BinaryHacking 的 _start 处下断点,发现执行的汇编代码咋和想象中的不太一样?
GDB非预期的在 libc.so 中的 _dl_start 下断点#
GDB 在BinaryHacking 的 _start 处下断点,发现执行的汇编代码咋和想象中的不太一样?

GDB 在 0x0000000000400480 处中断程序运行,但是run 之后发现咋跳到一个 奇怪的位置执行_dl_start,并且汇编代码完全不同:
objdump -d BinaryHacking -j.text --disassemble="_start" 输出:

这完全是两个不同的函数,并且地址也不一样,一个是0x0000000000400480,一个是0x0000007fb7fdac28。0x0000007fb7fdac28 处的 _dl_start 实际上是 GNU LIBC 的 _dl_start 函数,GDB 是先跳转到 libc.so 中的 _dl_tart 函数去执行了,然后再跳转到 BinaryHacking 的 _start 执行。
但如果我要调试的是被调试 ELF 文件中的 _start 而不是 libc.so 中的_dl_start 怎么办?
使用 info functions 指令查看 _start 在 ELF 中的地址,然后 使用 b *address 在 ELF 处的 _start 下断点。
比如说 _start 的地址为:

使用 b *0x0000000000400480 打断点。使用 run 运行到 0x0000000000400480 处查看汇编代码:

这回确实是被调试 ELF 中的 _start入口函数了。
libc.so 中的 _dl_start 函数#
感兴趣的同学可以自己去stepin GNU LIBC 的_dl_start,但前提是你有足够的时间不至于气的掀桌子。
然后源码分析可以看这里 _dl_start源码分析___dl_start入参_二侠的博客-CSDN博客
但基本上都符合下面的给出的流程。
Statically-linked 文件
- The ELF headers points program start at
_start. _start(sysdeps/mach/hurd/i386/static-start.S) calls_hurd_stack_setup_hurd_stack_setup(sysdeps/mach/hurd/i386/init-first.c) callsfirst_initwhich calls__mach_initto initialize enough to run RPCs, then runs the_hurd_preinit_hookhooks, which initialize global variables of libc._hurd_stack_setup(sysdeps/mach/hurd/i386/init-first.c) calls_hurd_startup._hurd_startup(hurd/hurdstartup.c) gets hurdish information from servers and calls itsmainparameter.- the
mainparameter was actuallydoinit(in sysdeps/mach/hurd/i386/init-first.c), which mangles the stack and callsdoinit1which callsinit. initsets threadvars, tries to initialize threads (and perhaps switches to the new stack) and gets to callinit1.init1gets the Hurd block, calls_hurd_initon it_hurd_init(hurd/hurdinit.c) initializes initial ports, starts the signal thread, runs the_hurd_subinithooks (init_dtablehurd/dtable.c notably initializes the FD table and the_hurd_fd_subinithooks, which notably checksstd*).- We are back to
_start, which jumps to_start1which is the normal libc startup which calls__libc_start_main __libc_start_main(actually calledLIBC_START_MAINin csu/libc-start.c) initializes libc, tls, libpthread, atexit__libc_start_maincalls initialization function given as parameter__libc_csu_init,__libc_csu_init(csu/elf-init.c) callspreinit_array_startfunctions__libc_csu_initcalls_init_init(sysdeps/i386/crti.S) callsPREINIT_FUNCTION, (actually libpthread on Linux,__gmon_start__on hurd)- back to
__libc_csu_initcallsinit_array_startfunctions - back to
__libc_start_main, it calls calls application’smain, thenexit.
dynamically-linked ELF文件
- dl.so ELF headers point its start at
_start. _start(sysdeps/i386/dl-machine.h) calls_dl_start._dl_start(elf/rtld.c) initializesbootstrap_map, calls_dl_start_final_dl_start_finalcalls_dl_sysdep_start._dl_sysdep_start(sysdeps/mach/hurd/dl-sysdep.c) calls__mach_initto initialize enough to run RPCs, then calls_hurd_startup._hurd_startup(hurd/hurdstartup.c) gets hurdish information from servers and calls itsmainparameter.- the
mainparameter was actuallygoinside_dl_sysdep_start, which callsdl_main. dl_main(elf/rtld.c) interprets ld.so parameters, loads the binary and libraries, calls_dl_allocate_tls_init.- we are back to
go, which branches to_dl_start_user. _dl_start_user(./sysdeps/i386/dl-machine.h) runsRTLD_START_SPECIAL_INIT(sysdeps/mach/hurd/i386/dl-machine.h) which calls_dl_init_first._dl_init_first(sysdeps/mach/hurd/i386/init-first.c) callsfirst_initwhich calls__mach_initto initialize enough to run RPCs, then runs the_hurd_preinit_hookhooks, which initialize global variables of libc._dl_init_firstcallsinit.initsets threadvars, tries to initialize threads (and perhaps switches to the new stack) and gets to callinit1.init1gets the Hurd block, calls_hurd_initon it_hurd_init(hurd/hurdinit.c) initializes initial ports, starts the signal thread, runs the_hurd_subinithooks (init_dtablehurd/dtable.c notably initializes the FD table and the_hurd_fd_subinithooks, which notably checksstd*).- we are back to
_dl_start_user, which calls_dl_init(elf/dl-init.c) which calls application initializers. _dl_start_userjumps to the application’s entry point,_start_start(sysdeps/i386/start.S) calls__libc_start_main__libc_start_main(actually calledLIBC_START_MAINin csu/libc-start.c) initializes libc, atexit,__libc_start_maincalls initialization function given as parameter__libc_csu_init,__libc_csu_init(csu/elf-init.c) calls_init_init(sysdeps/i386/crti.S) callsPREINIT_FUNCTION, (actually libpthread on Linux,__gmon_start__on hurd)- back to
__libc_csu_initcallsinit_array_startfunctions - back to
__libc_start_main, it calls application’smain, thenexit.

