What are "ins" and "outs" in Dalvik bytecode? - android

In dex code (e.g., as produced by the dexdump tool), for each method definition I see "ins" and "outs" in addition to other metadata such as "registers", "insns size".
I am instrumenting dex code to introduce new registers. The instrumentation is failing, and I suspect that I may have to change the "ins" and "outs" values based on the number of new registers I add.
So my question is: What do those "ins" and "outs" represent?
(fyi: I am using dexlib2 for this.)

These fields are documented at http://source.android.com/devices/tech/dalvik/dex-format.html.
ins_size | the number of words of incoming arguments to the method that this code is for
outs_size | the number of words of outgoing argument space required by this code for method invocation
ins_size is mostly self-explanatory - it's the number of 32-bit words required to store the method arguments (including the implicit "this" argument, for non-static methods). All arguments require 1 "word" except longs (J) and doubles (D), which require 2 words.
outs_size basically the opposite. outs_size must be set large enough to hold the arguments for any method call that occurs within the method.
If you want to instrument a dex file without having to worry about details like this, you might consider using dexlib2 (the library developed for and used by smali/baksmali to read/write dex files). The library is available in the maven repository, so it's easy to link against if you're using gradle/mvn.

Related

Making sense of symbol table entry (when header function is not present)

I have a JNI function in a C++ library.
When I create the library using cmake (but forget to put function declaration) in the header file, the library is created successfully.
When I look for function name in library symbol table I get following output
nm libuserlibrary.so | grep printxx
00506e60 T _Z60Java_com_example_user_myapplication_userlibrary_printxxP7JNIEnv_P8_jobject
But when I give function declaration in the header file, I get following output
nm libuserlibrary.so | grep printxx
00506e50 T Java_com_example_user_myapplication_userlibrary_printxx
Why is there this difference between these two symbol table entries? What is the purpose of _Z60 and P7JNIEnv_P8_jobject around the function name?
I also noticed that in the first case, I cannot call the JNI funciton from Android java code (it says unsatisfied-linker-error, implementation not found).
C++ allows function overloads and namespaces like Java does. So, it annotated the function name with parameter information so the linker can bind to the correct overload.
JNI was designed for C which does not allow function overloads or namespaces. So it invented it's own annotation system and provides the javah tool to help you use it. The header can be used in C++ too. C++ was designed to allow some functions to be called as if they written in C. The header has code that indicates that to the compiler. So, put it all together and you can write Java-callable functions in C++.

Do private methods increase Dex Count in Android?

I was doing code review and told someone to remove a private method that was only used once. They said that it didn't matter since dex count wouldn't get increased by private method references. Is this true? I wasn't able to find an answer with a simple google search.
The 64k limit is a limit on the number of unique method references in a dex file. A method reference consists of a specific class name, the method name and the method prototype, and is created when you either invoke a method or declare/define/override a method.
So yes, defining a new private method will add a method reference to the dex file.
For more information, see: https://source.android.com/devices/tech/dalvik/dex-format.html and https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html, which are the main references for the dex format.
The "method reference list" is a sorted list of method_id_items in the dex file. e.g. look for "method_ids" in the "File layout" section of dex-format.html. And further down the page, method_id_item is defined as consisting of a class reference, a method name and a method prototype.
The class_data_item section is used to define the methods and fields that are defined by the class. The "direct_methods" and "virtual_methods" lists are lists of indexes into the method_ids list - which requires that a reference for that method exists in the method_ids list.
And in dalvik-bytecode.html, the invoke-* instructions use a method index to refer the method to invoke.
Interestingly, the method reference list itself is defined with a 32-bit size value (search for "method_ids_size" in dex-format.html). So the list of method references itself can be as large as 4294967296 entries.
However, the problem comes when you need to reference any of these methods. The invoke-* instructions only use 16 bits to encode the method index.
Additionally, the method references in the class_data item can be up to the full 32 bits. So you could theoretically have definitions of methods past the 64k limit in a dex file, as long as you never actually tried to invoke them from within that dex file. But they could still be invoked from another dex file.
They said that it didn't matter since dex count wouldn't get increased by private method references. Is this true?
I am going to assume that you are worried about the 64K DEX method reference limit. In this case, the reviewee is correct: whether this code is wrapped in a method or not has no impact.
The "method reference" of relevance in "the 64K DEX method reference limit" refers to one DEX referring to a method in another DEX. In conventional Android projects, there are two DEXes of relevance: yours and the framework's. How many methods your own code is divided into does not matter. What matters is how many methods of the framework you are referencing (where by "you" I mean your code plus any library modules and JARs you are including).
When you enable multidex on a project, you are splitting your code into more than one DEX file. Each can refer to 64K methods in other DEX files. Here, though, "other DEX files" refers to both the framework DEX and the other DEX files of your own app created by multidex. However, AFAIK, multidex does not split a single class across DEX files. Since this is a private method, it could only be referenced by another method in the same class, and so both methods should be in the same DEX file. Hence, even in this case, having the private method would not add to the DEX method reference count of the DEX containing that method.
Based on JesusFreke's comments, I retract my original position. Defining a private method will increase the DEX method reference count.
That being said, on a one-off basis, worrying about inlining an individual method, just to reduce the DEX method reference count, is premature optimization IMHO. If you are bumping up towards the DEX method reference limit (and Android Studio's APK Analyzer can help you determine this), worry first about "trimming the fat" in libraries. Otherwise, worry about maintainability. Now, it may be that removing the method actually helps with that (e.g., it's a two-line method, not worth pulling out separately). But if there is maintainability value in having the method, leave it alone.

Multidex file format

I'm interested in understanding how a dex file (classesN.dex) references methods in another classesN.dex file.
In a standard dex layout, you have all of the class, method, type, etc... definitions in different tables. Things that are dynamically linked (such as those from the Android framework) simply have their method prototypes included, but no code data. Is it true that in a multidex setup, each classesN.dex contains a set of class implementations, and methods that are implemented in other dex files are merely included in the same way as dynamically linked calls?
In other words, if classes.dex needs to reference a method classes1.dex, it will include that method as a prototype within classes.dex, and then include its implementation in classes1.dex?
I ended up solving this question: it turns out that in a multidex layout the relevant method and class definitions are included in each dex file. For example, if classes.dex references methods foo() from classes1.dex, it will include a relevant entry in the method table for foo() within classes.dex's method table. But the implementation of foo() will appear in classes1.dex. This works because foo() is usually something like the entry of a library used by the app. The entry points of that library can be used without all of the methods called by foo. In classes.dex, foo will be defined without a corresponding code item, just as if it were a part of the dynamically linked Android standard library.

Feature comparison: V8 vs. iOS JavaScriptCore

Without using any non-deafult switches (i.e. no --harmony), are there language features, global properties, etc. that exist in V8 (at 69a0664) but not in JSC (at f27bfeb) and vice versa?
I'm doing Android/iOS work and want to make sure the same scripts will work on both.
In terms of ECMAScript 5 features, going by this table, both have attempted to implement everything.
test262 failures for Mobile Safari (iOS 6.1.3):
10.4.2_1.1 eval within global execution context
10.4.2_1.2 eval within global execution context
15.5.4.9_3 Tests that String.prototype.localeCompare treats a missing "that" argument, undefined and "undefined" as equivalent
15.5.4.9_CE Tests that String.prototype.localeCompare returns 0 when comparing Strings that are considered canonically equivalent by the Unicode standard.
15.9.3.1_5 multi-argument Date construction
test262 failures for Chrome 28:
11.2.3-3_3 Call arguments are not evaluated before the check is made to see if the object is actually callable (undefined member)
15.5.4.9_6 Checking String.prototype.localeCompare.prototype
15.5.4.9_7 Checking if creating the String.prototype.localeCompare object fails
15.8.2.8_6 Checking if Math.exp is approximately equals to its mathematical values on the set of 64 argument values; all the sample values is calculated with LibC
15.9.3.1_5 multi-argument Date construction
Caveat: these aren't necessarily the corresponding versions, but are just what I have to hand.

Creating .map file with mapfilewriter plugin for osmosis

I tried to make a .map file to use it in my android application. My point is to show map on screen with help of mapsforge library. Library requires a .map file. The problem is generating it with osmosis mapfilewriter plugin. When I use command
./osmosis --rx file=/home/user/poland.osm --mw file=result.map bbox=51.09,16.9,51.14,17
I get
SEVERE: Thread for task 1-rx failed
java.lang.OutOfMemoryError: Java heap space
I tried using another order of arguments but it also doesn't work. I also tried using -Xmx1200m option to increase javas heap memory but usage of memory was this same and didn't help.
I would be grateful for help.
Use the parameter type=hd.
The type parameter has two options ram and hd. Although I don't see that the documentation doesn't explicitly state what hd means, I would guess it means "hard disk", meaning it would offload data to disk, rather than keeping it all in memory.
The resulting command would be then:
./osmosis --rx file=/home/user/poland.osm --mw file=result.map bbox=51.09,16.9,51.14,17 type=hd
If you have enough memory, you need to tell Java about it (it will only use a limited amount otherwise); but this is not an argument passed directly to osmosis.
On Windows, you can follow this advice given by Emilie Laffray on the OSM-dev list:
In osmosis.bat is the following line... REM # JAVACMD_OPTIONS - The
options to append to the java command, typically used to modify jvm
settings such as max memory.
so, either modify osmosis.bat or, create a new file called osmosis.bat
in the all users profile directory or your profile directory, to
include a 'set JAVACMD_OPTIONS = -Xmx1024M' line (to set maximum
memory usage to 1GB, if you have enough RAM)...
On Linux (and I'd assume Mac OS X also), you can create the file ~/.osmosis
containing the line
JAVACMD_OPTIONS=-Xmx1024M
which will be loaded by osmosis on startup. Note that both examples above use the value 1024M, i.e. you're giving Java access to 1024 MB of RAM - you could use a different value depending on your system.

Categories

Resources