Отладка сторонней библиотеки Linux
От: keeper-andrew  
Дата: 23.05.13 16:04
Оценка:
Сразу предупрежу, что на С/С++ не программировал уже много лет. А для Linux на C/C++ не программировал никогда. И очень нужна помощь в отладке одной библиотечки, а пофиксать я и сам смогу. К сожалению ее разработчики еще не шевелятся, а релиз наступает на пятки.

Исходные данные.

Linux: Ubuntu Linux hhost 3.2.0-43-generic #68-Ubuntu SMP Wed May 15 03:33:33 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
LIBC: 2.15
libNRJavaSerial.so: библиотечка, вот с ней у нас и проблемы. К счастью есть исходники.

Работает приложение с USB портами. Спустя час-два вылетает. Бактрейс следующий:

*** buffer overflow detected ***: /usr/bin/java terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f3f5712d817]
/lib/x86_64-linux-gnu/libc.so.6(+0x109710)[0x7f3f5712c710]
/lib/x86_64-linux-gnu/libc.so.6(+0x10a7ce)[0x7f3f5712d7ce]
/opt/tomcat7/temp/libNRJavaSerial_keeper_0/libNRJavaSerial.so(initialise_event_info_struct+0x1ca)[0x7f3f44fcd8aa]
/opt/tomcat7/temp/libNRJavaSerial_keeper_0/libNRJavaSerial.so(Java_gnu_io_RXTXPort_eventLoop+0x5c)[0x7f3f44fcf30c]
[0x7f3f4d011f90]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 5125809 /usr/lib/java/jdk1.7.0_21/bin/java
00600000-00601000 rw-p 00000000 08:01 5125809 /usr/lib/java/jdk1.7.0_21/bin/java

ну и так далее.....

Очевидно что валится в методе initialise_event_info_struct из-за какого-то кривого указателя. Но какая при этом выполняется сишная операция мне понятно. gdb показал код ассемблерный:
(gdb) x/20i initialise_event_info_struct+0x1ca-10
0x5fc0 <initialise_event_info_struct+448>: stos %rax,%es:(%rdi)
0x5fc2 <initialise_event_info_struct+450>: movslq (%rbx),%rdi
0x5fc5 <initialise_event_info_struct+453>: callq 0x37b0 <__fdelt_chk@plt>
0x5fca <initialise_event_info_struct+458>: mov (%rbx),%ecx
0x5fcc <initialise_event_info_struct+460>: mov $0x1,%edx
0x5fd1 <initialise_event_info_struct+465>: movq $0x0,0x158(%rbx)
0x5fdc <initialise_event_info_struct+476>: movq $0x3e8,0x160(%rbx)
0x5fe7 <initialise_event_info_struct+487>: movl $0x1,0x30(%rbx)
0x5fee <initialise_event_info_struct+494>: shl %cl,%rdx
0x5ff1 <initialise_event_info_struct+497>: or %rdx,0xd8(%rbx,%rax,8)
0x5ff9 <initialise_event_info_struct+505>: mov $0x1,%eax
0x5ffe <initialise_event_info_struct+510>: add $0x8,%rsp
0x6002 <initialise_event_info_struct+514>: pop %rbx
0x6003 <initialise_event_info_struct+515>: pop %rbp
0x6004 <initialise_event_info_struct+516>: retq
0x6005 <initialise_event_info_struct+517>: nopl (%rax)
0x6008 <initialise_event_info_struct+520>: test %rdx,%rdx
0x600b <initialise_event_info_struct+523>: movb $0x0,(%rdi)
0x600e <initialise_event_info_struct+526>: jne 0x5eab <initialise_event_info_struct+171>
0x6014 <initialise_event_info_struct+532>: jmpq 0x5e87 <initialise_event_info_struct+135>

Жирным я выделил адрес который соответствует initialise_event_info_struct+0x1ca если я ничего не перепутал.

У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой. Но gdb не показывает сишный код. У меня есть Eclipse и KDevelop. Помогите пожалуйста установить точный оператор на котором валится приложение. Может быть есть способ отладки чтобы сопоставить код и этот адрес?

P.S. Вы не ошиблись все это крутится через жаву, но чтобы не уводить тему в оффтоп я об этом тактично умолчал.
Re: Отладка сторонней библиотеки Linux
От: ДимДимыч Украина http://klug.org.ua
Дата: 23.05.13 16:09
Оценка:
Здравствуйте, keeper-andrew, Вы писали:

KA>У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой.


Как именно? Флаг -ggdb указывал?
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: Отладка сторонней библиотеки Linux
От: zaufi Земля  
Дата: 23.05.13 16:23
Оценка: 3 (1) +2
Здравствуйте, keeper-andrew, Вы писали:

KA>Очевидно что валится в методе initialise_event_info_struct из-за какого-то кривого указателя. Но какая при этом выполняется сишная операция мне понятно. gdb показал код ассемблерный:

<skip>

KA>Жирным я выделил адрес который соответствует initialise_event_info_struct+0x1ca если я ничего не перепутал.

это всего лишь адрес возврата, полученный раскруткой stack frameов, куда мы вернемся после вызова __fdelt_chk.

KA>У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой. Но gdb не показывает сишный код.


чтобы он показывал код, ему нужно сказать где он (читать здесь)


KA> Может быть есть способ отладки чтобы сопоставить код и этот адрес?

`man addr2line`
если отладочная инфа включена, должен хотябы показать номер строки

а вообще, тебе же glibc явно написал: buffer overflow detected (все собрано с fortify).
поэтому я бы рекомендовал более надлежащий для этого tool: http://valgrind.org/docs/manual/mc-manual.html
он тебе покажет кто и что делает с памятью не так... вполне вероятно что не придется ждать 2 часа пока все упадет -- если есть кривая работа с памятью, valgrind тебя завалит спамом...
Re[2]: Отладка сторонней библиотеки Linux
От: keeper-andrew  
Дата: 23.05.13 18:22
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>Здравствуйте, keeper-andrew, Вы писали:


KA>>У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой.


ДД>Как именно? Флаг -ggdb указывал?


Я указывал -g3. Попробую -ggdb, спасибо.
Re[2]: Отладка сторонней библиотеки Linux
От: keeper-andrew  
Дата: 23.05.13 19:05
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, keeper-andrew, Вы писали:


KA>>Очевидно что валится в методе initialise_event_info_struct из-за какого-то кривого указателя. Но какая при этом выполняется сишная операция мне понятно. gdb показал код ассемблерный:

Z><skip>

KA>>Жирным я выделил адрес который соответствует initialise_event_info_struct+0x1ca если я ничего не перепутал.

Z>это всего лишь адрес возврата, полученный раскруткой stack frameов, куда мы вернемся после вызова __fdelt_chk.

Спасибо. Теперь мне стало понятно откуда в бактрейсе еще 3 позиции из libc.

KA>>У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой. Но gdb не показывает сишный код.


Z>чтобы он показывал код, ему нужно сказать где он (читать здесь)


KA>> Может быть есть способ отладки чтобы сопоставить код и этот адрес?

Z>`man addr2line`
Z>если отладочная инфа включена, должен хотябы показать номер строки

Огромное спасибо. Номер строки показал. Но там мега макрос так что теперь вопросов появилось больше чем ответов.
FD_SET( eis->fd, &eis->rfds );
из select.h

Z>а вообще, тебе же glibc явно написал: buffer overflow detected (все собрано с fortify).

Специально я этот fortify не подключал. Даже понятия не имею о том что это такое.

Z>поэтому я бы рекомендовал более надлежащий для этого tool: http://valgrind.org/docs/manual/mc-manual.html

Z>он тебе покажет кто и что делает с памятью не так... вполне вероятно что не придется ждать 2 часа пока все упадет -- если есть кривая работа с памятью, valgrind тебя завалит спамом...

Охблин. А казалось все будет проще....
Re[3]: Отладка сторонней библиотеки Linux
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 24.05.13 04:29
Оценка: 3 (1)
Здравствуйте, keeper-andrew, Вы писали:

KA>Огромное спасибо. Номер строки показал. Но там мега макрос так что теперь вопросов появилось больше чем ответов.

KA>FD_SET( eis->fd, &eis->rfds );
KA>из select.h

Так это банальный макрос, он ставит в 1 бит, соответствующий fd.
Надо, сделать assert, что eis_fd >= 0 && eis_fd < FD_SETSIZE. Например, есть вариант, что он равен -1, потому что забыли вовремя инициализировать или, наоборот, закрыли слишком рано.
Затем посмотреть, что такое eis->rfds. Если это статический fd_set, то тут проблем нет, но если выделяется явно malloc'ом, то посмотреть, сколько выделяется.

Z>>а вообще, тебе же glibc явно написал: buffer overflow detected (все собрано с fortify).

KA>Специально я этот fortify не подключал. Даже понятия не имею о том что это такое.

А оно автоматом включается во многих дистрибутивах. Но можно отключать опцией.
The God is real, unless declared integer.
Re[4]: Отладка сторонней библиотеки Linux
От: keeper-andrew  
Дата: 27.05.13 16:36
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, keeper-andrew, Вы писали:


KA>>Огромное спасибо. Номер строки показал. Но там мега макрос так что теперь вопросов появилось больше чем ответов.

KA>>FD_SET( eis->fd, &eis->rfds );
KA>>из select.h

N>Так это банальный макрос, он ставит в 1 бит, соответствующий fd.

N>Надо, сделать assert, что eis_fd >= 0 && eis_fd < FD_SETSIZE. Например, есть вариант, что он равен -1, потому что забыли вовремя инициализировать или, наоборот, закрыли слишком рано.
N>Затем посмотреть, что такое eis->rfds. Если это статический fd_set, то тут проблем нет, но если выделяется явно malloc'ом, то посмотреть, сколько выделяется.

Огромное Вам спасибо. Проблема была еще в другом методе, который не закрывал файловые дескрипторы. Поэтому идентификатор файла достигал значений больше 1024. Что и вызывало проблему. У меня другой вопрос. Открытие файла с айдишником большим 1024 это нормально (для линукса), а вот полноценная работа с ним уже невозможна. Это вообще нормально? И как с этим бороться? Я уверен что приложение теоретически будет держать больше 1024 открытых файловых дескриптора: это сервер приложений, для него это нормально.
Re[5]: Отладка сторонней библиотеки Linux
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 27.05.13 17:36
Оценка: 3 (1)
Здравствуйте, keeper-andrew, Вы писали:

KA> Открытие файла с айдишником большим 1024 это нормально (для линукса), а вот полноценная работа с ним уже невозможна.


Возможна. Только не надо применять select().

KA> Это вообще нормально? И как с этим бороться?


poll, epoll.

KA> Я уверен что приложение теоретически будет держать больше 1024 открытых файловых дескриптора: это сервер приложений, для него это нормально.


Никаких проблем. Просто не пользуйтесь legacy, или пользуйтесь там, где её адекватно поддерживают. В случае BSD систем можно переопределить FD_SETSIZE. В случае Linux этого нет, но вместо можно аллоцировать самому массивы нужного размера. Но повторюсь — лучше переходить на более современные средства.
The God is real, unless declared integer.
Re[6]: Отладка сторонней библиотеки Linux
От: keeper-andrew  
Дата: 28.05.13 07:42
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, keeper-andrew, Вы писали:


KA>> Открытие файла с айдишником большим 1024 это нормально (для линукса), а вот полноценная работа с ним уже невозможна.


N>Возможна. Только не надо применять select().


KA>> Это вообще нормально? И как с этим бороться?


N>poll, epoll.


Курнув тему я понял что мне это не под силу. Поскольку мой уровень С менее чем лузерский. Написал разработчикам в надежде что найдется кто-нибудь более профессиональный, а пока что обойдусь костылями.

KA>> Я уверен что приложение теоретически будет держать больше 1024 открытых файловых дескриптора: это сервер приложений, для него это нормально.


N>Никаких проблем. Просто не пользуйтесь legacy, или пользуйтесь там, где её адекватно поддерживают. В случае BSD систем можно переопределить FD_SETSIZE. В случае Linux этого нет, но вместо можно аллоцировать самому массивы нужного размера. Но повторюсь — лучше переходить на более современные средства.


Огромное спасибо всем откликнувшимся за помощь!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.