corert icon indicating copy to clipboard operation
corert copied to clipboard

ARM32 crash at startup due to misalignment

Open Const-me opened this issue 6 years ago • 5 comments

Here’s output from gdb:

Thread 1 "MyApp" received signal SIGBUS, Bus error.
RhpLockCmpXchg64 () at /home/linaro/corert/src/Native/Runtime/arm/Interlocked.S:47
47                cmp          r6, r4
(gdb) bt
#0  RhpLockCmpXchg64 () at /home/linaro/corert/src/Native/Runtime/arm/Interlocked.S:47
#1  0x0049c5ee in S_P_CoreLib_System_IO_UnmanagedMemoryStream__get_PositionPointer ()

gdb probably has off by 1 bug, I think it’s the previous instruction which crashed the app.

The failing line of C# code is probably this https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/UnmanagedMemoryStream.cs#L329 but I’m not 100% sure, as there’s no debug information in the binary due to another CoreRT ARM32 bug.

I wasn’t able to make minimal repro, when I wrote a class with a long field, Interlocked.Read(ref long) returned the value without crashing. Probably clang optimizes away.

Any idea how to fix or workaround?

Const-me avatar Oct 17 '19 14:10 Const-me

This is a problem with the object layout or GC not respecting the required alignment. Does a program like this reproduce the crash?

using System;
using System.Threading;
using System.IO;

class My
{
    static unsafe void Main()
    {
        new Thread(() => { GC.Collect(); Thread.Sleep(1); }).Start();
        Random r = new Random();

        for (;;)
        {
            byte b;
            var s = new UnmanagedMemoryStream(&b, 1);
            GC.KeepAlive(new String('a', r.Next(100)));
            Console.WriteLine(s.Position);
        }
    }
}

If yes, the thing to check by looking at the disassembly are:

  • Does new UnmanagedMemoryStream call RhpNewFastAlign8 allocation helper?
  • Is the UnmanagedMemoryStream._position field offset aligned at 8 bytes?

jkotas avatar Oct 17 '19 15:10 jkotas

Yes, it prints 0, on the next line Bus error, then quits. When debugging, gdb says it’s same location, Interlocked.S:47.

I’m afraid I don’t know how to check the things that you’ve mentioned. I normally use debuggers to find out who called what or native layout details, but debug symbol writer appears to be broken on ARM32, so gdb is of limited help.

Const-me avatar Oct 17 '19 15:10 Const-me

Does it also crash immediately when you comment out the new Thread(() => { GC.Collect(); Thread.Sleep(1); }).Start(); line in the repro?

jkotas avatar Oct 17 '19 16:10 jkotas

ilc compiler crashed with segfault. Attaching a pic. segfault Fortunately, same dotnet publish command worked the second time. Yes, the output is identical, 0 then Bus error.

Const-me avatar Oct 17 '19 16:10 Const-me

The place to set a breakpoint is RhpNewFastAlign8 and step through it. This method is supposed to return aligned pointer, but it is not doing that for some reason. The bug is likely going to be somewhere in RhpGcAlloc that is called by this method.

jkotas avatar Oct 18 '19 00:10 jkotas