Символы и источники Linux
В этой статье описывается, как WinDbg поддерживает стандартные символы и источники Linux. Для поддержки отладки в Linux требуется WinDbg версии 1.2402.24001.0 или более поздней.
Серверы символов DebugInfoD
Отладчик окна использует стандарт DebugInfoD для автоматического скачивания артефактов сборки для Linux. Аналогичным образом DebugInfoD — это сочетание серверов символов Майкрософт и технологий исходного сервера. Он позволяет автоматически загружать три типа артефактов (исполняемые файлы (ELF), отладочную информацию (DWARF) и исходный (код) на основе идентификатора сборки. Различные дистрибутивы Linux теперь размещают собственные серверы DebugInfoD, которые предоставляют некоторые типы артефактов. В ELFUTILS https://debuginfod.elfutils.orgперечислены различные серверы DebugInfoD.
Общие сведения об DebugInfoD доступны здесь:
Тег DebugInfoD*
может указывать на один или несколько серверов DebugInfoD с каждым URL-адресом сервера, отформатированным как https://domain.com
и разделенным *
. Серверы будут искать в том же порядке, что и в исходном пути, и файлы будут получены из первого соответствующего URL-адреса.
Например, можно задать путь к символам, как показано ниже.
.sympath+ DebugInfoD*https://debuginfod.elfutils.org
Используйте команду для отображения сведений о загрузке !sym noisy
символов. Дополнительные сведения см. в разделе !sym.
Команда исходного пути (Srcpath, Lsrcpath (Set Source Path)) поддерживает извлечение файлов из серверов DebugInfoD с помощью DebugInfoD*
тега, что позволяет получить артефакты исходного кода. Например, можно задать исходный путь, как показано ниже.
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org
Дополнительные сведения см. в статье "Расширенный доступ к исходному коду".
Символы DWARF
DWARF — это широко используемый стандартизированный формат данных отладки. ПЕРВОНАЧАЛЬНО ОН был разработан вместе с исполняемым и компоноваемым форматом (ELF), хотя он не зависит от форматов файлов объектов. Дополнительные сведения см. в разделе "Стандартный" версии 5, см. в разделе https://en.wikipedia.org/wiki/DWARF"КАРЛИК" версии 5.
Используйте команду дампа объекта, чтобы определить версию символа DWARF. В этом примере версия 5.
bob@BOB:/mnt/c/Users/BOB$ objdump -g DisplayGreeting | grep -A 2 'Compilation Unit @'
Compilation Unit @ offset 0x0:
Length: 0x285c (32-bit)
Version: 5
Поддержка WinDbg DWARF
WinDbg поддерживает следующие способы использования DWARF и ELF.
Пользовательский режим Linux— открытие дампов Linux ELF Core (
-z <core dump>
) и выполнение последующей отладки и анализа с полными частными символами DWARF.Режим ядра Linux— открытие дампов ядра Linux (ELF VMCORE) и выполнение послеморочной отладки и анализа с полными частными символами DWARF.
Режим ядра Linux— открытие сжатых KDUMPs ядра Linux и выполнение послеморозной отладки и анализа с полными частными символами DWARF (WinDbg поддерживает только сжатые KDUMP-файлы ZLIB. LZO и Snappy сжатые KDUMPs не поддерживаются.)
Открытие изображений ELF (
-z <ELF image>
) и изучение содержимого, дизассембли и т. д.Другие сценарии . Общие сведения о изображениях ELF и символах DWARF в смешанных средах PE/ELF (например, отладка компонентов Open Enclave, загруженных в Windows. Дополнительные сведения см. в разделе Open Enclave debugging.)
Поддержка WinDbg GDBServer Linux
Отладчик GNU, GDBServer используется в Linux для поддержки подключения WinDbg. Дополнительные сведения о GDBServer см. в статье https://en.wikipedia.org/wiki/Gdbserver. Здесь можно просмотреть документацию по удаленной отладке gdb. https://sourceware.org/gdb/current/onlinedocs/gdb#Remote-Debugging
Дополнительные сведения об использовании GDBServer с WinDbg и пошаговом руководстве по коду см . в статье об отладке динамического процесса Linux. В примерах здесь используется Ubuntu, запущенная в подсистема Windows для Linux (WSL), но другие реализации Linux также можно использовать.
Реализация DWARF
Символы DWARF поддерживаются в исходном образе (отладочном двоичном файле) или разделены на отдельный образ ELF (пакет отладки).
Чтобы пошаговое руководство по стеку Linux DWARF выполнялось успешно, исходный двоичный образ для любого модуля, загруженного в процесс Linux, должен быть найден.
Символы DWARF/ОБРАЗы ELF (отрезаемые или нет) можно найти с помощью симпатии отладчика или сервера символов (индексировано как на .NET Core через хэш идентификатора сборки GNU).
Символы DWARF можно найти с помощью установки пакета отладки стиля Linux. Такое значение присваивается каталогом, именованным .build-id
в пути символа. В этом разделе перечислены каталоги с именем в соответствии с первым байтом хэша идентификатора сборки GNU. В каждом таком каталоге находится файл с именем <remaining 18 bytes of GNU Build ID hash>
.debug.
Когда отладчик открывает символы DWARF, он выполняет начальный шаг индексирования, так как сам формат не включает необходимые таблицы подстановки. Для больших наборов символов DWARF (например, частных данных DWARF для ядра Linux) это может занять 10 –30 секунд.
!addsourcemap для автоматического получения источника из известного репозитория или фиксации
Если вы выполняете отладку компонентов, созданных из известного репозитория и фиксации, существует расширение, !addsourcemap
команда отладчика позволяет сообщить отладчику, что для заданного модуля и пути вы хотите автоматически извлекать источники из известного URL-адреса. Использование расширения:
!addsourcemap <module> <local spec> <remote spec>
Где:
<module>
— имя интересующего модуля.
<local spec>
— это путь к источникам в этом модуле, который будет искать по URL-адресу. Этот путь должен заканчиваться диким карта.
<remote spec>
— ЭТО URL-адрес, по которому будут искать файлы, соответствующие <local spec>
. Этот путь должен заканчиваться диким карта который будет заменен на то, как дикий карта в <local spec>
совпадениях с определенным исходным путем.
Чтобы задать исходную карту, убедитесь, что модуль присутствует с помощью lm (список загруженных модулей). Затем определите удаленное расположение источника.
В этом примере модуль vmlinux устанавливается в определенную сборку, доступную на сайте GitHub.
0:000> !addsourcemap vmlinux /build/linux/* https://raw.githubusercontent.com/torvalds/linux/6e61dde82e8bfe65e8ebbe43da45e615bc529236/
Source map /build/linux/* -> https://raw.githubusercontent.com/torvalds/linux/6e61dde82e8bfe65e8ebbe43da45e615bc529236/ successfully added
После выдачи команды sourcemap ряд вещей активирует исходную нагрузку, например переключение кадров обратно и назад или перезагрузку с помощью команды reload. После этого произойдет автоматическое извлечение источника из GitHub.
!sourcemaps
Используйте команду для перечисления !sourcemaps
существующих карт источников.
0:000> !sourcemaps
Source maps for vmlinux.6:
/build/linux/* -> https://raw.githubusercontent.com/torvalds/linux/6e61dde82e8bfe65e8ebbe43da45e615bc529236/
!removesourcemaps
!removesourcemaps
Используйте команду для удаления существующей карты источника.
0:000> !removesourcemaps vmlinux /build/linux/* https://raw.githubusercontent.com/torvalds/linux/6e61dde82e8bfe65e8ebbe43da45e615bc529236/
1 source maps successfully removed
Устранение неполадок с символами DWARF
При отладке дампов Linux или Android (или других целевых объектов, использующих символы DWARF), может потребоваться просмотреть необработанное содержимое символов, чтобы понять, почему локальные переменные, определения типов или определения функций неверны. Для этого отладчик имеет некоторые встроенные команды расширения для дампа необработанного содержимого символов DWARF. Кроме того, используйте служебные программы Linux, такие как readelf и dumpdwarf, для отображения сведений о внутренних символах.
команда readelf
Используйте команду readelf в командной строке Linux, чтобы отобразить идентификатор сборки отладки, созданный для примера программы DisplayGreeting, созданной в динамической отладке удаленного процесса Linux. В этом примере возвращается идентификатор сборки aba82dd158b997b09903d4165f3dbfd37f5e5c1 .
Bob@BOB6:/mnt/c/Users/Bob$ readelf -n DisplayGreeting
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000020 NT_GNU_PROPERTY_TYPE_0
Properties: x86 feature: IBT, SHSTK
x86 ISA needed: x86-64-baseline
Displaying notes found in: .note.gnu.build-id
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: aba822dd158b997b09903d4165f3dbfd37f5e5c1
Displaying notes found in: .note.ABI-tag
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 3.2.0
Readelf можно использовать с grep для возврата версии символа.
readelf --debug-dump=info DisplayGreeting | grep -A 2 'Compilation Unit @'
Compilation Unit @ offset 0x0:
Length: 0x285c (32-bit)
Version: 5
карликовая думп
Команда linux для карликовой платформы печатает или проверка разделы DWARF по запросу определенных параметров. Используйте dwarfdump -h для просмотра множества вариантов.
bob@BOB6:/mnt/c/Users/BOB$ dwarfdump -h
Дополнительные сведения об использовании карликовойdump в Ubuntu см. в статье о карликовойdump .
!diesym
Эта команда отладчика отобразит поддерев DIE (или DIE) для любого символа в заданном выражении (может быть адресом, именем функции и т. д.) с необязательным заданным уровнем рекурсии. Он находит die для символа (обычно функция, но может быть данными и т. д.), содержащимся в заданном адресе, и выполняет диагностический дамп DIE, аналогичный запуску карликовой или llvm-карликовойdump на символах и поиске DIE.
!diesym [options] <expression>
-r#
: рекурсивно дампа N уровней. Как правило, это один, и только сам DIE сбрасывается.
<expression>
— адрес, на который нужно найти DIE, присваивается выражением. Это может быть неструктурированный шестнадцатеричный адрес (0x<blah>
) или это может быть другое уникальное имя функции.
Она должна оцениваться с помощью стандартной оценки модели данных. Используйте команду dx для проверки того, что выражение модели. Дополнительные сведения об использовании команды dx см. в разделе dx (Выражение объектной модели отладчика отладчика).
0:000> dx DisplayGreeting!GetCppConGreeting
DisplayGreeting!GetCppConGreeting : DisplayGreeting!GetCppConGreeting+0x0 [Type: GetCppConGreeting]
Отображение сведений о символах DIE для примера программы DisplayGreeting, функции GetCppConGreeting.
0:000> !diesym DisplayGreeting!GetCppConGreeting
0x2816: DW_TAG_subprogram [^^^]
DW_AT_external (true)
DW_AT_name 'GetCppConGreeting'
DW_AT_decl_file 1 ('/mnt/c/Users/BOB/DisplayGreeting.cpp')
DW_AT_decl_line 0x7
DW_AT_decl_column 0x6
DW_AT_linkage_name '_Z17GetCppConGreetingPwm'
DW_AT_low_pc 0x11E9
DW_AT_high_pc +0x3c (== 0x1225)
DW_AT_frame_base DW_OP_call_frame_cfa
DW_AT_call_all_tail_calls (true)
Используйте параметр -r2 для отображения дополнительных сведений о символах DIE.
0:000> !diesym -r2 DisplayGreeting!GetCppConGreeting
0x2816: DW_TAG_subprogram [^^^]
DW_AT_external (true)
DW_AT_name 'GetCppConGreeting'
DW_AT_decl_file 1 ('/mnt/c/Users/BOB/DisplayGreeting.cpp')
DW_AT_decl_line 0x7
DW_AT_decl_column 0x6
DW_AT_linkage_name '_Z17GetCppConGreetingPwm'
DW_AT_low_pc 0x11E9
DW_AT_high_pc +0x3c (== 0x1225)
DW_AT_frame_base DW_OP_call_frame_cfa
DW_AT_call_all_tail_calls (true)
0x2834: DW_TAG_formal_parameter [^^^]
DW_AT_name 'buffer'
DW_AT_decl_file 1 ('/mnt/c/Users/BOB/DisplayGreeting.cpp')
DW_AT_decl_line 0x7
DW_AT_decl_column 0x21
DW_AT_type (CU + 0x12f7 == 0x12f7)
DW_AT_location DW_OP_fbreg(-40)
!Умереть
!die
будет отображать поддерев DIE (или DIE) для того, что die находится в заданном выражении смещения в разделе отладки DWARF с необязательным заданным уровнем рекурсии.
!die [-r#] [-t] -m <module base expression> <offset expression>
-r#
: рекурсивно дампа N уровней.
-t
: если функция DIE находится в единице типа в .debug_types вместо единицы компиляции в .debug_info, необходимо указать параметр -t.
Укажите базовый -m <module base expression>
адрес любого модуля, о который вы запрашиваете.
Размер <offset expression>
смещения DIE.
В командной строке Linux используйте карликовую думпу с параметром -r, чтобы распечатать раздел .debug_aranges ФАЙЛА DWARF, чтобы найти смещение DIE.
bob@BOB6:/mnt/c/Users/BOB$ dwarfdump -r DisplayGreeting
.debug_aranges
COMPILE_UNIT<header overall offset = 0x00000000>:
< 0><0x0000000c> DW_TAG_compile_unit
DW_AT_producer GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection
DW_AT_language DW_LANG_C_plus_plus_14
DW_AT_name DisplayGreeting.cpp
DW_AT_comp_dir /mnt/c/Users/BOB
DW_AT_ranges 0x0000000c
Offset of rnglists entries: 0x0000000c
[ 0] start,end 0x000011e9 0x0000134a
[ 1] start,end 0x0000134a 0x00001368
[ 2] start,end 0x00001368 0x0000137b
[ 3] start,end 0x0000137b 0x0000138d
[ 4] end of list
DW_AT_low_pc 0x00000000
DW_AT_stmt_list 0x00000000
arange starts at 0x000011e9, length of 0x00000161, cu_die_offset = 0x0000000c
arange starts at 0x0000134a, length of 0x0000001e, cu_die_offset = 0x0000000c
arange starts at 0x00001368, length of 0x00000013, cu_die_offset = 0x0000000c
arange starts at 0x0000137b, length of 0x00000012, cu_die_offset = 0x0000000c
Обратите внимание на значение 0x0000000c
DW_AT_ranges . В отладчике используйте это значение смещения и имя модуля DisplayGreeting для отображения сведений о символах DIE.
0:000> !die -m DisplayGreeting 0x0000000c
0xc: DW_TAG_compile_unit [^^^]
DW_AT_producer 'GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection'
DW_AT_language 0x21
DW_AT_name
DW_AT_comp_dir
DW_AT_ranges
[0x11e9 - 0x134a)
[0x134a - 0x1368)
[0x1368 - 0x137b)
[0x137b - 0x138d)
DW_AT_low_pc 0x0
DW_AT_stmt_list
!dieancestry
Команда !dieancestry
ведет себя аналогично !die
тому, что она идет вверх по дереву DIE к содержащей компиляции или единице типа вместо дерева.
!dieancestry [-r#] [-t] -m <module base expression> <offset expression>
-r#
: рекурсивно дампа N уровней.
Укажите базовый -m <module base expression>
адрес любого модуля, о который вы запрашиваете.
Размер <offset expression>
смещения DIE.
Пример:
0:000> !dieancestry -m DisplayGreeting 0x0000000c
0xc: DW_TAG_compile_unit [^^^]
DW_AT_producer 'GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection'
DW_AT_language 0x21
DW_AT_name
DW_AT_comp_dir
DW_AT_ranges
[0x11e9 - 0x134a)
[0x134a - 0x1368)
[0x1368 - 0x137b)
[0x137b - 0x138d)
DW_AT_low_pc 0x0
DW_AT_stmt_list
Обратите внимание, что ссылки, например с родителями или братьями и сестрами, можно щелкнуть для дальнейшего обхода дерева символов DWARF.
0:000> !die -r2 -m 0x555555554000 0xc
0xc: DW_TAG_compile_unit [^^^]
DW_AT_producer 'GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection'
DW_AT_language 0x21
DW_AT_name
DW_AT_comp_dir
DW_AT_ranges
[0x11e9 - 0x134a)
[0x134a - 0x1368)
[0x1368 - 0x137b)
[0x137b - 0x138d)
DW_AT_low_pc 0x0
DW_AT_stmt_list
0x2a: DW_TAG_namespace [^^^]
DW_AT_name 'std'
DW_AT_decl_file 9 ('/usr/include/c++/11/bits/exception_ptr.h')
DW_AT_decl_line 0x116
DW_AT_decl_column 0xb
DW_AT_sibling (CU + 0xf01 == 0xf01)
0xf01: DW_TAG_base_type [^^^]
DW_AT_byte_size 0x1
DW_AT_encoding DW_ATE_boolean (2)
DW_AT_name 'bool'
0xf08: DW_TAG_base_type [^^^]
DW_AT_byte_size 0x8
DW_AT_encoding DW_ATE_unsigned (7)
DW_AT_name 'long unsigned int'
...
Не все выходные данные отображаются.
!dwunwind
!dwunwind
несколько похож на Fnent (отображаемые данные функции) для изображений PE. В нем отображаются правила очистки DWARF для адреса, заданного выражением. Он также похож на команду readelf --unwind, которая отображает сведения о очистке, когда он доступен.
!dwunwind <expression>
В этом примере отображаются правила очистки функции GetCppConGreeting в программе DisplayGreeting.
0:000> !dwunwind DisplayGreeting!GetCppConGreeting
DW_FRAME_SAME_VAL: 0('rax'), 1('rdx'), 2('rcx'), 3('rbx'), 4('rsi'), 5('rdi'), 6('rbp'), 7('rsp'), 8('r8'), 9('r9'), 10('r10'), 11('r11'), 12('r12'), 13('r13'), 14('r14'), 15('r15')
0('CFA'): DW_EXPR_OFFSET 7('rsp') + 8
16('<Return Address>'): DW_EXPR_OFFSET 12290('CFA') + -8
Откроется стек очистки для регистра указателя инструкции.
0:000> !dwunwind @rip
DW_FRAME_SAME_VAL: 0('rax'), 1('rdx'), 2('rcx'), 4('rsi'), 5('rdi'), 7('rsp'), 8('r8'), 9('r9'), 10('r10'), 11('r11'), 14('r14'), 15('r15')
0('CFA'): DW_EXPR_OFFSET 7('rsp') + 208
3('rbx'): DW_EXPR_OFFSET 12290('CFA') + -40
6('rbp'): DW_EXPR_OFFSET 12290('CFA') + -32
12('r12'): DW_EXPR_OFFSET 12290('CFA') + -24
13('r13'): DW_EXPR_OFFSET 12290('CFA') + -16
16('<Return Address>'): DW_EXPR_OFFSET 12290('CFA') + -8
Ниже приведен пример счетчика программ.
0:000> !dwunwind @pc
DW_FRAME_SAME_VAL: 0('x0'), 1('x1'), 2('x2'), 3('x3'), 4('x4'), 5('x5'), 6('x6'), 7('x7'), 8('x8'), 9('x9'), 10('x10'), 11('x11'), 12('x12'), 13('x13'), 14('x14'), 15('x15'), 16('x16'), 17('x17'), 18('x18'), 31('sp'), 32('pc')
0('CFA'): DW_EXPR_OFFSET 31('sp') + 208
19('x19'): DW_EXPR_OFFSET 1436('CFA') + -192
20('x20'): DW_EXPR_OFFSET 1436('CFA') + -184
21('x21'): DW_EXPR_OFFSET 1436('CFA') + -176
22('x22'): DW_EXPR_OFFSET 1436('CFA') + -168
23('x23'): DW_EXPR_OFFSET 1436('CFA') + -160
24('x24'): DW_EXPR_OFFSET 1436('CFA') + -152
25('x25'): DW_EXPR_OFFSET 1436('CFA') + -144
26('x26'): DW_EXPR_OFFSET 1436('CFA') + -136
27('x27'): DW_EXPR_OFFSET 1436('CFA') + -128
28('x28'): DW_EXPR_OFFSET 1436('CFA') + -120
29('fp'): DW_EXPR_OFFSET 1436('CFA') + -208
30('lr'): DW_EXPR_OFFSET 1436('CFA') + -200
!dietree
Дамп дерева DIE для данного модуля на заданном уровне рекурсии, аналогичному запуску карликовой или llvm-карликовойdump на символах и поиске DIE.
!dietree [OPTIONS] -m <module base> <offset expression>
-r#
: укажите уровень рекурсии
-t
: .debug_types дампа и не .debug_info
База модуля для модуля, содержащего DIE, должна быть предоставлена параметром -m <expression>
.
Размер <offset expression>
смещения DIE.
Пример:
0:000> !dietree -m DisplayGreeting 0x0000000c
0xc: DW_TAG_compile_unit [^^^]
DW_AT_producer 'GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection'
DW_AT_language 0x21
DW_AT_name
DW_AT_comp_dir
DW_AT_ranges
[0x11e9 - 0x134a)
[0x134a - 0x1368)
[0x1368 - 0x137b)
[0x137b - 0x138d)
DW_AT_low_pc 0x0
DW_AT_stmt_list
Используйте параметр -r2 для отображения дополнительных значений в диете.
0:000> !dietree -r2 -m DisplayGreeting 0x0000000c
0xc: DW_TAG_compile_unit [^^^]
DW_AT_producer 'GNU C++17 11.4.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables -fstack-protector-strong -fstack-clash-protection -fcf-protection'
DW_AT_language 0x21
DW_AT_name
DW_AT_comp_dir
DW_AT_ranges
[0x11e9 - 0x134a)
[0x134a - 0x1368)
[0x1368 - 0x137b)
[0x137b - 0x138d)
DW_AT_low_pc 0x0
DW_AT_stmt_list
0x2a: DW_TAG_namespace [^^^]
DW_AT_name 'std'
DW_AT_decl_file 9 ('/usr/include/c++/11/bits/exception_ptr.h')
DW_AT_decl_line 0x116
DW_AT_decl_column 0xb
DW_AT_sibling (CU + 0xf01 == 0xf01)
0xf01: DW_TAG_base_type [^^^]
DW_AT_byte_size 0x1
DW_AT_encoding DW_ATE_boolean (2)
DW_AT_name 'bool'
0xf08: DW_TAG_base_type [^^^]
DW_AT_byte_size 0x8
DW_AT_encoding DW_ATE_unsigned (7)
DW_AT_name 'long unsigned int'
0xf0f: DW_TAG_base_type [^^^]
DW_AT_byte_size 0x1
DW_AT_encoding DW_ATE_unsigned_char (8)
DW_AT_name 'unsigned char'
...
Не все выходные данные отображаются. Обратите внимание, что ссылки, например с братьями и сестрами, можно щелкнуть для дальнейшего обхода дерева символов DWARF.
!dielocal
Находит die для локальной переменной с именем "name" и выполняет диагностический дамп DIE, аналогичный запуску карликовой или llvm-карликовойdump на символах и поиске DIE.
!dielocal [options] <name>
-r#
: рекурсивно дампа N уровней. Как правило, это один, и только сам DIE сбрасывается.
<name>
: локальная переменная с именем name.
Пример:
0:000> !dielocal greeting
0x2806: DW_TAG_variable [^^^]
DW_AT_name 'greeting'
DW_AT_decl_file 1 ('/mnt/c/Users/BOB/DisplayGreeting.cpp')
DW_AT_decl_line 0xf
DW_AT_decl_column 0x1d
DW_AT_type (CU + 0xb18 == 0xb18)
DW_AT_location DW_OP_fbreg(-240)