Почему GDB ищет файлы сборки?

Я пытаюсь узнать о GDB с помощью Ubuntu 13.10. Я использую компилятор gcc и следующий пример:

https://en.wikipedia.org/wiki/Gdb#An_example_session

Вместо вывода, показанного в Например, я получаю:

Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2_pminub () at ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S:38
38      ../sysdeps/x86_64/multiarch/strlen-sse2-pminub.S: No such file or directory.

Почему отладчик ищет то, что, как я полагаю, является исходным файлом сборки, который я, очевидно, не установил?

0
задан 30 October 2013 в 02:26

3 ответа

Обратите внимание, что на вики-странице написано, что ваш вывод может отличаться. Вы можете следить за обсуждением этого примера , которое привело к тому, что это предупреждение было добавлено на вики-страницу LinuxQuestions.

В общем, эти различия основаны на том, как такие вещи, как libc (и, возможно, gdb), компилируются в разных системах. Обратите внимание, что пример запускается на Fedora, а не на Ubuntu; поэтому базовая система может иметь некоторые ключевые отличия в настройке.

Я думаю, что это главная причина разницы. Фактически, я запустил пример на Fedora и получил вывод, который был более или менее идентичен выводу в примере.

Суть в том, что вывод, который вы получаете, является нормальным выходом для Ubuntu. Я получил тот же вывод. Вы можете выполнить команду bt с этой точки, и следующий набор выходных данных будет очень похож на выходной в примере.

Так почему же GDB ищет файлы сборки, когда вы работаете в C? Хорошо, имейте в виду, что именно libc ищет файл сборки. GDB просто сообщает, что случилось.

И libc ищет файл сборки в основном потому, что он должен: части библиотеки реализованы в сборке.

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

Но обратите внимание на две вещи в этом примере:

  1. Речь идет о длине, которая по определению попадет в определения, зависящие от системы.

    Если вы посмотрите на сообщение, то увидите, что действительно библиотека ищет в своем собственном внутреннем каталоге sysdeps, где хранятся системные зависимые каталоги. Этот каталог является частью скомпилированной библиотеки и не является частью видимой файловой системы на компьютере.

    Согласно документации GNU C Library эта структура создается на основе результата утилиты configure, которая определяет, как библиотека компилируется.

    Если вы посмотрите на исходный код для libc, вы увидите, что strlen вызывает скрытые встроенные функции, основанные на архитектуре системы, которая, в свою очередь, вызывает другую скрытую встроенную системно-зависимую сборку strlen.S (Я насчитал 18 файлов с таким именем, все для разных арок), что, в свою очередь, вызывает (или может вызвать?) Дополнительную скрытую встроенную функцию .S для разных процессоров. sse и pminub относятся к деталям процессора.

  2. И почему он не находит файл? Я предполагаю, что это не находит это, потому что это не там. Скомпилированный двоичный файл не включает его (я предполагаю), потому что он не нужен в этой системе, и configure не сказал, что он должен быть создан во время сборки.

    Дело в том, что в данном примере передается NULL функции, которая ожидает строку, что является большой ошибкой. В отличие от языков более высокого уровня, компилятор не улавливает это. Результатом является неопределенное поведение, поэтому может произойти все что угодно.

    Я предполагаю, что библиотека пытается найти версию функции, которая, по ее мнению, имеет больше смысла; но поскольку здесь NULL не имеет смысла, он угадывает неверно и ищет версию, которой там нет.

    В любом случае это не удастся с дампом ядра. Я также предположил бы, что библиотека, скомпилированная для Fedora, не демонстрирует абсолютно одинаковое поведение из-за различных системных различий и из-за того, что на данном этапе любое поведение является законным.

0
ответ дан 30 October 2013 в 02:26

Я нашел ответ на на этом сайте

Вот короткая версия

  1. Из терминала запустите strace -o gdboutput.txt gdb example и пройдите через Пример вики, который вы связали с

  2. Откройте gdboutput.txt и найдите текст No such file or directory. Там вы найдете путь для strlen-sse2-pminub.S

  3. Загрузите самую последнюю библиотеку glibc, используя sudo apt-get source glibc

  4. Ищите strlen-sse2-pminub.S в каталоге, который вы только что загрузили, используя find -iname strlen-sse2-pminub.S

  5. Переместите glibc в местоположение, найденное на шаге 2. Возможно, вам потребуется создать каталог. Или вы можете изменить место, где GDB ищет эти файлы (пока я не знаю достаточно, чтобы это сделать)

Теперь при запуске примера GDB не будет возвращена ошибка «файл не найден». Но это все еще не дало мне результат википедии. Я использую Ubuntu. Он работал на центробежке, как показано в Википедии.

Я скопирую полное обсуждение ниже на случай, если сайт закроется.


Отладка в Ubuntu 12.10 - отсутствует файл syscall-template.S ПРИМЕЧАНИЕ. В нижней части этого поста есть обновление. Пожалуйста, прочтите его!

После обновления моей машины для разработки до Ubuntu 12.04 я был разочарован, обнаружив, что отладка внезапно перестала работать должным образом. Каждый раз, когда я пытался, я получал сообщение об ошибке:

Cannot find file ‘../sysdeps/unix/syscall-template.S’

После этого ни одна из отладок не имела особого смысла (а повторяющиеся предупреждения только мешали).

Жизнь как-то мешала, и я долгое время не занимался разработкой на С - настолько, что обновление 12.10 появилось еще до того, как я даже больше не думал об этом. К сожалению, проблема не исчезла, поэтому после очередного периода бездействия я теперь исправляю ее.

Я обнаружил, что рассматриваемый файл находится в источниках для libc6. Их можно получить с помощью следующей команды:

sudo apt-get source libc6

Это загружает источники в текущий каталог. Вернемся к отладчику, и он все еще не может найти файлы - не удивительно, но я не знал, куда их поместить. В отчаянии я запустил strace на отладчике (в данном случае nemiver), чтобы посмотреть, где он ищет нашего друга. Вот что я получил:

stat(“/build/buildd/eglibc-2.15/misc/../sysdeps/unix/syscall-template.S”, 0x7fff0ba361f0) = -1 ENOENT (No such file or directory)
stat(“/home/test/../sysdeps/unix/syscall-template.S”, 0x7fff0ba361f0) = -1 ENOENT (No such file or directory)
stat(“/build/buildd/eglibc-2.15/misc/syscall-template.S”, 0x7fff0ba36200) = -1 ENOENT (No such file or directory)
stat(“/home/test/syscall-template.S”, 0x7fff0ba36200) = -1 ENOENT (No such file or directory)

Не зная внутренней работы отладчиков и не желая, чтобы файлы были видны всем пользователям, я решил создать каталог /build/buildd и поместить туда источники libc6. :

sudo mkdir -p /build/buildd
cd /build/buildd
sudo mv ~/eglic* .

Удачи! Немивер нашел файлы и был счастлив навсегда. И поскольку nemiver является оберткой для gdb, я проверил и подтвердил, что это тоже радует, поэтому, если вы один из тех сумасшедших людей, которые могут понимать gdb *, тогда это сработает для вас.

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

* Моим единственным опытом отладки до изучения C была отладка Java, которая является самым приятным опытом отладки, который вы можете иметь. После этого GDB становится страшным кошмаром.

ОБНОВЛЕНИЕ 6 мая 2014 года. Похоже, что исходные коды libc6 доступны в более новых выпусках Ubuntu в виде устанавливаемого пакета. Вы должны просто сделать

sudo apt-get install eglibc-source

, и все будет установлено в нужном месте и будет видно отладчику.

Эта информация пришла ко мне из «Приключений в коде».

0
ответ дан 30 October 2013 в 02:26

Почему он ищет исходный файл сборки?

Поскольку рассматриваемый код - это библиотечный код, который написан на ассемблере, а отладочная информация для него ссылается на этот файл. (В частности, это одна из оптимизированных strlen() реализаций [e] glibc для x86-64 (он же amd64).)

Предположительно, отладчик передал неверный аргумент strlen(), и это сделал это сбой. (Теоретически это может быть проблемой с реализацией strlen(), но такая фундаментальная функция вряд ли может содержать ошибки, особенно учитывая популярность amd64 и тот факт, что [e] glibc имеет только 3 варианта из strlen() ] на этой арке

Почему этот файл не установлен?

Главным образом из-за того, что это нелегко организовать.

Далее следует довольно техническое резюме об этих проблемах, и, возможно, вы ожидаете получить много знаний, которых у вас нет, если у вас есть вопросы, вы можете задать их в # debian-mentors на OFTC .

Ключевые факты:

  • Ubuntu использует в основном ту же коллекцию исходных пакетов, что и Debian, с относительно небольшим количеством пакетов, которые не взяты прямо из Debian.

  • Большая часть отладочной информации Ubuntu находится в -dbgsym пакетах, автоматически генерируемых в dh_strip время pkg-create-dbgsym (который устанавливает оболочку вокруг dh_strip). ( Это не происходит в Дебии n.) Это работает, потому что 99% пакетов используют dh_strip для удаления своих двоичных файлов.

  • Несколько ключевых исходных пакетов явно генерируют свои собственные -dbg пакеты, в первую очередь, чтобы они быть доступным в Debian, но, возможно, также потому, что им нужно установить не только отдельную информацию DWARF.

  • eglibc - один из этих ключевых пакетов исходного кода.

Из-за почти безграничной свободы, которую исходные пакеты Debian имеют в том, как они могут собираться, для универсального инструмента определенно нетривиально определить, какие именно файлы являются соответствующими исходными файлами, которые должны быть объединены в пакет debugging-source.

Вы можете подумать, что достаточно просто распаковать пакет с исходным кодом, но это не очень хорошо сработает с пакетами типа gcc, которые на самом деле содержат tarball внутри своего так называемого .orig tarball или даже с пакетами, которые просто используют систему патчей, более сложную, чем та, которую вы получаете с форматом 3.0 (quilt). (Еще одна вещь, которая может испортить ситуацию, - это если исходный пакет генерирует какие-либо источники во время сборки, которые либо не содержат директив #line, либо ссылаются на себя в этих директивах #line.)

Однако, похоже, что двоичные файлы и содержат абсолютные пути ко всем исходным файлам, поэтому , если они еще не повреждены, в это время они могут быть упакованы. К сожалению, я, кажется, галлюцинировал флаги objcopy, которые позволили бы вам переписать исходные пути в DWARF в соответствии с путями установки, поэтому GDB все равно не сможет их найти .

0
ответ дан 30 October 2013 в 02:26

Другие вопросы по тегам:

Похожие вопросы: