The gdb method traverses keys of the EG (symbol_table) hash table. SaraGolemon wrote an article about whether the GLOBALS array can be found in a special place? The answer is that the EG (symbol_table)-ExecutorGlobals structure exists. She also wrote an article titled Sara Golemon, which mentioned: "Is there a special place to find the GLOBALS array ?" The answer is "exist", that is, the EG (symbol_table)-Executor Globals structure. She also provided the specific instance for finding, as shown below:
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 );
}
Compile the php test code after being loaded into so.
$ Abc = 'string ';
$ Def = 'string2 ';
Var_dump (confirm_getGlobal_compiled ('ABC '));
Execution result
String (6) "string"
You may be wondering why I wrote another def variable. this is what is going on below. let's take a look at this hashtable.
Gdb -- args bin/php-c php. ini a. php
The debugging code is as follows:
(Gdb) B renzhi. c: 301 // add a breakpoint to the write extension
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 // run to the breakpoint
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. 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 // enter the zend_hash_find hash lookup function
Zend_hash_find (ht = 0x82e3250, arKey = 0x837a42c "abc", nKeyLength = 4, pData = 0xbfffc484) at/root/php-src-5.3/Zend/zend_hash.c: 872
Next, let's take a look at the key points.
(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 = 0x80000c58, pDataPtr = 0x80000b60, pListNext = 0x80000c7c, pListLast = 0x83edc98, pNext = 0x0, pLast = 0x0,
ArKey = ""}
(Gdb) p * ht. pListHead. pListNext. pListNext
$4 = {h = 253398818, nKeyLength = 5, pData = 0x80000c88, pDataPtr = 0x80000c30, pListNext = 0x80000d20, pListLast = 0x80000c4c, pNext = 0x0, pLast = 0x0,
ArKey = ""}
(Gdb) p * ht. pListHead. pListNext
$5 = {h = 3947724458, nKeyLength = 6, pData = 0x80000d2c, pDataPtr = 0x80000cac, pListNext = 0x80000d54, pListLast = 0x80000c7c, pNext = 0x0, pLast = 0x0,
ArKey = "_"}
(Gdb) p * ht. pListHead. pListNext
$6 = {h = 249444164, nKeyLength = 5, pData = 0x80000d60, pDataPtr = 0x83edd1c, pListNext = 0x80000d84, pListLast = 0x80000d20, pNext = 0x0, pLast = 0x0,
ArKey = "_"}
(Gdb) p * ht. pListHead. pListNext
$7 = {h = 195471710, nKeyLength = 8, pData = 0x80000d90, pDataPtr = 0x83edd38, pListNext = 0x80000e2c, pListLast = 0x80000d54, pNext = 0x0, pLast = 0x0,
ArKey = "_"}
(Gdb) p * ht. pListHead. pListNext
$8 = {h = 1027153623, nKeyLength = 7, pData = 0x80000e38, pDataPtr = 0x80000db8, pListNext = 0x80000e8c, pListLast = 0x80000d84, pNext = 0x0, pLast = 0x0,
ArKey = "_"}
(Gdb) p * ht. pListHead. pListNext
$9 = {h = 3291685243, nKeyLength = 8, pData = 0x80000e98, pDataPtr = 0x80000e88, pListNext = 0x837a3cc, pListLast = 0x80000e2c, pNext = 0x0, pLast = 0x0,
ArKey = "_"}
(Gdb) p * ht. pListHead. pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x81_ef8, pListNext = 0x837a3fc, pListLast = 0x81_e8c, pNext = 0x0, pLast = 0x0,
ArKey = ""}
(Gdb) p * ht. pListHead. pListNext
$11 = {h = 2090180660, nKeyLength = 4, pData = 0x837a408, pDataPtr = 0x81_edc, pListNext = 0x0, pListLast = 0x837a3cc, pNext = 0x0, pLast = 0x0,
ArKey = "d "}
A bit messy. The first one here is the reality. for example, the hash table contains nNumOfElements = 10 elements.
Here
(Gdb) p * ht. pListHead. pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x81_ef8, pListNext = 0x837a3fc, pListLast = 0x81_e8c, pNext = 0x0, pLast = 0x0,
ArKey = ""}
(Gdb) p * ht. pListHead. pListNext
$11 = {h = 2090180660, nKeyLength = 4, pData = 0x837a408, pDataPtr = 0x81_edc, pListNext = 0x0, pListLast = 0x837a3cc, pNext = 0x0, pLast = 0x0,
ArKey = "d "}
Is to test the php code
$ Abc = 'string ';
$ Def = 'string2 ';
The bucket for the specific hash of the two variable names
(Gdb) p * ht. pListHead. pListNext
$10 = {h = 2090069483, nKeyLength = 4, pData = 0x837a3d8, pDataPtr = 0x81_ef8, pListNext = 0x837a3fc, pListLast = 0x81_e8c, pNext = 0x0, pLast = 0x0,
ArKey = ""}
The first character, arKey, is a and has a length of nKeyLength = 4.
(Gdb) p ht. pListHead. pListNext. arKey [0]
$10 = 97 'A'
(Gdb) p ht. pListHead. pListNext. arKey [1]
$11 = 98 'B'
(Gdb) p ht. pListHead. pListNext. arKey [2]
$12 = 99 'C'
(Gdb) p ht. pListHead. pListNext. arKey [3]
$13 = 0' \ 000'
How can I get the pointer in the gdb mode and see the zval content of the corresponding execution?
The pData in the bucket struct is executed.
(Gdb) p ht. pListHead. pListNext. pData
$19 = (void *) 0x837a3d8
However, you do not know how to obtain the returned result.
Understand
(Gdb) p * ht. pListHead. pListNext
$29 = {h = 2090069483, nKeyLength = 4, pData = 0x839fe28, pDataPtr = 0x839f948, pListNext = 0x839fe4c, pListLast = 0x839f8dc, pNext = 0x0, pLast = 0x0,
ArKey = ""}
(Gdb) p * (zval *) $29-> pDataPtr
$30 = {value = {lval = 138024112, dval = 1.2800167717828578e-313, str = {val = 0x83a14b0 "string", len = 6}, ht = 0x83a14b0, obj = {hand = 138024112,
Handlers = 0x6 }}, refcount _ gc = 1, type = 6' \ 006 ', is_ref _ gc = 0' \ 000 '}
Haha, you can see the specific hash pointing value.
But what is the relationship between pData and pDataPtr?
(Gdb) p & $29-> pDataPtr
$46 = (void **) 0x839fe28
(Gdb) p $29-> pData
$47 = (void *) 0x839fe28
That is, pData stores the pDataPtr address.
From the column xiaoq3406
Http://www.bkjia.com/PHPjc/478497.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/478497.htmlTechArticleSara Golemon wrote an article saying: is there a special place to find the GLOBALS array? The answer is yes, that is, the EG (symbol_table)-Executor Globals structure. she also gives...