Как проследить файл XS .so?

У меня есть небольшая программа на Perl. Программа загружает модуль. Модуль загружает файл .so с помощью XSLoader. Этот Perl работает в Linux и собран с помощью gcc и -DDEBUGGING, а затем и файл .so. Я могу перекомпилировать.

Как выполнить трассировку функций C в файле .so при выполнении программы Perl? Мне нужно знать имена функций в том порядке, в котором они выполняются. Было бы неплохо иметь и аргументы функции.


person daxim    schedule 01.06.2018    source источник
comment
Вы можете найти соответствующую информацию в perlhacktips.   -  person Håkon Hægland    schedule 01.06.2018
comment
Вам придется использовать отладчик низкого уровня, например gdb.   -  person nwellnhof    schedule 03.06.2018
comment
Если вас интересуют только системные вызовы, вы можете использовать strace   -  person FelixEnescu    schedule 19.06.2018
comment
Похоже, что это возможно с gdb, см. Как автоматически печатать каждую выполняемую строку в GDB, пока не будет достигнута заданная точка останова? и принятый ответ в нем.   -  person Håkon Hægland    schedule 18.01.2019


Ответы (1)


Вот пример использования gdb для входа в разделяемую библиотеку. Я использую Linux (Ubuntu 18.04).

Сначала я установил отладочную версию Perl, используя perlbrew:

perlbrew install perl-5.26.2 --as=5.26.2d -DDEBUGGING
perlbrew use 5.26.2d

Затем я создал общую библиотеку (урезанную до минимального содержимого для целей тестирования) в папке /home/hakon/mylib:

mylib.c

Эта функция адаптирована из примера 3 в perlxstut:

#include <math.h>
#include "myclib.h"
double my_clib_function( double arg ) {
    if (arg > 0.0) {
        arg = floor(arg + 0.5);
    } else if (arg < 0.0) {
        arg = ceil(arg - 0.5);
    } else {
        arg = 0.0;
    }
    return arg;
}

myclib.h:

double my_clib_function( double arg );

Затем я создал разделяемую библиотеку libmylib.so:

gcc -g -c -fpic mylib.c
gcc -g -shared -o libmylib.so mylib.o

Обратите внимание, что мы включили символы отладки в libmylib.so, установив переключатель -g в положение gcc.

Теперь мы можем создать файл .xs, который будет вызывать функцию общей библиотеки (в папке /home/hakon/myxstest):

Mytest.xs

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "myclib.h"

MODULE = Mytest     PACKAGE = Mytest        

void
wrapper(arg)
        double  arg
    CODE:
        arg = my_clib_function( arg);
    OUTPUT:
        arg

Затем нам нужно связать файл XS с именем пакета Perl:

lib/Mytest.pm:

package Mytest;
use 5.022001;
use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw() ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw();
our $VERSION = '0.01';

require XSLoader;
XSLoader::load('Mytest', $VERSION);

Затем нам нужна система сборки, такая как ExtUtils::MakeMaker, для компиляции файла XS (в другую общую библиотеку):

Makefile.PL:

use 5.022001;
use ExtUtils::MakeMaker;
my $lib_dir = '/home/hakon/mylib';
WriteMakefile(
    NAME              => 'Mytest',
    VERSION_FROM      => 'lib/Mytest.pm', 
    PREREQ_PM         => {},
    ABSTRACT_FROM     => 'lib/Mytest.pm',
    AUTHOR            => 'Håkon Hægland <[email protected]>',
    LIBS              => ["-L$lib_dir -lmylib"],
    INC               => "-I. -I$lib_dir",
    OPTIMIZE          => '-g',
);

Обратите внимание, что мы запрашиваем символы отладки (для общего объекта Mytest.so) с помощью OPTIMIZE => '-g' и сообщаем о расположении другой общей библиотеки libmylib.so, используя аргумент LIBS для WriteMakefile().

Затем мы компилируем код XS:

perl Makefile.PL
make

Наконец, пишем небольшой тестовый Perl-скрипт:

стр.пл

#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
use ExtUtils::testlib;
use Mytest;

my $res = 3.5;
Mytest::wrapper( $res ); # <-- Warning: modifies $res in place !
say $res;

Мы можем узнать запуск gdb в нашем тестовом скрипте p.pl:

$ gdb -q --args perl p.pl
Reading symbols from perl...done.

Мы устанавливаем точку останова в строке 14 в файле XS:

(gdb) break Mytest.xs:14
No source file named Mytest.xs.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (Mytest.xs:14) pending.

Затем запустите скрипт:

(gdb) run
Starting program: /home/hakon/perlbrew/perls/5.26.2d/bin/perl p.pl
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Breakpoint 1, XS_Mytest_wrapper (cv=0x555555bdc860) at Mytest.xs:14
14          arg = my_clib_function( arg);

Теперь мы остановились в том месте файла XS, где мы будем вызывать функцию общей библиотеки. Если мы хотим, мы можем проверить аргументы, которые будут переданы:

(gdb) p arg
$1 = 3.5

Затем войдите в общую библиотеку:

(gdb) s
my_clib_function (arg=3.5) at mylib.c:5
5       if (arg > 0.0) {

и так далее..

person Håkon Hægland    schedule 03.06.2018