LINUX.ORG.RU

Корки странно читаются на разных машинах

 , ,


1

3

Ситуация такая:

Есть rhel6 с rt ядром. Есть локально убунточка с lowlatency ядром. Есть докер контейнер с centos6

Версии софта в centos6 и rhel6 совпадают, согласно диффанью выхлопа rpm -q.

Когда читаю корку с rhel6, что под убунточкой, что под centos6 получаю различия выхлопа вполть до разной глубины стектрейса и количества потоков.

Как такое вообще может быть, куда смотреть? Что влияет на формат core dump'a и то как оно читается, и где про это почитать?

Корки смотрел как от падений, так и снятые gcore. Бинари я ессно проверил что одни и те же.

Тащу корку с помощью scp, предварительно пожав gzip'om.

Версии gdb везде 7.11.

★★★★★

Как такое вообще может быть

Легко. В корке нет отладочных символов, они загружаются из той системы, в которой ты исследуешь core дамп. Так что либо воспроизводи систему в точности, либо исследуй core дампы прямо на месте.

i-rinat ★★★★★
()

Пример можешь дать (вывод bt того же на разных машинах)? Интересно, хотя я не удивлен

anonymous
()

На машинах разные библиотеки, в основном это касается libc. Нужно брать оригинальные rpm пакеты от rhel6, распаковывать и подсовывать gdb, иначе он возьмёт их от убунты - а они то наверняка собраны иначе и бинарно не совпадают.

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от anonymous

Я как-то раз пока пакет с отладочными символами ставил, обновил libc6, но сразу не заметил. Все вызовы в bt поплыли.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Отладочные символы же есть в бинарях. Более того, я специально проверял для других раскладов, например centos6 vs ubuntu 14.04 на разных машинах и оно работало.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Кстати вот нагуглил:

https://lists.gnu.org/archive/html/help-gplusplus/2008-02/msg00031.html


> And this is what i get after i scp the exe and dump to a different
>  computer (a kubuntu box):
>  (gdb) bt
>  #0  0xffffe410 in __kernel_vsyscall ()
>  #1  0x4017a101 in modff () from /lib/libc.so.6
>  #2  0x4017b8e8 in sigorset () from /lib/libc.so.6
>  #3  0x400ed794 in ?? ()
...
> As you can see, the backtraces differ, and i lose almost all symbols.
>  What am i doing wrong?

You aren't necessarily doing anything wrong.

The core dump contains memory image of the various writable (data)
segments of the process, but it does not contain copies of the
executable code (read-only sections), to save space [1].

Because of that, gdb backtrace requires access to the *exact*
version of all executable sections that were used when the core
dump was produced. This means that you need to tell gdb where to
find the main executable *and the shared libraries* which were used
by the running process, so it can extract symbol table from them,
and decode addresses in the core-dump into symbol names.

Without matching shared libraries, gdb just uses whatever libraries
are installed on the current system, if these don't match what's
in the dump, you get "garbage".

So, copy all the shared libraries (use gdb "info shared" to find
what they are) from the "original" computer to a subdirectory on
the second one (DO NOT overwrite /lib/libc.so.6 or any other libs
on the second computer -- that will likely render it unbootable),
and tell gdb to use them with gdb "solib-absolute-prefix". From
"info gdb":

`set solib-absolute-prefix PATH'
     If this variable is set, PATH will be used as a prefix for any
     absolute shared library paths; many runtime loaders store the
     absolute paths to the shared library in the target program's
     memory.  If you use `solib-absolute-prefix' to find shared
     libraries, they need to be laid out in the same way that they are
     on the target, with e.g. a `/usr/lib' hierarchy under PATH.

For example, if "info shared" says:

    From        To          Syms Read   Shared Object Library
    0x004880c0  0x0048d590  Yes         /lib/tls/librt.so.1
    0x00b74890  0x00c56f48  Yes         /lib/tls/libc.so.6
    0x00daa2f0  0x00db2608  Yes         /lib/tls/libpthread.so.0
    0x00b477a0  0x00b58a47  Yes         /lib/ld-linux.so.2

then do this:

  # on "original" computer:

    cd / 
    tar czf /tmp/to-copy.tgz \
       path/to/exe path/to/core lib/tls/librt.so.1 \
       lib/tls/libc.so.6 lib/tls/libpthread.so.0 lib/ld-linux.so.2

  # on the "second" computer:
  
    mkdir /tmp/libs.orig; cd /tmp/libs.orig
    tar xvzf to-copy.tgz

    gdb path/to/exe
    set solib-absolute-prefix /tmp/libs.orig
    core path/to/core
    where                # should give reasonable back trace

Cheers,

[1] Solaris allows inclusion of executable sections into core
with coreadm(1), but I don't believe such capability exists in linux.

i-rinat ★★★★★
()
Ответ на: комментарий от pon4ik

специально проверял для других раскладов

IMHO, это лотерея.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

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

gdb
thread apply all bt

Thread 40 (Thread 0x7f6972a2c700 (LWP 34689)):
#0  0x000000385ea0b98e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f69740db410 
#2  0x00000000025eaf10 
#3  0x0000000002f2e858 
#4  0x00007f6972a2bd10 
#5  0x000000385f203e46 
#6  0x000000000003fc8d 
#7  0x00000000025eaf10 
#8  0x000000041410351a 
#9  0x0000000002f2e820 
#10 0x0000000002f2e888 
#11 0x00000000025eaf10 
#12 0x00007f69740d87e1 
#13 0x00007f6972a2c9c0 
#14 0x000000385de14725 in _dl_close_worker () from /lib64/ld-linux-x86-64.so.2
........

и такой вот на удалённой машине:

Thread 40 (Thread 0x7f6972a2c700 (LWP 34689)):
#0  0x000000385ea0b98e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f69740db410 in 
#2  0x00007f69740d87e1 in 
#3  0x00007f69740cbad7 in 
#4  0x00007f69740cbc89 in 
#5  0x000000385ea079d1 in 
#6  0x000000385e6e8b6d in 
pon4ik ★★★★★
() автор топика
Ответ на: комментарий от mashina

Ну с убунтой - поверю. А как быть с контейнером с центосью? Они же обещают бинарную совместимость, хм.

pon4ik ★★★★★
() автор топика

Вообщем общую идею уловил, попробую прост папку с либами утащить as-is с rhel

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

Ну с убунтой - поверю. А как быть с контейнером с центосью? Они же обещают бинарную совместимость, хм.

Бинарная совсестимость пакетов это не то же самое, что и бинарная идентичность секций кода в библиотеках. Так что с centos нужно делать аналогично.

Вообщем общую идею уловил, попробую прост папку с либами утащить as-is с rhel

Проще брать два rpm с libc (сама либа + debug символы) и распаковывать их в отдельной директории. libс кидает файлы по многим путям и руками набирать конетнт может оказаться не очень удобно.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Интересно, а почему в адреса в трейсе разные? GDB трейс не из %rbp строит? Понятно было бы, если функции разные, а тут и адреса тоже другие. Библиотеки всё равно одинаковые нужны, но всё же

anonymous
()
Ответ на: комментарий от mashina

Да, хорошая идея, спасибо. Там не только libc, но думаю лучше для всего так сделать.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

А «низушки»?

В %rbp предыдущее значение %rbp, в %rbp+8 - return point. Как ещё можно стек раскрутить даже не знаю

anonymous
()
Ответ на: комментарий от anonymous

да, чет не подумал. Кстати адреса начинают не сразу отличаться.

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Интересно, а почему в адреса в трейсе разные? GDB трейс не из %rbp строит? Понятно было бы, если функции разные, а тут и адреса тоже другие.

%rbp, вообще говоря, может не быть с ожидаемым результатом, т.е. с началом адреса кадра, даже для текущей функции - фрейма может вообще не быть (-fomit-frame-pointer) или ф-я могла заюзать временно %rbp в месте останова для чего-либо.

да, чет не подумал. Кстати адреса начинают не сразу отличаться.

Почему именно тут gdb не разрулил хз, но вообще откат стека операция нетривиальная. И по трейсам видно что gdb начинает делать это как-то неправильно т.к. залезает на стек или в кучу (адреса типа 0x00007f6972a2bd10)

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от anonymous

При оптимизации компилятор может выпиливать сохранение стекового кадра в rbp, если у функции нет локальных переменных (либо получилось их все распихать по регистрам). В этом случае без полной отладочной информации однозначно раскрутить стек нельзя.

KivApple ★★★★★
()
Ответ на: комментарий от mashina

%rbp, вообще говоря, может не быть с ожидаемым результатом, т.е. с началом адреса кадра, даже для текущей функции - фрейма может вообще не быть (-fomit-frame-pointer) или ф-я могла заюзать временно %rbp в месте останова для чего-либо.

Точно, но тогда нормального трейса не вышло бы нигде))

Короче, это мистика

just-one-question
()
Ответ на: комментарий от just-one-question

Точно, но тогда нормального трейса не вышло бы нигде))

Как минимум ещё бывает отладочная информация в которой есть некоторые детали. Ну и часто бывает достаточно посмотреть на пролог функции чтобы понять делает ли она фрейм, а если нет - то сколько статически отгрызает себе стека. Этого достаточно на x86 чтобы разруливать многие трейсы и gdb явно практикует использование подобных «эвристик».

mashina ★★★★★
()

вообще, есть такая хрень как google breakpad. он как раз заточен под то, чтобы собирать дампы при падениях (если это твоя программа). и в нём удобно смотреть стектрейс. при падении он создаёт минидамп (это их собственный формат, очень компактный).

причём в самом бинаре нет дебажной информации. минидамп куда более диетический, чем коредамп. дебажная информация хранится отдельно, у тебя на машине, и когда где-то что-то падает, ты получаешь минидамп и смотришь, что там случилось. это удобно в продакшне, когда на куче разных машин выполняется какой-то крупный софт и в нём где-то трудноотлавливаемая бага (например, google breakpad используется для отладки мозиллы). я его использовала много где, ощущения весьма положительные. причём до кучи дампы можно снимать «по запросу». то есть, делать снимки стека в любой момент работы софта, что тоже иногда удобно (при зависаниях и непонятных тормозах, например).

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 2)
Ответ на: комментарий от Iron_Bug

Штука интересная (с ms слизанная :)), однако, вангую таже проблема проявится и там.

Т.е. по сути выигрыш в размере целевого файла, что не актуально, ибо машин 5 с половиной штук, а канал широкий? Или есть ещё какое то весомое преимущество кроме размера дампа?

Ибо телодвижений поделка требует больше, а профит по сравнению со штатными средствами только один - размер файла (ещё я так понял оно кроссплатформенно, однако в данном случае это не актуально).

pon4ik ★★★★★
() автор топика
Ответ на: комментарий от pon4ik

ну, например, недебажный бинарник (стрипнутый) на рабочих машинах. при этом все символы и т.д. лежат отдельно у тебя на машине и можно всё подробненько читать. ещё там можно настроить глубину стека для дампа (правда, в коде, но это элементарно).

плюс, как я написала, можно эту херь «по требованию» навешивать на любое событие и вуаля - снимок всех процессов со стектрейсами в любой момент. иногда очень полезно, когда процесс вроде завис или как-то странно работает, но сам не умирает.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 2)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.