Maison > Article > développement back-end > Compréhension approfondie de PHP : débogage du code source avec gdb
Cet article vous apporte des connaissances pertinentes sur PHP, qui présente principalement le contenu pertinent sur l'utilisation de gdb pour déboguer le code source. J'espère qu'il sera utile à tout le monde.
Étude recommandée : "Tutoriel vidéo PHP"
PHP a un mode de débogage lors de la compilation. Ce mode désactivera l'optimisation de la mémoire, provoquera des fuites de mémoire et protégera l'optimisation de la pile d'appels afin que nous puissions voir le PHP complet. Pile d’appels de niveau C.
Habituellement, je compile deux versions de PHP (une normale, une avec le débogage activé) dans des répertoires différents et je décide laquelle utiliser via l'exportation.
Vous pouvez voir les options de configuration via la commande php-config, modifier le préfixe et with-config-file-path vers le nouveau répertoire, puis ajouter la commande --enable-debug
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]
Après la modification, il semble comme ça, puis compilez et installez pour obtenir la version de débogage
--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
Voir DEBUG dans 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
Remarque : la version de débogage de l'extension doit être compilée et réinstallée, et la version normale de celle-ci ne peut pas l'être. copié. La méthode d'installation est la même que celle de l'extension ordinaire. Généralement, il n'est pas nécessaire d'ouvrir des paramètres de débogage supplémentaires. Si vous devez déboguer une extension telle que swoole, vous devez définir les paramètres de débogage de l'extension. Vous pouvez vous référer à la description du fichier ./configure de l'extension.
Voici une brève introduction à l'utilisation de base de gdb Pour une utilisation plus détaillée, vous pouvez le rechercher vous-même sur Google.
Démarrer gdb
Processus de capture
gdb -p {pid}
exécuter la méthode start
gdb php run test3.php
via le fichier principal
gdb -c core.8451
Breakpoint
break n : définir un point d'arrêt à la ligne n (peut être apporté le chemin du code et nom de code)
//注意:这里只能断点c代码,php文件不行的,var.c:201在php-7.1.33是var_dump的入口 break var.c:201
b fn1 si a>b : réglage du point d'arrêt conditionnel
break func (break est abrégé en b) : définir un point d'arrêt à l'entrée de la fonction func()
//大部分php的方法在c层面的方法名都是zif_ + php方法名。 例如 var_dump 在c的方法名叫zif_var_dump break zif_var_dump
supprimer le numéro du point d'arrêt n : supprimer le nième breakpoint
disable Breakpoint number n : mettre en pause le nième point d'arrêt
enable Breakpoint number n : activer le nième point d'arrêt
clear Line number n : effacer le point d'arrêt de la nième ligne
info b (info breakpoints) : affiche les paramètres du point d'arrêt du programme actuel
supprimer les points d'arrêt : efface tous les points d'arrêt
Autres
liste (en abrégé l), sa fonction est de lister la source du programme Code, 10 lignes sont affichées à la fois par défaut.
list line number : affichera les 10 lignes de code avant et après le fichier courant centré sur le "line number",
print a : affichera la valeur d'un
continue (abréviation c ) : continuer l'exécution, passer au point d'arrêt suivant (ou à la fin de l'exécution). Vous devez appuyer dessus après avoir défini un point d'arrêt.
next (abréviation n) : fonction actuelle, ligne suivante
step (abréviation s) : accéder à l'intérieur de la fonction
where/bt : liste de piles en cours d'exécution
C'est l'objet de cet article. PHP fournit un ensemble de petits outils pour gdb Dans le fichier .gdbinit du répertoire du code source, cela peut nous aider à mieux comprendre le code source de gdb PHP.
Préparation
Pour une meilleure démonstration, je vais préparer un fichier php ici.
<?php const A = 'test const'; const B = 'test const B'; class B { public $a = 'test'; public function funB() { var_dump('test funB'); } } class C extends B { public function funC() { var_dump('test funC'); } } $a = 'test'; $b = ['a1' => 1, 'a2' => 2]; $c = new B(); $d = [A, B]; $e = new C(); $f = $b; var_dump($a, $b, $c, $d, $e, $f); get_object_vars($e);
Démarrez gdb et définissez 2 points d'arrêt.
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
Ensuite, chargez le gadget
source /data/env/runtime/php-7.1.33-src/.gdbinit
Utilisez
zbacktrace pour afficher la pile d'appels php actuelle
(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
dump_bt pour afficher la pile d'appels actuelle et zbacktrace similaire à la valeur zend de sortie de
(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
printzv
(gdb) printzv &args[0] [0x7ffff1614250] (refcount=0) string: test
print_global_vars Output Variables globales
(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_const_table Sortie des constantes définies
(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_zstr Sortie de la chaîne zend
(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_cvs Imprimer les variables compilées et leurs valeurs Il doit transmettre une valeur de type zend_execute_data. Vous pouvez d’abord jeter un œil à la pile d’appels.
(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] 'a' [0x7ffff1614080] (refcount=0) string: test [1] 'b' [0x7ffff1614090] (refcount=5) array: Hash(2)[0x7ffff170e300]: { [0] a1 => [0x7ffff1793e20] long: 1 [1] a2 => [0x7ffff1793e40] long: 2 } [2] 'c' [0x7ffff16140a0] (refcount=2) object(B) #2 Properties Hash(1)[0x7ffff170e480]: { [0] a => [0x7ffff1793f60] indirect: [0x7ffff170e388] (refcount=4) string: test } [3] 'd' [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] 'e' [0x7ffff16140c0] (refcount=2) object(C) #3 Properties Hash(1)[0x7ffff170e4e0]: { [0] a => [0x7ffff17940a0] indirect: [0x7ffff170e448] (refcount=4) string: test } [5] 'f' [0x7ffff16140d0] (refcount=5) array: Hash(2)[0x7ffff170e300]: { [0] a1 => [0x7ffff1793e20] long: 1 [1] a2 => [0x7ffff1793e40] long: 2 }
print_ht produit HashTable. HashTable est une structure de données importante au bas de PHP. Vous pouvez le comprendre comme un tableau PHP de niveau C est également largement utilisé dans le code source PHP pour stocker divers. k v structures ou structures de tableau.
(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_htptr est similaire à print_ht. Il affiche l'adresse de zval, pas la valeur de zval.
(gdb) print_htptr args[1].value Hash(2)[0x7ffff170e300]: { [0] a1 => 0x7ffff1793e20 [1] a2 => 0x7ffff1793e40 }
print_htstr est similaire à print_ht, sauf que la HashTable stocke c char au lieu de zval. dans le code source. Maintenant, dans la plupart des cas de stockage de chaînes, la chaîne zend sera utilisée directement. J'ai cherché et trouvé un endroit pour utiliser php_cli_server_mime_type_ctor
(gdb) print_htstr &server->extension_mime_types Hash(2)[0x11b9228]: { [0] ez => application/andrew-inset [1] aw => application/applixware }
print_ft est similaire à print_ht, sauf que l'adresse de zend_function est stockée dans. la HashTable.
(gdb) print_ft &args[2].value.obj.ce.function_table Hash(1)[0x7ffff1783210]: { [0] funb => "funB" }
print_inh génère des informations relatives à la classe.
(gdb) print_inh &args[4].value.obj.ce class C extends B { class B { } }
print_pi génère des informations relatives aux attributs de l'objet. Il doit transmettre une adresse de type zend_property_info, qui est utilisée dans zend_object_handlers.c:492. par get_object_vars($e) en PHP.
(gdb) c Continuing. Breakpoint 2, zend_check_property_access (zobj=0x7ffff170e420, prop_info_name=0x7ffff173c2c0) at /data/env/runtime/php-7.1.33-src/Zend/zend_object_handlers.c:492 492 zend_string_release(member); (gdb) print_pi property_info [0x7ffff17833c8] { offset = 0x28 ce = [0x7ffff17831d0] B flags = 0x100 (ZEND_ACC_PUBLIC) name = string(1) "a" default value: [0x7ffff17690c0] (refcount=4) string: test }
Apprentissage recommandé : "Tutoriel vidéo PHP"
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!