Я пытаюсь узнать о 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.
Почему отладчик ищет то, что, как я полагаю, является исходным файлом сборки, который я, очевидно, не установил?
Обратите внимание, что на вики-странице написано, что ваш вывод может отличаться. Вы можете следить за обсуждением этого примера , которое привело к тому, что это предупреждение было добавлено на вики-страницу LinuxQuestions.
В общем, эти различия основаны на том, как такие вещи, как libc
(и, возможно, gdb
), компилируются в разных системах. Обратите внимание, что пример запускается на Fedora, а не на Ubuntu; поэтому базовая система может иметь некоторые ключевые отличия в настройке.
Я думаю, что это главная причина разницы. Фактически, я запустил пример на Fedora и получил вывод, который был более или менее идентичен выводу в примере.
Суть в том, что вывод, который вы получаете, является нормальным выходом для Ubuntu. Я получил тот же вывод. Вы можете выполнить команду bt
с этой точки, и следующий набор выходных данных будет очень похож на выходной в примере.
Так почему же GDB ищет файлы сборки, когда вы работаете в C? Хорошо, имейте в виду, что именно libc
ищет файл сборки. GDB просто сообщает, что случилось.
И libc
ищет файл сборки в основном потому, что он должен: части библиотеки реализованы в сборке.
Я не гуру во внутренней работе стандартной библиотеки C или сборки, поэтому я хочу быть осторожным, чтобы не сказать что-то неправильное.
Но обратите внимание на две вещи в этом примере:
Речь идет о длине, которая по определению попадет в определения, зависящие от системы.
Если вы посмотрите на сообщение, то увидите, что действительно библиотека ищет в своем собственном внутреннем каталоге sysdeps
, где хранятся системные зависимые каталоги. Этот каталог является частью скомпилированной библиотеки и не является частью видимой файловой системы на компьютере.
Согласно документации GNU C Library эта структура создается на основе результата утилиты configure
, которая определяет, как библиотека компилируется.
Если вы посмотрите на исходный код для libc, вы увидите, что strlen
вызывает скрытые встроенные функции, основанные на архитектуре системы, которая, в свою очередь, вызывает другую скрытую встроенную системно-зависимую сборку strlen.S
(Я насчитал 18 файлов с таким именем, все для разных арок), что, в свою очередь, вызывает (или может вызвать?) Дополнительную скрытую встроенную функцию .S
для разных процессоров. sse
и pminub
относятся к деталям процессора.
И почему он не находит файл? Я предполагаю, что это не находит это, потому что это не там. Скомпилированный двоичный файл не включает его (я предполагаю), потому что он не нужен в этой системе, и configure
не сказал, что он должен быть создан во время сборки.
Дело в том, что в данном примере передается NULL
функции, которая ожидает строку, что является большой ошибкой. В отличие от языков более высокого уровня, компилятор не улавливает это. Результатом является неопределенное поведение, поэтому может произойти все что угодно.
Я предполагаю, что библиотека пытается найти версию функции, которая, по ее мнению, имеет больше смысла; но поскольку здесь NULL
не имеет смысла, он угадывает неверно и ищет версию, которой там нет.
В любом случае это не удастся с дампом ядра. Я также предположил бы, что библиотека, скомпилированная для Fedora, не демонстрирует абсолютно одинаковое поведение из-за различных системных различий и из-за того, что на данном этапе любое поведение является законным.
Я нашел ответ на на этом сайте
Вот короткая версия
Из терминала запустите strace -o gdboutput.txt gdb example
и пройдите через Пример вики, который вы связали с
Откройте gdboutput.txt
и найдите текст No such file or directory
. Там вы найдете путь для strlen-sse2-pminub.S
Загрузите самую последнюю библиотеку glibc, используя sudo apt-get source glibc
Ищите strlen-sse2-pminub.S
в каталоге, который вы только что загрузили, используя find -iname strlen-sse2-pminub.S
Переместите 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
, и все будет установлено в нужном месте и будет видно отладчику.
Эта информация пришла ко мне из «Приключений в коде».
Поскольку рассматриваемый код - это библиотечный код, который написан на ассемблере, а отладочная информация для него ссылается на этот файл. (В частности, это одна из оптимизированных 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 все равно не сможет их найти .