Как вставить источник в pdb и использовать его отладчик?
ПРИМЕЧАНИЕ: моя целевая задача - это С#, предназначенный для CLR с обычным MSIL, если есть что-то, что работает для этого, но не в более общем случае.
Некоторые существующие примеры поддержки отладки источника
Недавно был выпущен проект Sourcepack, который позволяет пользователю переписывать исходные пути в файле pdb для указания в разных местах. Это очень полезно, когда у вас есть источник для сборки, но не хотите пытаться вставлять его в то же место файловой системы, что и при его создании.
http://lowleveldesign.wordpress.com/2011/08/26/sourcepack-released/
Для проектов с открытым исходным кодом, используя http://www.symbolsource.org/, чтобы упростить пользователям вашего проекта получение символов и источника отличная идея.
Проблема
Однако очень часто есть проекты, где либо по юридическим соображениям, либо по соображениям удобства, использование такого подхода не представляется возможным. Кроме того, набор людей, которые могут отлаживать проект, может быть относительно небольшим или содержать.
По умолчанию pdb для проекта включает указатели на файлы на диске (IIRC), а затем индексирование источника может добавить возможность вставлять указатели в исходные местоположения (например, в систему управления версиями), с источником затем используйте указатели для фактического извлечения источника.
Цель
Похоже, что вещи могут быть проще (для некоторых построений, таких как debug и/или internal-only) просто поместить фактический источник в pdb (фактически просто разыменовывая указатель, написанный в настоящее время в PDB). Похоже, что вы можете пропустить всю часть исходного сервера (по крайней мере теоретически) и устранить несколько зависимостей от истории отладочного времени. Является ли сохранение источника сжатым или нет, в основном ортогональным, но первый проход, вероятно, не сделает этого, чтобы упростить реализацию существующих отладчиков.
Поскольку бинарная история PDB-соответствия уже очень хороша, включение источника в PDB будет даже лучше, чем указатель исходного сервера, поскольку указатель может прерываться со временем (система управления исходным кодом перемещается или изменяется на другую система или что-то еще), но фактический источник, сидящий в PDB, хорош "навсегда".
Как это отличается от "исходного сервера"?
(это было добавлено посредством редактирования после комментария Тиграна, спрашивающего, какие преимущества будут)
Сценарий "базовой линии", к которому это следует сравнивать, относится к "нормальному" опыту отладки с использованием "нормального" экземпляра исходного сервера сегодня. В этом сценарии (AFAIK) механизм отладки получает указатель из PDB (через альтернативный поток), затем использует зарегистрированный исходный сервер (ы), чтобы попытаться получить источник через этот указатель. Поскольку данная сборка обычно включает несколько исходных файлов, имеется либо один указатель, который содержит базовое местоположение, либо несколько PDU (или что-то еще), но это должно быть ортогонально этому обсуждению.
Для проекта, где желательно сохранить скрытый/недоступный источник (большинство продуктов Microsoft, например, Windows, Office, Visual Studio и т.д.), тогда наличие PDB содержит указатели FAR, превосходящие фактический источник (даже если он был зашифрован). Такие указатели бессмысленны без необходимого доступа к сети и разрешений, поэтому такой подход означает, что вы можете отправить PDB кому-либо на планете, не беспокоясь о том, что они могут получить доступ к вашему источнику (в худшем случае они получают представление о том, как ваш источник дерево устроено, я бы подумал).
Однако есть два больших набора проектов (и, в частности, строит), где этого "скрывать источник" не существует.
Первыми являются сборки, которые используются только людьми, имеющими доступ к источнику в любом случае. Сборка на вашей собственной машине, которая никогда не покинет эту машину, - отличный пример, так как злоумышленник должен будет читать файлы из вашей файловой системы в любом случае, чтобы получить источник, поэтому чтение из одного файла (.cs) по сравнению с другим (. pdb) - относительно небольшая разница в терминах сложности/вектора атаки. Точно так же создаются и выполняются в тестовой/промежуточной среде, где люди, которые обращаются к pdb на машине, равны или подмножество людей, которые могут нормально обращаться к источнику.
Второй (несколько явно) проект с открытым исходным кодом, где источник для проекта уже открыт для всех в любом случае, поэтому нет никакой пользы для скрытия источника от кого-либо.
Обратите внимание, что это можно было бы относительно легко расширить, включив источник в зашифрованную форму (так как мы уже говорим о необходимости хранить данные формата и кодирования), но добавленная сложность этого сделает такой сценарий вероятно, менее полезно, чем просто использовать "нормальный" исходный сервер.
Преимущества?
С учетом приведенных выше описаний список возможных преимуществ для этого включает (но не ограничивается ими) следующие, которые появляются в моей голове на данный момент:
- Не нужно иметь дело с настройкой поддержки исходного сервера. Это Just Works (IJW), по крайней мере, когда/если отладчики знали, что нужно посмотреть в pdb.
- В то же время вы все равно можете использовать "фиксированный" исходный сервер, который был всего лишь манекеном, который извлек исходный код и передал его вызывающему. Такая конфигурация может быть одинаковой для всех (например, с помощью localhost), все еще устраняя текущую потребность в фактической настройке исходного сервера.
- Не нужно, чтобы сборка включала "индексацию источника",
- Так как сборка читает исходные файлы и записывает файлы pdb в любом случае, мы просто модифицируем то, что написано в pdb, и не принимаем никаких попыток создания времени для выполнения сетевых вызовов или чтения данных, которых мы еще не имеем в память.
- До тех пор, пока не будет встроена поддержка build для размещения источника, это может быть простой шаг после сборки, вероятно, реализованный сначала через небольшую вилку проекта Sourcepack, поскольку он
уже выполняет работу по чтению/изменению файлов PDB:)
- Нет зависимости от команды/проекта, имеющей систему управления версиями.
- Никакая зависимость от конкретной версии каждого файла, проверяемого в исходной системе управления (большинство людей не проверяют для каждой отдельной сборки, которую они делают в своей среде IDE).
- Не нужно иметь доступ к конкретной системе управления версиями, у которой есть файл
- в случае DVCS, например, указатель PDB может быть для некоторого "случайного" экземпляра git или меркуриального или что-то еще, не обязательно у вас есть доступ к
- инструментальное средство исходного сервера для отслеживания этой версии обратно к экземпляру сервера исходного управления, к которому у вас есть доступ (если он существует) еще не существует AFAIK)
- Нет проблем, если проект умирает (удаляется) или перемещается
- например, если проект перемещается из одного в другое из: self-hosting, sourceforge, github, bitbucket, codeplex, code.google.com и т.д.
- Нет проблем, если машина, от которой вы отлаживаете, не имеет (или недостаточно) доступа к сети
- Например, если вы делаете "сетевой KVM" в поле для отладки проблемы, но у нее нет сети или она может разговаривать только с отключенными сетями, чтобы она не могла получить доступ к серверу управления версиями).
- в крайнем случае, возможность восстановить часть источника проекта из сборки.;)
ПРИМЕЧАНИЕ: другой подход включал бы источник в фактическую сборку (например, в качестве ресурса), но pdb - лучший выбор (легко отправить сборку без pdb, никакого нормального исполнения не удастся, если источник в pdb, поскольку сборка - это тот же самый код и тот же размер и т.д.)
Как реализовать?
Поверхность этого вида поддержки не кажется слишком сложной для добавления, но я чувствую это потому, что я действительно не знаю достаточно о механизме, а не о том, что на самом деле это простая вещь для реализации.:)
Мое предположение было бы следующим:
- Добавьте шаг post-build, который сделает что-то похожее на Sourcepack, но вместо изменения указателя он заменит его на фактический источник.
- В зависимости от того, что должен делать исходный сервер, возможно, потребуется получить префикс, или фактический источник будет находиться в другом альтернативном потоке данных, а "указатель" будет обновлен до "source-in-pdb: ads- foo.cs 'или что угодно. префикс или указатель может включать в себя также то, как был сохранен исходный файл (несжатый, gzip, bzip2 и т.д. вместе с кодировкой файла).
- Реализовать "исходный сервер", который фактически извлекает источник из рассматриваемого pdb и возвращает его обратно.
- Не знаю, имеет ли исходный сервер API доступ к информации о местоположении PDB, не говоря уже о том, будет ли у него разрешение на фактическое чтение содержимого.
Проверка работоспособности?
С болтовней сверху, вопросы на самом деле:
- Разве такое уже существует? (и если да, укажите указатели!)
- Предполагая, что он еще не существует, делает ли это вышеозначение как реализацию первого прохода? Есть ли подводные камни или сложности, описанные выше, пропускаются?
- Предполагая "нет" и "да" для вышеизложенного, существует ли существующий проект, который имеет смысл с точки зрения принятия этого (он близок или в их существующей области)?
Ответы
Ответ 1
Я прочитал это и хотел подытожить свое понимание для ясности
Сегодня отладчик использует PDB для получения пути к файлу и контрольной суммы, которая была скомпилирована для создания данного раздела исполняемого файла. Затем отладчик пытается загрузить файл, используя как локальный диск, так и доступный сервер символов. В рамках этого предложения мы пропустим среднего человека, просто вставив сам файл в PDB. Эврика, больше не искать источник!
Как и кто-то, кто сделал свою справедливую долю копания для исходного кода таким образом, мне нравится идея иметь один пакет для всех ваших потребностей отладки. Тем не менее, есть несколько аспектов, чтобы рассмотреть это предложение.
Первое - это фактическое внедрение исходного кода в PDB. Это очень удобно. PDB - это, по сути, легкая файловая база данных. Существует структура, которую он кодирует, но AFAIK вы можете поместить все, что хотите, в определенные слоты (например, локальные значения переменных/типы). В некоторых слотах могут быть ограничения по размеру, но я уверен, что вы можете придумать схему кодирования, чтобы разбить большие файлы на куски.
Второй аспект заключается в том, что отладчик фактически загружает файл из PDB и ищет его на диске. Я не так хорошо знаком с этой частью отладчика, но из того, что, как я понимаю, использует только 2 части информации для поиска файла
- Путь к файлу на диске
- Контрольная сумма указанного файла (используется для устранения неоднозначности файлов с тем же именем)
Я уверен, что это единственная информация, которую он передает на сервер символов. Это делает невозможным внедрение сервера символов, потому что у него не будет доступа к PDB (при условии, конечно, что я прав).
Я рылся в надежде, что есть компонент VS COM, который вы можете переопределить, что позволит вам перехватить загрузку файла для заданного пути, но я не смог его найти.
Один подход, который я думаю, был бы осуществим, хотя будет
- Вставить источник в PDB
- У вас есть инструмент, который может как извлечь источник в известное место, так и переписать PDB, чтобы указать на это место.
Это не совсем то, чего вы хотите.