Heim  >  Artikel  >  Backend-Entwicklung  >  Tiefes Verständnis von PHP: Quellcode mit GDB debuggen

Tiefes Verständnis von PHP: Quellcode mit GDB debuggen

WBOY
WBOYnach vorne
2022-12-28 18:12:254504Durchsuche

Dieser Artikel vermittelt Ihnen relevantes Wissen über PHP, das hauptsächlich die relevanten Inhalte zur Verwendung von GDB zum Debuggen von Quellcode vorstellt. Ich hoffe, es wird für alle hilfreich sein.

Tiefes Verständnis von PHP: Quellcode mit GDB debuggen

Empfohlene Studie: „PHP-Video-Tutorial

PHP verfügt beim Kompilieren über einen Debug-Modus, der Speicherlecks meldet und die Aufrufstapeloptimierung abschirmt, sodass wir das vollständige PHP sehen können C-Level-Call-Stack.

Normalerweise kompiliere ich zwei PHP-Versionen (eine normale, eine mit aktiviertem Debug) in verschiedenen Verzeichnissen und entscheide durch den Export, welche ich verwenden möchte.

Sie können die Konfigurationsoptionen über den Befehl php-config anzeigen, das Präfix und den Pfad mit der Konfigurationsdatei zum neuen Verzeichnis ändern und dann den Befehl --enable-debug hinzufügen

yongkbmaster ➜  ~ php-config
Usage: /data/env/runtime/php-7.1.33-debug/bin/php-config [OPTION]
Options:
  --prefix            [/data/env/runtime/php-7.1.33-debug]
  --includes          [-I/data/env/runtime/php-7.1.33-debug/include/php -I/data/env/runtime/php-7.1.33-debug/include/php/main -I/data/env/runtime/php-7.1.33-debug/include/php/TSRM -I/data/env/runtime/php-7.1.33-debug/include/php/Zend -I/data/env/runtime/php-7.1.33-debug/include/php/ext -I/data/env/runtime/php-7.1.33-debug/include/php/ext/date/lib]
  --ldflags           []
  --libs              [-lcrypt   -lz -lexslt -lresolv -lcrypt -lrt -lldap -llber -lpng -lz -ljpeg -lcurl -lbz2 -lz -lrt -lm -ldl -lnsl  -lxml2 -lz -lm -ldl -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lssl -lcrypto -lcurl -lxml2 -lz -lm -ldl -lfreetype -lxml2 -lz -lm -ldl -lxml2 -lz -lm -ldl -lcrypt -lxml2 -lz -lm -ldl -lxml2 -lz -lm -ldl -lxml2 -lz -lm -ldl -lxml2 -lz -lm -ldl -lxslt -lxml2 -lz -ldl -lm -lssl -lcrypto -lcrypt ]
  --extension-dir     [/data/env/runtime/php-7.1.33-debug/lib/php/extensions/debug-non-zts-20160303]
  --include-dir       [/data/env/runtime/php-7.1.33-debug/include/php]
  --man-dir           [/data/env/runtime/php-7.1.33-debug/php/man]
  --php-binary        [/data/env/runtime/php-7.1.33-debug/bin/php]
  --php-sapis         [ cli fpm phpdbg cgi]
  --configure-options [--prefix=/data/env/runtime/php-7.1.33-debug --enable-debug --enable-phpdbg-debug --with-config-file-path=/data/env/runtime/php-7.1.33-debug/etc --with-curl --with-freetype-dir --with-gd --with-gettext --with-iconv-dir --with-kerberos --with-libdir=lib64 --with-libxml-dir --with-mysqli --with-openssl --with-pcre-regex --with-pdo-mysql --with-pdo-sqlite --with-pear --with-png-dir --with-jpeg-dir --with-xmlrpc --with-xsl --with-zlib --with-bz2 --with-mhash --enable-fpm --enable-bcmath --enable-libxml --enable-inline-optimization --enable-gd-native-ttf --enable-mbregex --enable-mbstring --enable-opcache --enable-pcntl --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-sysvshm --enable-xml --enable-zip --with-ldap]
  --version           [7.1.33]
  --vernum            [70133]

Nach der Änderung sieht es so aus so, und dann Kompilieren und installieren, um die Debug-Version zu erhalten

--prefix=/data/env/runtime/php-7.1.33-debug --enable-debug --enable-phpdbg-debug --with-config-file-path=/data/env/runtime/php-7.1.33-debug/etc --with-curl --with-freetype-dir --with-gd --with-gettext --with-iconv-dir --with-kerberos --with-libdir=lib64 --with-libxml-dir --with-mysqli --with-openssl --with-pcre-regex --with-pdo-mysql --with-pdo-sqlite --with-pear --with-png-dir --with-jpeg-dir --with-xmlrpc --with-xsl --with-zlib --with-bz2 --with-mhash --enable-fpm --enable-bcmath --enable-libxml --enable-inline-optimization --enable-gd-native-ttf --enable-mbregex --enable-mbstring --enable-opcache --enable-pcntl --enable-shmop --enable-soap --enable-sockets --enable-sysvsem --enable-sysvshm --enable-xml --enable-zip --with-ldap

Sehen Sie sich einfach DEBUG in php --version

yongkbmaster ➜  ~ /data/env/runtime/php-7.1.33-debug/bin/php --version
PHP 7.1.33 (cli) (built: Dec 29 2020 19:16:50) ( NTS DEBUG )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologie

Hinweis: Die Debug-Version der Erweiterung muss erneut kompiliert und installiert werden, die normale Version kann dies jedoch nicht Die Installationsmethode ist die gleiche wie bei der normalen Erweiterung. Im Allgemeinen ist es nicht erforderlich, zusätzliche Debug-Parameter zu öffnen. Wenn Sie eine Erweiterung wie swoole debuggen müssen, müssen Sie die Debug-Parameter der Erweiterung festlegen. Sie können sich auf die Dateibeschreibung ./configure der Erweiterung beziehen.

Verwendung von gdb

Hier finden Sie eine kurze Einführung in die grundlegende Verwendung von gdb. Für eine detailliertere Verwendung können Sie es selbst googeln.

gdb starten

Erfassungsprozess

gdb -p {pid}

Methodenstart ausführen

gdb php
run test3.php

über Kerndatei

gdb -c core.8451

Haltepunkt

break n: Legen Sie einen Haltepunkt fest Zeile n (kann mitgebracht werden Codepfad und Codename)

//注意:这里只能断点c代码,php文件不行的,var.c:201在php-7.1.33是var_dump的入口
break var.c:201

b fn1 if a>b: Bedingte Haltepunkteinstellung

break func (break wird als b abgekürzt): Setze einen Haltepunkt am Eingang der Funktion func()

//大部分php的方法在c层面的方法名都是zif_ + php方法名。 例如 var_dump 在c的方法名叫zif_var_dump
break zif_var_dump

delete Haltepunktnummer n: Lösche den n-ten Haltepunkt

Disable Haltepunkt Nummer n: Den n-ten Haltepunkt anhalten

enable Haltepunkt Nummer n: Den n-ten Haltepunkt aktivieren

clear Zeilennummer n: Den Haltepunkt der n-ten Zeile löschen

info b (Info Haltepunkte): Zeigt die Haltepunkteinstellungen an des aktuellen Programms

Haltepunkte löschen: Löscht alle Haltepunkte

Andere

  • Liste (abgekürzt als l), ihre Funktion besteht darin, die Quelle des Programmcodes aufzulisten, 10 Zeilen werden gleichzeitig angezeigt Standard.

  • Zeilennummer auflisten: zeigt die 10 Codezeilen vor und nach der aktuellen Datei zentriert auf der „Zeilennummer“ an,

  • a drucken: zeigt den Wert von a an

  • weiter (Abkürzung c ): Ausführung fortsetzen, zum nächsten Haltepunkt (oder Ende des Laufs) gehen. Sie müssen diese Taste drücken, nachdem Sie einen Haltepunkt festgelegt haben.

  • next (Abkürzung n): aktuelle Funktion, nächste Zeile

  • step (Abkürzung s): Sprung in das Innere der Funktion

  • where/bt: aktuell laufende Stack-Liste;

php Kleine gdb-Tools

Dieser Artikel stellt eine Reihe kleiner gdb-Tools im Quellcodeverzeichnis bereit, die uns helfen können, den gdb-PHP-Quellcode besser zu verstehen.

Vorbereitung

Zur besseren Demonstration werde ich hier eine PHP-Datei vorbereiten.

<?php
const A = &#39;test const&#39;;
const B = &#39;test const B&#39;;
class B {
        public $a = &#39;test&#39;;
        public function funB() {
                var_dump(&#39;test funB&#39;);
        }
}
class C extends B {
        public function funC() {
                var_dump(&#39;test funC&#39;);
        }
}
$a = &#39;test&#39;;
$b = [&#39;a1&#39; => 1, &#39;a2&#39; => 2];
$c = new B();
$d = [A, B];
$e = new C();
$f = $b;
var_dump($a, $b, $c, $d, $e, $f);
get_object_vars($e);

Starten Sie gdb und setzen Sie 2 Haltepunkte.

gdb php //注意这里要用debug版本的
(gdb) break var.c:211
Breakpoint 1 at 0x76e717: file /data/env/runtime/php-7.1.33-src/ext/standard/var.c, line 211.
(gdb) break zend_object_handlers.c:492
Breakpoint 2 at 0x86ce9d: file /data/env/runtime/php-7.1.33-src/Zend/zend_object_handlers.c, line 492.
(gdb) r test4.php

Laden Sie dann das Gadget.

source /data/env/runtime/php-7.1.33-src/.gdbinit

Verwenden Sie

zbacktrace, um den aktuellen PHP-Aufrufstapel anzuzeigen value

(gdb) zbacktrace
[0x7ffff1614200] var_dump("test", array(2)[0x7ffff1614260], object[0x7ffff1614270], array(2)[0x7ffff1614280], object[0x7ffff1614290], array(2)[0x7ffff16142a0]) [internal function]
[0x7ffff1614030] (main) /root/test4.php:26

print_global_vars globale Variablen ausgeben

(gdb) dump_bt executor_globals.current_execute_data
[0x7ffff1614200] var_dump("test", array(2)[0x7ffff1614260], object[0x7ffff1614270], array(2)[0x7ffff1614280], object[0x7ffff1614290], array(2)[0x7ffff16142a0]) [internal function]
[0x7ffff1614030] (main) /root/test4.php:26

print_const_table Definierte Konstanten ausgeben

(gdb) printzv &args[0]
[0x7ffff1614250] (refcount=0) string: test

print_zstr Zend-String ausgeben

(gdb) print_global_vars
Hash(13)[0x11bf0d0]: {
  [0] _GET => [0x7ffff1657100] (refcount=2) array:
  [1] _POST => [0x7ffff1657120] (refcount=2) array:
  [2] _COOKIE => [0x7ffff1657140] (refcount=2) array:
  [3] _FILES => [0x7ffff1657160] (refcount=2) array:
  [4] argv => [0x7ffff1657180] (refcount=2) array:
  [5] argc => [0x7ffff16571a0] long: 1
  [6] _SERVER => [0x7ffff16571c0] (refcount=2) array:
  [7] a => [0x7ffff16571e0] indirect: [0x7ffff1613080] (refcount=0) string: test
  [8] b => [0x7ffff1657200] indirect: [0x7ffff1613090] (refcount=5) array:
  [9] c => [0x7ffff1657220] indirect: [0x7ffff16130a0] (refcount=2) object(B) #2
  [10] d => [0x7ffff1657240] indirect: [0x7ffff16130b0] (refcount=2) array:
  [11] e => [0x7ffff1657260] indirect: [0x7ffff16130c0] (refcount=2) object(C) #3
  [12] f => [0x7ffff1657280] indirect: [0x7ffff16130d0] (refcount=5) array:

print_cvs Kompilierte Variablen und ihre Werte drucken Es muss ein Wert vom Typ zend_execute_data übergeben werden. Sie können sich zunächst den Aufrufstapel ansehen.

(gdb) print_const_table executor_globals.zend_constants
[0x14e8380] {
  Hash(2340)[0x14e8380]: {
    [0] E_ERROR => [0x14fd660] long: 1
    [1] E_RECOVERABLE_ERROR => [0x14fe8a0] long: 4096
    [2] E_WARNING => [0x14fe900] long: 2
    [3] E_PARSE => [0x14fe960] long: 4
    [4] E_NOTICE => [0x14fe9c0] long: 8
    [5] E_STRICT => [0x14fea20] long: 2048
    [6] E_DEPRECATED => [0x14fea80] long: 8192
    [7] E_CORE_ERROR => [0x14feae0] long: 16
    [8] E_CORE_WARNING => [0x14feb40] long: 32
    [9] E_COMPILE_ERROR => [0x14feba0] long: 64
    [10] E_COMPILE_WARNING => [0x14fec10] long: 128
    [11] E_USER_ERROR => [0x14fec70] long: 256
    [12] E_USER_WARNING => [0x14fecd0] long: 512
    [13] E_USER_NOTICE => [0x14fed30] long: 1024
    [14] E_USER_DEPRECATED => [0x14feda0] long: 16384
    [15] E_ALL => [0x14fee00] long: 32767
    [16] DEBUG_BACKTRACE_PROVIDE_OBJECT => [0x14fee70] long: 1
    [17] DEBUG_BACKTRACE_IGNORE_ARGS => [0x14feee0] long: 2
    [18] true => [0x14fef70] bool: true
    [19] false => [0x14ff000] bool: false
    [20] ZEND_THREAD_SAFE => [0x14ff070] bool: false
    [21] ZEND_DEBUG_BUILD => [0x14ff0e0] bool: true
    [22] null => [0x14ff170] NULL
    [23] PHP_VERSION => [0x1500380] (refcount=1) string: 7.1.33
 ......

print_ht gibt HashTable aus. Es handelt sich um die Implementierung eines PHP-Arrays, das auch häufig im PHP-Quellcode verwendet wird k v-Strukturen oder Array-Strukturen.

(gdb) print_zstr args[0]
string(4) "test"
(gdb) print_zstr args[0] 2
string(4) "te..."
(gdb) print_zstr args[0] 4
string(4) "test"

print_htptr ähnelt print_ht. Es gibt die Adresse von zval aus, nicht den Wert von zval.

(gdb) bt //这里看到 #2 层这里是 zend_vm_execute 的执行入口,这里有zend_execute_data 类型的值。
#0  zif_var_dump (execute_data=0x7ffff1614120, return_value=0x7fffffffa9b0) at /data/env/runtime/php-7.1.33-src/ext/standard/var.c:209
#1  0x0000000000ab08d4 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER () at /data/env/runtime/php-7.1.33-src/Zend/zend_vm_execute.h:628
#2  0x0000000000ab01c3 in execute_ex (ex=0x7ffff1614030) at /data/env/runtime/php-7.1.33-src/Zend/zend_vm_execute.h:429
#3  0x0000000000ab02d5 in zend_execute (op_array=0x7ffff1672d00, return_value=0x0) at /data/env/runtime/php-7.1.33-src/Zend/zend_vm_execute.h:474
#4  0x0000000000a510f9 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /data/env/runtime/php-7.1.33-src/Zend/zend.c:1482
#5  0x00000000009c02f4 in php_execute_script (primary_file=0x7fffffffdf30) at /data/env/runtime/php-7.1.33-src/main/main.c:2577
#6  0x0000000000b31387 in do_cli (argc=2, argv=0x14e7f30) at /data/env/runtime/php-7.1.33-src/sapi/cli/php_cli.c:993
#7  0x0000000000b32346 in main (argc=2, argv=0x14e7f30) at /data/env/runtime/php-7.1.33-src/sapi/cli/php_cli.c:1381
(gdb) f 2 //跳到#2 这一层
#2  0x0000000000ab01c3 in execute_ex (ex=0x7ffff1614030) at /data/env/runtime/php-7.1.33-src/Zend/zend_vm_execute.h:429
429                     ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
(gdb) print_cvs ex //输出
Compiled variables count: 6
[0] &#39;a&#39;
[0x7ffff1614080] (refcount=0) string: test
[1] &#39;b&#39;
[0x7ffff1614090] (refcount=5) array:     Hash(2)[0x7ffff170e300]: {
      [0] a1 => [0x7ffff1793e20] long: 1
      [1] a2 => [0x7ffff1793e40] long: 2
}
[2] &#39;c&#39;
[0x7ffff16140a0] (refcount=2) object(B) #2
Properties     Hash(1)[0x7ffff170e480]: {
      [0] a => [0x7ffff1793f60] indirect: [0x7ffff170e388] (refcount=4) string: test
}
[3] &#39;d&#39;
[0x7ffff16140b0] (refcount=2) array:     Packed(2)[0x7ffff170e3c0]: {
      [0] 0 => [0x7ffff1793688] (refcount=1) string: test const
      [1] 1 => [0x7ffff17936a8] (refcount=1) string: test const B
}
[4] &#39;e&#39;
[0x7ffff16140c0] (refcount=2) object(C) #3
Properties     Hash(1)[0x7ffff170e4e0]: {
      [0] a => [0x7ffff17940a0] indirect: [0x7ffff170e448] (refcount=4) string: test
}
[5] &#39;f&#39;
[0x7ffff16140d0] (refcount=5) array:     Hash(2)[0x7ffff170e300]: {
      [0] a1 => [0x7ffff1793e20] long: 1
      [1] a2 => [0x7ffff1793e40] long: 2
}

print_htstr speichert c char anstelle von zval Im Quellcode wird meistens der Zend-String direkt verwendet und ein Ort gefunden, an dem php_cli_server_mime_type_ctor verwendet werden kann.

(gdb) print_ht args[1].value
Hash(2)[0x7ffff170e300]: {
  [0] a1 => [0x7ffff1793e20] long: 1
  [1] a2 => [0x7ffff1793e40] long: 2
}
(gdb) print_ht args[3].value
Packed(2)[0x7ffff170e3c0]: {
  [0] 0 => [0x7ffff1793688] (refcount=1) string: test const
  [1] 1 => [0x7ffff17936a8] (refcount=1) string: test const B
}

print_ft ist ähnlich wie print_ht, außer dass die Adresse von zend_function gespeichert ist HashTable.

(gdb) print_htptr args[1].value
Hash(2)[0x7ffff170e300]: {
  [0] a1 => 0x7ffff1793e20
  [1] a2 => 0x7ffff1793e40
}

print_inh gibt klassenbezogene Informationen aus. Es muss eine Adresse vom Typ zend_property_info übergeben werden, die in zend_object_handlers.c:492 verwendet werden kann get_object_vars($e) in PHP.

(gdb) print_htstr &server->extension_mime_types
Hash(2)[0x11b9228]: {
  [0] ez => application/andrew-inset
  [1] aw => application/applixware
}

Empfohlenes Lernen: „

PHP-Video-Tutorial

Das obige ist der detaillierte Inhalt vonTiefes Verständnis von PHP: Quellcode mit GDB debuggen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:腾讯技术工程微信公众号. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen