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++.
Related
I'm debugging an android application and am confusing about one android shared library and here i wanna explain the problem.
There is a native function defined in java code (java side) like this:
public static native void nativeInitialize();
Package:
package com.example.ExClass;
I loaded the shared library in IDA Pro.
I thought that i can find that function in exported functions and it should be something like this Java_com_example_ExClass_nativeInitialize
But the function is not in export list and as i debugged the java side codes, i know the function is calling from java but i don't know how it is working ?!
If the name-mangling scheme (Java_...) is not used, then it is possible the library uses the RegisterNatives approach to associate method names with function pointers. Try searching for structs that embed the string "nativeInitialize", they should be the methods argument to RegisterNatives. Look through the JNI_OnLoad function for the call site.
On Aarch64 assembly it should look like:
ldr x4, [x8,#1720] # RegisterNatives is the 215th member, times 8 bytes per pointer
bl x4 # Could also be a br if this was the last call of the function
In Android, we can use HIDL data types in lieu of normal C++ data types. Their functionality remains mostly the same, and this proxy code is for behind-the-scenes serialization and IPC which HIDL takes care of.
Now when I try to check if a HIDL vector is empty, I get the error that empty is not a member of hidl_vec. How then can I check this? Some other functions that work on a normal vector work with hidl_vec such as foo.size(), foo.begin(), foo.end() but I prefer to not use the size check for this reason.
#include "gmock/gmock.h"
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
hidl_vec<hidl_string> foo;
ASSERT_FALSE(foo.empty());
Throws the error:
error: no member named 'empty' in 'android::hardware::hidl_vecandroid::hardware::hidl_string'
ASSERT_FALSE(foo.empty());
i am making an Android Shapefile reader app on Android with the use of NDK. I want to use C++ to parse shape files. I found library "Shapefile C Library". Github: https://github.com/sw897/shapelib.
I am using Android studio and have no idea how to import it to my Android project so i could use functions described in: http://shapelib.maptools.org/shp_api.html
Any tips?
First, start hacking away at the Hello-JNI example from Google:
https://github.com/googlesamples/android-ndk/tree/master/hello-jni
Use that as a test bed.
Then, create a Java Class with public native methods that let you interact with your library. Something of a high level API, probably to pass a file name or buffer to SHPOpenLL and return a pointer to the ShapeFile context (ShapeHandle). Looks like your library is written in C, so you should be able to write a similar interface to query the shapefile passing a (jint) c-style cast of your ShapeHandle pointer.
Next, you need to play around with javah to generate the header for your shapefile interface. Once the header is generated, you can use it to implement your interface in a .cc file. From there you will basically make Java calls to your C interface and it will return jobjects. (jint, jbool, jstring, etc...)
I'm looking at the ShapeLib that you want to use and while it's easy enough, there will be some gotchas.
You will need to implement SAHooks for file I/O. I suggest looking at NVFile for an example how to access APK files (or downloaded files). You will need to init it using activity.context.assetmanager. Then use nv_file to wrap FRead/FSeek/etc...
Passing info back to java is going to be tough. Personally, I would build a Java class to hold the shape information and fill it out on the C side. However, you might be tempted to query these parameters from the SHPObject one at a time. Will be slow, but less error prone.
E.g.
// Java
MyJavaShapeObject obj = new MyJavaShapeObject();
_c_retrieveShapeObj((jint)pShapeFile, obj);
// C
java_blah_blah_c_retrieveShapeObj(JNIEnv* env, jclass activity, jint theShapeFile, jobject theObj){
ShapeHandle pShapeFileHandle = (ShapeHandle)theShapeFile; // c style conversion
// http://stackoverflow.com/questions/11647646/how-to-use-the-jni-to-change-the-fields-of-a-java-class
// http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16613
// http://stackoverflow.com/a/36759159/7949696
}
I'm currently developing the SO plugin loader for the existing SO library (GTA SA for Android).
The SO libraries on Android are Unix ELF files.
Having no source code of the library I cannot simply add the imported function in source code and compile the SO library again.
There is libGTASA.so, which I want to edit and alter the import table, adding a new symbol RunSOpluginLoader, which would be implemented in libFastman92pluginLoader.so, which is already loaded before libGTASA.so gets loaded, by Java code (classes.dex) that I also have modified.
For EXE files on Windows there are plenty of programs to edit the imports and I'd use LordPE.
For ELF file I need a different solution however and I'm having a trouble with finding one.
I tried using HT Editor, which is supposed to open and edit the ELF files, but few seconds after libGTASA.so gets opened in HT Editor the application simply crashes.
I need a solution to add an import to SO library, preferably the solution that would run on Windows, but if there's none then I am willing to do it on Linux system.
After properly adding an import I am going to edit a bit of ARM code inside the libGTASA.so to actually call the newly imported function.
Essentially:
libGTASA.so - I want to add an imported symbol RunSOpluginLoader to this file.
Few days after I wrote the question I figured out how to do this task.
I had written a simple ELF file manager class in C++ and program, which does the following:
load the ELF file - create a representation of header, sections and program segments, dynamic table (pointed by PT_DYNAMIC)
added new section (.fastman92_code, with permissions RWX)
added new program segment that covers a new section
I noticed the program segment must be aligned, I made an alignment of 32768 and it worked.
added new string to string table (pointed by this->header.e_shstrndx), string "fastman92.code", it's the section name.
sections are rellocated and will be written at the end of file, elfManager.header.e_shoff had to be updated.
rellocated .dynstr (the section pointed by DT_STRTAB), adding two importedentries to it:
{"libFastman92pluginLoader.so"},
{"ProcessPluginLoading"}
rellocated .dynsym, adding these two entries to the array.
reallocated section pointed by DT_JMPREL from dynamic table, added one entry to point into ProcessLoadingPlugin, near my added Jni_OnLoad function
rellocated program segments, added PT_DYNAMIC entry, which is neccessary, because the program segments are longer a part of the first loadable segment. They're no longer a part of segment with virtual address of 0x0.
added a simple function, a replacement of Jni_OnLoad which would call an imported symbol ProcessPluginLoading, which is implemented in libFastman92pluginLoader.so, then execute functions from .init_array, then call real an original Jni_OnLoad. A symbol "Jni_OnLoad" had to be pointed to my few function.
edited dynamic table, added DT_NEEDED with offset of string pointing to "libFastman92pluginLoader.so"
edited dynamic table, disabled .init_array, set up a size of it to be zero (InitArraySzIt->d_un.d_val = 0;) where auto InitArraySzIt = elfManager.FindFirstEntryInDynamicTableWithTag(0x1B);
save a new .so file
If you want to learn more about or get the code, feel free to contact me.
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.