Как увидеть boost:: данные хешированного индекса multi index с использованием gdb
я хотел бы видеть данные, содержащиеся в boost::multi_index(версия 1.67.0) с помощью gdb.
Сначала я попробовал https://github.com/ruediger/Boost-Pretty-Printer.
Кажется, что хэшированные индексы, такие как hashed_unique
не поддерживается.
я заметил, что если первый индекс является поддерживаемым типом таких как sequenced
, Boost-Pretty-принтер работает нормально.
Однако я не могу редактировать код сейчас. Мне нужно отладить основной файл и двоичный исполняемый файл.
я пытался понять внутренняя структура multi_index с хешированный индекс.
я worte следующий тестовый код:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
namespace mi = boost::multi_index;
struct t_hash{};
using elems = mi::multi_index_container<
int,
mi::indexed_by<
mi::hashed_unique<
mi::tag<t_hash>,
mi::identity<int>
>
>
>;
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
Я получил следующий вывод:
= {
<boost::base_from_member<std::allocator<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag> >, 0>> = {
member = {
<__gnu_cxx::new_allocator<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag> >> = {<No data fields>}, <No data fields>}
},
<boost::multi_index::detail::header_holder<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> > >> = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
members of boost::multi_index::detail::header_holder<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> > >:
member = 0x55555576ee70
},
<boost::multi_index::detail::hashed_index<boost::multi_index::identity<int>, boost::hash<int>, std::equal_to<int>, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> >, boost::mpl::v_item<t_hash, boost::mpl::vector0<mpl_::na>, 0>, boost::multi_index::detail::hashed_unique_tag>> = {
<boost::multi_index::detail::index_base<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> >> = {<No data fields>},
members of boost::multi_index::detail::hashed_index<boost::multi_index::identity<int>, boost::hash<int>, std::equal_to<int>, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> >, boost::mpl::v_item<t_hash, boost::mpl::vector0<mpl_::na>, 0>, boost::multi_index::detail::hashed_unique_tag>:
key = {
<boost::multi_index::detail::non_const_identity_base<int>> = {<No data fields>}, <No data fields>},
hash_ = {
<boost::hash_detail::hash_base<int>> = {
<std::unary_function<int, unsigned long>> = {<No data fields>}, <No data fields>}, <No data fields>},
eq_ = {
<std::binary_function<int, int, bool>> = {<No data fields>}, <No data fields>},
buckets = {
<boost::multi_index::detail::bucket_array_base<true>> = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
},
members of boost::multi_index::detail::bucket_array<std::allocator<int> >:
size_index_ = 0,
spc = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
members of boost::multi_index::detail::auto_space<boost::multi_index::detail::hashed_index_base_node_impl<std::allocator<char> >, std::allocator<int> >:
al_ = {
<__gnu_cxx::new_allocator<boost::multi_index::detail::hashed_index_base_node_impl<std::allocator<char> > >> = {<No data fields>}, <No data fields>},
n_ = 54,
data_ = 0x55555576ee90
}
},
mlf = 1,
max_load = 53
},
members of boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, 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>, boost::multi_index::identity<int>, 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<int> >:
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
- Do
set environment LD_PRELOAD ./dp.so
. - установить точка прерывания.
- Do
r
- когда точка останова попадает, do
call debug_print(data)
.data
- это цель, которую вы хотите видеть.
этот подход не требует повторной компиляции цели. Однако, когда я загружаю основной файл,debug_print()
больше не находится в памяти. Таким образом, этот подход не работает с core file.
Я ищу forcibly load dp.so
после загрузки основного файла, но я не мог найти путь, до сих пор.
внутренняя структура трассировки multi_index использование gdb
этот подход-работа с core-file. Этот подход основан на комментарии @Joaquín M López Muñoz.
- запустите gdb с основным файлом.
gdb target_executable_file core_file
. - выполните следующую команду для доступа к данным.
T
тип элемента multi_index по.data
является переменной контейнера multi_index.N
- количество индексов.
1-й данные
p *(T*)((char*)(*data.member).prior_ - sizeof(T) - 0x10 * (N - 1))
2-й данные
p *(T*)((char*)(*(*data.member).prior_).prior_ - sizeof(T) - 0x10 * (N - 1))
...следуйте той же схеме.
большое спасибо @sele и @Joaquín M Лопес Муньос !!
изменить: 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-битной среде 64bit = 8byte, 8 * 2 = 16 = 0x10. В 32 битной среде 32 бит = длину 4 байта, 4 * 2 = 8 = бит 0x08.
я также обновил запрос.
изменить: 2018/08/02 09: 30 JST
наконец, я отправил два запросы и оба слились. Теперь мы можем просто использовать Boost-Pretty-Printer и распечатать контейнер multi_index, который имеет hashed_index в качестве первого индекса.
https://github.com/ruediger/Boost-Pretty-Printer/pull/36
https://github.com/ruediger/Boost-Pretty-Printer/pull/37
вот внутренняя структура и перебор алгоритм:
3 ответов
Я посмотрел на реализацию этих довольно принтеров Python, и я согласен, что это будет нелегко.
возможно, вы можете определить некоторые функции отладки-печати в другом месте, например, другую единицу перевода, которую вы can изменить, или даже в другой библиотеке, которую вы потом поджать. Если вы делаете последнее, убедитесь, что вы используете те же версии библиотеки/компилятора и флаги, или вы просто получите неопределенные результаты. В обоих сценариях убедитесь, что функция не оптимизирована во время соединения.
затем вы можете использовать gdb
call
команда для оценки этой функции, например:
структура хэш-таблицы Boost.Мультииндекс изображен на втором рисунке в этой статье. Комплекс, как он выглядит, оказывается, вы можете пройти все узлы в обратном порядке, начиная с фиктивного узла заголовка (используемого для сигнала конца контейнера) и следуя prior_
указатели. На этот узел заголовка указывает member
на boost::multi_index::detail::header_holder<...>
. Надеюсь, это поможет.
решение для новой версии Boost
если вы используете Boost 1.56.0 или более поздней версии, вы можете распечатать контейнер с помощью Boost-Pretty-Printer.
Установить Boost-Pretty-Printer
сайт github является https://github.com/ruediger/Boost-Pretty-Printer
руководство по установке https://github.com/ruediger/Boost-Pretty-Printer#installation
сделать команду печати на gdb.
тогда вы можете получить результат.
если вы уже установили Boost-Pretty-Printer и не смогли получить результат печати, вам нужно его обновить.
поддержка hashed_index вводится с https://github.com/ruediger/Boost-Pretty-Printer/commit/d8557f664e0dd3d11bb0464d8f670e99946e88b9
решение для старой версии Boost
если вы используете версию Boost менее 1.56.0, у вас есть некоторые выбор.
1. Обновление импульс.
просто обновите библиотеку boost и повторно скомпилируйте свою программу.
плюсы
- если вы можете сделать, это самый простой способ.
минусы
- это требует повторной компиляции цели.
- это может ввести проблему comatibility для вашего приложения.
- он не работает с существующим двоичным исполняемым файлом и ядром файл.
2. Динамическая загрузка общей библиотеки
запись функции отладки печати. Вот пример кода:
dp.cpp
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
namespace mi = boost::multi_index;
struct t_hash{};
// define the same structure of the debug target
using elems = mi::multi_index_container<
int,
mi::indexed_by<
mi::hashed_unique<
mi::tag<t_hash>,
mi::identity<int>
>
>
>;
#include <iostream>
// debug print function
void dp(elems const& es) {
for (auto const& e : es) {
std::cout << e << std::endl;
}
}
скомпилируйте его, используя тот же параметр компилятора, что и цель. И добавить -fPIC
для общей библиотеки.
clang++ -g -c dp.cpp -fPIC
затем вы получите dp.o
связать его как общую библиотеку
clang++ -shared -o dp.so dp.o
тогда вы получите dp.so
запустить gdb. gdb target_executable_file
Do set environment LD_PRELOAD ./dp.so
.
установить точки останова.
Do r
когда точка останова попадает, do call dp(data)
. data-это цель, которую вы хотите увидеть
плюсы
- повторная компиляция цели не требуется.
минусы
- не работает с основным файлом.
3. Разработка поддержки Boost-Pretty-Print для пожилых людей версия
к сожалению, текущий Boost-Pretty-Print hashed_indexes поддерживает только Boost 1.56.0 или более позднюю версию. Но вы можете реализовать старую поддержку самостоятельно.
Вот описание структуры данных, которое ориентировано на итерацию и алгоритм итерации для версии >= 1.56. Я думаю, что это хороший намек на реализацию итерации старой версии алгоритм.
и мои запросы (слили). https://github.com/ruediger/Boost-Pretty-Printer/pull/36
https://github.com/ruediger/Boost-Pretty-Printer/pull/37
для версии
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
namespace mi = boost::multi_index;
struct t_hash{};
using elems = mi::multi_index_container<
int,
mi::indexed_by<
mi::hashed_non_unique<
mi::tag<t_hash>,
mi::identity<int>
>
>
>;
int main(int argc, char** argv) {
auto size = boost::lexical_cast<int>(argv[1]);
elems es;
for (int i = 0; i != size; ++i) {
es.insert(i);
}
return 0; // break here
}
и я получил следующий вывод gdb:
b 30
r 5
p es.member
0x555555770e70
p (*es.member).next_
0x555555771038
p (*(*es.member).next_).next_
0x555555770e78
p (*(*(*es.member).next_).next_).next_
0x555555771038
...
x /200xb 0x555555771030
0x555555771030: 0x30 0x10 0x77 0x55 0x55 0x55 0x00 0x00
0x555555771038: 0x78 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x555555771040: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771048: 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771050: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x555555771058: 0x90 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x555555771060: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771068: 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771070: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x555555771078: 0x98 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x555555771080: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771088: 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x555555771090: 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x555555771098: 0xa0 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x5555557710a0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710a8: 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710b0: 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x5555557710b8: 0xa8 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x5555557710c0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710c8: 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710d0: 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0x5555557710d8: 0xb0 0x0e 0x77 0x55 0x55 0x55 0x00 0x00
0x5555557710e0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710e8: 0x21 0xef 0x00 0x00 0x00 0x00 0x00 0x00
0x5555557710f0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
...
эта информация и @Хоакин м Лопеса Муньоса комментарий также может быть хорошим намеком на реализацию
плюсы
- повторная компиляция цели не требуется.
- хорошо работать с основным файлом.
минусы
- вам нужно реализовать Поддержка Boost-Pretty-принтера.