04 February, 2009

Секреты IL инструментации и профайлерного API для .NET Framework

По роду своей деятельности я занимаюсь в том числе и инструментацией IL. Задача состоит в инжекции в оригинальный IL callback'ов: в начало каждого стейтмента (вынимается из PDB) и в каждую точку выхода из функции. С точками возврата есть две проблемы: префикс tail. и throw/rethrow.

Первый в реальных программах практически не встречается, но при встрече гарантирует автору инструментатора головную боль. По спецификации после префикса tail. должен следовать call/calli/callvirt, а после него обязательно ret. Все бы хорошо, но по спецификации на ret разрешен переход (и какой урод это придумал). Объясню более подробно - вы должны проинструментировать все точки выхода из программы, с одной стороны вы не имеете права вставлять свои команды между tail., call/calli/callvirt и ret, а с другой стороны вы должны вставить перед командой ret код, в случае перехода на этот самый ret. Выход один - править структуру метода...

Второй вариант коварнее. При кидании exception'а невозможно на основании только кода метода понять куда нас этот exception занесет. Мы можем остаться в том же самом методе - в обработчике exception, а можем вылететь из метода как пробка из бутылки на несколько функций наверх по стеку. К чему я все это говорю? А к тому - слава великому Аллаху, что как минимум одному сотруднику компании Microsoft пришла в голову мысль добавить немного жизненно нужных event'ов в профайлерное API. Особый интерес представляют: ExceptionUnwindFunctionEnter, ExceptionUnwindFunctionLeave и ExceptionCatcherEnter.

И еще, в свете вышесказанного, флаги COR_PRF_MONITOR_EXCEPTIONS, COR_PRF_MONITOR_ENTERLEAVE и COR_PRF_MONITOR_CODE_TRANSITIONS должны всегда устанавливаться вместе. Последний флаг - это вообще магия без него нет метаданных в памяти для mscorlib и нет 90% Enter/Leave/Tailcall или Enter2/Leave2/Tailcall2 для managed кода.

А напоследок граф переходов обработчика exception так сказать для полноты картины:


22 January, 2009

Непреодолимые приступы нежности к Microsoft

И снова .NET Compact Framewok! Читаем документацию для методов System.Type.InvokeMember. Из прочитанного видим, что эти методы поддерживаются .NET Compact Framewok (MSDN VS2008) - есть значек рядом с методом.

Используем в приложении, запускаем и ... получаем NotSupportedException. Берем .NET Reflector и с удивлением выясняем, что метод вообще не реализован! Другими словами работающей рефлексии в .NET Compact Framewok v3.5.7283 вообще нет!

P.S. После начинаем вчитываться в документацию и случайно видим такую строчку в одной из двух доступных реализаций сего метода: NotSupportedException - The .NET Compact Framework does not currently support this method. Лезем в MSDN в и-нете - а вот там уже все нормально.

27 December, 2008

Очень старый .NET VB compiler bug

Это эту неделю написал несколько классов на C++ для работы с телом .NET IL метода. Данный код жизненно необходим в новом dotTrace для line-by-line & coverage profiling. Прошло 1.5 года с того момента, когда я нашел несоответствие кода порождаемого .NET VB compiler спецификации Ecma-335, Partition II (Metadata Definition and Semantics), 25.4.5 (Method data section). После нескольких .NET Framework Service Pack и выхода VS2008 ничего не поменялось - эта bug живет и здравствует.

Суть проблемы в том, что поле DataSize для структур IMAGE_COR_ILMETHOD_SECT_FAT и IMAGE_COR_ILMETHOD_SECT_SMALL содержит длину секции БЕЗ УЧЕТА заголовка секции (4 байта). По спецификации значение должно быть 4+24*n или 4+12*n соответственно.

02 December, 2008

Особенности реализации стандартных API функций в WindowsMobile

MSDN for WindowsMobile 5.0

"... If the thread is making a kernel call, SuspendThread fails. An application might need to repeat the SuspendThread several times for it to succeed. ..."

21 November, 2008

В семье не без урода

.NET Compact Framework есть существо обделенное не только функциональностью, но и интеллектом. Целый день ковырял странный exception о том, что тип не загружен. Мало того, что не говорится какой именно тип не загружен, но и возникает он в станном месте, где по идее ничего криминального нет. Обидно еще то, что отладчик напрочь отказался коннектиться к приложению на симуляторе. Пришлось отлаживать итерационным методом: исправил, запустил, проверил, что сюда дошли и так по кругу...

Расковырял: оказалось, что любой exception в статическом конструкторе подменяется exception о незагрузке типа без указания что же блин произошло там внутри. Простенько и со вкусом. Дальше больше: код ассембли был скомпилирован для .NET Framework v1.0, а запускался он на .NET Compact Framework v3.5. Так вот в коде были случайно использованы классы и методы (из System.dll) отсутствующие на .NET Compact Framework. Естественно при порытке обратиться к отсутствующему классу программу посылали, но как красиво: сборка System, Culture=null, Version= бла_бла_бла, Token=бла_бла_бла, ... НЕ НАЙДЕНА !!!

11 November, 2008

Мудёр

Вчера обнаружил очень приятную особенность компилятора С++ от VisualStudio 2008 для x86 - он автоматически удаляет блок try/catch если во всех вызовах функций между ними (в том числе и дочерних) не может возникнуть exception.

07 November, 2008

How much does Exception Handling cost, really?

Чувак (он же Kevin Frei) толково рассказывает про то как устроен SEH / C++EH мир для x86 и x64. Что, почем и какого дъявола происходит. Тем, кто еще не забыл С++ и еще может читать по слогам ассемблер посвящается...

Короче, установи PowerPoint и тыкай сюда.

06 November, 2008

Новое в Visual Studio 2010

Я за то чтобы языки программирования развивались в сторону упрощения конструкций, удобства использования, ну и естественно не в ущерб скорости. Особенно это касается С++. Давненько тут не было ничего принципиально нового. Так, по мелочи, что-то менялось и все, но в основном полировались старые и создавались новые библиотеки.

И вот наконец-то появилось что-то новенькое и вкусное для меня - С++ lambda. Все это конечно как бы есть в boost и stl, но кто этим пользовался меня поймет: пишется ну очень много никому не нужных букв для простецкого действия.

На всем этом жиждется еще одна новая фича - паралельные вычисления. Об этом складно и долго вещал чувак из MS на PDC2008. Есть две версии паралельных вычислений: для Managed и для С++ разарботчиков. В VS2010 интегрирована поддержка этого дела - сильно модифицированы отладчик и профайлер, ну и компилятор естественно.

От чего вдруг такая забота? На мой взгляд очень просто - 2 или 4 ядра у проца сейчас норма. А в большинстве случаев программа в один момент времени занимает только один процессор. Программерам просто влом писать параллельный код - работы много и шеф не погладит по головке за убитое время, а результат простому глазу особенно не виден. А тут на тебе 1 функция и дело в шляпе. Быстро удобно и думать почти не нужно. Это то о чем так мечтали большевики... Правда не понятно с накладными расходами на это дело. Вот разгребу накопившиеся дела, поставлю VS2010 и попробую...