fastcall on arm (Android NDK) - android

IDA (the interactive disassembler by hex-rays.com) reports native C++ functions (Android NDK, arm) as __fastcall, for example:
// int __fastcall QVariant::toULongLong(_DWORD, _DWORD); weak
By the way, this function is declared in the docs as
qulonglong QVariant::toULongLong ( bool * ok = 0 ) const
When I define a native function with __attribute__((fastcall)), I get
warning: 'fastcall' attribute directive ignored [-Wattributes]
Question:
I need to call a library function whose prototype I can (hopefully) guess.
How do I declare functions so that they would be called with the right calling convention (namely, the __fastcall one reported by IDA)?

IDA just uses fastcall for any calling convention involving registers. In the case of ARM, fastcall basically means "default calling convention".
Adding #define __fastcall to the source should let you compile it. However, there is an additional issue for this function:
Note that QVariant::toULongLong() is a C++ method, so the first argument shown by the decompiler is actually the hidden this pointer which is passed to all non-static methods of C++ classes. Since the decompiler does not support C++ it converts it to an explicit argument. You may need to undo this operation to make it valid C++ code.
Or you could just use the actual source code.

Related

Where to put Scudo allocator __scudo_default_options callback?

From Scudo page:
Some parameters of the allocator can be defined on a per-process basis through several ways:
Statically: Define a __scudo_default_options function in the program that returns the options string to be parsed. This function must have the following prototype: extern "C" const char *__scudo_default_options().
Dynamically: Use the environment variable SCUDO_OPTIONS containing the options string to be parsed. Options defined this way override any definition made through __scudo_default_options.
Im fairly new to Android, could someone help me understand where to put functions like __scudo_default_options in cpp code, I have MainActivity.cpp and MidiManager.cpp
The function can be located anywhere within the application, as long as it's discoverable by the linker. Putting it in the vicinity of your main compilation unit is probably better.
You want to make sure that the symbol has a public visibility.
You can refer to the example in the tests here:
https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/scudo/standalone/tests/scudo_unit_test_main.cpp#L23
eg. in MainActivity.cpp, something to the extent of:
extern "C" __attribute__((visibility("default"))) const char *
__scudo_default_options() {
return "quarantine_size_kb=256:thread_local_quarantine_size_kb=128:"
"quarantine_max_chunk_size=512";
}

I want to call c language through android, call assembly language through c language, but it appears undefined reference to `MyASMTest (int, int) ' [duplicate]

I am trying to call external C++ function from NASM. As I was searching on google I did not find any related solution.
C++
void kernel_main()
{
char* vidmem = (char*)0xb8000;
/* And so on... */
}
NASM
;Some calls before
section .text
;nothing special here
global start
extern kernel_main ;our problem
After running compiling these two files I am getting this error: kernel.asm(.text+0xe): undefined reference to kernel_main'
What is wrong here? Thanks.
There is no standardized method of calling C++ functions from assembly, as of now. This is due to a feature called name-mangling. The C++ compiler toolchain does not emit symbols with the names exactly written in the code. Therefore, you don't know what the name will be for the symbol representing the function coded with the name kernel_main or kernelMain, whatever.
Why is name-mangling required?
You can declare multiple entities (classes, functions, methods, namespaces, etc.) with the same name in C++, but under different parent namespaces. This causes symbol conflicts if two entities with the name local name (e.g. local name of class SomeContainer in namespace SymbolDomain is SomeContainer but global name is SymbolDomain::SomeContainer, atleast to talk in this answer, okay) have the same symbol name.
Conflicts also occur with method overloading, therefore, the types of each argument are also emitted (in some form) for methods of classes. To cope with this, the C++ toolchain will somehow mangle the actual names in the ELF binary object.
So, can't I use the C++ mangled name in assembly?
Yes, this is one solution. You can use readelf -s fileName with the object-file for kernel_main. You'll have to search for a symbol having some similarity with kernel_main. Once you think you got it, then confirm that with echo _ZnSymbolName | c++filt which should output kernel_main.
You use this name in assembly instead of kernel_main.
The problem with this solution is that, if for some reason, you change the arguments, return value, or anything else (we don't know what affects name-mangling), your assembly code may break. Therefore, you have to be careful about this. On the other hand, this is not a good practice, as your going into non-standard stuff.
Note that name-mangling is not standardized, and varies from toolchain to toolchain. By depending on it, your sticking to the same compiler too.
Can't I do something standardized?
Yep. You could use a C function in C++ by declaring the function extern "C" like this
extern "C" void kernelMain(void);
This is the best solution in your case, as your kernel_main is already a C-style function with no parent class and namespace. Note that, the C function is written in C++ and still uses C++ features (internally).
Other solutions include using a macro indirection, where a C function calls the C++ function, if you really need to. Something like this -
///
/// Simple class containing a method to illustrate the concept of
/// indirection.
///
class SomeContainer
{
public:
int execute(int y)
{
}
}
#define _SepArg_ , // Comma macro, to pass into args, comma not used directly
///
/// Indirection for methods having return values and arguments (other than
/// this). For methods returning void or having no arguments, make something
/// similar).
///
#define _Generate_Indirection_RetEArgs(ret, name, ThisType, thisArg, eargs) \
extern "C" ret name ( ThisType thisArg, eargs ) \
{ \
return thisArg -> name ( eargs ); \
} \
_Generate_Indirection_RetEArgs(int, execute, SomeContainer, x, int y);

Generic method for callback to IOS/Android Application Layer from Native Layer (CPP)

I have Mobile Application projects for IOS & Android which internally uses the same Native cpp code. IOS project calls the Native file 'MyNativeFile.cpp' from 'MyApplication.m'. Android project calls the Native file 'MyNativeFile.cpp' through 'MyActivity.java' (Application Layer) via 'MyJNIInterface.cpp' (JNI Interface).
I need a generic implementation in my Native layer file 'MyNativeFile.cpp' through which some char string type data in Native layer can be sent to Application Layers (IOS/Android). (Please note that if I use JNI callback methods like the one mentioned in https://github.com/googlesamples/android-ndk/tree/master/hello-jniCallback it would not work for IOS environment)
My Android Application has below files
MyActivity.java (Application Layer)
MyJNIInterface.cpp (JNI Interface)
MyNativeFile.cpp (Native implementation)
My IOS Project has below files
MyApplication.m (Application Layer)
MyNativeFile.cpp (Native implementation)
One way of doing this is writing the character string to a file from Native code & then reading the same file in Application layer. But this method will have performance issues.
Please suggest a good way for doing this. Share some sample code if possible.
Even I am doing such a project where strings, integer arrays and other longer data types have to be returned.
I need a generic implementation in my Native layer file
'MyNativeFile.cpp' through which some char string type data in Native
layer can be sent to Application Layers
A method for your problem of returning a string can be solved by a reference to string, in your .cpp file, the function should have a parameter of a pointer to a character array, i.e, std::string & varName.
In this parameter, be it your .m file in iOS or JNI in JAVA, all you have to do is first declare an empty in string. Then pass this empty string while you call your function.
The header file of my project is as follows.
//.h file
class FindData {
public:
void findDataPt(int corrOut, string &result_array);
//In this function make changes to result_array directly and they'll reflect on the original string too
};
To call this from .m, I IMPORT THE .h first and then do the following in iOS:
Note: Make the .m as .mm to include C++ includes and functionality
//ViewController.mm
#include <string>
viewDidLoad{
string varName;
FindData fd;
fd. findDataPt(15,varName);
}
After this, make changes to the string, in findDataPt function.

jni table overflow even after deleteLocalRef

When I run the code, I get an error "failed adding to JNI local ref table has 512 entries"
This is my code:
jstring pJNIData = pJNIEnv->NewStringUTF ( variables[0].GetStringValue() );
pJNIEnv->CallStaticVoidMethod ( pJNIActivityClass, pJNIMethodIDStartTime, pJNIData ) ;
pJNIEnv->DeleteLocalRef(pJNIData);
I have read several suggestions, but none of them work! In spite of the DeleteLocalRef, it fails to works. The function is used in a profiler that literally calls all the functions...
I have seen this when a JNI method called Java code (in my case, the method was not static). As I understand, unused local references are not automatically deleted when a Java method is called from JNI (I mean, until the top-level JNI function returns).
IIRC either there already was information about memory objects in the log, or I could add some logging; from that information I identified garbage items that I did not mention before. They were two arrays and a class, created in subsequent calls but not garbage-collected.
// in a function that calls a Java method from JNI
jbyteArray srcArray = env->NewByteArray(len);
jclass cls = env->FindClass("com/something/MyClass");
jmethodID mid = env->GetMethodID(cls, "mymethod", "([BI)[B");
jbyteArray resArray = (jbyteArray)env->CallObjectMethod(obj, mid, srcArray, XXXX);
...
env->DeleteLocalRef(cls);
env->DeleteLocalRef(resArray);
env->DeleteLocalRef(srcArray);
// no need to do anything with mid
Note that although these three local references were obtained differently, all of them were hanging around.
Useful link:
http://www.netmite.com/android/mydroid/dalvik/docs/jni-tips.html#local_vs_global_references
(or find the Dalvik VM docs dalvik/docs/jni-tips.html and locate the section "Local vs. Global References")
Every object that JNI returns is a "local reference". This means that it's valid for the duration of the current native method in the current thread. Even if the object itself continues to live on after the native method returns, the reference is not valid. This applies to all sub-classes of jobject, including jclass and jarray. [...] Note: method and field IDs are just 32-bit identifiers, not object references, and should not be passed to NewGlobalRef. The raw data pointers returned by functions like GetStringUTFChars and GetByteArrayElements are also not objects.
I thought I would chip in just in case anyone else runs into this issue. This is a weird case that kept me confused for hours!
Ok so I have an NDK app and the Java code being called is inside an apk that is loaded at runtime. I have no idea if the runtime loading effects this in any way but I thought I should mention it.
Now in a c++ method I use find class and getmethodid to get the constuctor to a HashMap and call it to get a new HashMap instance. I then populate the HashMap from the c++ side using jni calls. So far so good.
I then pass the HashMap to java code and, again, all is working as expected. Once the java code has returned I call DeleteLocalRef on the HashMap. No errors are thrown but the reference is not deleted.
This only came up when I finally ran over 512 local references (from multiple calls to this function) and the error dump showed that the last 10 items in the localref store were nearly all HashMaps. I would understand that the GC would not collect these references at the end of the method as I am make a multithreaded ndk app. However the DeleteLocalRef should have worked.
The Fix:
In the end I found that creating the HashMap from a jni call to a java method I wrote was fine, and the reference was then free'able. It seems crazy to have a java function that literally just returns a new HashMap but it worked so for now I am living with it :)

Passing Function Pointers to Native functions as parameters

I am working with the android NDK trying to use an existing library to build an Application.
The following function is declared in the library...
BYTE __stdcall InitRelay(fp_setbaud _setbaud, fp_get _get, fp_put _put, fp_flush _flush, fp_delay _delay){
These are the declarations for the parameters passed to InitRelay...
typedef void (__stdcall *fp_setbaud)(WORD);
typedef short (__stdcall *fp_get)(WORD);
typedef void (__stdcall *fp_put)(BYTE);
typedef void (__stdcall *fp_flush)(void);
typedef void (__stdcall *fp_delay)(WORD);
typedef short (__stdcall *fp_ProgressUpdate)(WORD);
I've been to this thread, but still am not sure what to do. The difference between what I am doing and what they are doing, is that I want to call a native function in C that requires a function pointer as a parameter.
I was considering writing a wrapper function in the Native code, does that sound right? My main problem is that I cannot change the native code i've been given, but I can add new functions. I know people will ask me to post my java code, so I will, but it is literally useless. It is just a method call with parameters that currently don't make sense to java.
// InitRelay
InitRelay( fp_setbaud _setbaud, fp_get _get, fp_put, fp_flush _flush, fp_delay _delay );
Yes, write native wrappers. You will need to do this anyway as jni has very particular naming requirements for the interface functions. Non-trivial data types will also require copy conversion from/to jni references.
Process-level static state in the library can also give you a lot of headaches, since android does not link the lifetime of a process to a user perceptible session lifetime. Android will also quite happily put multiple distinct sessions into the same process.

Categories

Resources