Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Windows RT on ARM native code calling convention?

I couldn't find any documentation on the Windows RT on ARM calling convention used by Visual Studio C++. Is Microsoft using ARM's AAPCS?

If Microsoft is using the AAPCS/EABI for Windows RT on ARM, is it also using ARM's C++ ABI (which is derived from the Itanium C++ ABI)? Maybe even the ARM exception handling ABI?

Does the calling convention used by Windows RT on ARM differ from that used by other (embedded) ARM Windows variants?

Is there a reliable way to detect Windows RT on ARM through predefined compiler macros?

Update: Added the question regarding the C++ ABI.

like image 537
Stephan Tolksdorf Avatar asked Dec 20 '22 06:12

Stephan Tolksdorf


2 Answers

Unlike Windows CE (which uses original APCS aka Old ABI), Windows RT on ARM uses EABI. More specifically, the variant which uses floating-point registers to pass floating-point data and 8-byte stack/argument alignment.

If I take the following function:

int g(float x) {
  return x;
}

and compile it with VS2012's ARM compiler, I get the following assembly:

|g| PROC
    vcvt.s32.f32 s0,s0
    vmov        r0,s0
    bx          lr
    ENDP  ; |g|

You can see that it's using S0 and not R0 for the argument.

The one from VS2008 (which can be used to target older Windows CE versions) produces this:

str     lr, [sp,#-4]!
ldr     r3, =__imp___stoi
ldr     r3, [r3]
mov     lr, pc
bx      r3
ldr     pc, [sp],#4

This code is calling a helper function to perform the conversion.

The Windows CE compiler shipped with Windows Compact 7 supports both the old calling convention (called "cdecl" by MS) and EABI. See What's New in Platform Builder 7.

EDIT: just now noticed you added a question about C++. Microsoft does not use Itanium-style C++ ABI, since their implementation predates it. You can read about Microsoft's implementation in my OpenRCE articles (1, 2) and the follow-up Recon presentation. See also the original description from the designer Jan Gray: PDF.

like image 146
Igor Skochinsky Avatar answered Dec 24 '22 02:12

Igor Skochinsky


I can only answer the 2nd question.

Does the calling convention used by Windows RT on ARM differ from that used by other (embedded) ARM Windows variants?

There are actually three concept that should be understood. One is the ARM Procedure Call Standard, another is the Language ABI and a third is the system call convention. Briefly, the ARM Procedure Call Standard describes register use in a prologue/epilogue. The Language ABI describe how language variables are passed. Ie, a double, a long long, the this pointer, dynamic_cast<>, etc. The first is needed to interface assembler with the compiler, the 2nd is needed for compiler interoperability. The 3rd is how OS calls are made.

ARM Procedure Call Standard

The apcs.txt document helps to understand some of the ARM variants. There are 16 variants based on four different choices.

  1. 32 bit vs 26 bit PC - all post 2000 version will use 32 bit.
  2. stack limit checking - possibly re-phrased as MMU or no MMU.
  3. floating point - supported on most CPU after approximately 2005.
  4. Re-entrant vs non-re-entrant - a pure software choice; shared libraries?

So while there are sixteen theoretical variations, for modern systems using an MMU there are only two. The Debian ARM hard float wiki gives information that some Linux/gcc distributions have under went. I would guess that Window RT is using hard float as they would not want to pay a performance price to support outdated hardware. Finally, it is hard to think that shared library or DLL support wouldn't be present in Window RT. So the ARM Procedure Call Standard seems to be identical to a Linux hard float ABI.

'C/C++' ABI

The AAPCS defines how languages are meant to map high level function/methods to low level details. Name mangling ensures that symbols has canonical names so that cross tool linking is possible. AAPCS tools should theoretically inter-operate, but issues may appear with support libraries and other system level interfaces.

OABI/EABI

The Embedded ARM wiki gives some information on this standard. An OS using an MMU will use some calls to transition from user mode to system mode. Generally, these are library only features and are not part of the compiler. However, you can certainly find some ARM systems that use the OABI convention. As Microsoft is late the ARM game, they will either use the EABI or invented something new. For instance, calling malloc() with a gcc linux hard-float compiler will not work as the system calls will be completely different. Generally you will have to compile with -nostdlib and invent your own C-library.

I have googled a little bit to find specifics on Visual C++.

  • MSDN on ARM Windows CE
  • SO ARM calling conventions
  • SO on Mingw ARM compilers

So to answer your 2nd question, there are a lot of compilers/systems that will generate similar prologue/epilogue. If the Visual C++ uses the AAPCS, then it can inter-operate with other AAPCS compilers. You may have to create custom libraries to get another compiler to call Windows RT system calls. The other questions should be answered in a manual.

Edit: GCC's ARM -mabi selects the ABI. aapcs-linux is AAPCS/EABI, apcs-gnu is the OABI defining prologue/epilogue and argument mappings. Compiler configuration select the target OS and instruction/back-end/CPU type; so we have compilers with different names, like arm-linux-eabi-gcc, arm-linux-gnueabi-gcc`, etc.

like image 33
artless noise Avatar answered Dec 24 '22 02:12

artless noise