In Depth Analysis of SIGILL in Android Emulator

If you have read the previous article about SIGILL in Android Emulator when trying to perform debugging of native application, I’ve place the end statement for Android Developers out there to respond this issue.

Several months and maybe years πŸ™‚ already passed, and I still got no response about this issue. Maybe those Developers do not yet read this matter, or this issue is too dumb to be taken into matters. So after I have set aside some time slot, I decided to investigate this issue further.

The article below assume that you have properly installed Android NDK in your machine.

So, suppose I have a hello.c that compiles to ARM architecture and shows the “Hello, World” message.

sig01

Prepare environment variables:

sig02

Creates batch file COMPILE.BAT in C:\NDK with content as follow:

sig03

Execute it:

sig04

Deploy it into the emulator:

sig05

Here is partial dump of dissasembly:

sig06

Suppose I change the instruction with invalid one like 0x1000F1FF:

sig07

Re-deploy and re-execute the program (the above statement is repeated), then viewing the logcat:

sig08

This is the base info to be used against more mysterious crashes such as this one on debugging process:

sig09

This message is triggered by Android source code located at:

sig10

The difference between the above logcat info is that debugging crashes do not contain information about location and instruction that causes SIGILL.

But let’s leave the above issue for a moment, let’s examine the kernel state when SIGILL occurs:

sig11

To arrive at the above condition, I’ve create a custom global variable called prb_addr1 and prb_addr2 in my compiled emulator-arm.exe with debug symbol in it.

The prb_addr1 and prb_addr2 then can be filled with address range of __und_usr_unknown Android kernel address. In my instance of kernel, the address range is between 3221280196 (0xC000D5C4) 3221280212 (0xC000D5D4).

This address is obtained using kallsyms file:

c000d5c4 t __und_usr_unknown

Methods to obtain this file can be found on the net.

Then I’ve already modified the emulator source code in tb_find_fast function in cpu-exec.c source file by adding a dummy code for the purpose of placing the break-point on it:

sig12

The desired condition is then achieved using gdb debugger commands as follow:

sig13

The address 0x514605 points to the prb_addr1 = prb_addr1 statement.

Why not use the -s -S option in the qemu emulator for kernel debugging ? Well, at my version of qemu, there’s a problem that either causes the emulator crashes or client debugger can’t talk to the emulator, so this option is not possible. Again, another unresolved issue by Android Developers out there.

By executing hello program that causes SIGILL, then we can break into kernel address space inside __und_usr_unknown and inspect its registers.

Register of interest is located at R0 and R4, which contains 4293984272 and 33376 respectively. As you can see, 4293984272 = 0xFFF10010 and 33376 = 0x8260, which are instruction and location that causes SIGILL kernel trap.

We have now base information for SIGILL mechanism, for arm mode executable. So, let’s again repeat the above steps by compiling the hello.c in thumb mode:

sig14

Again change it to invalid instruction for instance: 0xDE88. Let’s see what’s the logcat say about this:

sig15

What about kernel state ?

sig16

R5 which contains 56968 (0xDE88) is the instruction causes SIGILL. R4 now contains PC+2, i.e. location of next thumb instruction, so it is necessary to subtract this value by 2 to determine exact location of PC that causes SIGILL.

Now, revert back the misbehave hello program to the usual normal one, this time, it will be used in an interactive debugging session against emulator, which causes SIGILL as below:

sig17

The kernel state for the above condition:

sig18

R4 = 33544 = 0x8308 is the location of said faulted instruction, since R5 contains value that is greater than word value, the fault instruction must be located in:

R0 = 3891266032 = 0xE7F001F0, and there is no displacement correction for instruction location because the supposed arm opcode is in arm mode (32 bit opcode).

Let’s prove whether the above instruction is indeed invalid:

sig19

The original instruction at 0x8308 is actually 0xE3A03000. So, where the invalid instruction 0xE7F001F0 came from ?

sig20

Seems it came from the gdbserver, but to be sure, we have to examine the source code and also, the most difficult and time cosuming, to compile gdbserver into android arm platform. This tedious task should be the job of Android Developers.

But for the mean time, I will again be patient and leave this matter to Android Developers out there to respond, if they happen to read this article πŸ™‚

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: