当前位置: 首页 > 后端技术 > PHP

使用gdb调试php

时间:2023-03-29 17:49:22 PHP

简介gdb是c语言的代码调试工具,可以用来调试php、python、mysql等。调试gdb主要有四种形式:启动后,使用attachpid跟踪程序gdb[选项][可执行文件]-file[核心文件或进程ID]]gdb[选项]--args可执行文件[劣质参数...]gdb[选项][--python|-P]脚本文件[脚本参数...]常用调试命令attachpid例子:如果要跟踪调试mysql代码1.先找到mysqlID:101112然后attach10111跟踪mysqllayout显示源代码/汇编指令Layoutnamesare:src:Displayssourceand命令窗口。显示源代码asm:显示反汇编和命令窗口。DisplayassemblyCommandsplit:显示源代码、反汇编和命令窗口。显示源代码和汇编命令regs:显示寄存器窗口。如果现有布局是源/命令或程序集/命令,则显示注册窗口。如果显示source/assembly/command(split),则显示寄存器窗口和当前逻辑焦点所在的窗口breakb增加断点信息b显示断点信息deletenum删除指定断点continue[num]cnum执行到num一个断点,num可以留空,default=1next[num]nnum执行到下一个num行,num可以留空,default=1,不进入函数内部step[num]snum执行到下一个numline,num可以留空Default=1,不进入函数backtracebt查看当前调用栈print[value]pvalue打印变量信息helplayout查看命令如何使用debugphpcode1.添加一个新的php文件Thisisfreesoftware:您可以自由更改和重新分发它。在法律允许的范围内,不提供任何保证。键入“showcopying”和“showwarranty”以获取详细信息。这个GDB是配置为“x86_64-redhat-linux-gnu”。错误报告说明请参见:。(gdb)attach1127Attachingtoprocess1127Readingsymbolsfrom/usr/local/php/sbin/php-fpm...完成。从/usr/lib64/libcrypt.so.1读取符号...正在从/usr/lib/debug/usr/lib64/libcrypt-2.17读取符号。所以.debug...done.done.4。断点,这里是timelib_update_ts和do_years方法中的断点,这里需要看php源码,看哪里需要调试代码(gdb)btimelib_update_tsBreakpoint1at0x48ba90:file/opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c,line499.(gdb)bdo_years`Breakpoint3at0x48bb95:file/opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c,第381行。`5。请求测试文件请求后,发现并没有立即看到返回结果,卡在了这里,说明执行到了断点[root@test~]#curllocalhost/3.php6。查看调试信息通过p*time(gdb)cContinuing.Breakpoint1,timelib_update_ts(time=time@entry=0x7fc63ec02000,tzi=tzi@entry=0x7fc63ec75000)at/opt/lnmp1.6/可以看到变量time的内容src/php-7.3.11/ext/date/lib/tm2unixtime.c:499499{(gdb)cContinuing.Breakpoint3,timelib_update_ts(time=time@entry=0x7fc63ec02000,tzi=tzi@entry=0x7fc63ec75000)at/opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c:505505res+=do_years(time->y);(gdb)sdo_years(year=2020)在/opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c:381381eras=(年-1970)/40000;(gdb)stimelib_update_ts(time=time@entry=0x7fc63ec02000,tzi=tzi@entry=0x7fc63ec75000)在/opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c:504504do_adjust_special(time);(gdb)p*time$1={y=2020,m=7,d=31,h=0,i=0,s=0,us=0,z=28800,tz_abbr=0x7fc63ec71018"CST",tz_info=0x7fc63ec75000,dst=0,relative={y=0,m=2,d=0,h=0,i=0,s=0,us=0,weekday=0,weekday_behavior=0,first_last_day_of=2,invert=0,days=-99999,special={type=0,amount=0},have_weekday_relative=0,have_special_relative=0},sse=0,have_time=0,have_date=0,有_zone=0,have_relative=1,have_weeknr_day=0,sse_uptodate=0,tim_uptodate=0,is_localtime=1,zone_type=3}(gdb)下面是do_years方法的代码statictimelib_slldo_years(timelib_sllyear){timelib_slli;timelib_sllres=0;timelib_sll时代;时代=(年-1970)/40000;如果(纪元!=0){年=年-(纪元*40000);res+=(SECS_PER_ERA*eras*100);}if(year>=1970){for(i=year-1;i>=1970;i--){//判断是不是闰年,闰年366天,平年365天if(timelib_is_leap(i)){res+=(DAYS_PER_LYEAR*SECS_PER_DAY);}else{res+=(DAYS_PER_YEAR*SECS_PER_DAY);}}}else{for(i=1969;i>=year;i--){if(timelib_is_leap(i)){res-=(DAYS_PER_LYEAR*SECS_PER_DAY);}else{res-=(DAYS_PER_YEAR*SECS_PER_DAY);}}}returnres;}总结束通过gdb跟踪非常方便我们调试代码信息,查看底层代码跳栈,对学习源码很有帮助。这里也总结一下php的strtotime方法的实现逻辑。如果当前年份>=1970,则循环判断[1970-(currentyear-1)]每一年是否为闰年,如果是闰年则为86400366,否则为86400355(86400是一天中的秒数),月日时分秒的计算逻辑不再重复,最后加/减时区。上海是东八区要减去8小时。东八区(UTC/GMT+08:00)是一个比协调世界时(UTC)/格林威治标准时间(GMT)快8小时的时区,用php代码将年份转换成时间戳=1970;$i--){if(is_leap($i)){$res+=YEARLEEP*86400;}else{$res+=YEAR*86400;}}//上海为东八区,减少8小时$res-=8*3600;返回$res;}echogetStime('2020');