我想看看boost :: multi_index(版本1.67.0)使用gdb包含的数据.首先我尝试了https://github.com/ruediger/Boost-Pretty-Printer.似乎hashed_unique
不支持散列索引.
我注意到,如果第一个索引是支持的类型,如sequenced
Boost-Pretty-Printer工作正常.但是,我现在无法编辑代码.我需要调试核心文件和二进制可执行文件.
我试图理解带有散列索引的multi_index的内部结构.
我打了下面的测试代码:
#include
#include
#include
namespace mi = boost::multi_index;
struct t_hash{};
using elems = mi::multi_index_container<
int,
mi::indexed_by<
mi::hashed_unique<
mi::tag,
mi::identity
>
>
>;
int main() {
elems es { 0x12, 0x34 };
return 0; // set break point here and (gdb) p es
}
https://wandbox.org/permlink/UtMfVRI4rT5AXUOZ
当我打印es时,(gdb) p es
我得到以下输出:
$1 = {
>, boost::multi_index::detail::hashed_unique_tag> >, 0>> = {
member = {
<__gnu_cxx::new_allocator >, boost::multi_index::detail::hashed_unique_tag> >> = {}, }
},
>, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator > >> = {
= {},
members of boost::multi_index::detail::header_holder >, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator > >:
member = 0x55555576ee70
},
, boost::hash, std::equal_to, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >, boost::mpl::v_item, 0>, boost::multi_index::detail::hashed_unique_tag>> = {
, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >> = {},
members of boost::multi_index::detail::hashed_index, boost::hash, std::equal_to, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >, boost::mpl::v_item, 0>, boost::multi_index::detail::hashed_unique_tag>:
key = {
> = {}, },
hash_ = {
> = {
> = {}, }, },
eq_ = {
> = {}, },
buckets = {
> = {
= {},
},
members of boost::multi_index::detail::bucket_array >:
size_index_ = 0,
spc = {
= {},
members of boost::multi_index::detail::auto_space >, std::allocator >:
al_ = {
<__gnu_cxx::new_allocator > >> = {}, },
n_ = 54,
data_ = 0x55555576ee90
}
},
mlf = 1,
max_load = 53
},
members of boost::multi_index::multi_index_container, boost::multi_index::identity, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator >:
node_count = 2
}
我找到了node_count = 2
.看来元素的数量.我试着挖掘成员变量.例如)member
,buckets
等等.但我不能找到的数据0x12
和0x34
,到目前为止.
我怎么得到它们?
编辑:2018/07/28 11:51 JST
感谢您的评论,我找到了解决方案.我根据评论总结了两种方法.
基于@sehe方法的运行时共享库加载,
将调试打印函数(debug_print()
)写为共享库(dp.so
).
运行gdb. gdb target_executable_file
做set environment LD_PRELOAD ./dp.so
.
设置断点.
做 r
当断点命中时,做call debug_print(data)
.data
是你想要看到的目标.
这种方法不需要重新编译目标.但是,当我加载核心文件时,debug_print()
不再是内存.所以这种方法不适用于核心文件.我正在寻找加载dp.so
核心文件后强行加载,但到目前为止我找不到方法.
使用gdb跟踪multi_index的内部结构
这种方法适用于核心文件.这种方法基于@JoaquínMLópezMuñoz的评论.
使用核心文件运行gdb.gdb target_executable_file core_file
.
执行以下命令以访问数据.T
是multi_index的元素类型.data
是multi_index容器变量.N
是索引的数量.
第一个数据
p *(T*)((char*)(*data.member).prior_ - sizeof(T) - 0x10 * (N - 1))
第二个数据
p *(T*)((char*)(*(*data.member).prior_).prior_ - sizeof(T) - 0x10 * (N - 1))
......遵循相同的模式.
非常感谢@sele和@JoaquínMLópezMuñoz!!
编辑:2018/07/28 15:22 JST
我为Boost-Pretty-Printer实现了散列索引支持.它基于上述方法.
我发送了拉取请求:
https://github.com/ruediger/Boost-Pretty-Printer/pull/36
编辑:2018/07/28 15:42 JST
我想出了0x10的意思.指针大小乘以2.因此在64位环境中,64位= 8byte,8*2 = 16 = 0x10.在32位环境中,32位= 4byte,4*2 = 8 = 0x08.
我还更新了拉取请求.
编辑:2018/08/02 09:30 JST
最后,我发送了两个pull请求,两者都合并了.现在,我们可以简单地使用Boost-Pretty-Printer并打印具有hashed_index作为第一个索引的multi_index容器.
https://github.com/ruediger/Boost-Pretty-Printer/pull/36
https://github.com/ruediger/Boost-Pretty-Printer/pull/37
这是内部结构和迭代算法:
https://speakerdeck.com/redboltz/boost-multi-index-version-equals-1-dot-56-dot-0-internal-structure-and-iteration-algorithm-for-gdb-boost-prerry-printer