Daneel: Type inference for Dalvik bytecode

In the last blog post about Daneel I mentioned one particular caveat of Dalvik bytecode, namely the existence of untyped instructions, which has a huge impact on how we transform bytecode. I want to take a similar approach as last time and look at one specific example to illustrate those implications. So let us take a look at the following Java method.

public float untyped(float[] array, boolean flag) {
   if (flag) {
      float delta = 0.5f;
      return array[7] + delta;
   } else {
      return 0.2f;
   }
}

The above is a straightforward snippet and most of you probably know how the generated Java bytecode will look like. So let’s jump right to the Dalvik bytecode and discuss that in detail.

UntypedSample.untyped:([FZ)F:
  [regs=5, ins=3, outs=0]
   0000: if-eqz v4, 0009
   0002: const/high16 v0, #0x3f000000
   0004: const/4 v1, #0x7
   0005: aget v1, v3, v1
   0007: add-float/2addr v0, v1
   0008: return v0
   0009: const v0, #0x3e4ccccd
   000c: goto 0008

Keep in mind that Daneel doesn’t like to remember things, so he wants to look through the code just once from top to bottom and emit Java bytecode while doing so. He gets really puzzled at certain points in the code.

  • Label 2: What is the type of register v0?
  • Label 4: What is the type of register v1?
  • Label 9: Register v0 again? What’s the type at this point?

You, as a reader, do have the answer because you know and understand the semantic of the underlying Java code, but Daneel doesn’t, so he tries to infer the types. Let’s look through the code in the same way Daneel does.

At method entry he knows about the types of method parameters. Dalvik passes parameters in the last registers (in this case in v3 and v4). Also we have a register (in this case v2) holding a this reference. So we start out with the following register types at method entry.

UntypedSample.untyped:([FZ)F:
  [regs=5, ins=3, outs=0]               uninit uninit object [float bool

The array to the right represents the inferred register types at each point in the instruction stream as determined by the abstract interpreter. Note that we also have to keep track of the dimension count and the element type for array references. Now let’s look at the first block of instructions.

   0002: const/high16 v0, #0x3f000000   u32    uninit object [float bool
   0004: const/4 v1, #0x7               u32    u32    object [float bool
   0005: aget v1, v3, v1                u32    float  object [float bool
   0007: add-float/2addr v0, v1         float  float  object [float bool

Each line shows the register type after the instruction has been processed. At each line Daneel learns something new about the register types.

  • Label 2: I don’t know the type of v0, only that it holds an untyped 32-bit value.
  • Label 4: Same applies for v1 here, it’s an untyped 32-bit value as well.
  • Label 5: Now I know v1 is used as an array index, it must have been an integer value. Also the array reference in register v3 is accessed, so I know the result is a float value. The result is stored in v1, overwriting it’s previous content.
  • Label 7: Now I know v0 is used in a floating-point addition, it must have been a float value.

Keep in mind that at each line, Daneel emits appropriate Java bytecode. So whenever he learns the concrete type of a register, he might need to retroactively patch previously emitted instructions, because some of his assumptions about the type were broken.

Finally we look at the second block of instructions reached through the conditional branch as part of the if-statement.

   0009: const v0, #0x3e4ccccd          u32    uninit object [float bool
   000c: goto 0008                      float  uninit object [float bool

When reaching this block we basically have the same information as at method entry. Again Daneel learns in the process.

  • Label 9: I don’t know the type of v0, only that it holds an untyped 32-bit value.
  • Label 12: Now I know that v0 has to be a float value because the unconditional branch targets the join-point at label 8. And I already looked at that code and know that we expect a float value in that register at that point.

This illustrates why our abstract interpreter also has to remember and merge register type information at each join-point. It’s important to keep in mind that Daneel follows the instruction stream from top to bottom, as opposed to the control-flow of the code.

Now imagine scrambling up the code so that instruction stream and control-flow are vastly different from each other, together with a few exception handlers and an optimal register re-usage as produced by some SSA representation. That’s where Daneel still keeps choking at the moment. But we can handle most of the code produced by the dx tool already and will hunt down all those nasty bugs triggered by obfuscated code as well.

Disclaimer: The abstract interpreter and the method rewriter were mostly written by Rémi Forax, with this post I take no credit for it’s implementation whatsoever, I just want to explain how it works.

This article was written by a

This article was written by a real thinking writer. I agree with many of the solid points made by the writer. Thanks for sharing!

Dalvik dex files and Soot's

Dalvik dex files and Soot's fast typing component for the type inference.

project can be a big

project can be a big endeavor.

It's awesome to visit this

It's awesome to visit this site and reading the views of all mates about this piece of writing, while I am also keen of getting experience. http://www.authorstream.com/pubgcardsdose/

And I've fallen in a trench

And I've fallen in a trench https://guitarlessonsdenvercolorado.com

any update on this article?

any update on this article? thanks in advance guys!

This post will assist the

This post will assist the internet visitors for creating new
website or even a blog from start to end. https://bibliocrunch.com/profile/pubgcardsdose/

any update here?

any update here?

I havent't heard of this

I havent't heard of this before.

Well explained. Thank you!

Well explained. Thank you!

I can see you standin'

I've been looking for this

I've been looking for this Java method for a month now! Thanks for sharing this. https://www.inspectionmanaging.com/

Cant believe this article

Cant believe this article made soo much sense now. You really have a talent for this! Continue pressing on!

Say you'll see me again

Say you'll see me again https://privateinvestigatormiamifl.com

they present an efficient and

they present an efficient and practical algorithm for inferring static types for local variables in a 3-address.

If you’re looking to take

If you’re looking to take your floors to the next level and protect the foundation of your property, Elite St Petersburg Epoxy Flooring is here with everything you need under one roof.

Great website. Plenty of

Great website. Plenty of helpful info here

These type of articles keeps

These type of articles keeps the users interest in the website, and keep on sharing more.
https://greasescrapers.com/

I totally agree with most of

I totally agree with most of these replies. Where can I get more information?

Thanks for taking the time to

Thanks for taking the time to discuss this. https://partypicsnj.com/

The post is written in very a

The post is written in very a good manner and it contains many useful information for me. Frank Dietrich Virginia https://www.a-zbusinessfinder.com/business-directory/Frank-Roland-Dietri...

You know your projects stand

You know your projects stand out of the herd. There is something special about them. It seems to me all of them are really brilliant! Frank Dietrich VA http://www.travelful.net/location/5083256/united-states/frank-roland-die...

Your website is really cool

Your website is really cool and this is a great inspiring article. Frank Dietrich http://frankdietrich.net/

They make our daily life so

They make our daily life so much more convenient, and for that, I am so thankful. Let's not stop working for more of these beneficial adjustments!