[runtime] Parameters passed on the stack use at least 8 bytes on x86-64. Fixes #58367. (#2393)

* [runtime] Make debug spew compile.

* [tests] Add test case for bug #58367.

https://bugzilla.xamarin.com/show_bug.cgi?id=58367

* [runtime] Parameters passed on the stack use at least 8 bytes on x86-64. Fixes #58367.

https://bugzilla.xamarin.com/show_bug.cgi?id=58367
This commit is contained in:
Rolf Bjarne Kvinge 2017-08-02 08:26:29 +02:00 коммит произвёл GitHub
Родитель 336087ff59
Коммит f2d0a80699
6 изменённых файлов: 93 добавлений и 2 удалений

Просмотреть файл

@ -241,7 +241,7 @@ param_iter_next (enum IteratorAction action, void *context, const char *type, si
it->byte_count = (it->state->type & Tramp_Stret) == Tramp_Stret ? 24 : 16;
it->float_count = 0;
it->stack_next = (uint8_t *) (2 + (uint64_t *) it->state->rbp);
LOGZ("initialized parameter iterator to %p stret to %p\n", it->stack_next, it->stret);
LOGZ("initialized parameter iterator. byte count: %i stack next: %p\n", it->byte_count, it->stack_next);
return;
} else if (action == IteratorEnd) {
return;
@ -294,7 +294,12 @@ param_iter_next (enum IteratorAction action, void *context, const char *type, si
it->float_count++;
if (it->byte_count % 8 != 0)
it->byte_count += 8 - it->byte_count % 8;
// CHECK: do we need to round the stack pointer to?
// All arguments use at least 8 bytes, so round up.
uintptr_t stack_next = (uintptr_t) it->stack_next;
if ((stack_next % 8) != 0) {
stack_next += 8 - stack_next % 8;
it->stack_next = (uint8_t *) stack_next;
}
}
static void

Просмотреть файл

@ -203,6 +203,11 @@ namespace Bindings.Test {
[Export ("idAsIntPtr:")]
void IdAsIntPtr (IntPtr id);
[Export ("outNSErrorOnStack:i:i:i:i:i:err:")]
void OutNSErrorOnStack (int i1, int i2, int i3, int i4, int i5, int i6, out NSError error);
[Export ("outNSErrorOnStack:obj:obj:int64:i:err:")]
void OutNSErrorOnStack (NSObject i1, NSObject i2, NSObject i3, long i4, int i5, out NSError error);
}
[BaseType (typeof (NSObject))]

Просмотреть файл

@ -75,6 +75,12 @@ namespace MonoTouch.ObjCRuntime
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
public extern static void void_objc_msgSend_int (IntPtr receiver, IntPtr selector, int value);
[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public extern static void void_objc_msgSend_int_int_int_int_int_int_IntPtr (IntPtr receiver, IntPtr selector, int p1, int p2, int p3, int p4, int p5, int p6, IntPtr p7);
[DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")]
public extern static void void_objc_msgSend_IntPtr_IntPtr_IntPtr_long_int_IntPtr (IntPtr receiver, IntPtr selector, IntPtr p1, IntPtr p2, IntPtr p3, long p4, int p5, IntPtr p7);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
public extern static void void_objc_msgSend_long (IntPtr receiver, IntPtr selector, long value);

Просмотреть файл

@ -1736,6 +1736,68 @@ namespace MonoTouchFixtures.ObjCRuntime {
Assert.AreEqual (IntPtr.Zero, id, "Zero");
}
}
[Test]
public void OutNSErrorOnStack1 ()
{
using (var obj = new OutNSErrorOnStackClass ()) {
Messaging.void_objc_msgSend_int_int_int_int_int_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:i:i:i:i:i:err:"), 0, 0, 0, 0, 0, 0, IntPtr.Zero);
var ptr = Marshal.AllocHGlobal (IntPtr.Size);
Marshal.WriteIntPtr (ptr, IntPtr.Zero);
Console.WriteLine ("ptr: 0x{0} = 0x{1}", ptr.ToString ("x"), Marshal.ReadIntPtr (ptr));
Messaging.void_objc_msgSend_int_int_int_int_int_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:i:i:i:i:i:err:"), 0, 0, 0, 0, 0, 0, ptr);
Assert.AreEqual (IntPtr.Zero, Marshal.ReadIntPtr (ptr), "#1");
Marshal.FreeHGlobal (ptr);
ptr = IntPtr.Zero;
unsafe {
IntPtr* ptrFixed = &ptr;
Console.WriteLine ("ptr: 0x{0}", ptr.ToString ("x"));
Messaging.void_objc_msgSend_int_int_int_int_int_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:i:i:i:i:i:err:"), 0, 0, 0, 0, 0, 0, (IntPtr) ptrFixed);
Assert.AreEqual (IntPtr.Zero, ptr, "#2");
}
}
}
[Test]
public void OutNSErrorOnStack2 ()
{
using (var obj = new OutNSErrorOnStackClass ()) {
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_long_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:obj:obj:int64:i:err:"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, 2, IntPtr.Zero);
var ptr = Marshal.AllocHGlobal (IntPtr.Size);
Marshal.WriteIntPtr (ptr, IntPtr.Zero);
Console.WriteLine ("ptr: 0x{0} = 0x{1}", ptr.ToString ("x"), Marshal.ReadIntPtr (ptr));
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_long_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:obj:obj:int64:i:err:"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, 2, ptr);
Assert.AreEqual (IntPtr.Zero, Marshal.ReadIntPtr (ptr), "#1");
Marshal.FreeHGlobal (ptr);
ptr = IntPtr.Zero;
unsafe {
IntPtr* ptrFixed = &ptr;
Console.WriteLine ("ptr: 0x{0}", ptr.ToString ("x"));
Messaging.void_objc_msgSend_IntPtr_IntPtr_IntPtr_long_int_IntPtr (obj.Handle, Selector.GetHandle ("outNSErrorOnStack:obj:obj:int64:i:err:"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, 2, (IntPtr) ptrFixed);
Assert.AreEqual (IntPtr.Zero, ptr, "#2");
}
}
}
public class OutNSErrorOnStackClass : ObjCRegistrarTest
{
public override void OutNSErrorOnStack (int i1, int i2, int i3, int i4, int i5, int i6, out NSError error)
{
error = null;
}
public override void OutNSErrorOnStack (NSObject i1, NSObject i2, NSObject i3, long i4, int i5, out NSError error)
{
Assert.AreEqual (i4, 1, "#long");
Assert.AreEqual (i5, 2, "#int");
error = null;
}
}
#endif
#if !__TVOS__ && !__WATCHOS__ && !MONOMAC

Просмотреть файл

@ -85,6 +85,8 @@ typedef unsigned int (^RegistrarTestBlock) (unsigned int magic);
-(bool) testBlocks;
-(void) idAsIntPtr: (id)p1;
-(void) outNSErrorOnStack:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 err:(NSError **)err; // 6 in regs, 7th (out) in mem (on all architectures)
-(void) outNSErrorOnStack:(id)obj1 obj:(id)obj2 obj:(id)obj3 int64:(long long)l4 i:(int)i5 err:(NSError **)err; // 5 in regs, 6th (out) in mem (on at least x86-64)
@end
/*

Просмотреть файл

@ -199,6 +199,17 @@ static UltimateMachine *shared;
{
// Nothing to do here.
}
-(void) outNSErrorOnStack:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 err:(NSError **)err
{
// Nothing to do here
}
-(void) outNSErrorOnStack:(id)obj1 obj:(id)obj2 obj:(id)obj3 int64:(long long)l4 i:(int)i5 err:(NSError **)err
{
// Nothing to do here
}
@end
@implementation ObjCExceptionTest