PInvoke methods using SetLastError get dropped on Windows x64 full AOT.
authorlateralusX <lateralusx.github@gmail.com>
Thu, 14 Jul 2016 18:40:58 +0000 (20:40 +0200)
committerlateralusX <lateralusx.github@gmail.com>
Thu, 14 Jul 2016 18:40:58 +0000 (20:40 +0200)
commite53f07efa2a11dc76e42e49bc927fcf27409bb92
tree5ff3348c0176bf8a053bf0f86eb8e67081aab15d
parent06c0592f9d6d606dfb87da1eefdfca716f879876
PInvoke methods using SetLastError get dropped on Windows x64 full AOT.

This happens because current implementation is doing a direct call to Win32
GetLastError in order to get the value before it get clobbered by the icall
setting the last error value in mono. When running AOT all constructs that tries
to call a method using a direct address will be dropped since that will not work
in full AOT. This results in incomplete compiled libraries causing runtime exceptions
in full AOT.

The fix on Windows x64 is to introduce a new OP code, GET_LAST_ERROR that will
retrieve the last error without clobbering it in the process. This is done by
emitting code reading the value directly from the TEB (thread environment block)
and will be lowered to just a move from the segment register holding the TEB data
structure on Windows x64. This is how GetLastError is doing this as well, but since
we won’t be able to call the method in a “safe” way in full AOT, using the segment
register directly will solve the issue. We use the segment register for accessing TLS,
so we already relying on the TEB structure.

NOTE, this will only be applied to Windows x64, full AOT for now.
mono/cil/cil-opcodes.xml
mono/cil/opcode.def
mono/metadata/marshal.c
mono/mini/cpu-amd64.md
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-ops.h