Как можно изменить PDB несовпадающего возраста, чтобы она соответствовала должным образом?

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

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

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

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

Любые идеи?

РЕДАКТИРОВАТЬ: я не знаю, помогает ли это, но в моем конкретном случае разница в возрасте была вызвана ненужным повторным связыванием DLL, что также привело бы к воссозданию файлов PDB. Однако наш процесс сборки хранил исходные библиотеки DLL (до повторной ссылки) и pdb после повторной ссылки. Подумал как-нибудь вручную воссоздать такую ​​ситуацию. Это означает принудительное повторное связывание DLL, но сохранение pdb в обоих случаях. Затем я мог бы провести двоичное сравнение двух файлов, чтобы увидеть, как они изменились. Может быть, запустить какое-нибудь программное обеспечение для установки исправлений, которое сделает это автоматически? Увидев, что именно изменилось в моем контрольном случае, возможно, я смогу сделать то же самое с библиотеками DLL и PDB, сохраненными в процессе сборки моей компании?

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


person pj4533    schedule 13.04.2009    source источник


Ответы (4)


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

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

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

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

person Richard Myers    schedule 07.12.2011

Хотя, как сказал 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 / ^ / \ = (line ('. ').': ') /

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

    :v/:/d

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

    :%s/:.*//

    Это приведет к обрезке: 88 и оставлению смещения в покое.

    :% s /.*/\= (субматч (0) - 1) /

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

    :w

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

    Теперь у нас есть текстовый файл, в котором каждая строка содержит десятичное число, представляющее смещение, от этого смещения следующие 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 по-прежнему не может соответствовать.

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

person zhaorufei    schedule 03.09.2012
comment
Не знаю, работает ли это ... Мне нужно изменить возраст 2 на 1, и последовательность байтов 02000000 кажется гораздо более распространенной. 18845 возможных местоположений. :) Все еще жду завершения скрипта. - person Oskar Berggren; 21.01.2013
comment
У меня не работает (VS 2013 - набор инструментов v120). Я потратил 3 или 4 дня на создание инструмента, который вызывает ChkMatch.exe, затем CDB для получения возраста PDB, а затем перебирает даты так же, как и вы. Я заменил 1 на 1 все 9546 возможных возрастов в моем PDB (вызывая Symchk после каждого из них) и не нашел совпадений. - person Violet Giraffe; 23.04.2015

Используйте symopt команда для включения SYMOPT_LOAD_ANYTHING:

.symopt+ 0x40

Из документов:

Эта опция символа снижает придирчивость обработчика символов, когда он пытается сопоставить символы.

По умолчанию этот параметр отключен во всех отладчиках. Когда отладчик запущен, его можно включить или выключить с помощью .symopt+0x40 или .symopt-0x40 соответственно.

Эта опция по умолчанию отключена в DBH. Когда DBH запущен, его можно включить или выключить с помощью symopt +40 или symopt -40 соответственно.

Подробнее см. http://ntcoder.com/bab/2012/03/06/how-to-force-symbol-loading-in-windbg/

person Daoquan Ye    schedule 03.04.2021

person    schedule
comment
Правильно, поменять подпись несложно. Но возраст другой. Я четко заявляю, что хочу обновить pdb. Подобно тому, как работает chkmatch. - person pj4533; 14.04.2009
comment
хороший сайт! Сейчас я проверяю эту книгу ... возможно, она направит меня на верный путь. Я сообщу, когда / если я что-то выясню. - person pj4533; 14.04.2009
comment
ВЫ ПРАВИЛИ! Спасибо, что предложили этот сайт, я разобрался! - person pj4533; 14.04.2009
comment
Спустя более 6 лет Microsoft опубликовала спецификацию формата PDB: github.com/Microsoft/microsoft-pdb < / а>. - person codekaizen; 31.12.2015
comment
@ pj4533 Возможно ли сопоставить dll, созданную без отладочной информации, с pdb, созданным позже, и как? - person waterd; 06.03.2019