Создание отладки языка CLR / .NET - PullRequest
19 голосов
/ 05 декабря 2010

Какие есть ресурсы для отладки языка CLR / .NET? Я разрабатываю компилятор ActionScript 3 to IL, который использует DLR CallSites и CallSiteBinders для обработки динамических аспектов в других случаях статического языка программирования. Я ищу любую информацию о том, как сделать выдаваемую карту IL обратно в исходный код, и я также хотел бы знать, как я могу сделать так, чтобы сайты динамического вызова также отображались обратно.

Итак, в конечном итоге это два вопроса:

  • Как сделать отладочную версию IL ?
  • Как я могу сделать сайты вызовов DLR отлаживаемыми?

Любая помощь будет принята с благодарностью!

Что я ищу в терминах "debuggabilty"

В подключенном экземпляре Visual Studio:

  • Шаг через код
  • Просмотр местных жителей
  • Просмотр трассировки стека

1 Ответ

21 голосов
/ 08 декабря 2010

Чтобы сделать IL отлаживаемым, вам нужно скомпилировать код в отлаживаемую сборку. Есть также непосредственный недостаток в том, что сборка не будет коллекционироваться GC. Для этого вы делаете AppDomain.CurrentDomain.DefineDynamicAssembly, затем вызываете DefineDynamicModule и определяете модуль в сборке. Чтобы сделать его отлаживаемым, вам нужно установить некоторые атрибуты:

DebuggableAttribute.DebuggingModes attrs =
    DebuggableAttribute.DebuggingModes.Default |
    DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
    DebuggableAttribute.DebuggingModes.DisableOptimizations;

Type[] argTypes = new Type[] { typeof(DebuggableAttribute.DebuggingModes) };
Object[] argValues = new Object[] { attrs };

_myAssembly.SetCustomAttribute(new CustomAttributeBuilder(
   typeof(DebuggableAttribute).GetConstructor(argTypes), argValues)
);

_myModule.SetCustomAttribute(new CustomAttributeBuilder(
    typeof(DebuggableAttribute).GetConstructor(argTypes), argValues)
);

Наконец, при излучении IL, вы вызываете MarkSequencePoint, чтобы отметить строки для следующих инструкций IL.

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

Для компиляции метода необходимо использовать LambdaExpression<T>.CompileToMethod. MethodBuilder, который вам нужно будет предоставить, должен быть статическим методом, определенным в типе в отлаживаемой сборке, которую вы создали ранее.

Для предоставления этого делегата DLR у вас есть два варианта. Вероятно, проще всего было бы на самом деле вернуть выражение, которое вызывает скомпилированный отлаживаемый делегат (просто удерживая его через константу). Более сложным, но в некотором смысле более элегантным способом было бы переопределить BindDelegate<T> на сайте вызовов и вернуть скомпилированный делегат. Это начинается с создания соответствующего аргумента Expression s и вызова методов Bind* для создания дерева выражений самостоятельно.

Все это делается во внешнем слое DLR / IronPython / IronRuby - все доступно на ironpython.codeplex.com . Вы можете посмотреть на CompilerHelpers.CompileToMethod как пример выполнения компиляции, класс Snippets (и связанные классы AssemblyGen / TypeGen / ILGen для создания отлаживаемых сборок и даже компилятор дерева выражений DLR ( в Runtime\Microsoft.Scripting.Core\Compiler) для примера выдачи информации о строке.

...