From: David Y. <dav...@in...> - 2011-05-06 16:26:40
|
Hi, I developed a small method to fix prototypes at link time (thus, it is implemented in Mono.Cecil). Basically, it compares the signature of each function involved in a *direct* call with the signature of the corresponding function definition. If they differ (right now I only care about the return value), it updates the signature in the call statement. In addition, if the call signature was "not void" typed, while the actual function is "void" typed, the next instruction is checked. If this instruction is "pop", it is deleted (thus we avoid an incorrect stack error). As limitation, it doesn't apply to indirect calls (since we don't know the callee function). Since I don't have write access to the Mono.Cecil repository (and also we work on a version, why?), I just attach the patch. I'm still experiencing with it, but it worked properly in all my tests. Finally, just an example of the problem and the solution (introduced at link time): *** Source code file1.c --- void foo (char ** argv) { } --- file2.c --- int main (int argc, char ** argv) { foo (argv); -> guessed as 'int foo (char**)' } --- *** After cil32 file1.cil32 --- .method public static void 'foo' (int8 * * 'argv') cil managed { ... } --- file2.cil32 --- .method public static int32 'main' (int32 'argc', int8 * * 'argv') cil managed { ... call int32 [ExternalAssembly]ExternalAssembly::'no_prototype' (native int) pop ldc.i4 0 ... } --- *** After link (with our pass) .method public static default int32 main (int32 argc, int8** argv) cil managed { // Method begins at RVA 0x2084 // Code size 9 (0x9) .maxstack 8 IL_0000: ldarg.1 IL_0001: conv.i IL_0002: call void test::foo(int8**) //Fixed return value IL_0007: ldc.i4.0 //Pop removed, the stack is correct IL_0008: ret } // end of method test::main David |