使用vscode调试PHP底层C源码

使用vscode调试PHP底层C源码

一直想着有机会调试一下php底层代码来着,这周正好心血来潮,就跟着教程配置了一下。本篇文章是基于macOS,可能在编译php源码之前的步骤对使用windows的师傅没啥可参考的。

windows下比较麻烦,主要是在编译php源码这一步,最方便的办法是用docker来远程调试。具体可以参考这篇文章vscode远程调试php底层代码。使用p牛的dockerfile来自己建一个调试用docker。

说回mac下调试PHP源码需要的准备

下载并编译PHP

使用git来下载源码,这样切换PHP版本会较为方便。(不过我现在应该不会这么做,因为下载下来的源码并不能直接编译成功,需要自己修改。改完的源码不舍得切换了)

 git clone https://github.com/php/php-src
 cd php-src/
 git checkout PHP-7.3.67

当然,不排除个人环境的原因,通过checkout切换分支,重新编译一下还是很方便的,如果编译不出错的话。

如果是mac,编译PHP前需要安装一下最新版的bison,mac自带的版本太老。

brew install bison
# bison的具体路径可以通过brew list bison来查看
export PATH=/opt/homebrew/Cellar/bison/3.8.2/bin:$PATH

编译需要调试的PHP。像我这里就开启了debug模式,开启了phar扩展,如果需要开启别的扩展,需要再./configure命令后面自行指定。

 ./buildconf
 ./configure --disable-all --enable-debug --enable-phar --prefix=/source/php7.3.6/
 make
 make install

编译完后,编译结果都在/source/php7.3.6/文件夹下,/source/php7.3.6/bin/php为可执行文件。

编译好的PHP,执行./php -v 会显示NTS DEBUG

截屏2022-09-07 00.36.50

编译过程中的错误

在进行make编译的时候,碰到了两次报错。

第一个报错:

 /Users/niushaogang/jkbPhpPackage/php-5.4.45/main/reentrancy.c:139:23: error: too few arguments to function call, expected 3, have 2
        readdir_r(dirp, entry);
        ~~~~~~~~~            ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/dirent.h:110:5: note: 'readdir_r' declared here
int readdir_r(DIR *, struct dirent *, struct dirent **) __DARWIN_INODE64(readdir_r);
    ^
1 error generated.
make: *** [main/reentrancy.lo] Error 1

根据网上的教程,了解到这是php源码调用readdir_r函数的时候少传了一个参数。

查看php-src/main/reentrancy.c

函数定义:

int readdir_r(DIR *, struct dirent *, struct dirent **)

php调用:

readdir_r(dirp, entry)

readdir_r(dirp, entry) 修改为 readdir_r(dirp, entry,&entry)即可编译通过

image-20220912142049128

第二个报错:

/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1317:5: error: implicit declaration of function 'yystpcpy' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 
                                yystpcpy(yyres, "end of file");
 
                                ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1317:5: note: did you mean 'stpcpy'?
 
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/string.h:130:7: note: 'stpcpy' declared here
 
char    *stpcpy(char *__dst, const char *__src);
 
         ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1324:29: error: implicit declaration of function 'yystrlen' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 
                yystr_len = (unsigned int)yystrlen(yystr);
 
                                          ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1324:29: note: did you mean 'strlen'?
 
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/string.h:82:9: note: 'strlen' declared here
 
size_t   strlen(const char *__s);
 
         ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1345:4: error: implicit declaration of function 'yystpcpy' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 
                        yystpcpy(yyres, buffer);
 
                        ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1352:10: error: implicit declaration of function 'yystrlen' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 
                return yystrlen(yystr) - (*yystr == '"' ? 2 : 0);
 
                       ^
 
/Users/dre0m1/CTF/学习笔记/PHP源码/php-src/Zend/zend_language_parser.y:1365:2: error: implicit declaration of function 'yystpcpy' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
 
        yystpcpy(yyres, yystr);
 
        ^
 
5 errors generated.
 
make: *** [Zend/zend_language_parser.lo] Error 1

报错内容较多,出现在Zend/zend_language_parser.lo位置。当时查找了好久的资料,都没有找到相关的内容。只知道implicit declaration of function 'yystrlen' is invalid in C99这种报错类型是因为缺少相应的定义,由报错中的提示可以看出应该是缺少了yystpcpy这个函数。

访问文件php-src/Zend/zend_language_parser.c,可以看到这样一段代码

img

格式和yystpcpy还有yystrlen异常的统一,我当时就怀疑应该是在这个c文件中进行了函数重命名。

代码中出现yystpcpy函数的位置一共有三处:

if (yyres) {
				yystpcpy(yyres, "end of file");
			}
			return sizeof("end of file")-1;
		}

yystpcpy(yyres, buffer);

yystpcpy(yyres, yystr);

看样子应该就是stpcpy函数没错了,试着在上面的#define处加入yystpcpyyystrlen的定义:

#define yystpcpy     zendstpcpy
#define yystrlen     zenddtrlen

依旧报错,这边是我没动脑子了,光想着和上面的define内容结构统一,但是strlen和stpcpy这两个函数前面其实是不需要zend前缀的。

img

修改之后重新编译,make成功。

vscode调试

用vscode打开PHP源码,增加一个调试的配置:

image-20220912143921200

选择环境c++(GDB/LLDB)-> Default Configuration,然后会生成一个配置文件:

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "debuug php source",
            "type": "cppdbg",
            "request": "launch",
            "program": "/Users/dre0m1/CTF/学习笔记/PHP源码/source/bin/php",
            "args": ["-f","/Users/dre0m1/CTF/学习笔记/PHP源码/1.php"],
            "stopAtEntry": true,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "lldb"
        }
        

    ]
}

参数详解:

  • program 可执行的PHP文件的路径(编译生成的php文件)
  • args 传给php的参数列表,像我上面所填写的执行的就是php -f /Users/dre0m1/CTF/学习笔记/PHP源码/1.php
  • cwd 当前目录,如果调试web应用,可以改成web根目录的路径
  • stopAtEntry 是否在main函数的时候断下

之后就可以正常调试了。

原文链接:https://www.cnblogs.com/dre0m1/p/17050929.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用vscode调试PHP底层C源码 - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • php实现简易计算器

    让我来详细讲解一下如何实现用 PHP 编写简易计算器的攻略。 步骤一:创建 HTML 页面 首先,我们需要在项目中创建一个 HTML 页面,用于接收用户的输入和显示计算结果。可以正常的使用 HTML5 语法,建议使用表单元素来接收用户的输入。需要注意的是,我们的 HTML 页面需要引入一个 PHP 的处理文件,代码如下: <!DOCTYPE html&…

    PHP 2023年5月23日
    00
  • 用PHP实现WEB动态网页静态

    要用PHP实现WEB动态网页静态,需要通过以下步骤完成: 1. 设置Apache服务器 在本地计算机上安装并设置Apache服务器。这可以使用WAMP,XAMPP或MAMP中的任何一个来完成。这些是预先配置好的Web服务器软件包,可以轻松地在Windows,Mac OS和Linux上设置和运行Apache。 2. 创建静态HTML文件 创建一个简单的HTML…

    PHP 2023年5月27日
    00
  • PHP中单引号和双引号的区别详解

    下面是“PHP中单引号和双引号的区别详解”的完整使用攻略,包括问题原因、解决方法和两个示例说明。 问题原因 在PHP中,单引号和双引号都可以用来表示字符串。但是,它们之间有一些区别,这可能会导致一些问题。 解决方法 以下是解决PHP中单引号和双引号的区别的方法: 单引号和双引号的区别 单引号和双引号的主要区别在于,双引号中的变量会被解析,而单引号中的变量不会…

    PHP 2023年5月12日
    00
  • PHP 类商品秒杀计时实现代码

    下面是详细讲解“PHP 类商品秒杀计时实现代码”的攻略。 需求描述 在电商网站中,经常会有商品秒杀的活动。在秒杀活动中,用户必须在限定的时间内抢购商品,否则秒杀失败。 本文将介绍如何使用 PHP 类来实现商品秒杀计时的功能,以及简单的演示示例。 思路分析 为实现商品秒杀计时的功能,我们需要实现以下几个步骤: 获取当前时间并计算与秒杀活动开始时间和结束时间的差…

    PHP 2023年5月27日
    00
  • php动态生成函数示例

    下面是针对“PHP动态生成函数示例”的完整攻略,包括了两个示例说明。 什么是PHP动态生成函数 在PHP中,我们可以使用动态生成函数(Dynamic Function)的方式定义函数。动态生成函数的特点是:我们不需要在代码中预定义函数,而是可以根据需要,在运行时动态地创建函数。在生成函数的时候,需要给出函数名和函数体的字符串。 示例 1:使用eval函数动态…

    PHP 2023年5月25日
    00
  • php中替换字符串中的空格为逗号’,’的方法

    在PHP中,有多种方法可以将字符串中的空格替换为逗号。以下是其中两种方法的示例解释: 方法一:使用str_replace函数 str_replace函数可以用于将字符串中指定的字符替换为另一个字符。我们可以使用该函数将空格替换为逗号。 $string = ‘Hello world PHP’; $new_string = str_replace(‘ ‘, ‘,…

    PHP 2023年5月26日
    00
  • Ubuntu 命令技巧大全整理

    Ubuntu 命令技巧大全整理 1. 命令行快捷键 1.1 光标移动 Ctrl + a:移动到行首 Ctrl + e:移动到行尾 Ctrl + b:向后移动一个字符 Ctrl + f:向前移动一个字符 Alt + b:向后移动一个单词 Alt + f:向前移动一个单词 1.2 命令操作 Ctrl + u:删除光标之前的所有文本 Ctrl + k:删除光标之后…

    PHP 2023年5月27日
    00
  • 究竟什么是Node.js?Node.js有什么好处?

    Node.js是一种基于Chrome V8引擎的JavaScript运行环境,具备事件驱动、非阻塞I/O等特性,可以用于构建高效的网络应用程序和服务端应用。 Node.js有以下好处: 异步I/O:Node.js采用了异步I/O的方式,能够处理大量的并发连接,而不必像传统的服务器一样,为每个连接开一个线程,这大大降低了服务器的内存开销。 高效性能:由于Nod…

    PHP 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部