Открытые и закрытые символы
Когда полноразмерный файл символов PDB или DBG создается компоновщиком, он содержит две различные коллекции данных: частные данные символов и общедоступную таблицу символов. Эти коллекции отличаются списком элементов, которые они содержат, и информацией, которую они хранят о каждом элементе.
Данные частных символов включают в себя следующие элементы:
Функции
Глобальные переменные
Локальные переменные
Сведения о определяемых пользователем структурах, классах и типах данных
Имя исходного файла и номер строки в этом файле, соответствующие каждой двоичной инструкции.
Таблица открытых символов содержит меньше элементов:
Функции (за исключением функций, объявленных статическими)
Глобальные переменные, указанные как extern (и любые другие глобальные переменные, видимые в нескольких объектных файлах)
Как правило, общедоступная таблица символов содержит именно те элементы, которые доступны из одного исходного файла в другой. Элементы, видимые только в одном объектном файле, такие как статические функции, переменные, которые являются глобальными только в пределах одного исходного файла и локальные переменные, не включаются в общедоступную таблицу символов.
Эти две коллекции данных также отличаются тем, какие сведения они включают для каждого элемента. Для каждого элемента, содержащегося в данных закрытых символов, обычно включаются следующие сведения:
Имя элемента
Адрес элемента в виртуальной памяти
Тип данных каждой переменной, структуры и функции
Типы и имена параметров для каждой функции
Область действия каждой локальной переменной
Символы, связанные с каждой строкой в каждом исходном файле
Записи пропуска указателя кадра (FPO) для каждой функции, используемой для доступа к стеку
С другой стороны, в таблице открытых символов хранятся только следующие сведения о каждом элементе, включенном в нее:
Имя элемента.
Адрес элемента в виртуальном пространстве памяти модуля. Для функции это адрес ее точки входа.
Пропуска указателя кадра (FPO) записываются для каждой функции.
Может включать префиксы и суффиксы символов, называемые украшениями.
Данные открытых символов можно рассматривать как подмножество частных данных символов двумя способами: они содержат более короткий список элементов и содержат меньше сведений о каждом элементе. Например, данные открытых символов вообще не включают локальные переменные.
Каждая локальная переменная включается только в частные символьные данные с ее адресом, типом данных и область. Функции, с другой стороны, включаются как в частные данные символов, так и в таблицу открытых символов, но в то время как частные данные символов включают имя функции, адрес, записи FPO, имена и типы входных параметров, а также тип выходных данных, таблица открытых символов содержит только имя функции, адрес и запись FPO.
Существует еще одно различие между данными закрытых символов и открытой таблицей символов. Имена многих элементов в открытой таблице символов имеют префикс, суффикс или и то, и другое. Эти украшения добавляются компилятором C, компилятором C++ и ассемблером MASM. Типичные префиксы включают ряд символов подчеркивания или строку __imp_ (обозначающую импортированную функцию). Типичные суффиксы включают один или несколько знаков ( @ ), за которым следуют адреса или другие идентифицирующие строки. Эти украшения используются компоновщиком для устранения неоднозначности символа, так как имена функций или глобальных переменных могут повторяться в разных модулях. Эти украшения являются исключением из общего правила, согласно которому общедоступная таблица символов является подмножеством данных частных символов.
Полные файлы символов и файлы символов с разделимы
Полный файл символов содержит как частные данные символов, так и общедоступную таблицу символов. Этот тип файла иногда называют частным файлом символов, но это имя вводит в заблуждение, так как такой файл содержит как частные, так и открытые символы.
Файл символов с разделителями — это файл меньшего размера, содержащий только общедоступную таблицу символов или, в некоторых случаях, только подмножество открытой таблицы символов. Этот файл иногда называют общедоступным файлом символов.
Создание полных и урезаемых файлов символов
При сборке двоичных файлов с помощью Visual Studio можно создавать полные или урезаемые файлы символов. Сведения о создании урезанных символов см. в разделе /PDBSTRIPPED (полосы закрытых символов).
С помощью инструмента BinPlace можно создать файл символов, урезаемый из полного файла символов. Если используются наиболее распространенные параметры BinPlace (-a -x -s -n), урезаные файлы символов помещаются в каталог, указанный после параметра -s , а полные файлы символов — в каталог, указанный после параметра -n . Когда BinPlace удаляет файл символов, урезаемая и полная версии файла получают одинаковые сигнатуры и другие идентифицирующие сведения. Это позволяет использовать для отладки обе версии. Дополнительные сведения о BinPlace см. в разделе BinPlace.
С помощью средства PDBCopy можно создать файл символов, очищенный от полного файла символов, удалив закрытые данные символов. PDBCopy также может удалить указанное подмножество таблицы открытых символов. Дополнительные сведения см. в разделе PDBCopy.
С помощью средства SymChk можно определить, содержит ли файл символов закрытые символы. Дополнительные сведения см. в разделе SymChk.
Просмотр открытых и закрытых символов в отладчике
Для просмотра символов можно использовать WinDbg, KD или CDB. Если один из этих отладчиков имеет доступ к полному файлу символов, он содержит как сведения, перечисленные в частных данных символов, так и сведения, перечисленные в открытой таблице символов. Данные открытого символа содержат украшения символов.
При доступе к закрытым символам данные закрытых символов всегда используются, так как эти символы не включаются в общедоступную таблицу символов. Эти символы никогда не украшаются.
Команду .symopt (Set Symbol Options) можно использовать для управления параметрами символов , которые определяют, как открытые и закрытые символы используются отладчиком. Например, эта команда включает символы для отладки информации.
.symopt+ 0x80000000
Следующие параметры изменяют способ использования открытых и закрытых символов в отладчике.
Если параметр SYMOPT_UNDNAME включен, украшения не включаются при отображении имени открытого символа. Кроме того, при поиске символов украшения игнорируются. Если этот параметр отключен, украшения отображаются при отображении общедоступных символов, а украшения используются при поиске. Частные символы никогда не украшаются ни при каких обстоятельствах. Этот параметр включен по умолчанию во всех отладчиках.
Если параметр SYMOPT_PUBLICS_ONLY включен, данные закрытых символов игнорируются, и используется только общедоступная таблица символов. Этот параметр отключен по умолчанию во всех отладчиках.
Если параметр SYMOPT_NO_PUBLICS включен, общедоступная таблица символов игнорируется, а поиск и сведения о символах используют только личные данные символов. Этот параметр отключен по умолчанию во всех отладчиках.
Если параметр SYMOPT_AUTO_PUBLICS включен (и SYMOPT_PUBLICS_ONLY и SYMOPT_NO_PUBLICS отключены), выполняется первый поиск символов в личных данных символов. Если нужный символ найден там, поиск завершается. В противном случае выполняется поиск в таблице открытых символов. Так как таблица открытых символов содержит подмножество символов в частных данных, обычно это приводит к тому, что таблица открытых символов игнорируется.
Если все параметры SYMOPT_PUBLICS_ONLY, SYMOPT_NO_PUBLICS и SYMOPT_AUTO_PUBLICS отключены, поиск в личных данных символов и в открытой таблице символов выполняется каждый раз, когда требуется символ. Однако при обнаружении совпадений в обоих местах используется совпадение в данных закрытых символов. Таким образом, поведение в этом экземпляре такое же, как при включенном SYMOPT_AUTO_PUBLICS, за исключением того, что использование SYMOPT_AUTO_PUBLICS может привести к тому, что поиск символов выполняется немного быстрее.
Ниже приведен пример, в котором команда x (Проверить символы) используется три раза. В первый раз используются параметры символов по умолчанию, поэтому сведения берутся из частных данных символов. Обратите внимание, что сюда входят сведения об адресе, размере и типе данных массива typeingString. Затем используется команда .symopt+ 4000, в результате чего отладчик игнорирует данные закрытых символов. При повторном выполнении команды x используется таблица открытых символов; на этот раз нет сведений о размере и типе данных для typeingString. Наконец, используется команда .symopt-2, которая приводит к тому, что отладчик включает украшения. При выполнении команды x в последний раз отображается декорированная версия имени функции , _typingString.
0:000> x /t /d *!*typingstring*
00434420 char [128] TimeTest!typingString = char [128] ""
0:000> .symopt+ 4000
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!typingString = <no type information>
0:000> .symopt- 2
0:000> x /t /d *!*typingstring*
00434420 <NoType> TimeTest!_typingString = <no type information>
Просмотр открытых и закрытых символов с помощью средства DBH
Другим способом просмотра символов является использование средства DBH . Отображение параметров справки с помощью /?
параметра .
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh /?
dbh dbghelp shell
usage: dbh [-n] [-c] [-d] [-?] [-??] [-p] [targetmodule] [command]
[-n] display noisy symbol spew
[-d] use decorated publics
[-p:XXXX] attaches to process ID XXXX
[-s:SSSS] set symbol path to SSSS
[-c] callbacks return false
[targetmodule] load symbols for specified module
[command] execute command and exit
[-?] display these usage instructions
[-??] display detailed usage instructions
Используйте средство, например Tlist, для вывода списка идентификаторов процессов и параметр -p для подключения к существующему процессу.
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh -p:4308
DBH использует те же параметры символов, что и отладчик. Как и отладчик, DBH по умолчанию отключает SYMOPT_PUBLICS_ONLY и SYMOPT_NO_PUBLICS , а по умолчанию включает SYMOPT_UNDNAME и SYMOPT_AUTO_PUBLICS . Эти значения по умолчанию можно переопределить с помощью параметра командной строки или команды DBH.
Ниже приведен пример, в котором команда DBH addr 414fe0 используется три раза. В первый раз используются параметры символов по умолчанию, поэтому информация берется из частных данных символов. Обратите внимание, что сюда входят сведения об адресе, размере и типе данных функций fget. Затем используется команда symopt +4000, которая приводит к тому, что DBH игнорирует частные данные символов. При повторном запуске надстройки 414fe0 используется общедоступная таблица символов; на этот раз отсутствуют сведения о размере и типе данных для функции fget. Наконец, используется команда symopt -2, которая приводит к тому, что DBH включает украшения. Когда надстройка 414fe0 запускается в этот последний раз, отображается декорированная версия имени функции , _fgets.
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 113
flags : 0
type : 7e
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagFunction (5)
index : 7d
pid:4308 mod:TimeTest[400000]: symopt +4000
Symbol Options: 0x10c13
Symbol Options: 0x14c13
pid:4308 mod:TimeTest[400000]: addr 414fe0
fgets
name : fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
pid:4308 mod:TimeTest[400000]: symopt -2
Symbol Options: 0x14c13
Symbol Options: 0x14c11
pid:4308 mod:TimeTest[400000]: addr 414fe0
_fgets
name : _fgets
addr : 414fe0
size : 0
flags : 0
type : 0
modbase : 400000
value : 0
reg : 0
scope : SymTagNull (0)
tag : SymTagPublicSymbol (a)
index : 7f
Дополнительные сведения
Дополнительные сведения о символах см. в разделах Синтаксис символов и Сопоставление символов, Параметры символов, Сокращения состояния символов и Отложенная загрузка символов.