使用vscode調試PHP底層C源碼

来源:https://www.cnblogs.com/dre0m1/archive/2023/01/13/17050929.html
-Advertisement-
Play Games

使用vscode調試PHP底層C源碼 一直想著有機會調試一下php底層代碼來著,這周正好心血來潮,就跟著教程配置了一下。本篇文章是基於macOS,可能在編譯php源碼之前的步驟對使用windows的師傅沒啥可參考的。 windows下比較麻煩,主要是在編譯php源碼這一步,最方便的辦法是用docke ...


使用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函數的時候斷下

之後就可以正常調試了。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.按鈕點擊後添加loading,介面返回成功後再移除loading(經過多次嘗試發現,此方法不能完全確保只調用一次介面,第二次添加時仍會多次調用介面),方法如下: html代碼: <el-button @click="onSave" :loading="onLoading">保存</el-butt ...
  • JavaScript 中,對於普通對象,不能直接使用 length 來獲取對象的長度,因為 JavaScript 對象並不是一種有序的集合,沒有長度的概念。 對於數組或者類數組對象,可以使用 .length 來獲取它們的長度,因為它們是有序集合。 對於字元串也可以使用.length來獲取長度,因為字... ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 前言 訪問控制(Access control)是指對訪問者向受保護資源進行訪問操作的控制管理。該控制管理保證被授權者可訪問受保護資源,未被授權者不能訪問受保護資源。 現 ...
  • 在 CSS 中,倒影是一種比較常見的效果。今天,我們就將嘗試,使用 CSS 完成各類不同的倒影效果,話不多說,直接進入主題。 實現倒影的兩種方式 首先,快速過一下在 CSS 中,實現倒影的 2 種方式。 使用 -webkit-box-reflect 正常而言,-webkit-box-reflect ...
  • 基於AWS雲SaaS多租戶架構設計租戶與用戶概念單租戶與多租戶多租戶的好處 採用多租戶架構方法將為你的SaaS應用程式帶來廣泛的有價值的好處。 讓我們來看看下麵的貢獻。 a) 利用多租戶架構策略,減少伺服器基礎設施成本。 與其為每個客戶創建一個SaaS環境,不如為所有客戶提供一個應用環境。這使你的A ...
  • 隨著互聯網的發展,用戶在使用網路時對網站的瀏覽速度和效果愈加重視,但由於網民數量激增,網路訪問路徑過長,從 而使用戶的訪問質量受到嚴重影響。特別是當用戶與網站之間的鏈路被突發的大流量數據擁塞時,對於異地互聯網用戶急速增加的地區來說,訪問質量不良更是一個 急待解決的問題。如何才能讓各地的用戶都能夠進行 ...
  • 作為一個後端研發人員,開發服務介面是我正常不過的工作了,這些介面不管是面向前端HTTP或者是供其他服務RPC遠程調用的,都繞不開一個共同的話題就是“高可用”,介面開發往往看似簡單,但保證高可用這塊實現起來卻不並沒有想想的那麼容易,接下來我們就看一下,一個高可用的介面是該考慮哪些內容,同時文中有不足的... ...
  • 摘要:跨域,對後端工程師來說,可謂既熟悉又陌生。 本文分享自華為雲社區《後端老司機的跨域之旅》,作者: 勇哥java實戰分享。 跨域,對後端工程師來說,可謂既熟悉又陌生。 這兩個月我以架構師的角色參與一款教育產品的孵化,有了一段難忘的跨域之旅。 寫這篇文章,我想分享我在跨域這個知識點的經歷和思考,希 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...