2012-06-20 8 views
3

Как я могу связать основной файл со связанными с ним исполняемыми файлами и совместно используемыми библиотеками?Как связать основной файл со связанными с ним исполняемыми файлами?

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

Так что мне хотелось бы, чтобы связать основной файл со всеми другими двоичными файлами, которые он ссылается, в один большой файл.

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

ответ

2

GDB уже имеет информацию, которую вы хотели (info sharedlib):

$ gdb -ex 'set height 0' -ex 'set confirm off' \ 
    -ex 'file /path/to/exe' -ex 'core-file core.pid' \ 
    -ex 'info sharedlib' -ex quit 

Поэтому, естественно, вы можете попросить GDB, чтобы дать вам этот список, и оттуда вы можете создать «GDB-расслоение» тарболл, который содержит исполняемый файл и все общие библиотеки, которые gdb сообщил.

Я написал сценарий для автоматизации этого:

#!/bin/sh 
me=$(basename $0) 

usage() { 
    echo "Usage: 
    $me -p <pid> 
    $me <executable> <core> 

DESCRIPTION 
    $me - Creates a tarball containing the executable, it's core dump and 
     all the shared libraries that gdb said it loads. 

OPTIONS 
    -p <pid> A running process id of a process to be bundled. 
    -h  Show this help message" 
} 

pid= 
while getopts hp: opt 
do 
    case "$opt" in 
     p) 
      pid="$OPTARG" 
      ;; 
     h) 
      usage 
      exit 
      ;; 
     \?) 
      echo Unknown option 
      exit 
      ;; 
    esac 
done 
shift $(($OPTIND -1)) 
executable=$1 
corename=$2 

if [ -n "$pid" ]; then 
    test "$pid" -gt 0 || { echo "pid must be numeric"; exit 1; } 
    proc=/proc/$pid/exe 
    executable=`readlink -e $proc` || 
     { echo "Could not readlink $proc"; exit 1; } 
    corename=${basename}.$pid.core 
else 
    test -z "$executable" && usage && exit 1; 
    test -z "$corename" && usage && exit 1; 
fi 

basename=$(basename $executable) 
if [ -n "$pid" ]; then 
    sharedlibs=$(gdb -ex "attach $pid" -ex 'set height 0' \ 
     -ex 'set confirm off' -ex "generate-core-file $corename" \ 
     -ex 'info sharedlib' -ex quit| 
     sed -n '/Shared Object Library/,/^(/p'|grep -E '(Yes|No)'| 
     sed -e 's,[^/]\+,,') || exit 1 
    dir="gdb-${basename}.$pid.$(date +%F-%H%M%S)" 
else 
    sharedlibs=$(gdb -ex 'set height 0' -ex 'set confirm off' \ 
     -ex "file $executable" -ex "core-file $corename" \ 
     -ex 'info sharedlib' -ex quit| 
     sed -n '/Shared Object Library/,/^(/p'|grep -E '(Yes|No)'| 
     sed -e 's,[^/]\+,,') || exit 1 
    dir="gdb-${basename}.$(date +%F-%H%M%S)" 
fi 

mkdir "$dir" && cp "$corename" "$dir" && 
tar chf - $sharedlibs $executable|tar -C $dir -xf - && 
echo -e "gdb:\n\tgdb -ex 'set solib-absolute-prefix ./'" \ 
    "-ex 'file .$executable' -ex 'core-file ./$corename' " \ 
    > $dir/makefile && 
echo tar czf $dir.tar.gz $dir && 
tar czf $dir.tar.gz $dir 
0

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

0

Сначала найдите двоичный файл, связанный с ядром. У вас есть несколько вариантов:

  1. настроить систему на сердечники имени после того, как бинарная причиненный им, и ваши исполняемые файлы будут установлены в стандартном месте вашего сценарий может захватить их. Инструкции по наименованию ядер are here, также см. Ядро (5).

  2. Если вы не можете настроить систему, лучшее, что я придумал, это запустить строки в ядре, а затем для каждой строки, которая является допустимым путем, на которой запущен «файл», и grepping для «ELF», и "исполняемый файл". Это может привести к неправильному ответу, в частности, если двоичный код был вызван другой утилитой (например, make), они могут отображаться в ядре, поэтому вы можете добавлять дополнительные фильтры, например, исключая пути внутри/bin и/usr/bin, если вы знаете ваши двоичные файлы всегда находятся в say/opt и выбирают бинарный файл с самым последним mtime (более новое программное обеспечение, скорее всего, будет coring и скорее всего ваше, а не программное обеспечение, поставляемое вместе с системой).

  3. Дополнительный трюк состоит в том, чтобы искать «_ =/your/binary/here» в выводе строк - «_» - это специальная переменная среды, устанавливаемая некоторыми оболочками/WM/приложениями в двоичный файл. ссылающееся. Это также может вводить в заблуждение (например, это будет/usr/bin/make, когда вы вызываете ваш двоичный файл).

Во-вторых, собрать зависимости для двоичного файла:

  1. Grep выходной строки из ядра снова для значений LD_PRELOAD и LD_LIBRARY_PATH. Это может повлиять на то, какие библиотеки фактически связаны между собой.
  2. Запустите «ldd» в двоичном формате, с теми переменными, которые установлены на одни и те же значения, и разделить на «=>», чтобы найти имена файлов каждой из библиотек.

Затем скопируйте все это в каталог и запустите tar. Копирование файлов журнала в каталог часто также полезно.

Смежные вопросы