Sunday, May 22, 2011

Bug Fixes in Android NDK Profiler

One of the biggest outstanding bugs in my Android NDK profiler library was that it would produce the gmon.out file but when you ran it through gprof you would see "no accumulate time" and the timing information was nowhere to be found. Now you can thank Justin Wick for debugging the root cause of the problem and providing a fix.

The library size I was using was too small to trigger the problem. It turned out that on larger libraries the calculation that inserted the addresses into the hystogram buckets had an overflow bug that caused the information to be lost. This was a left over from using the profiling code from Visual Boy Advance, since on the GBA the address space tends to be much smaller especially as it doesn't use random address layouts.

I tested this out using the Android port of FreeCiv, which prior to the change didn't show timing information, and with the change it now shows the times for each call. Once again, thanks to Justin for debugging the problem and figuring this out.

Using armeabi-v7a

The other problem you may have seen mentioned in the comments was with armeabi-v7a. In theory you can combine armeabi and armeabi-v7a together and things just work. Sadly I've had reports that doing this causes code compiled as armeabi-v7a to crash.

I finally got round to looking at what gcc spits out when you use the APP_ABI variable and set it to armeabi-v7a. There was a slight surprise in store for me that would explain the crashes. In a nutshell, when I said in my original post that I had to save all the registers in the profiling glue code, I had made an assumption that the link register (lr) did not have to be saved. With Thumb2 it looks like I do have to save that one as well, since gcc forgets that calling __gnu_mcount_nc (the profiling glue) is a function call that wrecks lr.

Look at this bit of C code:

int foo(int x)
{
        return x * 3;
}

When I compile it with -Os -mthumb --save-temps it gives the following:

foo:
        lsl     r3, r0, #1
        add     r0, r3, r0
        bx      lr

Now if I add in -pg to get the profiling calls I get this:

foo:
        push    {r4, lr}
        push    {lr}
        bl      __gnu_mcount_nc
        lsl     r3, r0, #1
        add     r0, r3, r0
        pop     {r4}
        pop     {r1}
        bx      r1

You can see it pushes lr twice - once for the use in the actual function, and a second time for __gnu_mcount_nc to do what it likes with it. Now if I compile for thumb2 using -march=armv7-a -mthumb I get this:

foo:
        @ link register save eliminated.
        push    {lr}
        bl      __gnu_mcount_nc
        movs    r3, #3
        mul     r0, r3, r0
        bx      lr

That comment is quite interesting. If you squint a bit it almost looks like a subtle compiler bug, since when you add profiling it should consider the call to __gnu_mcount_nc just like another function call and save lr. But as I haven't been able to test this on a real device yet, I'm not 100% sure that it's the only problem with using armeabi-v7a in combination with the profiling library. Plus once I saw what was going on I've been able to work around it anyway. If you get the chance to try this out, and are using armeabi-v7a let me know how the latest release works out for you.

Friday, May 20, 2011

Black screen of death on HTC Desire

It seems that my version of Elite [edit - no longer available] on Android is not behaving very well on the HTC Desire. The comments speak for themselves:
Black screen on start up, freezes phone, have to remove battery on HTC desire. I loved this game back in the day too.
by starbuck (May 20, 2011)
Don't download this app, this app has crashed my f*cking htc desire
by Marco (May 19, 2011)
I am giving it a 4 , but it has crashed a few times and clearer instructions would help. Desire hd
by Thomas (May 7, 2011)
Intro music played but black screen and phone locked. Had to remove battery. Desire
by Robert (May 6, 2011)
Black screen lock-up on starting. Had to remove battery to recover. Not good. Desire.
by Grampian (April 26, 2011)

If there are any HTC Desire owners who want to help fix this problem then please get in touch. I'm obviously doing something wrong, but the platform shouldn't crash to such an extent that you have to take the battery out! Especially when the game does run on some HTC Desires as well as on many other types of phone.

I don't know which is more frustrating: the crashes themselves or the attitude of the people leaving these drive-by 1 star reviews. Writing such a comment may make them feel better (hey! my free stuff doesn't work!) but in the long term it doesn't help anybody.

So if you have a Desire and are experiencing crashes, please, please try and send me a "logcat" of the crash so I can work out what's going on and fix it. There's an application in the Market called aLogcat that lets you capture the log and email it out. Check that no personal information is in there (there shouldn't be any) and send me the info if you can. Otherwise there is nothing I can do, short of blacklisting Desires.

On a happier note: A new version of Chaos is out that fixes all the bugs that were reported, except one. The Nintendo DS and GBA versions are based on this same code. Fixes on all platforms are:
  • Make sound fx volume more consistent
  • Fix dismount wizard bug
  • Speed up magic bolt
  • Add a message when Meditate's side effect kicks in (it freezes the wizard)
The one bug that I can't reproduce is (surprise) Android only, and seems like another "Android hates me" oddity:
  • black screen after pause/resume
I've made a change that may help, but who can tell. Interestingly, a lot of commercial games seem to just kill the activity when you move away from it instead of dealing with this issue.