首页后端开发PHP如何使用gdb调试php,有哪形式

如何使用gdb调试php,有哪形式

时间2024-03-22 21:12:03发布访客分类PHP浏览420
导读:这篇文章给大家分享的是“如何使用gdb调试php,有哪形式”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“如何使用gdb调试php,有哪形式”吧。 使用gdb调试ph...
这篇文章给大家分享的是“如何使用gdb调试php,有哪形式”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“如何使用gdb调试php,有哪形式”吧。

使用gdb调试php

简介

gdb 是c语言的代码调试工具
可以用来调试php、python、mysql等

调试主要有4种形式

gdb:启动之后用attach pid 追踪程序
gdb [options] [executable-file [core-file or process-id]]
gdb [options] --args executable-file [inferior-arguments ...]
gdb [options] [--python|-P] script-file [script-arguments ...]

常用调试命令

attach pid

例:如果向跟踪调试mysql代码
1.先找到mysql进行ID:10111

2.再attach 10111追踪mysql

layout

显示源码/汇编指令

Layout names are:
   src      : Displays source and command windows. 显示源码
   asm      : Displays disassembly    and command windows. 显示汇编指令
   split : Displays source, disassembly    and command windows. 显示源码和汇编指令
   regs     : Displays register window. If    existing layout
              is source/command or    assembly/command, the 
              register window is displayed. If the
              source/assembly/command (split) is displayed, 
              the register    window is displayed with 
              the window that has current logical focus

break

  • b 增加断点
  • info b 显示断点信息
  • delete num 删除指定断点

continue [num]

  • c num 执行到num个断点,num可以不填默认=1

next [num]

  • n num 执行到下num行,num可以不填默认=1,不进入函数内部

step [num]

  • s num 执行到下num行,num可以不填默认=1,不进入函数内部

backtrace

  • bt 查看当前调用栈

print [value]

  • p value 打印变量信息

help

  • help layout 查看命令如何使用

调试php代码

1. 新增一个php文件

?php
echo date('Y-m-d', strtotime("last day of +2month", strtotime('2020-05-31')));
    

2.查看php-fpm work进程PID

我这里通过修改php-fpm配置只启动一个work进程方便追踪

pm = static
pm.max_children = 1
[root@test ~]# ps aux|grep php-fpm
www        1127  0.0  0.1 279352  2816 ?        S    5月12   0:00 php-fpm: pool www
root      12224  0.0  0.0 112736   976 pts/0    S+   17:37   0:00 grep --color=auto php-fpm

3.追踪PID

[root@test ~]# gdb
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-115.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html>
    
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/>
.
(gdb) attach 1127
Attaching to process 1127
Reading symbols from /usr/local/php/sbin/php-fpm...done.
Reading symbols from /usr/lib64/libcrypt.so.1...Reading symbols 
from /usr/lib/debug/usr/lib64/libcrypt-2.17.so.debug...done.
done.

4.打断点,这里在timelib_update_tsdo_years方法打了一个断点,这里需要你看下php源码,看你需要在哪里调试代码

(gdb) b timelib_update_ts
Breakpoint 1 at 0x48ba90: file /opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c, line 499.
(gdb) b do_years
`Breakpoint 3 at 0x48bb95: file /opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c, line 381.`

5.请求测试文件

请求之后发现没有立刻看到返回结果,被阻塞在了这里,说明执行到了断点的地方

[root@test ~]# curl localhost/3.php

6.查看调试信息

通过p *time可以看到变量time里面的内容

(gdb) c
Continuing.

Breakpoint 1, 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:499
499    {
    
(gdb) c
Continuing.

Breakpoint 3, 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:505
505        res += do_years(time->
    y);
    
(gdb) s
do_years (year=2020) at /opt/lnmp1.6/src/php-7.3.11/ext/date/lib/tm2unixtime.c:381
381        eras = (year - 1970) / 40000;
    
(gdb) s
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:504
504        do_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, have_zone = 0, 
    have_relative = 1, have_weeknr_day = 0, 
  sse_uptodate = 0, tim_uptodate = 0, is_localtime = 1, zone_type = 3}

(gdb)

下面是do_years方法的代码

static timelib_sll do_years(timelib_sll year)
{
    
    timelib_sll i;
    
    timelib_sll res = 0;
    
    timelib_sll eras;
    

    eras = (year - 1970) / 40000;

    if (eras != 0) {
    
        year = year - (eras * 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);

            }

        }

    }
    
    return res;

}
    

总结

通过gdb追踪很方便我们debug代码信息,查看底层代码跳用栈,对学习源码有很大的帮助
这里也总结下php strtotime方法的实现逻辑
如果当前年> =1970,则循环判断[1970-(当前年-1)]中每一年是否是闰年,是闰年则86400 366,不是则86400355 ( 86400是一天的秒数),月天时分秒计算逻辑不再累述,最后还会加上/减去时区,上海是东八区会减去8小时。
东八区(UTC/GMT+08:00)是比世界协调时间(UTC)/格林尼治时间(GMT)快8小时的时区,
附php代码实现年转化成时间戳
?php

const YEARLEEP = 366;
    //闰年366天
const YEAR     = 365;
//平年365天

//判断是否是闰年
function is_leap($year)
{
    
    return ($year % 4 == 0) &
    &
     ($year % 100 != 0 || $year % 400 == 0);

}


//将年转换成时间戳
function getStime($year)
{
    
    $res = 0;
    
    for ($i = $year - 1;
     $i >
    = 1970;
 $i--) {

        if (is_leap($i)) {
    
            $res += YEARLEEP * 86400;

        }
 else {
    
            $res += YEAR * 86400;

        }

    }
    
    //上海是东八区要减8小时
    $res -= 8 * 3600;
    
    return $res;

}
    

echo getStime('2020');
    

以上就是关于如何使用gdb调试php,有哪形式的介绍,本文内容仅供参考,有需要的朋友可以借鉴了解看看,希望对大家学习或工作,想要了解更多欢迎关注网络,小编每天都会为大家更新不同的知识。

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

php

若转载请注明出处: 如何使用gdb调试php,有哪形式
本文地址: https://pptw.com/jishu/650881.html
python异步中selectors库有什么用,基本用法是什么 MySQL数据库启动失败的问题怎么解决

游客 回复需填写必要信息