GDB показывает имена файлов исходного кода для глобальных переменных и функций.

Вопрос или проблема

Я использую gdb для подключения к запущенному процессу на системе Linux. Как вы можете видеть, info files показывает секции из исполняемого файла ELF, которые отображены в виртуальной памяти процесса, а также секции загруженных общих библиотек .so.

root@host:/# gdb -q attach 7173
attach: Нет такого файла или каталога.
Подключение к процессу 7173
[Новый LWP 17381]
[Новый LWP 17380]
[Новый LWP 17379]

предупреждение: Ожидался абсолютный путь для libpthread в подчинённом процессе, но получен target:/lib64/libpthread.so.0.

предупреждение: Невозможно найти libthread_db, соответствующую библиотеке потоков подчинённого процесса, отладка потоков не будет доступна.
0x00007f0bf997ac73 in epoll_wait () at ../sysdeps/unix/syscall-template.S:81

предупреждение: 81     ../sysdeps/unix/syscall-template.S: Нет такого файла или каталога
(gdb) info files
Символы из "target:/proc/7173/exe".
Нативный процесс:
        Используется запущенный образ прикрепленного процесса 7173.
        При выполнении этого GDB не получает доступ к памяти из...
Локальный исполняемый файл:
        `target:/proc/7173/exe', тип файла elf64-x86-64.
        Точка входа: 0x564521600970
        0x00005645215fa200 - 0x00005645215fa21c это .interp
        0x00005645215fa21c - 0x00005645215fa23c это .note.ABI-tag
        0x00005645215fa23c - 0x00005645215fa260 это .note.gnu.build-id
        0x00005645215fa260 - 0x00005645215fb0b8 это .dynsym
        0x00005645215fb0b8 - 0x00005645215fb1ea это .gnu.version
        0x00005645215fb1ec - 0x00005645215fb23c это .gnu.version_r
        0x00005645215fb240 - 0x00005645215fb588 это .gnu.hash
        0x00005645215fb588 - 0x00005645215fcc2c это .dynstr
        0x00005645215fcc30 - 0x00005645215fe850 это .rela.dyn
        0x00005645215fe850 - 0x00005645215feaf0 это .rela.plt
        0x00005645215feaf0 - 0x00005645215fff41 это .rodata
        0x00005645215fff44 - 0x0000564521600140 это .eh_frame_hdr
        0x0000564521600140 - 0x000056452160096c это .eh_frame
        0x0000564521600970 - 0x00005645216012f1 это .text
        0x00005645216012f4 - 0x000056452160130e это .init
        0x0000564521601310 - 0x0000564521601319 это .fini
        0x0000564521601320 - 0x00005645216014f0 это .plt
        0x0000564521602000 - 0x0000564521602010 это .data
        0x0000564521602010 - 0x0000564521602018 это .jcr
        0x0000564521602018 - 0x0000564521602018 это .tm_clone_table
        0x0000564521602018 - 0x0000564521602020 это .fini_array
        0x0000564521602020 - 0x0000564521602028 это .init_array
        0x0000564521602028 - 0x0000564521602fe8 это .data.rel.ro
        0x0000564521602fe8 - 0x0000564521603298 это .dynamic
        0x0000564521603298 - 0x00005645216034e0 это .got
        0x00005645216034e0 - 0x00005645216035d8 это .got.plt
        0x00005645216035e0 - 0x0000564521603ee4 это .bss
        0x00007f0bfa9e4190 - 0x00007f0bfa9e41b4 это .note.gnu.build-id в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e41b8 - 0x00007f0bfa9e467c это .hash в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e4680 - 0x00007f0bfa9e56a0 это .dynsym в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e56a0 - 0x00007f0bfa9e60d1 это .dynstr в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e60d2 - 0x00007f0bfa9e622a это .gnu.version в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e6230 - 0x00007f0bfa9e62d0 это .gnu.version_r в target:/pkg/lib/libmemdbg.so
        0x00007f0bfa9e62d0 - 0x00007f0bfa9e6690 это .rela.dyn в target:/pkg/lib/libmemdbg.so
--Нажмите <RET> для получения дополнительной информации, q для выхода, c для продолжения без постраничного отображения--
        0x00007f0bfa9e6690 - 0x00007f0bfa9e7158 это .rela.plt в target:/pkg/lib/libmemdbg.so

Вывод info variables показывает тип и имя (глобальных?) доступных переменных в адресном пространстве процесса вместе с именем исходного файла, в котором они определены.

(gdb)info variables 
Все определенные переменные:

Файл ../csu/init-first.c:
38:     int __libc_argc;
39:     char **__libc_argv;
34:     int __libc_multiple_libcs;

Файл ../elf/dl-sysdep.c:
61:     void *__GI___libc_stack_end;
56:     int __libc_enable_secure;
57:     int __libc_enable_secure_internal;
58:     int __libc_multiple_libcs;
62:     void *__libc_stack_end;
63:     void *_dl_random;
<вывод сокращён........>
(gdb) 

Как gdb получает имена этих исходных файлов? Их нет на системе, на которой работает gdb.

Спасибо.

Ответ или решение

Как GDB Получает Имена Файлов Исходного Кода для Глобальных Переменных и Функций?

Когда вы используете GDB для подключения к работающему процессу на операционной системе Linux, возможно встретить ситуацию, когда вы видите имена исходных файлов для глобальных переменных и функций в выводе команды info variables. Это может вызывать вопросы, особенно если на вашей системе отсутствуют указанные файлы. В этом ответе мы рассмотрим, как GDB получает информацию об именах этих файлов и откуда она берётся.

1. Процесс Сборки и Отладочная Информация

При компиляции исходного кода с использованием компилятора, такого как GCC, разработчик может включить опции, которые добавляют отладочную информацию в исполняемый файл. Это осуществляется с помощью флага -g, который позволяет компилятору сохранять информацию о соответствиях между исполняемым кодом и исходными файлами. Например, при компиляции файла example.c команда может выглядеть так:

gcc -g -o example example.c

В результате этого в облике ELF-исполняемого файла будет добавлена информация о строках исходного кода, их номерах и именах файлов. Эта информация сохраняется в специальных секциях, таких как .debug_info, .debug_abbrev, и других отладочных секциях.

2. Взаимодействие GDB и ELF Формата

Когда GDB подключается к исполняемому процессу, он использует информацию, сохранённую в ELF-файле, чтобы отобразить имена переменных и функций. Тем не менее, важно отметить, что, хотя указанные файлы могут отсутствовать в файловой системе в месте, где работает GDB, информация о них всё равно может быть доступна.

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

  • info variables: Команда показывает все определенные глобальные переменные, включая их типы и имена, а также имена файлов, в которых они определены.
  • info files: Эта команда отображает информацию об ELF-исполняемом файле и загруженных библиотеках.

3. Почему Имена Файлов Могут Отсутствовать в Файловой Системе

Существует несколько причин, почему GDB показывает имена файлов, которые отсутствуют на системе:

  • Удалённый или контейнерный процесс: Если вы подключаетесь к процессу, который был создан или запущен в другом окружении, имени исходного файла могут быть недоступны на вашей текущей системе.
  • Удалённые исходники: Исходные файлы могут быть удалены после создания бинарного файла, но информация о них все ещё сохраняется в отладочной информации, что позволяет GDB её извлекать.
  • Безопасность и конфиденциальность: Некоторые приложения, особенно в производственных системах, могут либо не распространять, либо удалять исходные файлы для предотвращения несанкционированного доступа.

4. Настройка GDB для Эффективной Отладки

Если вы хотите видеть полные пути к исходным файлам и их содержимое при отладке вашего приложения, вы можете:

  • Убедиться, что вы компилируете ваш код с флагом -g, чтобы сохранить отладочную информацию.
  • Использовать strip с осторожностью, так как эта команда может удалить отладочную информацию, сделав ваш исполняемый файл менее информативным.
  • Применять настройку путей для отладочных информации в GDB, чтобы указать, где искать соответствующие исходные файлы с помощью команды directory.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...