Отладчик GDB (GNU debugger) построчно выполняет код программы, чтобы выявить ошибки в процессе её выполнения. Отладчик GDB позволяет менять значения переменных, устанавливать контрольные точки и условия остановки запущенной программы.
С помощью отладчика GDB вы можете:
- задать условия, которые могут повлиять на поведение программы;
- начать выполнение программы с заданными условиями;
- указать условия, при наступлении которых выполнение программы будет остановлено;
- исследовать причины остановки программы;
- изменить код программы, чтобы устранить эффекты одной ошибки и продолжить выявление других.
Подготовка окружения и запуск отладчика
-
Установите пакеты ПО:
CentOS 7, AlmaLinux 9yum install -y billmanager-corporate-devel gdb gcc-c++
Ubuntu 20.04, AstraLinux 1.7.4apt install -y billmanager-corporate-devel gdb gcc-c++
- Запустите BILLmanager.
-
Подключитесь к процесcу BILLmanager:
gdb -p $(ps aux | grep billmgr | head -1 | awk '{print $2}')
Отладочные символы
Отладка возможна, если сборка осуществлена с отладочными символами. Подробнее о сборке проекта см. статью Взаимодействие на низком уровне, плагины с++.
Чтобы проверить наличие отладочных символов, выполните:
objdump -x {PATH_TO_SO_FILE} | grep debug
Если в сборке присутствуют отладочные символы, то результат будет следующим:
[root@gdb-bill privatbank]# objdump -x /usr/local/mgr5/libexec/pmprivatbank.so | grep debug
26 .debug_aranges 000010d0 0000000000000000 0000000000000000 0001daf5 2**0
27 .debug_info 0002325b 0000000000000000 0000000000000000 0001ebc5 2**0
28 .debug_abbrev 00000e4c 0000000000000000 0000000000000000 00041e20 2**0
29 .debug_line 00002ae3 0000000000000000 0000000000000000 00042c6c 2**0
30 .debug_str 00034dad 0000000000000000 0000000000000000 0004574f 2**0
31 .debug_ranges 00001120 0000000000000000 0000000000000000 0007a4fc 2**0
0000000000000000 l d .debug_aranges 0000000000000000 .debug_aranges
0000000000000000 l d .debug_info 0000000000000000 .debug_info
0000000000000000 l d .debug_abbrev 0000000000000000 .debug_abbrev
0000000000000000 l d .debug_line 0000000000000000 .debug_line
0000000000000000 l d .debug_str 0000000000000000 .debug_str
0000000000000000 l d .debug_ranges 0000000000000000 .debug_ranges
[root@gdb-bill privatbank]#
Переменная окружения WITHOUT_DEBUG=yes отвечает за отсутствие отладочных символов при сборке модулей BILLmanager. Например, для модуля pmprivatbank при сборке без отладочных символов будет следующий результат:
[root@gdb-bill privatbank]# WITHOUT_DEBUG=yes make install
Create folder .build/.obj
Create folder .build/.dep
Compiling pmprivatbank.cpp
Create symbolic link to external libs
Create symbolic link for local libs
Building wrapper backend pmprivatbank
Create /usr/local/mgr5/libexec/pmprivatbank.so ...
Compiling privatbankpayment.cpp
Building wrapper backend privatbankpayment
Create /usr/local/mgr5/libexec/privatbankpayment.so ...
Compiling privatbankresult.cpp
Building wrapper backend privatbankresult
Create /usr/local/mgr5/libexec/privatbankresult.so ...
Shutdown billmgr ... done
[root@gdb-bill privatbank]# objdump -x /usr/local/mgr5/libexec/pmprivatbank.so | grep debug
[root@gdb-bill privatbank]#
Примеры
Пример отладки подключаемой библиотеки
-
Создайте директорию /usr/local/mgr5/src/gdbtest/ со следующей структурой:
Структура директорииsrc/gdbtest/ ├── gdbtest.cpp ├── Makefile └── xml └── billmgr_mod_gdbtest.xml 1 directory, 3 files
Содержимое файла src/gdbtest/xml/billmgr_mod_gdbtest.xml<?xml version="1.0" encoding="UTF-8"?> <mgrdata> <library name="libgdbtest"/> </mgrdata>
Содержимое файла src/gdbtest/gdbtest.cpp#include <api/action.h> #include <mgr/mgrlog.h> #include <mgr/mgraccess.h> MODULE("gdbtest"); using namespace isp_api; class aTest : public StdListAction { public: aTest() : StdListAction("atest", MinLevel(lvAdmin)) {} void List(Session& ses) const override { int a; } }; MODULE_INIT(aTest, "billmgr") { new aTest; }
[root@gdb-bill mgr5]# cat src/gdbtest/Makefile MGR=billmgr PLUGIN=gdbtest LIB += libgdbtest libgdbtest_SOURCES += gdbtest.cpp libgdbtest_LDADD = -lmgrdb -lispapi include ../isp.mk
-
Соберите и установите модуль командой:
cd /usr/local/mgr5/src/gdbtest/ && make install
Результат выполнения команды:
[root@gdb-bill gdbtest]# cd /usr/local/mgr5/src/gdbtest/ && cp -f billmgr_mod_gdbtest.xml ../../etc/xml/ && make install DISTDIR=/usr/local/mgr5 Create folder .build/.obj Create folder .build/.dep Compiling gdbtest.cpp gdbtest.cpp: In member function ‘virtual void aTest::List(isp_api::Session&) const’: gdbtest.cpp:19:7: warning: unused variable ‘a’ [-Wunused-variable] int a; ^ Create symbolic link to external libs Create symbolic link for local libs Building library libgdbtest Create library ../../lib/libgdbtest.so Shutdown billmgr ... done
При сборке модуля BILLmanager будет остановлен.
-
Запустите BILLmanager.
/usr/local/mgr5/sbin/mgrctl -u billmgr
-
Подключитесь к BILLmanager:
cd /usr/local/mgr5/ && gdb -p $(ps aux | grep billmgr | head -1 | awk '{print $2}')
При успешном подключении будет следующий вывод и приглашение для ввода команд (gdb):
Reading symbols from lib/Libgdbtest.so…done. Loaded symbols for lib/libgdbtest…so 0x00007fc9d087be9d in nanosleep () from /lib64/libpthread.so.0 Missing separate debuginfos, use: debuginfo-install coremanager-5.399.0-2307201251307784. el7.x86_64 (gdb)
-
Проверьте, что отладочные символы для модуля подгрузились. Для этого выполните:
(gdb) list gdbtest.cpp:1
#include <api/action.h> #include <mgr/mgrlog.h> #include <mgr/mgraccess.h> MODULE("gdbtest"); using namespace isp_api;
-
Для отладки модуля:
-
Поставьте точку останова на 16 строку:
(gdb) b gdbtest.cpp:16 Breakpoint 1 at 0x7f2bb1304330: file gdbtest.cpp, line 16.
Пояснения -
Продолжите выполнение BILLmanager:
(gdb) c Continuing.
-
Откройте второе окно терминала и вызовите функцию из модуля:
cd /usr/local/mgr5/ && sbin/mgrctl -m billmgr atest
-
Вернитесь в окно терминала с отладчиком gdb, где программа достигла точки останова:
Breakpoint 1, aTest::List (this=0x37264a0, ses=...) at gdbtest.cpp:17 17 } (gdb)
В точке останова вы можете посмотреть значение переменных следующей командой:
(gdb) p a $1 = 0
Пояснения
-
Пример отладки платёжного модуля
Для примера использован модуль pmprivatbank, представленный в пакетах разработчика billmanager-devel/billmanager-corporate-devel.
Вы можете адаптировать данный пример для разрабатываемых модулей обработки услуг.
-
Установите зависимости:
yum -y install openssl-devel jsoncpp-devel
-
Соберите и установите модуль:
cd /usr/local/mgr5/src/examples/privatbank/ && make install
-
Запустите отладчик gdb с указанием исполняемого файла:
cd /usr/local/mgr5/ && gdb paymethods/pmprivatbank
Результат выполнения команды[root@gdb-bill mgr5]# cd /usr/local/mgr5/ && gdb paymethods/pmprivatbank GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7 Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /usr/local/mgr5/libexec/wrapper...(no debugging symbols found)...done. (gdb)
-
Установите точку останова на нужном месте в исходном коде. Если ответ содержит "Make breakpoint pending on future shared library load?", отправьте "y".
(gdb) b pmprivatbank.cpp:18 No symbol table is loaded. Use the "file" command. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (pmprivatbank.cpp:18) pending.
Пояснения -
Запустите исполняемый файл с требуемыми параметрами:
(gdb) run --command features Starting program: /usr/local/mgr5/paymethods/pmprivatbank --command features [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". process 7807 is executing new program: /usr/local/mgr5/libexec/wrapper Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64 [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1".gdbrun --command featuresё Breakpoint 1, payment::PrivatBank::PrivatBank (this=0x6473a0) at pmprivatbank.cpp:18 18 feature_map[PAYMENT_FEATURE_REDIRECT] = true; Missing separate debuginfos, use: debuginfo-install coremanager-5.399.0-2307201251307784.el7.x86_64
При успешном выполнении отладчик GDB остановится на строке 18 и будет ожидать ввода команд.
Пример отладки CGI-компонентов платёжного модуля
Для примера использован модуль pmprivatbank, представленный в пакетах разработчика billmanager-devel/billmanager-corporate-devel.
CGI-компоненты могут требовать дополнительные переменные окружения для своей работы:
- HTTP_COOKIE — содержит различные cookie, в том числе cookie с сессией пользователя;
- QUERY_STRING — содержит параметры запроса.
-
Установите зависимости:
yum -y install openssl-devel jsoncpp-devel
-
Соберите и установите модуль:
sh cd /usr/local/mgr5/src/examples/privatbank/ && make install
-
Запустите отладчик gdb с указанием исполняемого файла:
cd /usr/local/mgr5/ && gdb cgi/privatbankpayment
-
Укажите переменные окружения внутри отладчика gdb, необходимые для работы модуля:
(gdb) set env HTTP_COOKIE=billmgrses5=57f5aa8ce144c9e664b11508 (gdb) set env QUERY_STRING=elid=1
Пояснения -
Установите точку останова на нужном месте в исходном коде. Если ответ содержит "Make breakpoint pending on future shared library load?", отправьте "y".
(gdb) b privatbankpayment.cpp:29 No symbol table is loaded. Use the "file" command. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (privatbankpayment.cpp:29) pending.
Пояснения -
Запустите исполняемый файл:
(gdb) run Starting program: /usr/local/mgr5/cgi/privatbankpayment [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". process 14507 is executing new program: /usr/local/mgr5/libexec/wrapper [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". [New Thread 0x7fffed2cc700 (LWP 14511)] [Thread 0x7fffed2cc700 (LWP 14511) exited] Content-Type: text/html Set-Cookie: paymentcgises5=db19b8d7648b77196003677f; path=/mancgi/; HttpOnly; max-age=86400 Breakpoint 1, PrivatBankPayment::Process (this=0x646cc0) at privatbankpayment.cpp:29 29 string payment = "amt=" + Payment("amount") + "&ccy=" + Currency("iso") + "&details=" + Payment("description") + "&ext_details=" + Payment("number") + "&pay_way=privat24&order=" + Payment("id") + "&merchant=" + Method("merchid"); Missing separate debuginfos, use: debuginfo-install coremanager-5.399.0-2307201251307784.el7.x86_64
При успешном выполнении отладчик GDB остановится на строке 29 и будет ожидать ввода команд. После остановки вы можете посмотреть:
-
backtrace:
(gdb) bt #0 PrivatBankPayment::Process (this=0x646cc0) at privatbankpayment.cpp:29 #1 0x00007ffff698ad55 in payment::PaymentCgi::Execute(int, char**) () from /usr/local/mgr5/lib/libpaymentcgi.so #2 0x00007ffff6bc713e in ispmain (argc=1, argv=0x7fffffffe438) at privatbankpayment.cpp:65 #3 0x0000000000401af2 in main ()
-
листинг:
(gdb) list 24 25 virtual void Process() { 26 string post_url = "https://api.privatbank.ua/p24api/ishop"; 27 28 // “amt=15.25&ccy=UAH&details=книга Будь здоров!&ext_details=1000BDN01&pay_way=privat24&order=000AB1502ZGH&merchant= 75482”, 29 string payment = "amt=" + Payment("amount") + "&ccy=" + Currency("iso") + "&details=" + Payment("description") + "&ext_details=" + Payment("number") + "&pay_way=privat24&order=" + Payment("id") + "&merchant=" + Method("merchid"); 30 string signature = str::hex::Encode(mgr_hash::sha1(str::hex::Encode(mgr_hash::md5(payment + Method("passwd"))))); 31 32 string description = str::Trim(Payment("description")); 33 if (description.empty())
-
значение конкретной переменной:
(gdb) p post_url $1 = "https://api.privatbank.ua/p24api/ishop"
Подробнее см. документацию GDB: The GNU Project Debugger.