Trivial bit of IL does not work under Mono - mono

I have some .net code that generates an assembly then runs it. It has worked reliably under .net for some time. Under Mono the code works on some non-trivial instances but on others it dies with an illegal IL exception.
When attempting to isolate the problem I cut it down to the point where it just returns a native int. The example works fine under .net and dies under Mono. Reflector says the code is as follows, and this is as expected:
.method public hidebysig static native int Main() cil managed
{
.maxstack 8
L_0000: ldc.i8 4
L_0009: ret
}
The exception I get is: System.InvalidProgramException: Invalid IL code in HelloWorldType:Main (): IL_0009: ret
What am I doing wrong, please?

I would guess: An i8 is not considered the same type as a native int. If you want to return a native int, you'd need a conv.i in the middle. A native int is 8 bytes on a 64-bit platform but only 4 bytes on a 32-bit platform.

Related

CStringArray MFC serialization on 32bit and deserialization on 64 bit

I'm struggling a lot porting an MFC application from 32bit to 64bit.
I have same classes with CStringArray members and they use the CArchive serialization and all works fine in 32 bit app.
Now I split the same application into two parts, one in 32bit and the other in 64 bit and they need to share some serialized data; when I serialize a CStringArray member and try to deserialize it in the 64 bit app I get an CArchiveException, with cause=3 that should be "endOfFile".
It's not clear what's going on, I suspect that I can't serialize it a data in 32 bit and read it on 64 bit app due to the size. If I follow the GetSize() function of CStringArray, I see that the return is INT_PTR that is defined as follows:
This means there is no way to make a CStringArray serialization on 32bit and deserialization on 64 bit? Exist an workaround or something similar? There are other MFC data that I should check between 32 and 64 app?
EDIT: The problem is not related strictly on the CStringArray that (see the comments) is fine between 32/64.
I answer to my question for future readers. The problem was not related to the CStringArray but to other parts of code near it. The problem was that before CStringArray obj there is another member that was an CArray of a custom struct. This struct have a couple of members that use an override of the CArchive SerializeElements function to made a correct data serialization in 32 bit.
This serialize element was written in this way:
template<class TYPE> void AFXAPI SerializeElements (CArchive& ar, CRect* pElements, int nCount);
but the 64bit version does not use this override because the last parameter was int instead of INT_PTR and without using SerializeElements, I made a wrong serialization (less byte that needed, this is why I reach the endOfFile to soon while reading).
To fix it, just use the right declaration for the SerializeElements that is:
template<class TYPE> void AFXAPI SerializeElements (CArchive& ar, CRect* pElements, **INT_PTR** nCount);
Hope can help

GetHashCode - Generate hash code from 64-bit address

We've got a 32-bit C++/CLI assembly and one of the classes wraps a native object. It overrides GetHashCode to return the address of the native object it wraps (m_native is a pointer):
int NativeWrapper::GetHashCode()
{
return (int)m_native;
}
I'm now converting this assembly to support 64-bit, so the current GetHashCode implementation is no longer suitable. Are there any suitable algorithms to generate a hash code from a 64-bit address? Or am I missing an easier alternative?
I would use the same algorithm as the .Net framework does for generating the hash code of an Int64: the lower 32 bits XORed with the upper 32 bits.
int NativeWrapper::GetHashCode()
{
return ((int)m_native) ^ (int)(m_native >> 32);
}
Although, you could make a case for simple truncation: That's what IntPtr.GetHashCode does.
If you want to support a dual 32/64 compile, perhaps casting m_native to IntPtr and using its GetHashCode would be a good implementation that works in both 32 and 64 bit modes.

Casting System::IO::FileStream^ to FILE*

I am working on refactoring a large amount of code from an unmanaged C++ assembly into a C# assembly. There is currently a mixed-mode assembly going between the two with, of course, a mix of managed and unmanaged code. There is a function I am trying to call in the unmanaged C++ which relies on FILE*s (as defined in stdio.h). This function ties into a much larger process which cannot be refactored into the C# code yet, but which now needs to be called from the managed code.
I have searched but cannot find a definitive answer to what kind of underlying system pointer the System::IO::FileStream class uses. Is this just applied on top of a FILE*? Or is there some other way to convert a FileStream^ to a FILE*? I found FileStream::SafeFileHandle, on which I can call DangerousGetHandle().ToPointer() to get a native void*, but I'm just trying to be certain that if I cast this to FILE* that I'm doing the right thing...?
void Write(FILE *out)
{
Data->Write(out); // huge bulk of code, writing the data
}
virtual void __clrcall Write(System::IO::FileStream ^out)
{
// is this right??
FILE *pout = (FILE*)out->SafeFileHandle->DangerousGetHandle().ToPointer();
Write(pout);
}
You'll need _open_osfhandle followed by _fdopen.
Casting is not magic. Just because the input and types output are right for your situation doesn't mean the values are.

getprocaddress acting different from a dll and an exe

I'm trying get the address of GetProcAddress with GetProcAddress (yes. calling it on itself).
When I'm doing it from an empty exe project I get a valid address (between the allocated address of kernel32).
When I'm calling it from a dll, I'm getting invalid address (not in the range of the allocated kernel32)
What is the difference?
I'm running on windows 7 with 64 bit.
The project are compiled as 32 bit.
Here is the code that I'm running:
typedef FARPROC (WINAPI * GetProcAddressType)(HMODULE , LPCSTR );
HMODULE kernel32Hmodule = LoadLibraryW(L"c:\windows\system32\kernel32.dll");
GetProcAddressType abc = (GetProcAddressType)GetProcAddress(kernel32Hmodule, "GetProcAddress");
I also tried to get the address like this: void* a = GetProcAddress;
but it returns the same invalid address when running from a dll...
Please help.
Exe are normally loaded at their preferred addresses, DLL are often relocated (not loaded at their preferred addresses) when they opt for ASLR and when the relocation is needed (e.g. their preferred address is already taken). This could explain the delta you experienced between the behaviours.
ok i found the problem. when i loaded the dll with rundll32 it acted wierd... when i build a loader by myself (loadlibrary, than getprocaddress) it worked fine. rundll32 is the one caused the problems

Why isn't LocalBuilder.SetLocalSymInfo emitting variable names?

I tried running the sample code which appears on the documentation page for the System.Reflection.Emit.LocalBuilder class but it appears that the calls to LocalBuilder.SetLocalSymInfo(string, int, int) aren't doing anything since the IL Dissasembler shows this as the IL for SampleAssembly.dll:
.method public static string Function1(int32 A_0) cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init (string V_0,
int32 V_1)
IL_0000: ldarg.0
IL_0001: stloc.1
IL_0002: ldstr "string value"
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ret
} // end of method Example::Function1
Why aren't the variable names (myString and myInt) listed in the Dissasembler?
Enviroment Info:
Windows 7 64 bit
Visual Studio 2010 Professional SP1
.Net 4.0.30319 SP1
Target Framework: .Net 4 Client Profile
Debug configuration (for the program using System.Reflection.Emit)
Edit: As I noted in a comment, there is a SampleAssembly.pdb file being generated along with the SampleAssembly.dll file.
The debugging support in System.Reflection.Emit is pretty poor and quirky (and to a certain extent this is also true for IKVM.Reflection, because it inherits some of the brokenness from the underlying .pdb writer API that has to be used since the .pdb file format is not documented).
Anyway, the reason the sample doesn't work is that it is missing the following code:
ISymbolDocumentWriter doc = myModule.DefineDocument("sourcefile", Guid.Empty, Guid.Empty, Guid.Empty);
myMethodIL.MarkSequencePoint(doc, 1, 0, 1, 0);
There must be at least a single sequence point in the method, because that is the way the internal data structures are tied together.
Symbol names are stored in the PDB file and not in the assembly.
A tool like Reflector.NET will load the PDB file if present to give your disassembled code better names.
You can also verify this by debugging the code in a debugger with and without the PDB file.
I suspect this is because you are building the module as a release DLL.
Try passing true as the second parameter to AssemblyBuilder.DefineDynamicModule