_dl_runtime_resolve() 中的分段错误
Posted
技术标签:
【中文标题】_dl_runtime_resolve() 中的分段错误【英文标题】:Segmentation fault in _dl_runtime_resolve() 【发布时间】:2012-05-21 15:23:34 【问题描述】:我在遇到分段错误的代码中执行简单的字符串操作。我不知道确切的问题是什么。 请看看是否有人可以提供帮助。
核心的回溯是
(gdb) bt
#0 0x00007f595dee41da in _dl_fixup () from /lib64/ld-linux-x86-64.so.2
#1 0x00007f595deea105 in _dl_runtime_resolve () from /lib64/ld-linux-x86-64.so.2
#2 0x0000000000401d04 in getNodeInfo (node=0x7fffbfb4ba83 "TCU-0")
at hwdetails.cpp:294
#3 0x0000000000402178 in main (argc=3, argv=0x7fffbfb4aef8)
at hwdetails.cpp:369
在 第 294 行,崩溃即将发生在 cout
语句所在的位置。LdapDN
是 char *
而不是 NULL
。
if ( Epath && (Epath->Entry[0].EntityType == SAHPI_ENT_UNSPECIFIED ||
Epath->Entry[0].EntityType == SAHPI_ENT_ROOT ))
// nothing is mapped. Degrade the ldap dn path to slot.
if(LdapDN)
std::cout << "LdapDN " << LdapDN << std::endl;
std::string ldapDN;
ldapDN = LdapDN;
std::string slot = LDAP_PIU_ID;
if ( ldapDN.compare(0, slot.length(), slot) != 0 )
size_t pos = ldapDN.find(slot);
if ( pos != std::string::npos )
ldapDN = ldapDN.substr(pos);
LdapDN = (char *)ldapDN.c_str();
//getEntityPathFromLdapDn(ldapDN.c_str(), epath, domid);
【问题讨论】:
它在什么操作系统上运行?您正在使用哪些编译选项? 【参考方案1】:_dl_fixup
中的崩溃通常意味着您已损坏运行时加载程序的状态。
两个最常见的原因是:
-
堆损坏(溢出)或
glibc
本身的部分不匹配。
如果您没有设置,例如LD_LIBRARY_PATH
指向一个非标准的glibc
,那么我们可以忘记原因#2。
对于 #1,在 Valgrind 下运行您的程序,并确保它没有检测到错误。
如果实际上没有,请使用 disas
和 info registers
GDB 命令,使用它们的输出更新您的问题,您可能会收到更多帮助。
【讨论】:
【参考方案2】:这是 GOT 表的问题。 _dl_runtime_resolve - 当动态库中的某些函数第一次调用时,更改 GOT(全局偏移表)的过程。在下次使用更改的 GOT 条目时。 当您的代码中第一次调用来自动态库的函数(例如 libc.so 中的 printf())时:
-
转到 PLT(程序查找表)。 PLT 是一个蹦床,它从 GOT 中获取被调用函数的正确地址。
从 PLT 转到 GOT
返回PLT
调用_dl_runtime_resolve
存储实际函数跳转地址到GOT
从动态库调用函数
第二次函数调用是:
-
转到 PLT
转到 GOT
GOT 可以从动态库直接跳转到函数地址。
GOT 是对再次调用的函数的引用,而无需快速执行 _dl_runtime_resolve。
【讨论】:
“这是 GOT 表的问题”——你可能是对的,也可能是错的(_dl_runtime_resolve
中的崩溃还有许多其他可能的原因)。您没有提供任何证据来支持您的主张,而且您对惰性 PLT 解决过程中实际发生的情况的描述在许多细节上都是错误的,对于不熟悉它的任何人来说都是没有意义的。【参考方案3】:
我在这里看到内存泄漏:
当你这样做时,你基本上会丢失你以前的字符串LdapDN
if ( pos != std::string::npos )
ldapDN = ldapDN.substr(pos);
LdapDN = (char *)ldapDN.c_str();
//getEntityPathFromLdapDn(ldapDN.c_str(), epath, domid);
【讨论】:
以上是关于_dl_runtime_resolve() 中的分段错误的主要内容,如果未能解决你的问题,请参考以下文章
[ctf wiki pwn] stackoverflow:ret2dlresolve系列2(_dl_runtime_resolve glibc源码解析实践)