Как вы можете изменить несоответствующий возраст PDB, чтобы соответствовать должным образом? - PullRequest
28 голосов
/ 13 апреля 2009

Наш ночной процесс сборки долгое время нарушался, так что он генерировал файлы PDB, возраст которых несколько часов отличался от соответствующих файлов изображений. С тех пор я исправил проблему.

Однако я хотел бы начать использовать сервер символов, но не могу из-за необходимости использовать эти несовпадающие по возрасту файлы pdb. Я обхожу эту проблему, используя метод .symopt + 0x40 в windbg. Это означает, что я должен организовать все мои файлы pdb вручную, и после нескольких лет выпусков это складывается.

Я ищу способ изменить механизм, который windbg использует для обозначения возраста pdb, и заставить его соответствовать файлу моего изображения. Утилита ChkMatch делает нечто подобное, но для подписей pdb. Разработчик заявляет на странице «ChkMatch способен сопоставить исполняемый файл и файл PDB, если они имеют разные подписи, но одного возраста (см. Эту статью для получения дополнительной информации о подписи и возрасте PDB). Если возраст отличается, инструмент не может сделать файлы совпадают. "

Я заглянул внутрь гекседитора и даже нашел то, что выглядело как биты, соответствующие возрасту, но он должен вытащить еще несколько уловок, потому что я не мог заставить его работать.

Есть идеи?

EDIT : Я не знаю, помогает ли это, но в моем конкретном случае разница в возрасте была вызвана ненужной перекомпоновкой DLL, которая также воссоздала бы файлы PDB. Тем не менее, наш процесс сборки сохранял исходные dll (до перекомпоновки) и pdb после перекомпоновки. Я думал о том, чтобы как-то воссоздать такую ​​ситуацию вручную. Это означает, что необходимо принудительно перекомпилировать DLL, но в обоих случаях экономить на pdb. Затем я мог сделать двоичное сравнение двух файлов, чтобы увидеть, как они изменились. Возможно, запустите какое-нибудь исправление программного обеспечения, которое делает это автоматически? Видя, что именно изменилось в моем контрольном случае, возможно, я мог бы сделать то же самое с библиотеками DLL и PDB, сохраненными в процессе сборки моей компании?

EDIT : Я ПОНЯЛ!!!! Благодаря одному из комментариев к первому ответу, я проверил ссылку на PDF-файлы книги «Недокументированные секреты Windows 2000: поваренная книга программистов». И автор подробно описывает формат файла pdb. Как я уже говорил, я уже загрузил pdb в шестнадцатеричный редактор и перевернул несколько кусочков, показав, что сопоставил возраст / подпись, но это не сработало. Ну, после использования утилиты из книги секретов W2k для «взрыва» pdb во включенные потоки, я обнаружил, что они скрывают другую ссылку на возраст в потоке 3 !!!!!!! Как только я щелкнул тот, он совпал в windbg. ЭТО ОГРОМНО !!!! Большое спасибо .... сервер символов ЗДЕСЬ Я ПРИХОДУ!

Ответы [ 3 ]

10 голосов
/ 14 апреля 2009

windbg не изменяет возраст pdb - он только ищет его, чтобы соответствовать возрасту исполняемого файла - компилятор делает, когда он (повторно) генерирует исполняемые и отладочные файлы.

Теперь, основываясь на статье debuginfo.com, не так уж сложно найти правильный каталог отладки (типа codeview), сопоставить его с сигнатурой PDB7 и внести изменения в age или GUID внутри исполняемого файла. почему это не вариант?

Полагаю, вместо этого вы хотите обновить pdb? Боюсь, pdb - проприетарный формат. Есть несколько API только для чтения (dbghelp.dll и dia sdk), но что касается изменений, вам нужно угадать детали, чтобы иметь возможность изменять.

8 голосов
/ 08 декабря 2011

Или вы можете просто воспользоваться предложением здесь, чтобы windbg игнорировал несовпадающие подписи и возраст:

http://www.debuginfo.com/articles/debuginfomatch.html

... Хотя по умолчанию он [windbg] также не позволяет загружать несоответствующую отладочную информацию, команда .symopt debugger может изменить поведение по умолчанию. После того, как мы выполнили команду «.symopt + 0x40», отладчик с радостью примет и загрузит несопоставленные файлы PDB и DBG.

Надеюсь, это поможет.

4 голосов
/ 03 сентября 2012

Хотя, как сказал SamB, в PDB (формат 7, мой тест основан на сгенерированных VS2010 .exe и .pdb и windbg 6.9.0003.113 X86) есть одна дополнительная ссылка на возраст, так что всего будет изменено 3 возраста в файле PDB. К сожалению, SamB не рассказал нам, как найти волшебный 3-й век, стрим 3? нет! согласно моему тесту, я извлекаю более 100 потоков в pdb, я пробовал 02 (если SamB индексирован по 0) и 03, оба не могут найти возраст.

Исправить 2 других возраста легко, как только у вас есть редактор гексабонов и windbg.

  • Найдите GUID и возраст

с помощью symchk для получения подписи (GUID) вашего несоответствующего файла PDB: symchk your.exe / v / s.

Обычно вывод будет содержать:

[SYMCHK] ------------------------------------
SymbolCheckVersion  0x00000002
Result              0x00010001
DbgFilename         CPP_Snippet.dbg
DbgTimeDateStamp    0x00000000
DbgSizeOfImage      0x00000000
DbgChecksum         0x00000000
PdbFilename         E:\zrf\C_CPP\CPP_Snippet.pdb
PdbSignature        {6D8D99B0-E96B-4093-9D97-8BDC5152B6E0}
PdbDbiAge           0x00000188
  • Исправить 2 более легких возраста

Поиск в последней части GUID: 8BDC5152B6E0, поскольку только последняя часть не имеет порядка следования байтов из проблемы с прямым порядком байтов / байтов с прямым порядком байтов, она точно такая же, как в файлах pdb. Будьте внимательны при поиске как необработанного шестнадцатеричного значения, чтобы сделать его более точным, вы должны убедиться, что другие значения в GUID (необходимо изменить порядок байтов в X86) точно совпадают. В файле PDB будет найдено ровно 2 идентификатора GUID, сопровождающий возраст перед первым байтом идентификатора GUID. Изменить это. Вот и все!

  • мой грубый способ узнать 3-й возраст.

    сбросить шестнадцатеричный номер вашего файла PDB, один байт (2 шестнадцатеричных числа) на строку. od -v -t x1 your.pdb | sed 's / ^ [0-9a-f] * //; s / / \ n / g'> age_offset.txt

    получить номер строки каждого соответствующего возраста, в моем случае это 4 последовательных строки, значение которых равно 88 01 00 00, vim age_offset.txt : g / 88 \ n01 \ n00 \ n00 / s / ^ / \ = (строка ('.'). ':') /

    Это команда ex mode, которая должна поддерживаться последней версией vim.

    : V /: / d

    Это удалит все строки, которые не содержат ':', оставшиеся строки являются номерами строк, которые смещение каждого соответствующего возраста.

    :% s /:.*//

    Это урежет: 88 и оставит смещение в покое.

    :% s /.*/\= (submatch (0) - 1) /

    Эта команда вычитает каждое число на 1, я делаю это потому, что номер строки в vim равен 1 индексу, а смещение байтов каждого возраста должно быть равно 0, чтобы сделать утилиту сотрудника счастливой.

    : ш

    сохранить файл

    Теперь мы получаем текстовый файл, каждая строка которого содержит десятичное число, представляющее смещение, из этого смещения следующие 4 байта являются кандидатами на возраст вашего сна.

    Далее я пытаюсь изменить каждый потенциальный возраст, а затем пытаюсь проверить его с помощью symchk, пока он не совпадет, каждый раз, когда будет исправлено только одно смещение.

    Прежде всего, я сделаю резервную копию PDB с двумя возрастами (и GUID), которые будут изменены. Давайте назовем это ori.pdb

    Вот пакетный скрипт для выполнения тяжелой работы:

for /F usebackq %%i in (`type age_offset.txt`) DO (
  copy /y ori.pdb CPP_Snippet.pdb
  @rem dd if=ori.pdb bs=1c count=4 skip=%%i | xxd -g1 | grep "88 01 00 00" || echo "Bad data at %%i" && goto exit
  dd if=pdb_age.dat of=CPP_Snippet.pdb bs=1c count=4 seek=%%i conv=notrunc
  symchk CPP_Snippet.exe /s . && echo "Found it at offset %%i" && goto exit
  )
:exit

Удачи, я нашел правильное место на 38-м смещении.

Это не самый быстрый способ исправить ошибку смещения патча, но он работает для меня, это мой прототип, чтобы убедиться, что нужно исправить только 1 дополнительный возраст, в противном случае возможная комбинация огромна ( 111 возраст кандидата, чтобы попытаться) и, таким образом, способ "попытка-ошибка" не прагматичен.

Я думаю, что очень легко написать утилиту, которая сделает ту же работу быстрее.

Кстати: согласно моему тесту. chkmatch может сообщать о совпадении, в то время как symchk и windbg считают, что оно не совпадает.

команда windbg! Совпадение itoldyouso, тогда как .reload / f your_module.exe по-прежнему не может совпадать.

После исправления трех возрастов pdb-файлы могут загружать не только windbg, но и visual studio.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...