Выбор удаляемого открытого символа
PDBCopy предоставляет параметры -f и -F, чтобы можно было удалить произвольный набор открытых символов из файла символов с разделителями, оставив только те символы, к которым требуется доступ вашей аудитории для выполнения отладки.
PDBCopy часто используется для создания специальной версии файла символов для использования корпорацией Майкрософт в своей программе анализа сбоев в сети (OCA). OCA может назначить определенные функции как инертные. Это означает, что при обнаружении функции в трассировке стека она игнорируется. Функция обычно объявляется inert, если она является просто функцией-оболочкой или функцией "сквозной передачи", которая не выполняет значительных вычислений. Если такая функция обнаружена в стеке при анализе сбоев, можно предположить, что сама эта функция не была виновата и, в крайнем случае, она передала недопустимые или поврежденные данные, полученные от подпрограмм ранее в стеке. Игнорируя такие функции, OCA может лучше определить фактическую причину ошибки или повреждения.
Естественно, любая функция, которую вы хотите объявить inert, должна быть включена в таблицу открытых символов файла символов, используемого OCA. Однако это не единственные функции, которые необходимо включить, как показано в следующем примере.
Предположим, что вы создаете драйвер Windows и используете PDBCopy для удаления всех открытых символов из его файла символов, за исключением FunctionOne и FunctionSix, двух инертных функций. Вы ожидаете, что если functionOne или FunctionSix будут найдены в стеке после сбоя, они будут игнорироваться OCA. Если в стеке находится какая-либо другая часть драйвера, корпорация Майкрософт предоставит вам соответствующий адрес памяти, и вы можете использовать этот адрес для отладки драйвера.
Однако предположим, что драйвер занимает память в следующем макете:
Адрес | Содержимое памяти |
---|---|
0x1000 |
Базовый адрес модуля |
0x2000 |
Начало FunctionOne |
0x203F |
End of FunctionOne |
0x3000 |
Начало FunctionSix |
0x305F |
End of FunctionSix |
0x7FFF |
Конец модуля в памяти |
Если отладчик находит адрес в стеке, он выбирает символ со следующим нижним адресом. Так как таблица открытых символов содержит адрес каждого символа, но не содержит сведений о размере, отладчик не может узнать, попадает ли адрес в границы какого-либо конкретного символа.
Таким образом, если ошибка возникает на адресной 0x2031, отладчик, запущенный Microsoft OCA, правильно определяет ошибку как lyly in FunctionOne. Так как это функция inert, отладчик продолжает идти по стеку, чтобы найти причину сбоя.
Однако если ошибка возникает в 0x2052, отладчик по-прежнему сопоставляет этот адрес с FunctionOne, хотя он находится за пределами фактического конца этой функции (0x203F).
Следовательно, в файл с разделимыми символами необходимо включить не только функции, которые вы хотите предоставить, но и символы, которые следует сразу после этих функций. В этом примере необходимо предоставить functionOne, FunctionTwo, FunctionSix и FunctionSeven:
Адрес | Содержимое памяти |
---|---|
0x1000 |
Базовый адрес модуля |
0x2000 |
Начало FunctionOne |
0x203F |
End of FunctionOne |
0x2040 |
Начало функцииTwo |
0x3000 |
Начало FunctionSix |
0x305F |
End of FunctionSix |
0x3060 |
Начало ФункцииSeven |
0x7FFF |
Конец модуля в памяти |
Если включить все четыре из этих функций в файл с урезаными символами, то анализ Microsoft OCA не будет ошибочно рассматривать адрес 0x2052 как часть FunctionOne. В этом примере предполагается, что этот адрес является частью FunctionTwo, но это не важно, так как вы не зарегистрировали FunctionTwo с OCA в качестве инертной функции. Важно то, что адрес 0x2052 распознается как не попадающий в инертную функцию, поэтому OCA распознает это как значимую ошибку в вашем драйвере и может сообщить вам о ней.
Если вы не хотите обнародовать имена функций, следующих за каждой инертной функцией, можно вставить в код неважные функции, следующие за каждой инертной функцией, чтобы имена этих функций можно было включить в открытый файл символов. Убедитесь, что эти добавленные функции действительно соответствуют вашим инертным функциям в адресном пространстве двоичного файла, так как некоторые процедуры оптимизации могут изменить это или даже полностью удалить некоторые функции.