Сразу предупрежу, что на С/С++ не программировал уже много лет. А для 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 портами. Спустя час-два вылетает. Бактрейс следующий:
Очевидно что валится в методе 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. Вы не ошиблись все это крутится через жаву, но чтобы не уводить тему в оффтоп я об этом тактично умолчал.
Здравствуйте, 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 тебя завалит спамом...
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, keeper-andrew, Вы писали:
KA>>У меня есть исходник, у меня есть эта библиотечка и я собрал ее с максимальной отладочной инфой.
ДД>Как именно? Флаг -ggdb указывал?
Здравствуйте, 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 тебя завалит спамом...
Здравствуйте, 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 не подключал. Даже понятия не имею о том что это такое.
А оно автоматом включается во многих дистрибутивах. Но можно отключать опцией.
Здравствуйте, 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 открытых файловых дескриптора: это сервер приложений, для него это нормально.
Здравствуйте, keeper-andrew, Вы писали:
KA> Открытие файла с айдишником большим 1024 это нормально (для линукса), а вот полноценная работа с ним уже невозможна.
Возможна. Только не надо применять select().
KA> Это вообще нормально? И как с этим бороться?
poll, epoll.
KA> Я уверен что приложение теоретически будет держать больше 1024 открытых файловых дескриптора: это сервер приложений, для него это нормально.
Никаких проблем. Просто не пользуйтесь legacy, или пользуйтесь там, где её адекватно поддерживают. В случае BSD систем можно переопределить FD_SETSIZE. В случае Linux этого нет, но вместо можно аллоцировать самому массивы нужного размера. Но повторюсь — лучше переходить на более современные средства.
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, keeper-andrew, Вы писали:
KA>> Открытие файла с айдишником большим 1024 это нормально (для линукса), а вот полноценная работа с ним уже невозможна.
N>Возможна. Только не надо применять select().
KA>> Это вообще нормально? И как с этим бороться?
N>poll, epoll.
Курнув тему я понял что мне это не под силу. Поскольку мой уровень С менее чем лузерский. Написал разработчикам в надежде что найдется кто-нибудь более профессиональный, а пока что обойдусь костылями.
KA>> Я уверен что приложение теоретически будет держать больше 1024 открытых файловых дескриптора: это сервер приложений, для него это нормально.
N>Никаких проблем. Просто не пользуйтесь legacy, или пользуйтесь там, где её адекватно поддерживают. В случае BSD систем можно переопределить FD_SETSIZE. В случае Linux этого нет, но вместо можно аллоцировать самому массивы нужного размера. Но повторюсь — лучше переходить на более современные средства.