Smali - Undeclared static method - android

After compiling a certain apk and going through the smali code I stumbled upon this line in file com/name/name/r.smali:
invoke-static {v1, v0, v2}, Lcom/name/name/p;->a(Ljava/lang/String;Ljava/util/List;Lcom/name/name/CallbackI;)V
name is a placeholder in this situation
Unfortunately both of the classes p and CallbackI don't exist in com/name/name, how is this possible?

There are a few possibilities:
The code referencing those missing classes is dead code that never gets executed.
The app crashes when it tries to run that code.
The classes are defined elsewhere. Is the app using multi-dex? Or maybe the app uses a DexClassLoader to load another dex file?

Related

qt android ClassNotFoundException

I'm using Qt (qml) to make an android app but I'm getting errors trying to register native methods to be called from java. In one section on my native code I'm calling java static functions with no problems:
void NotificationClient::powerOff() {
QAndroidJniObject::callStaticMethod<void>("com/my_app/Utils",
"powerOff",
"()V"
);
}
Now I'm trying to add some calls from java back to my native code (based on this example) but it fails
QAndroidJniEnvironment env;
jclass objectClass = env->FindClass("com/my_app/Utils");
Results in:
Pending exception java.lang.ClassNotFoundException: Didn't find class "com.my_app.Utils" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib, /vendor/lib, /system/lib, /vendor/lib]]
I've checked the dexdump from classes.dex and the class string matches. All paths in my AndroidManifest.xml are absolute. I've cleaned and rebuilt. Nothing is getting around that problem and I can't figure out why the static method call works but the object one does not.
(Yes, yet another ClassNotFoundException post but I really have searched for answers already).
edit The original failed method based on creating an object threw a different error so I switched back to use FindClass which gives the ClassNotFound error
UPDATE
OK, so I think I've figured out why FindClass is failing: according to this FindClass will search the callstack to figure out which ClassLoader to use. Normally this is fine but I believe Qt for android loads under a different thread so the wrong ClassLoader is getting called.
The link recommends caching the classes in JNI_onLoad but with Qt that's behind the scenes. Is there some other place where I could cache class id's on the main thread instead of the qt thread?
To answer my own question for completeness ...
The reason it failed to find the classes was Qt runs on a different thread than the main java thread, which caused the java classloader to fail in the lookup (see link in question update).
As a solution I added a JNI_onLoad function in one of my cpp files, which is called on the main java thread so the class lookup works correctly.

Redundant opcodes in Android dex

I'm looking into some Android performance issues at the moment and noticing some sub-optimal patterns in the dex code. I'm just wondering if anyone knows if this is to be expected, and what the rationale behind it might be.
For example, consider the following Java code:
m_testField += i;
doSomething(m_testField);
When this is built and then run through baksmali it looks like the following:
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
add-int/2addr v1, v0
iput v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
iget v1, p0, Lcom/example/MainActivity$FieldTest;->m_testField:I
invoke-direct {p0, v1}, Lcom/example/MainActivity$FieldTest;->doSomething(I)V
The part that's concerning me is the iget opcode to read the value of the instance field into register v1. The same field was written from the very same v1 register in the preceding opcode, so the opcode would appear to be completely redundant.
The only thing I can think of is that this is done to make this more thread-safe. But surely that should be the programmer's responsibility (by using sync blocks) instead of the compiler's responsibility. Although I'm not 100% certain, I think the above behaviour is quite different to what most C/C++ compilers would do.
I should say that essentially the same dex is produced when ProGuard is used. I should also probably mention that I'm using the very latest Android tools and a late model JDK.
Every access to a field is independent. To get the behavior you describe, you need to add an extra local variable:
int local = m_testField; // iget
local = local + i;
m_testField = local; // iput
doSomething(local);
That said, some combination of the interpreter, just-in-time compiler and ahead-of-time compiler may end up making these optimizations for you at runtime anyway.
On a hunch, I've done some further research and I think I'm in a position to answer my own question...
The sub-optimal dex seems to be a by-product of the fact that it is generated from standard Java bytecode which is stack-based rather than register-based. I disassembled the .class file corresponding to the sample code in my question. The relevant section looks like this:
5: aload_0
6: dup
7: getfield #22 // Field m_testField:I
10: iload_1
11: iadd
12: putfield #22 // Field m_testField:I
15: aload_0
16: aload_0
17: getfield #22 // Field m_testField:I
20: invokespecial #33 // Method doSomething:(I)V
After the iadd opcode on line 11 is executed, the value of m_testField is at the top of the stack and the 'this' reference is second from the top. The problem is that the putfield opcode on line 12 removes these from the stack. This means that the field value has to be re-pushed to the stack on line 17.
I must say I'm pretty surprised by this inefficiency. I'd have thought that the dx tool that converts bytecode to dex would be clever enough to remove this redundancy. I'm just hoping that ART is clever enough to do this at runtime instead.

Native Android - Can't locate undefined method when loading a shared lib even though previously loaded shared lib contains the definition

I am building an Android app that loads in 2 native shared libraries at runtime: 1 that was built with an unresolved symbol in it and the other which resolves and defines that symbol. In Java, I load the shared library that defines the symbol first, then load the library that has the symbol declared as unresolved, and at this point, the runtime fails with:
"Cannot load library: reloc_library[]: 33 cannot locate 'someMethod'
So here's the one unique difference. The shared library with the undefined symbol obviously doesn't know about the shared library with the definition for the symbol in it.
I just assumed that if I loaded the library with the definition of the method first that when I loaded the 2nd library that called the method, it would be able to find it. Am I wrong on that? It seems in my case, an explicit dependency HAS to be compiled in between the two native libs, which means (I think) making .so's with unresolved symbols is useless.
I have searched vigorously for a similar issue with no luck. I think my problem is due to an architectural limitation, and I am considering approaching it a couple of other ways, but I would like to know if it can be fixed simply.
To be sure it wasn't some complexity of the library itself, I created two very simple C files:
fcn_defined.c:
int someMethod()
{
return 1;
}
fcn_undefined.c:
extern int someMethod();
int someOtherMethod()
{
someMethod();
}
Then build two shared objects where the fcn_undefined.c code creates a .so with someMethod still undefined and fcn_defined.c builds a .so with someMethod defined:
gcc -o libfcn_undefined.so fcn_undefined.c -shared -Wl,--export-dynamic
gcc -o libfcn_defined.so fcn_defined.c -shared -Wl,--export-dynamic
Doing a nm on these produces:
libfcn_undefined.so:
0001f08 d _DYNAMIC
00001fe8 d _GLOBAL_OFFSET_TABLE_
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002000 d __dso_handle
00000290 t __on_dlclose
00002004 A _edata
00002004 A _end
000002a0 t atexit
000002b4 T someOtherMethod
U someMethod
and libfcn_defined.so:
00001f0c d _DYNAMIC
00001fec d _GLOBAL_OFFSET_TABLE_
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002000 d __dso_handle
0000025c t __on_dlclose
00002004 A _edata
00002004 A _end
0000026c t atexit
00000280 T someMethod
So you can see someMethod() is defined in libfcn_defined.so (and it appears in the read elf dynsym section) and is undefined in the other lib.
If anyone is interested in the readelf output, I can add that as well.
In the Java side, I have a simple button in the emulator that I click, and it creates a class with the following in it:
static
{
System.loadLibrary("fcn_defined");
System.loadLibrary("fcn_undefined");
}
Just out of curiosity, I added a "-lfcn_defined" to the fcn_undefined compile line, and compared the nm and readelf outputs. the only difference in nm was that the "T someOtherMethod" started a few bytes further out and the readelf difference was the "NEEDED" line for fcn_defined. That's pretty much about what I expected. And it doesn't crash like this.
That's pretty much the full explanation. I did find some details about how Android forces you to load your libraries in reverse dependency order in Java, because it has (rather it had, has been fixed in API 18) no reference to your app's lib path in the LD_LIBRARY_PATH envvar. Unfortunately, I am requiring a minimum API lvl 10 to be able to use my app because of the market penetration, and secondly I tried API 19 anyway, and it still fails.
If I had to guess, I believe Android just doesn't support finding a symbol if you haven't explicitly told it to look at library X for the symbol. In other words, because I didn't build the library fcn_undefined with an explicit dependency on libfcn_defined.so, Android can't resolve it. Does anyone know if this is a bug or by design? Is this normal? It seems like you wouldn't have the option to create a .so with unresolved symbols if this was the case, and even funnier is that the Android NDK toolchain I'm using to build this has this feature on by default when you use ld (it doesn't complain about unresolved), and I tried turning the feature off but didn't seem to do anything, no warnings or errors generating the library.
So you may ask why I don't just compile the fcn_undefined library with a dependency on the fcn_defined library. Well that gets into a much bigger architectural discussion. The code I'm working with (fcn_undefined.c in this example) is a python extension built with a cross compiled python toolchain for ARM, and I'm calling this library from an NDK library, so now the NDK library depends on the python module which has an unresolved method in Python, which is defined in a static lib. Linking the static lib into the NDK shared lib means that I can't load the native shared libs in the correct order in Java (due to the issue mentioned previously that they fixed in API 18). I'm trying to work with the existing system since a team of others use it, and it is used to build for many platforms. sigh I clearly have other things to figure out, but I was hoping to nail the one above down at least.
The behavior you so beautifully demonstrated is by design (or lack of, if you will). You are right in part, the crazy_linker does resolve some of such issues (but not all of them). There is an easy but ugly workaround. Build a dummy libfcn_defined.so which only has T someMethod in its nm. Use it to link libfnc_undefined.so, using LD_LIBS. NDK will show a warning, but that's OK. LAoad the real libfcn_defined.so in your Java.
By Unix/ELF design, you need a NEEDED entry in libfnc_undefined.so that lists libfnc_defines.so as a dependency for the dynamic linker to look into it for missing symbols.
I.e. you should ensure that -lfcn_defined (or /path/to/libfcn_defined.so) appears in the link command that generated libfcn_undefined.so.
If you use ndk-build to generate both libraries, just list libfcn_defined.so as a LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES entry for libfcn_undefined.so.
If you use another build system, adapt accordingly.

Android No expanded opcode for R.java

I have an important problem while compiling Android Application.
Using Windev Mobile, it generates java code, compile and create apk, however, when the apk creation, an error happens:
command line: "myjavapath\java.exe" -Xmx1024m -Djava.ext.dirs=.\platform-tools\lib -jar .\platform-tools\lib\dx.jar --dex --output "path\classes.dex" "path\classes" "path\libs"
returned error:
Trouble writing output: No expanded opcode for 0004368d R.java:11#0001: invoke-direct v0:NffffLmynamespace/R$attr;, java.lang.Object.<init>:()v
Furthermore, R$attr in R.java contains nothing:
public static final class attr {
}
I assume there is a hard limit of 64k. But:
The R.java file contains only 364 lines, if these lines are
fields/methods references, I'm very far away from 64k hard limit.
This error happened when I add a specific window, in my Windev Mobile project. Window that I'm using in another project without error.
So, what do you think it comes from?
If you need any information, or document, no problem.
Thanks in advance.
PS: Maybe my english isn't perfect, I sorry for that.
There are various limits in the dex file format. It looks like the one you are encountering is that there can't be more than 64k method references. This limit is for all classes in your dex file, not for just a single class.
The fact that the error is occurring on that class has nothing to do with the class itself, that's just that where it happened to hit the limit.
The only solution currently, is to reduce the size of your code, or to split some classes out into a separate dex file that you load dynamically.

android mupdf libmupdf.so runtime error "No implementation found for native openFile"

I just finished compiling mupdf from mupdf.com on my mac. Took some time to figure it out but now I have a libmupdf.so in my libs/armeabi folder.
They provide an example of this class called MuPDFCore.java which is viewable here:
http://mupdf.com/repos/mupdf/android/src/com/artifex/mupdf/MuPDFCore.java
I used this class in my project and it says the following in LogCat:
Trying to load lib
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050
Added shared lib
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050
No JNI_OnLoad found in
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050, skipping init
No implementation found for native
Lcom/myapp/android/viewer/MuPDFCore;.openFile
(Ljava/lang/String;)I
DEBUG/AndroidRuntime(27523): Shutting
down VM
WARN/dalvikvm(27523): threadid=1:
thread exiting with uncaught exception
(group=0x400ee760)
ERROR/AndroidRuntime(27523): FATAL
EXCEPTION: main
ERROR/AndroidRuntime(27523):
java.lang.UnsatisfiedLinkError:
openFile
As far as I know the library is loading, before I figured out how to compile the library it kept crashing and saying the "mupdf" is a null link.
Their example pretty much says that openFile is a native function ... Just when I thought I figured this out another problem pops up. Ive been working on it all day. Any input would be great!
Is it a bad compile? I didn't get any errors in the terminal.
when you try to use it on your project with sample project's so files, it will throw "UnsatisfiedLinkError: Native method not found" exception. The cause is your app package name different from sample app package name("com.artifex.mupdf") because of jni binding system. You can solve this problem with below approaches:
1) long way: change mudef lib source code according to your package name, generate binaries(.so files) from it then use it in your project like #KuoCH said
2) short way: create "com.artifex.mupdf" package in your root source directory(beside project source folder, "src/main/java"), copy all classes from sample project to in it
At file mupdf.c L18-19:
#define JNI_FN(A) Java_com_artifex_mupdfdemo_ ## A
#define PACKAGENAME "com/artifex/mupdfdemo"
Change both to your package name.
I think you didn't change the your function names in mupdf.c to your corresponding java package name, that means, you should change the function Java_com_artifex_mupdf_MuPDFCore_openFile in your mupdf.c to Java_com_myapp_android_viewer_openFile.

Categories

Resources