重現PHP Core的呼叫棧

2021-09-08 18:42:54 字數 2215 閱讀 3649

以前, 我曾經介紹過如何通過php的core檔案獲取資訊:如何除錯php的core之獲取基本資訊

, 對於呼叫引數這塊, 當時介紹的獲取方法比較複雜.

於是今天我為php 5.4的.gdbinit做了乙個改進, 以後如果你遇到了php 5.4的core, 那麼就可以簡單的得到php 5.4發生core時, 包括引數的函式呼叫棧的資訊.

假設對於如下的指令碼:

<?php

class test

function

a($i

) function

b($i

) function

c($i

) function

d($i

) function

e($i) a

(); 使用後台執行以後, php5.4會sleep在e函式的sleep中, 這時, 如果我們使用gdb attach上去,

gdb --pid= *** //使用ps獲得後台執行指令碼的pid

然後, source php源**下面的.gdbinit:

(gdb) source php54-src/.gdbini

然後, 讓我們嘗試呼叫下zbacktrace, 看看什麼結果:

(gdb) zbacktrace

[0x2a95dac5e0] sleep(1000) /tmp/1.php:21

[0x2a95dac4c0] e(resource(#5)) /tmp/1.php:17

[0x2a95dac3f0] d(true) /tmp/1.php:13

[0x2a95dac300] c(array(3)[0x2a95de7db0]) /tmp/1.php:10

[0x2a95dac1c0] b(object[0x2a95de7840], 2.343200, "reader") /tmp/1.php:7

[0x2a95dac0e8] a() /tmp/1.php:2

恩, 對於array和object, 因為我們為了保持不要亂屏, 所以沒有展開, 不過, 如果我們要檢視這個array具體是什麼元素, 可以這樣做, 注意到上面的:array(3)[0x2a95de7db0]:

(gdb) print ((zval *)0x2a95de7db0)

$4 = (struct _zval_struct *) 0x2a95de7db0

(gdb) printzv $4

[0x2a95de7db0] (refcount=2) array(3): {

0 => [0x2a95de79d0] (refcount=1) long: 1

1 => [0x2a95de7b80] (refcount=1) long: 2

2 => [0x2a95de7c98] (refcount=1) long: 3

類似的, 對於object, 注意到上面的: object[0x2a95de7840]

(gdb) print ((zval *)0x2a95de7840)

$5 = (struct _zval_struct *) 0x2a95de7840

(gdb) printzv $5

[0x2a95de7840] (refcount=2) object

(test) #1"no properties found

要注意的一點是, 對於object, 如果你是在調式core檔案, 而不是attach到乙個執行的程序上, 那麼上面的嘗試會得到乙個錯誤:

(gdb) printzv $5

[0x2a95de7840] (refcount=2) objectyou can't do that without a process to debug

不過, 即使這樣, 我們還是有辦法, 只不過就比較麻煩了.在nts下面:

(gdb) p ((zval *)0x2a95de7840)->value.obj.handle

$6 = 1

//注意, 下面用到了這個$6的值:1

(gdb) p (zend_object*) executor_globals->objects_store.object_buckets[1].bucket.obj.object

$7 = (struct _zend_object *) 0x2a95de3ec0

(gdb) p $9->ce->name

$8 = 0x2a95e200b0 "test

呵呵, 怎麼樣, 有了這些資訊, 分析core的原因, 是不是就更簡單了呢? enjoy~

除錯檢視PHP Core的呼叫棧

php gdb.php 如下 class test function a i function b i function c i function d i function e i a 2 使用php cli模式執行指令碼 usr local php 7.3.4 bin php gdb.php檢視p...

棧的分析(一) 函式呼叫棧

當發生函式呼叫的時候,棧空間中存放的資料是這樣的 1 呼叫者函式把被調函式所需要的引數按照與被調函式的形參順序相反的順序壓入棧中,即 從右向左依次把被調函式所需要的引數壓入棧 2 呼叫者函式使用call指令呼叫被調函式,並把call指令的下一條指令的位址當成返回位址壓入棧中 這個壓棧操作隱含在cal...

函式呼叫棧

當程式進行函式呼叫的時候,系統會用到下面三種暫存器 3.ebp ebp暫存器裡儲存的是棧基址,是在函式呼叫之前,由esp賦值給ebp的。棧底方向,高位位址 call fun arg1,arg2,arg3 修改esp,棧向下增長,引數入棧,返回位址入棧 arg3 arg2 arg1 返回位址 上一層e...