Как увидеть 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,

  1. напишите функцию печати отладки (debug_print()) как общая библиотека (dp.so).
  2. запустить gdb. gdb target_executable_file
  3. Do set environment LD_PRELOAD ./dp.so.
  4. установить точка прерывания.
  5. Do r
  6. когда точка останова попадает, 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.

  1. запустите gdb с основным файлом. gdb target_executable_file core_file.
  2. выполните следующую команду для доступа к данным. 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

вот внутренняя структура и перебор алгоритм:

https://speakerdeck.com/redboltz/boost-multi-index-version-equals-1-dot-56-dot-0-internal-structure-and-iteration-algorithm-for-gdb-boost-prerry-printer

3 ответов


Я посмотрел на реализацию этих довольно принтеров Python, и я согласен, что это будет нелегко.

возможно, вы можете определить некоторые функции отладки-печати в другом месте, например, другую единицу перевода, которую вы can изменить, или даже в другой библиотеке, которую вы потом поджать. Если вы делаете последнее, убедитесь, что вы используете те же версии библиотеки/компилятора и флаги, или вы просто получите неопределенные результаты. В обоих сценариях убедитесь, что функция не оптимизирована во время соединения.

затем вы можете использовать gdb call команда для оценки этой функции, например:

enter image description here


структура хэш-таблицы 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://speakerdeck.com/redboltz/boost-multi-index-version-equals-1-dot-56-dot-0-internal-structure-and-iteration-algorithm-for-gdb-boost-prerry-printer

и мои запросы (слили). 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-принтера.