20091214

Android ARMv4T Donut Patch (revisited)

Several people have responded to my previous ARMv4T patch for the "Donut" branch of Android, and have provided excellent feedback.

I recently checked out the code again, and thought that it would be wise to do some rigorous testing of all native binaries on the Android filesystem.

Please find an updated (but still incomplete) patch for ARMv4T here.

I've thrown together a small script to disassemble and check binaries for invalid opcodes. You can find the output here.

The output shows which executables and shared libraries still have non-ARMv4T machine code, and currently only 103 of 160 components pass the test. Therefore, there is still quite a bit of work to be done. For the remaining 57 components that fail, the illegal (non-ARMv4T) opcodes are also revealed.

NB: Just in case you find diffs generated with 'repo diff' just as annoying as I do, you can use this utility to automate the patching process.

update-20091215: The build system is doing "ok", but its still not perfect. Independent of compile-time issues are, of course run-time issues. The most major issue is the subject of dynamic code generation and you can read some of my thoughts here. To address the issue, I will be working with the android-on-freerunner people. For any further discussion about this topic, I suggest you join the android-on-freerunner mailing list.

8 comments:

Christopher Friedt said...

I just thought that I would point out, there are likely a couple of easy fixes that will eliminate most of the failed opcodes.

1) ensure that the CFLAGS for each module contain "-march=armv4t". A check against TARGET_ARM_VERSION should be made in the respective Android.mk files.
2) using c preprocessor macros, ensure that generic C code is being called rather than inline ARMv5TE or ARMv6 asm.

The non-trivial solution in some cases may be to

3) re-write sections of assembler source (.S files) using the ARMv4T instruction set. This would also require accompanying checks against TARGET_ARM_VERSION in the Android.mk files, and likely also some C pre-processor magic.

ironox said...

Christopher:

i am really new to linux,arm,script....,so thanks for your patience:)

I run your script in my android donut source dir ,and get 100/160 files passed .
one thing I think I should let you know is I am using toolchain from http://gitorious.org/android-on-freerunner (koolu.org)
and they declare their android cupcake image could run on freerunner which have a cpu same as my board(armv4t),so i am really confused,why images from same toolchain not necessarily run on same cpu?

yesterday I also objdump -d two executable files:
app_process(zygote) and servicemanager

i get lots of "undefined instruction"
from both files, so why servicemanager run ,but zygote doesn't?

you suggest three fixes, these fixes all are diffcult to me,but i will keep to learn:)

Christopher Friedt said...

@ironix

Hi again,

There's no need to thank me - the fact that I'm doing something helpful is already enough ;-)

When doing 'objdump', it's very typical to encounter 'undefined instruction' entries. Don't worry - they usually refer to inline data sections as opposed to instructions. If you look at the script that I wrote, you should see that I've filtered all of the 'undefined' parts out completely.

Good luck!

Christopher Friedt said...

I've just updated my script. Now you can also call check-armv4t, and if there are any arguments, it will not look in the out/tar/get/product/generic/{system,root} directories, but rather check any arbitrary input file provided.

You still need to define ANDROID_HOME, but this is really only to use the given prebuilt arm-eabi-objdump that comes with the Android source.

Example:

check-armv4t $(find out/target/product/generic/obj/{EXECUTABLES,{SHARED,STATIC}_LIBRARIES} -type f -executable -or -name '*.o') | grep -v ": pass"

This can provide some more concise output, identifying exactly which module, and which compiled object (.o) contains non-armv4t code.

Christopher Friedt said...

It's probably wise to stop ignoring the elephant in the room.

Android has a fairly complex set of libraries dedicated to dynamic code generation. For example,

system/core/libpixelflinger/codeflinger/ARMAssembler.cpp

They have only implemented an interface for ARMv5TE and higher architectures. It might be the case that the "QemuTracing" code does not use ARMv5TE instructions, but I highly doubt it.

This is a bit of a mystery for me, and was the one thing that I have not yet addressed.

Therefore, I'm going to be working with the folks at android-on-freerunner to see a) what their general strategy was for dynamic code generation, and b) bringing ARMv4T patches up to date with the eclair userspace.

For any further discussion about this topic, I suggest you join the android-on-freerunner mailing list.

Swy said...

A bout Android ARMv4T Donut.
It served as a reference very much for me. Thanks.

Niels said...

I've looked at the binaries of current Android-on-freerunner Cupcake and Froyo with the validation script you prepared.

Cupcake is getting 24/174 and Froyo 140/232.

The variety of invalid instructions on Froyo is much less compared to Cupcake...

Christopher Friedt said...

Nice - I haven't picked up my FeeRunner in a while just because there is always such a strong influx of new and better hardware. In fact, I think the last time I did anything armv4t was porting u-boot to the ts-7260.

It would be awesome to redesign an OMAP3 board that was mechanically / electrically compatible with the FreeRunner case, battery, peripherals, etc. It really just is a superior SoC with hardware accelerated 3D graphics, DSP accelerated video codecs, NEON SIMD, etc. Plus the package-on-package design is much more space efficient.

Throw-in a 3G modem and I would gladly switch back to using the FR.

Incidentally, you might also want to check out Gentoo-Bionic. It will allow you to build library dependencies (i.e. shared libraries) much faster than if you were to simply bring all of the code into the Android build system.