Cross compiling for Cortex A9

Michael Jones mike at proclivis.com
Tue Jul 8 04:10:15 UTC 2014


I am having problems building a GHC cross compiler for Linux (Yocto on a Wandboard) running on a Cortex A9, and need some advice on how to debug it.

The cross compiler produces an executable that runs on the Target, but fails to print. So I need help coming up with a strategy to narrow down the root cause.

Some details:

The application:

main = do
    putStrLn "Haskell start"


The command line options work. The program runs, and I can step through assembly. Debug data is printed to the console. But putStrLn fails, and program enters an infinite loop.

I compile my app as follows:

arm-unknown-linux-gnueabi-ghc -debug -static Main.hs

Using -threaded does not fix the problem.

Let me compare debug data from a run on my HOST, with a run on my TARGET. First, a run from my HOST:

created capset 0 of type 2
created capset 1 of type 3
cap 0: initialised
assigned cap 0 to capset 0
assigned cap 0 to capset 1
cap 0: created thread 1
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (suspended while making a foreign call)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (finished)
cap 0: created thread 2
cap 0: running thread 2 (ThreadRunGHC)
cap 0: thread 2 stopped (finished)
cap 0: starting GC
cap 0: GC working
cap 0: GC idle
cap 0: GC done
cap 0: GC idle
cap 0: GC done
cap 0: GC idle
cap 0: GC done
cap 0: GC idle
cap 0: GC done
cap 0: all caps stopped for GC
cap 0: finished GC
removed cap 0 from capset 0
removed cap 0 from capset 1
cap 0: shutting down
deleted capset 0
deleted capset 1

And, it prints properly. So this is my referenced for what it should do on the TARGET.

When I run on my TARGET, I get:

created capset 0 of type 2
created capset 1 of type 3
cap 0: initialised
assigned cap 0 to capset 0
assigned cap 0 to capset 1
cap 0: created thread 1
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (heap overflow)
cap 0: starting GC
cap 0: GC working
cap 0: GC idle
cap 0: GC done
cap 0: GC idle
cap 0: GC done
cap 0: GC idle
cap 0: GC done
cap 0: all caps stopped for GC
cap 0: finished GC
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (yielding)
cap 0: running thread 1 (ThreadRunGHC)
cap 0: thread 1 stopped (stack overflow)
...

And the debug data goes on forever, just as debugging assembly demonstrated an infinite loop.

Clearly, the following does not occur:

cap 0: thread 1 stopped (suspended while making a foreign call)

And there are overflows.

If I had to guess, it is possible that some code is in a loop retrying to foreign call, and failing. Certainly, it is in some kind of a loop, because I found a place I can put a break point and and telling GDB to continue will cause the break over and over at the same place. So somewhere there is a loop.

I can step through the application with GDB and see names of files and offsets in assembly. But without a true source code debug, that is a bit rough, especially for someone that does not know the RTS code. If there was a way to compile such that C source code was available and a place to break, that would help. However, I suspect since it never makes a foreign call, there is no place in C to place the breakpoint anyway. So I am also assuming there is no direct way to debug with GDB.

But, I can see debug output printed to the console. My hope is there is a way to enable more printing, or a place I can add more print functions to help find the problem.

So I think I need one of the following:

- A solution from someone that has seen this before, perhaps on the iPhone
- How to enable more debug logging
- Where in the source code to add debug statements to narrow down the problem

Thanks for any help you can give.

Mike




More information about the Glasgow-haskell-users mailing list