разобрать проблему управляемого кода

Я использую Windbg для дизассемблирования управляемого кода (написанного на C #, консольное приложение) с помощью !Uкоманды Windbg из sos.dll. Я обнаружил, что при использовании !Uдля дизассемблирования управляемой функции в дизассемблированном коде IL содержатся только те вызовы функций, которые я сделал, а для остальных частей (например a=a*2, код вызова C # без вызова функции) и foreachциклы в C # отображается только код на родном языке ассемблера, это правильное ожидаемое поведение?

У меня вопрос, я хочу знать, способен ли! U разбирать бинарную DLL управляемого кода в IL со всем кодом (кроме кода вызова функции)?

Заранее спасибо Джордж

13.10.2009 04:42:47
2 ОТВЕТА

Я не думаю, что WinDbg работает на уровне IL. Возможно, вам придется использовать ildasmдля разборки IL.

1
13.10.2009 04:49:10
Я знаю, что ildasm или рефлектор могут это сделать. Но я отлаживаю во время выполнения или отладки в аварийном дампе, и мне нужна информация об адресе стека вызовов вместе с кодом IL (который ildasm или рефлектор не может предоставить). Если показан только собственный код сборки, его сложно отладить, и поэтому я хочу разобрать код IL с информацией об адресе стека вызовов. Есть комментарии или решения?
George2 13.10.2009 04:51:55

Если вы хотите сбросить IL во время отладки, вы можете использовать !dumpilкоманду из SOS. Он принимает указатель MethodDesc в качестве входных данных, поэтому вы должны сначала получить его.

Один из способов получить указатель MethodDesc - использовать !name2eeкоманду.

Так, например, если у вас есть метод Fooв типе Bar(в сборке ClassLibrary1), используйте !name2eeкак это

0:000> !name2ee ClassLibrary1!ClassLibrary1.Bar.Foo
Module: 001630bc (ClassLibrary1.dll)
Token: 0x06000001
MethodDesc: 00163450  <=== HERE
Name: ClassLibrary1.Bar.Foo()
JITTED Code Address: 007500f0

После этого, вы можете сделать, !dumpil 00163450чтобы сбросить IL для метода, Fooкак это

0:000> !dumpil 00163450
ilAddr = 73532050
IL_0000: ldstr "Foo"
IL_0005: call System.Console::WriteLine
9
13.10.2009 05:26:34
Я нахожу! Dumpil не может сбросить информацию об адресе? Например, если я обнаружу, что мой код дает сбой или разрывается по собственному адресу 0x11111111, я хочу посмотреть, какой код IL он выполняет? Может ли это сделать?
George2 13.10.2009 08:30:15
Вы должны помнить, что код IL на самом деле не работает. Он компилируется в собственный код, который затем запускается. Однако, если вы сделаете дамп процесса сбоя, у вас будет как JITTED-код, так и исходный IL-код, доступный как часть дампа. Используйте! U, чтобы показать CLR в курсе дизассемблирования сгенерированного кода. Используйте! Dumpil, чтобы показать IL. Из трассировки стека исключений и! Name2ee вы сможете найти JITTED и код IL по мере необходимости.
Brian Rasmussen 13.10.2009 08:58:37
Моя проблема заключается в том, что при использовании! U никогда не следует использовать IL-код для кода, не управляемого вызовом функции, для кода, не управляемого вызовом функции (например, a = a + 2 или цикл foreach), отображается только собственный код сборки. Это ожидаемое поведение?
George2 13.10.2009 09:03:47
! U разбирает JIT-скомпилированный код и, в отличие от его нативного аналога, поддерживает CLR, поэтому может сопоставлять некоторые внутренние вызовы вещам, которые имеют смысл для разработчика в управляемом мире. Тем не менее, это все еще разборка нативного кода. Конструкции высокого уровня, такие как foreach, выглядят очень по-разному при компиляции, потому что инструкции на языке высокого уровня, таком как C #, требуют много операций для реализации в машинном коде. Позвольте мне немного перевернуть это и спросить: чего вы пытаетесь достичь?
Brian Rasmussen 13.10.2009 10:10:52