2013-12-24 4 views
4

У меня есть следующий атрибут SecurityPermission(SecurityAction.Assert) по методу в моем классе. Я компилирую его (отладочную сборку) и просматриваю вывод в файле ildasm.exe, просматривая сырые кучи и глядя на кучу blob, содержащую blob PermissionSet. То, что я ожидал (на ECMA-335) составляет:Как компилятор Visual Studio компилирует атрибуты безопасности в CIL?

2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur< 
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.< 
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi< 
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc< 
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2< 
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=< 
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK< 
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56< 
31 39 33 34 65 30 38 39 00 00 

Но то, что я видел, было это:

2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur< 
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.< 
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi< 
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc< 
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2< 
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=< 
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK< 
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56< 
31 39 33 34 65 30 38 39 01 00 

В частности, обратите внимание на 01 00 в конце, где я ожидал 00 00. Спектр говорит, что после подсчитанной строки должно быть количество именованных аргументов. Поскольку я не проходя ни именованных аргументов я ожидал, что число будет 16-битным 0.

Это скомпилирован с .NET 2.0 с помощью Visual Studio 2013.

Чтобы усложнить ситуацию еще больше, если добавить в имени аргумента я получаю это:

2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur< 
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.< 
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi< 
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc< 
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2< 
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=< 
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK< 
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56< 
31 39 33 34 65 30 38 39 12 01 54 02 0d 55 6e 6d >1934e089 T Unm< 
61 6e 61 67 65 64 43 6f 64 65 01    >anagedCode  < 

Еще раз, смотрите в конце подсчитанных строк для атрибута, и вы можете увидеть 12 01 с последующим именованным списком аргументов (список из одного элемента). Я ожидал, что это будет 01 00, 16-разрядный маленький endian 1 для количества названных аргументов.

Исходя из этого, я предполагаю, что второй байт после подсчитанной строки является именованным числом параметров, но я до сих пор не понимаю, что такое первый байт (0x01 в первом примере, 0x12 в следующем).

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

Я задаю этот вопрос, потому что я пытаюсь создать blob-файл PermissionSet вручную (я пишу профилировщик CLR), и мне нужно знать, что положить в этот байт.

+0

Число, по-видимому, является количеством количества байтов в сигнатуре. Спецификация не упоминает об этом и фактически говорит, что там должно быть 16-битное количество атрибутов, а не длина (возможно, сжатая), за которой следует 1-байтовый счет. –

+1

Проверьте главу II.23.3 и обратите внимание на значение * Prolog *. Это int16 значение 1 так 0x01 0x00 в кучи блоба. Не пытайтесь самостоятельно анализировать необработанные метаданные, у вас есть как управляемые, так и неуправляемые интерфейсы, доступные для вас. –

+0

Я не смотрю на значение пролога, я смотрю на значение в позиции NumNamed, два байта после FixedArg на этой железнодорожной диаграмме. Кроме того, поскольку это атрибуты безопасности, а не пользовательские атрибуты, я не верю (и приведенный выше фрагмент байта согласен), что в них есть пролог. См. ECMA 335 §II.22.11: «Набор свойств, закодированных как именованные аргументы для пользовательского атрибута, будет (как в §II.23.3, начиная с NumNamed)». –

ответ

1

Я думаю, что вы правы в своем ужасе, я помню это из своего предыдущего опыта с указанными параметрами - NumNamed был реализован как сжатый int вместо int16, указанный в спецификации, и в отличие от примера, приведенного в §VI.B. 0,3. Я не знаю, изменилось ли это в последующих реализациях .NET 3.0+.

Для PermissionSet вы ищете,

... * Набор свойств, кодируются как названные аргументы обычая атрибут был бы (как в §II.23.3, начиная с NumNamed).

... §II.23.3 ...

Далее приводится описание необязательных «названных» полей и свойств. Это начинается с NumNamed - беззнакового int16, дающего число «названных» свойств или полей, которые следуют. ... В случае , где NumNamed отличен от нуля, за ним следуют повторы NumNamed из NamedArgs.

12 01 - это маленькое конечное целое число, указывающее количество свойств, которые следуют за ним. Одно именованное свойство и общая длина 18 (в десятичной, включительно).

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

NamesArgs:

... SerString - это кол-PackedLen байтов, а затем UTF8 символов

СОБСТВЕННОСТЬ является один байт 0x54. Поле FieldOrPropName - это имя поля , которое хранится как SerString (определено выше).

+0

Я пришел к тому же выводу, что это количество байтов, за которым следует один байт NumNamed. Является ли это известной ошибкой в ​​компиляторе VS или что-то, что я должен написать с ними? –

+0

Я не знаю об открытой ошибке, так что вы можете ее загрузить, но было бы лучше проверить, возникает ли эта проблема, если вы нацелились на более свежие версии .NET. – mockinterface

+1

Был поиск в Интернете, чтобы узнать, есть ли открытая ошибка, и наткнулся на этот камень в том, что кажется моно-реализацией, http://stuff.mit.edu/afs/athena/software/mono_v3.0/arch/ amd64_ubuntu1204/mono/external/ikvm/reflection/CustomAttributeData.cs // ... подсчет именованных аргументов является сжатым целым числом (вместо UInt16 как NumNamed в пользовательских атрибутах) Извинения, если вы уже знаете об этом бите , HTH. – mockinterface

Смежные вопросы