• 技术文章 >php教程 >php手册

    gdb方式遍历EG(symbol_table) 哈希表的key

    2016-06-13 10:46:00原创899
    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的专栏

    php入门到就业线上直播课:查看学习

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    上一篇:php文件缓存数据 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• smarty模板引擎从php中获取数据的方法,smarty模板• PHP类中的魔术方法(Magic Method)简明总结,magicmethod• php利用新浪接口查询ip获取地理位置• mysql 数据备份类代码• PHP之判断用户语言跳转网页
    1/1

    PHP中文网