Документация BILLmanager 6

Отладчик GDB

Отладчик GDB (GNU debugger) построчно выполняет код программы, чтобы выявить ошибки в процессе её выполнения. Отладчик GDB позволяет менять значения переменных, устанавливать контрольные точки и условия остановки запущенной программы.

С помощью отладчика GDB вы можете:

  • задать условия, которые могут повлиять на поведение программы;
  • начать выполнение программы с заданными условиями;
  • указать условия, при наступлении которых выполнение программы будет остановлено;
  • исследовать причины остановки программы;
  • изменить код программы, чтобы устранить эффекты одной ошибки и продолжить выявление других.

Подготовка окружения и запуск отладчика

  1. Установите пакеты ПО:

    CentOS 7, AlmaLinux 9
    yum install -y billmanager-corporate-devel gdb gcc-c++
    Ubuntu 20.04, AstraLinux 1.7.4
    apt install -y billmanager-corporate-devel gdb gcc-c++
  2. Запустите BILLmanager.
  3. Подключитесь к процес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]#

Примеры

Примеры ниже составлены для ОС CentOS 7. В других ОС шаги или выводы могут отличаться.

Пример отладки подключаемой библиотеки

  1. Создайте директорию /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
  2. Соберите и установите модуль командой:

    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 будет остановлен.

  3. Запустите BILLmanager.

    /usr/local/mgr5/sbin/mgrctl -u billmgr
  4. Подключитесь к 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)


  5. Проверьте, что отладочные символы для модуля подгрузились. Для этого выполните:

    (gdb) list gdbtest.cpp:1


    	#include <api/action.h>
    	#include <mgr/mgrlog.h>
    	#include <mgr/mgraccess.h>
    
    
    	MODULE("gdbtest");
    
    	using namespace isp_api;
  6. Для отладки модуля:

    1. Поставьте точку останова на 16 строку:

      (gdb) b gdbtest.cpp:16
      Breakpoint 1 at 0x7f2bb1304330: file gdbtest.cpp, line 16.
      Пояснения
    2. Продолжите выполнение BILLmanager:

      (gdb) c
      Continuing.
    3. Откройте второе окно терминала и вызовите функцию из модуля:

      cd /usr/local/mgr5/ && sbin/mgrctl -m billmgr atest
    4. Вернитесь в окно терминала с отладчиком 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.

Вы можете адаптировать данный пример для разрабатываемых модулей обработки услуг.

  1. Установите зависимости:

    yum -y install openssl-devel jsoncpp-devel
  2. Соберите и установите модуль:

    cd /usr/local/mgr5/src/examples/privatbank/ && make install
  3. Запустите отладчик 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)
  4. Установите точку останова на нужном месте в исходном коде. Если ответ содержит "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.
    Пояснения
  5. Запустите исполняемый файл с требуемыми параметрами:

    (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 — содержит параметры запроса.
  1. Установите зависимости:

    yum -y install openssl-devel jsoncpp-devel
  2. Соберите и установите модуль:

    sh cd /usr/local/mgr5/src/examples/privatbank/ && make install
  3. Запустите отладчик gdb с указанием исполняемого файла:

    cd /usr/local/mgr5/ && gdb cgi/privatbankpayment
  4. Укажите переменные окружения внутри отладчика gdb, необходимые для работы модуля:

    (gdb) set env HTTP_COOKIE=billmgrses5=57f5aa8ce144c9e664b11508 (gdb) set env QUERY_STRING=elid=1
    Пояснения
  5. Установите точку останова на нужном месте в исходном коде. Если ответ содержит "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.
    Пояснения
  6. Запустите исполняемый файл:

    (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.