Welcome to TechNet Blogs Sign in | Join | Help

Разрядность .NET сборок.

Вскоре после написания поста про определение разрядности исполняемых файлов выяснилось, что в мире .NET «всё совсем по-другому».

Для начала небольшое лирическое отступление. Компилятор Visual C++ использует ключ /clr для указания разрешенных типов кода в .NET сборке:

  • /clr - позволяет смешивать управляемый и неуправляемый код;
  • /clr:pure – указывает, что сборка будет содержать только управляемый код;
  • /clr:safe – идет ещё дальше, чем /clr:pure, разрешая только проверяемый код.

С точки зрения разрядности получаемых модулей тут важно то, что управляемый код по определению может выполняться на любой платформе (x86, amd64 и ia64), в то время как неуправляемый код предназначен для конкретного процессора. Т.е. можно бы было ожидать, что модули, собранные с /clr:pure или /clr:safe, можно использовать на любой платформе. На самом деле это не совсем так, о чём я и расскажу ниже.

Далее. Модули, содержащие управляемый код, можно отличить от «нормальных» модулей по непустой «COM Descriptor Directory». Команда “link /dump /headers” показывает её в конце списка директорий в «PE Optional Header»:

OPTIONAL HEADER VALUES
             10B magic # (PE32)
            8.00 linker version

            ...

               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
            87C4 [      64] RVA [size] of Import Directory
            A000 [     6A8] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
            B000 [     190] RVA [size] of Base Relocation Directory
            3100 [      1C] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Global Pointer Directory
               0 [       0] RVA [size] of Thread Storage Directory
            3188 [      40] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
            3000 [      A8] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
            311C [      48] RVA [size] of COM Descriptor Directory
               0 [       0] RVA [size] of Reserved Directory

Несмотря на название, эта директория не имеет отношения к COM. Насколько я понимаю, название осталось с тех времен, когда CLR еще только начинал разрабатываться. Содержимое этой директории, или, по крайней мере, часть её содержимого, можно посмотреть с помощью утилиты CorFlags.exe из .NET SDK.

> CorFlags.exe clr_rabbit.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 0
ILONLY    : 0
32BIT     : 0
Signed    : 0

Нас будут интересовать флаги ILONLY (только управляемый код) и 32BIT (32-х битный код), поскольку они непосредственно связаны с разрядностью сборки.

Я попробовал скомпилировать x86 и amd64 варианты стандартного “Hello World” для всех трёх значений флага /clr и посмотреть что получится. Получилась вот такая табличка:

Конфигурация PE заголовок Флаг ILONLY Флаг 32BIT Разрядность процесса в 32-х битной системе Разрядность процесса в 64-х битной системе
x86, /clr x86 0 0 32 32
x86, /clr:pure x86 1 1 32 32
x86, /clr:safe x86 1 0 32 64
amd64, /clr x64 0 0 - 64
amd64, /clr:pure x64 1 0 - 64
amd64, /clr:safe x86 1 0 32 64

Отсюда можно сделать вот такие выводы:

  • Флаг /clr жёстко привязывает полученный модуль к определённой платформе, так как такой модуль содержит неуправляемый код.
  • Не смотря на то, что модуль собранный с /clr:pure содержит только управляемый код, такой модуль привязан к определённой платформе не менее жестко чем предыдущий. 32-х битная система не сможет загрузить сборку "amd64, /clr:pure", а 64-х битная будет выполнять сборку "x86, /clr:pure" в Wow64. Насколько я понимаю, причина тут в том, что такой модуль может обращаться к неуправляемому коду из других модулей.
  • Только сборки, скомпилированные с /clr:safe по-настоящему переносимы. Интересно, что для них в PE заголовоке всегда будет указываться x86 в качестве целевой платформы.

Cross-posted from blog.not-a-kernel-guy.com.

Published Wednesday, December 19, 2007 7:25 AM by alexeypa

Comments

No Comments
New Comments to this post are disabled
 
Page view tracker