Каков процесс создания простого двоичного файла с помощью инструментов MSVC?

#windows #visual-studio #arm64 #firmware #bare-metal

#Windows #visual-studio #arm64 #прошивка #простой

Вопрос:

Каков процесс создания простого двоичного файла с помощью инструментов MSVC?

В GNU land вы cc компилируете или as собираете исходные файлы в объектные файлы, ld связываете объектные файлы в ELF (с помощью скрипта компоновщика), а затем objcopy соответствующие разделы из ELF в качестве «двоичного файла прошивки». Я хочу сделать то же самое, но только с использованием инструментов, предоставленных MSVC.

Я тестировал со следующим ARM64 startup.s :

  AREA .text, CODE, READONLY
start
 LDR w1, =0xDEADBEEF
 B .
 END
 

Предполагается, что просто загружаются младшие 32 бита регистра X1 с помощью 0xDEADBEEF, а затем выполняется вращение. Чтобы собрать код, который я запускаю:

 armasm64.exe startup.s
 

Я предполагаю, что если бы у меня был peripherals.c исходный файл, мне нужно было бы связать startup.s и peripherals.c в один исполняемый файл (COFF?, PE?). Наконец, мне нужно было бы удалить любые заголовки COFF / PE, чтобы микроконтроллер ARM мог выполнять код при загрузке.

Комментарии:

1. Вы хотите иметь возможность разрабатывать / компилировать под Windows или вы действительно хотите использовать ассемблер / компоновщик Microsoft arm64? Пожалуйста, обратите внимание, что поддержка может быть гораздо менее доступной. Например, я пытался выяснить, где скачать armasm64.exe от того, чтобы попытаться ответить на ваш вопрос, но безрезультатно…

2. Я действительно хочу использовать набор инструментов MSVC. Я получил armasm64.exe из «MSVC v142 — VS 2019 C ARM64 build tools (v14.28)», найденного на экране установки отдельных компонентов VS2019. Я знаю, что Microsoft теперь поддерживает устройства ARM и IoT, поэтому я подумал, что, возможно, инструменты сборки Visual Studio теперь должны поддерживать простую разработку. Я потратил немало часов, пытаясь заставить набор инструментов MSVC имитировать то, что я знаю из своего опыта работы с GNU, но я начал думать, что, возможно, у разработчика Windows было бы лучшее мышление, чтобы знать, возможно ли это или нет.

3. @Франт … что касается «Пожалуйста, обратите внимание, что поддержка может быть гораздо менее доступной». … вот почему я склоняюсь к SO. 😉

4. нет проблем, просто хотел убедиться, каковы ваши требования.

5. Я думаю, что я пытался использовать инструменты Microsoft еще тогда, когда появилась первая поддержка arm, в то время это был тупик. В то время я тоже не знал так много. Это просто один из тех, кто поднимается на гору, потому что там есть наказания или есть реальная цель / ожидание? Вероятно, лучше подходит для форума Microsoft или напрямую с Microsoft.

Ответ №1:

Отказ от ответственности: я не в своей области знаний, и я предлагаю ответ, основанный на некоторых тестах, которые я провел с использованием инструментов MSVC, после прочтения некоторой документации Microsoft и через три дня после того, как был задан вопрос, ответы на который еще не были предложены. Я надеюсь, что этот ответ вызовет более обоснованные ответы, так что я могу с радостью отказаться от него.

Ответ на вопрос «Каков процесс создания простого двоичного файла с помощью инструментов MSVC?» вероятно: «Его нет».

aarch64-pe.asm :

  AREA .text, CODE, READONLY
 EXPORT start
start
 LDR w1, =0xDEADBEEF
 B .
 END
 

(Символ «start» должен быть общедоступным с помощью EXPORT директивы, чтобы его разрешал компоновщик).

Сборка:

 armasm64.exe aarch64-pe.asm
 

Теперь компоновщик для aarch64 (версия 14.28.29334.0), например, поддерживает только ограниченный список целевых подсистем:

 BOOT_APPLICATION,
CONSOLE,
WINDOWS,
NATIVE,
POSIX,
EFI_APPLICATION, EFI_BOOT_SERVICE_DRIVER, EFI_ROM, EFI_RUNTIME_DRIVER
 

Из документации Microsoft и EFI кажется, что для всех этих подсистем требуется загрузчик, способный понимать PECOFF формат или иметь возможность запускать BCD WMI Provider среду в случае BOOT_APPLICATION подсистемы.

Не существует такой вещи, как подсистема «BAREMETAL». При попытке связать aarch64-pe.obj для каждой из подсистем, но EFI_ROM используя 0x0000000040000000 в качестве базового адреса, компоновщик завершал работу, отображая ту же ошибку, жалуясь, что начальный адрес не может быть меньше 4 ГБ:

 D:optmsvcarm64>for %I in (BOOT_APPLICATION CONSOLE WINDOWS NATIVE POSIX EFI_APPLICATION EFI_BOOT_SERVICE_DRIVER EFI_ROM EFI_RUNTIME_DRIVER) do link /entry:start /BASE:0x0000000040000000 /subsystem:%I aarch64-pe.obj

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:BOOT_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:CONSOLE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:WINDOWS aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:NATIVE aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:POSIX aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_APPLICATION aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_BOOT_SERVICE_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_ROM aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : warning LNK4075: ignoring '/BASE' due to '/SUBSYSTEM:EFI_ROM' specification

D:optmsvcarm64>link /entry:start /BASE:0x0000000040000000 /subsystem:EFI_RUNTIME_DRIVER aarch64-pe.obj
Microsoft (R) Incremental Linker Version 14.28.29334.0
Copyright (C) Microsoft Corporation.  All rights reserved.

LINK : fatal error LNK1355: invalid base address 0x40000000; ARM64 image cannot have base address below 4GB
 

Вероятно, это проблема для простой встроенной системы, или для этого может потребоваться, чтобы MMU был доступен и уже настроен … простой программой, начиная с того, что MMU отключен с начального адреса менее 4 ГБ.

При запуске dumpbin.exe с aarch64-pe.efi базовый адрес, по-видимому, был установлен на 0000000180000000 , поскольку ldr инструкция была расположена по адресу 0x0000000180001000 , а тип файла был установлен на DLL .

 dumpbin.exe  /disasm aarch64-pe.efi
File Type: DLL

  0000000180001000: 18000041  ldr         w1,0000000180001008
  0000000180001004: 14000000  b           0000000180001004
  0000000180001008: DEADBEEF

  Summary

        1000 .rdata
        1000 .text
 

При выполнении dumpbin.exe с исполняемыми файлами, созданными компоновщиком с 0x0000000100000000 базовым адресом, тип файла был согласованным EXECUTABLE IMAGE .

Более того, похоже, dumpbin.exe не предлагает преобразование результирующего исполняемого файла в стандартный формат, такой как s-record или intel hex либо.

Поэтому я пришел к выводу, что одни только инструменты MSVC не позволяют создавать приложения aarch64 на основе простого металла на данный момент.

Комментарии:

1. Это потрясающая информация! Спасибо, что посмотрели все это. Я смотрю на docs.microsoft.com/en-us/cpp/build/reference/… в котором говорится: «когда параметр /DYNAMICBASE:NO был установлен, операционная система сначала пытается загрузить программу по указанному … адресу. Если там недостаточно места, система перемещает программу. Чтобы предотвратить перемещение, используйте параметр /FIXED . » Странно, что это не позволит вам просто переопределить базовый адрес.

2. Когда у меня будет немного времени сегодня вечером, я поиграю с переопределением базового адреса… у вас есть ссылка на то, где задокументировано ограничение в 4 ГБ? Я собираюсь сделать запрос функции сообществу разработчиков VS, если нет документированной причины не иметь этой возможности.

3. У меня нет ссылки, я просто получал сообщение об ARM64 image cannot have base address below 4GB ошибке каждый раз, когда я использовал базовый адрес меньше 4 ГБ. И согласно документации Microsoft , базовый адрес по умолчанию для 64-разрядного исполняемого файла равен 0x140000000 .

4. Поскольку the operating system first attempts to load a program at its specified or default base address. If sufficient space is not available there, the system relocates the program. To prevent relocation, use the /FIXED option. это, по-моему, подтверждает, что инструменты Microsoft не подходят для создания простых программ: это означает, что для загрузки исполняемых программ, которые они создают, требуется сложный загрузчик с поддержкой MMU. В случае, если вы согласитесь или получите подтверждение, я был бы признателен, если бы вы приняли мой ответ, поскольку это может пометить его как действительный для других людей.

5. Я начинаю соглашаться. Я смог использовать asmarm.exe (32-битный) ассемблер для установки базового адреса в 0x0 без ошибок. Интересно, что он по-прежнему всегда будет иметь смещение VA в 0x1000 (4 КБ) байт. Я предполагаю, что это жестко запрограммировано, чтобы разработчики не могли ссылаться на ноль без SEGFAULT. Я подозреваю, что это связано с тем, что существует предположение, что весь код, созданный с помощью ассемблера MSVC, будет выполняться в среде виртуальных адресов, управляемой MMU. Позор… Я действительно надеялся на этот волшебный флаг «разрешить мне доступ к физической памяти». Ну что ж. Спасибо за все ваши усилия!