Ошибка сегментации в моно с использованием pinvoke на liblvm2app.so
Я пытаюсь написать aC# программу на моно, чтобы получить информацию о vgs (группы томов), lvs (логические тома) и pvs (физические тома). Я использую систему CentOS7. Чтобы получить информацию о lvm, определен API ( https://sourceware.org/git/?p=lvm2.git;a=blob;f=liblvm/lvm2app.h). Пример программы на C++ отлично работает ( https://www.redhat.com/archives/lvm-devel/2010-September/msg00025.html) с API-интерфейсом, указанным выше. Но у меня возникли проблемы с использованием pinvoke для вызовов API из моей программы на C#.
Мне удалось получить данные о версии. Поэтому я предполагаю, что пинвокинг библиотеки возможен.
lvm2app.h
Класс Wrapper:
public class liblvm2wrapper
{
[DllImport ("liblvm2app.so")]
public static extern IntPtr lvm_init (IntPtr system_dir);
[DllImport ("liblvm2app.so")]
public static extern IntPtr lvm_errmsg (IntPtr libh);
[DllImport ("liblvm2app.so", CharSet = CharSet.Ansi)]
public static extern IntPtr lvm_library_get_version ();
[DllImport ("liblvm2app.so", CharSet = CharSet.Ansi)]
public static extern IntPtr lvm_vg_open(IntPtr libh, [MarshalAs (UnmanagedType.LPStr)]string vgname, [MarshalAs (UnmanagedType.LPStr)]string mode, int flags);
[DllImport ("liblvm2app.so")]
public static extern void lvm_quit (IntPtr libh);
}
Главный
class Program
{
static void Main(string[] args)
{
IntPtr lvmHandle = liblvm2.lvm_init(IntPtr.Zero);
if(lvmHandle == IntPtr.Zero) return;
IntPtr versionPtr = liblvm2wrapper.lvm_library_get_version();
string version = Marshal.PtrToStringAnsi(versionPtr); // works
// segFault occurs at the next line of code, if the name describes an existing vg
// bash: line 1: 43812 Segmentation fault (core dumped) '/usr/bin/mono' --debug --debugger-agent=transport=dt_socket,address=127.0.0.1:51779 "home/user/Documents/test/bin/x64/Debug/test.exe"
IntPtr vgHandle = liblvm2wrapper.lvm_vg_open(lvmHandle , "volume_group", "r", 0);
if(vgHandle == IntPtr.Zero)
{
// if the string ("volume_group") passed to the function lvm_vg_open does not describe ane existing volume group, an empty pointer is returned and a valid error message is obtained calling the function below (lvm_errmsg)
Console.WriteLine(Marshal.PtrToStringAnsi(liblvm2wrapper.lvm_errmsg(lvmHandle)));
}
liblvm2wrapper.lvm_quit(lvmHandle);
}
}
Из того, что я слышал, ошибки сегментации должны анализироваться с использованием gdb. Я следовал примеру с http: //pastebin.com/Kza9kemJ (не могу опубликовать третью ссылку, потому что это новый аккаунт.
и получил следующий вывод:
[root@vm user]# gdb --args mono '/home/user/Documents/test/bin/x64/Debug/test.exe'
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-64.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/bin/mono-sgen...(no debugging symbols found)...done.
warning: File "/usr/bin/mono-sgen-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load:/usr/bin/mono-gdb.py".
To enable execution of this file add
add-auto-load-safe-path /usr/bin/mono-sgen-gdb.py
line to your configuration file "/root/.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "/root/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
(gdb) r
Starting program: /usr/bin/mono /home/user/Documents/test/bin/x64/Debug/test.exe
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7fffee916700 (LWP 43646)]
2.02.130(2)-RHEL7 (2015-10-14)
[Thread 0x7fffee916700 (LWP 43646) exited]
[Inferior 1 (process 43645) exited normally]
Program received signal SIGSEGV, Segmentation fault.
0x00007fffee3fda0c in lvm_lv_get_name () from /lib64/liblvm2app.so
(gdb) bt
#0 0x00007fffee3fda0c in lvm_lv_get_name () from /lib64/liblvm2app.so
#1 0x00000000400164e0 in ?? ()
#2 0x0000000000b22d18 in ?? ()
#3 0x00007ffff000b378 in ?? ()
#4 0x0000000000000000 in ?? ()
(gdb) info sharedlibrary liblvm2app.so
From To Syms Read Shared Object Library
0x00007fffee3fcc20 0x00007fffee4a02c8 Yes (*) /lib64/liblvm2app.so
(*): Shared library is missing debugging information.
(gdb) info register
rax 0x0 0
rbx 0xb22d70 11677040
rcx 0xa12590 10560912
rdx 0x0 0
rsi 0x7ffff000bae8 140737219967720
rdi 0xb22d70 11677040
rbp 0x7fffffffdbb0 0x7fffffffdbb0
rsp 0x7fffffffda80 0x7fffffffda80
r8 0x0 0
r9 0xaabc 43708
r10 0x7ffff72947b8 140737340065720
r11 0x7fffee3fd9f0 140737190550000
r12 0x7ffff000b378 140737219965816
r13 0x0 0
r14 0x7fffffffdf10 140737488346896
r15 0xb22d70 11677040
rip 0x7fffee3fda0c 0x7fffee3fda0c <lvm_lv_get_name+28>
eflags 0x10246 [ PF ZF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
---Type <return> to continue, or q <return> to quit---
gs 0x0 0
(gdb) info frame
Stack level 0, frame at 0x7fffffffdaa0:
rip = 0x7fffee3fda0c in lvm_lv_get_name; saved rip 0x400164e0
called by frame at 0x7fffffffdaa8
Arglist at 0x7fffffffda78, args:
Locals at 0x7fffffffda78, Previous frame's sp is 0x7fffffffdaa0
Saved registers:
rbx at 0x7fffffffda90, rip at 0x7fffffffda98
(gdb)
из этого вывода можно сделать вывод, что ошибка сегментации происходит при вызове функции lvm_lv_get_name. Странно то, что я не вызываю эту функцию.
Так что я сейчас в тупике и буду признателен за вашу помощь.
С уважением