gdb方式遍历EG(symbol_table) 哈希表的key_PHP教程
Sara Golemon写过一篇文章,里面提到:“是否存在特别的地方可以找到GLOBALS数组?”答案是“存在”,就是EG(symbol_table)-Executor Globals结构,她也给出了找的具体实例,如下
PHP_FUNCTION(confirm_getGlobal_compiled) {
char *varname;
int varname_len;
zval **varvalue;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &varname, &varname_len) == FAILURE) {
RETURN_NULL();
}
if (zend_hash_find(&EG(symbol_table), varname, varname_len + 1, (void**)&varvalue) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Undefined variable: %s", varname);
RETURN_NULL();
}
*return_value = **varvalue;
zval_copy_ctor(return_value);
}
编译成so加载后,编写php测试代码
$abc = 'string';
$def = 'string2';
var_dump(confirm_getGlobal_compiled('abc'));
执行结果
string(6) "string"
大家可能感觉奇怪,为什么多写了一个def变量,这就是下面要进行的,一起来看下EG这个hashtable
gdb --args bin/php -c php.ini a.php
调试代码如下
(gdb) b renzhi.c : 301 //在写的扩展地方加上断点
No source file named renzhi.c.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (renzhi.c : 301) pending.
(gdb) r //运行到断点处
Starting program: /root/php-src-5.3/bin/php -c php.ini ceshi.php
warning: .dynamic section for "/lib/libc.so.6" is not at the expected address
warning: difference appears to be caused by prelink, adjusting expectations
[Thread debugging using libthread_db enabled]
Breakpoint 1, zif_confirm_getGlobal_compiled (ht=1, return_value=0x837a43c, return_value_ptr=0x0, this_ptr=0x0, return_value_used=1)
at /root/php-src-5.3/ext/renzhi/renzhi.c:305
305 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &varname, &varname_len) == FAILURE) {
(gdb) n
309 if (zend_hash_find(&EG(symbol_table), varname, varname_len + 1, (void**)&varvalue) == FAILURE) {
(gdb) step //进入zend_hash_find哈希查找函数
zend_hash_find (ht=0x82e3250, arKey=0x837a42c "abc", nKeyLength=4, pData=0xbfffc484) at /root/php-src-5.3/Zend/zend_hash.c:872
下面看下关键
(gdb) p *ht
$9 = {nTableSize = 64, nTableMask = 63, nNumOfElements = 10, nNextFreeElement = 0, pInternalPointer = 0x83edc98, pListHead = 0x83edc98,
pListTail = 0x837a3fc, arBuckets = 0x83705a8, pDestructor = 0x81923b0 <_zval_ptr_dtor>, persistent = 0 '\000', nApplyCount = 0 '\000',
bApplyProtection = 1 '\001'}
(gdb) p *ht.pListHead
$2 = {h = 2572561225, nKeyLength = 8, pData = 0x83edca4, pDataPtr = 0x83edc7c, pListNext = 0x8378c4c, pListLast = 0x0, pNext = 0x0, pLast = 0x0,
arKey = "G"}
(gdb) p *ht.pListHead.pListNext
$3 = {h = 253399445, nKeyLength = 5, pData = 0x8378c58, pDataPtr = 0x8378b60, pListNext = 0x8378c7c, pListLast = 0x83edc98, pNext = 0x0, pLast = 0x0,
arKey = "a"}
(gdb) p *ht.pListHead.pListNext.pListNext
$4 = {h = 253398818, nKeyLength = 5, pData = 0x8378c88, pDataPtr = 0x8378c30, pListNext = 0x8378d20, pListLast = 0x8378c4c, pNext = 0x0, pLast = 0x0,
arKey = "a"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext
$5 = {h = 3947724458, nKeyLength = 6, pData = 0x8378d2c, pDataPtr = 0x8378cac, pListNext = 0x8378d54, pListLast = 0x8378c7c, pNext = 0x0, pLast = 0x0,
arKey = "_"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext
$6 = {h = 249444164, nKeyLength = 5, pData = 0x8378d60, pDataPtr = 0x83edd1c, pListNext = 0x8378d84, pListLast = 0x8378d20, pNext = 0x0, pLast = 0x0,
arKey = "_"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext
$7 = {h = 195471710, nKeyLength = 8, pData = 0x8378d90, pDataPtr = 0x83edd38, pListNext = 0x8378e2c, pListLast = 0x8378d54, pNext = 0x0, pLast = 0x0,
arKey = "_"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$8 = {h = 1027153623, nKeyLength = 7, pData = 0x8378e38, pDataPtr = 0x8378db8, pListNext = 0x8379e8c, pListLast = 0x8378d84, pNext = 0x0, pLast = 0x0,
arKey = "_"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$9 = {h = 3291685243, nKeyLength = 8, pData = 0x8379e98, pDataPtr = 0x8378e88, pListNext = 0x837a3cc, pListLast = 0x8378e2c, pNext = 0x0, pLast = 0x0,
arKey = "_"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x8379ef8, pListNext = 0x837a3fc, pListLast = 0x8379e8c, pNext = 0x0, pLast = 0x0,
arKey = "a"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$11 = {h = 2090180660, nKeyLength = 4, pData = 0x837a408, pDataPtr = 0x8379edc, pListNext = 0x0, pListLast = 0x837a3cc, pNext = 0x0, pLast = 0x0,
arKey = "d"}
有点乱,这里第一条就是现实了EG这个hash表里面有nNumOfElements =10个元素
这里的
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x8379ef8, pListNext = 0x837a3fc, pListLast = 0x8379e8c, pNext = 0x0, pLast = 0x0,
arKey = "a"}
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$11 = {h = 2090180660, nKeyLength = 4, pData = 0x837a408, pDataPtr = 0x8379edc, pListNext = 0x0, pListLast = 0x837a3cc, pNext = 0x0, pLast = 0x0,
arKey = "d"}
就是测试php代码里面的
$abc = 'string';
$def = 'string2';
这两个变量名称的具体hash的bucket了
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x8379ef8, pListNext = 0x837a3fc, pListLast = 0x8379e8c, pNext = 0x0, pLast = 0x0,
arKey = "a"}
第一个字符arKey为a,有nKeyLength = 4四个字符长度
(gdb) p ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.arKey[0]
$10 = 97 'a'
(gdb) p ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.arKey[1]
$11 = 98 'b'
(gdb) p ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.arKey[2]
$12 = 99 'c'
(gdb) p ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.arKey[3]
$13 = 0 '\000'
如何在gdb方式下拿到指针了,看到对应的执行的zval的内容呢?
已经知道了bucket结构体中的pData就执行了内容
(gdb) p ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pData
$19 = (void *) 0x837a3d8
但是返回的这个,还不知道如何获得,请高手帮助
搞明白了
(gdb) p *ht.pListHead.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext.pListNext
$29 = {h = 2090069483, nKeyLength = 4, pData = 0x839fe28, pDataPtr = 0x839f948, pListNext = 0x839fe4c, pListLast = 0x839f8dc, pNext = 0x0, pLast = 0x0,
arKey = "a"}
(gdb) p *(zval *)$29->pDataPtr
$30 = {value = {lval = 138024112, dval = 1.2800167717828578e-313, str = {val = 0x83a14b0 "string", len = 6}, ht = 0x83a14b0, obj = {handle = 138024112,
handlers = 0x6}}, refcount__gc = 1, type = 6 '\006', is_ref__gc = 0 '\000'}
哈哈,可以看到具体的hash指向的值了
但是又有点不明白了pData和pDataPtr到底有啥关系?
(gdb) p &$29->pDataPtr
$46 = (void **) 0x839fe28
(gdb) p $29->pData
$47 = (void *) 0x839fe28
也就是pData里面存得是pDataPtr的地址
摘自 xiaoq3406的专栏

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Bagaimana untuk menyediakan permulaan papan kekunci pada papan induk Gigabyte Pertama, jika ia perlu menyokong permulaan papan kekunci, ia mestilah papan kekunci PS2! ! Langkah-langkah tetapan adalah seperti berikut: Langkah 1: Tekan Del atau F2 untuk memasuki BIOS selepas but, dan masukkan mod Lanjutan (Lanjutan) BIOS Papan induk biasa masukkan mod EZ (Mudah) papan induk secara lalai untuk menekan F7 untuk beralih ke mod Lanjutan papan induk siri ROG masukkan BIOS secara lalai (kami menggunakan Bahasa Cina Mudah untuk menunjukkan) Langkah 2: Pilih untuk - [Lanjutan] - [Pengurusan Kuasa Lanjutan (APM)] Langkah 3: Cari pilihan [Bangun dengan papan kekunci PS2] Langkah 4: Pilihan lalai ini Dilumpuhkan Selepas menarik ke bawah, anda boleh melihat tiga pilihan tetapan yang berbeza, termasuk menekan [bar ruang] untuk menghidupkan komputer dan menekan butang kumpulan.

1. Bagaimanakah anda boleh membuat wang dengan menerbitkan artikel di Toutiao hari ini? Bagaimana untuk mendapatkan lebih banyak pendapatan dengan menerbitkan artikel di Toutiao hari ini! 1. Aktifkan hak dan kepentingan asas: Artikel asal boleh memperoleh keuntungan melalui pengiklanan dan video mestilah asli dalam mod skrin mendatar untuk memperoleh keuntungan. 2. Aktifkan hak 100 peminat: jika bilangan peminat mencecah 100 peminat ke atas, anda boleh mendapat keuntungan daripada tajuk mikro, ciptaan Soal Jawab asal dan Soal Jawab. 3. Menegaskan karya asli: Karya asal termasuk artikel, tajuk mikro, soalan, dsb., dan dikehendaki melebihi 300 patah perkataan. Sila ambil perhatian bahawa jika karya yang diciplak secara haram diterbitkan sebagai karya asli, mata kredit akan ditolak, malah sebarang keuntungan akan ditolak. 4. Ketegakan: Apabila menulis artikel dalam bidang profesional, anda tidak boleh menulis artikel merentas bidang sesuka hati Anda tidak akan mendapat cadangan yang sesuai, anda tidak akan dapat mencapai profesionalisme dan ketepatan kerja, dan sukar untuk menarik peminat. dan pembaca. 5. Aktiviti: aktiviti tinggi,

1. Pemproses Apabila memilih konfigurasi komputer, pemproses adalah salah satu komponen yang paling penting. Untuk permainan seperti CS, prestasi pemproses secara langsung mempengaruhi kelancaran dan kelajuan tindak balas permainan. Adalah disyorkan untuk memilih pemproses siri Intel Core i5 atau i7 kerana ia mempunyai keupayaan pemprosesan berbilang teras yang berkuasa dan frekuensi tinggi, dan dengan mudah boleh menampung keperluan CS yang tinggi. 2. Kad grafik Kad grafik merupakan salah satu faktor penting dalam prestasi permainan. Untuk permainan menembak seperti CS, prestasi kad grafik secara langsung mempengaruhi kejelasan dan kelancaran skrin permainan. Adalah disyorkan untuk memilih siri NVIDIA GeForce GTX atau kad grafik siri AMD Radeon RX Mereka mempunyai keupayaan pemprosesan grafik yang sangat baik dan output kadar bingkai yang tinggi, dan boleh memberikan pengalaman permainan yang lebih baik

Apakah Identity dalam SQL? Contoh kod khusus diperlukan Dalam SQL, Identity ialah jenis data khas yang digunakan untuk menjana nombor penambahan automatik. Ia sering digunakan untuk mengenal pasti setiap baris data dalam jadual. Lajur Identiti sering digunakan bersama dengan lajur kunci utama untuk memastikan setiap rekod mempunyai pengecam unik. Artikel ini akan memperincikan cara menggunakan Identiti dan beberapa contoh kod praktikal. Cara asas untuk menggunakan Identity ialah menggunakan Identit semasa membuat jadual.

Urutan talian sambungan SPDIFOUT pada papan induk Baru-baru ini, saya menghadapi masalah mengenai urutan pendawaian wayar. Saya menyemak dalam talian Beberapa maklumat mengatakan bahawa 1, 2, dan 4 sepadan dengan keluar, +5V, dan tanah manakala maklumat lain mengatakan bahawa 1, 2, dan 4 sepadan dengan keluar, tanah dan +5V. Cara terbaik ialah menyemak manual papan induk anda Jika anda tidak menemui manual, anda boleh menggunakan multimeter untuk mengukurnya. Cari tanah dahulu, kemudian anda boleh menentukan susunan pendawaian yang lain. Cara menyambung pendawaian VDG papan induk Apabila menyambungkan pendawaian VDG papan induk, anda perlu palamkan satu hujung kabel VGA ke antara muka VGA monitor dan hujung satu lagi ke antara muka VGA kad grafik komputer. Sila berhati-hati untuk tidak memasukkannya ke dalam port VGA motherboard. Setelah disambungkan, anda boleh

Glodon Software ialah sebuah syarikat perisian yang memfokuskan pada bidang pemformatan bangunan. Produknya digunakan secara meluas dalam semua aspek reka bentuk seni bina, pembinaan dan operasi. Oleh kerana fungsi kompleks dan volum data yang besar perisian Glodon, ia memerlukan konfigurasi komputer yang tinggi. Artikel ini akan menghuraikan cadangan konfigurasi komputer Perisian Glodon dari banyak aspek untuk membantu pembaca memilih pemproses konfigurasi komputer yang sesuai memerlukan pengiraan dan pemprosesan data yang besar apabila melakukan reka bentuk seni bina, simulasi dan operasi lain kerana pemproses lebih tinggi. Adalah disyorkan untuk memilih pemproses berbilang teras, frekuensi tinggi, seperti siri Intel i7 atau siri AMD Ryzen. Pemproses ini mempunyai kuasa pengkomputeran yang kuat dan keupayaan pemprosesan berbilang benang, dan boleh memenuhi keperluan perisian Glodon dengan lebih baik. Memori Memori menjejaskan pengkomputeran

Cara menggunakan algoritma carian cincang dalam C++ Algoritma carian cincang ialah teknologi carian dan storan yang cekap Ia menukar kata kunci kepada indeks panjang tetap melalui fungsi cincang, dan kemudian menggunakan indeks ini dalam Carian struktur data. Dalam C++, kita boleh melaksanakan algoritma carian hash dengan menggunakan bekas cincang dan fungsi cincang dalam perpustakaan standard. Artikel ini akan memperkenalkan cara menggunakan algoritma carian hash dalam C++ dan memberikan contoh kod khusus. Memperkenalkan fail pengepala dan ruang nama Pertama, sebelum menggunakan algoritma carian hash dalam C++

Java ialah bahasa pengaturcaraan yang popular dengan keupayaan pengendalian fail yang berkuasa. Di Java, melintasi folder dan mendapatkan semua nama fail adalah operasi biasa, yang boleh membantu kami mencari dan memproses fail dengan cepat dalam direktori tertentu. Artikel ini akan memperkenalkan cara melaksanakan kaedah melintasi folder dan mendapatkan semua nama fail dalam Java, dan memberikan contoh kod khusus. 1. Gunakan kaedah rekursif untuk melintasi folder Kita boleh menggunakan kaedah rekursif untuk melintasi folder.
