Im building a project that needs to modify the behavior of some bionic methods (e.g getaddrinfo, __android_print). I've been able to create the hooked library both using a standalone compiler or including it directly in the Apk using Cmake. I've been able to preload the shared library using setprop wrap.com.foo.bar and LD_PRELOAD, and it is working and I get the result I want. However, I want to preload the hooked library programatically so I dont need to go through the specific steps of LD_PRELOAD (a.k.a disable SELinux, root device, setprop), every time after rebooting a device.
I tried using
// MainActivity
companion object {
System.load("/data/data/com.foo.bar/lib/libhookedmethod.so")
}
But I don't see the method being replaced.
As a reference, the hooked method is rather simple. Here's an extreme simplification:
int __android_print(varargs a) {
int realmethod(...);
realmethod = dlsym("__android_print");
doStuff();
int res = realmethod(a) ;
return res;
}
Again, compiling and using LD_PRELOAD works, but I want to achieve it without using LD_PRELOAD...
Anything helps! Thanks in advance
The LD_PRELOAD works by asking the dynamic loader to load referenced library before any other. The loader resolves references to a given symbol by searching loaded libraries in their load order.
Once a symbol is resolved to a particular library, it will not be rebound to some other library for the duration of this process.
Above explanation should make it obvious why loading libhookedmethod.so after the program is already running has no effect.
About the only way you can achieve what you want is to setenv() (if not already set) and re-exec() the current process. Something like this:
int main(int argc, char *argv[])
{
char *e = getenv("LD_PRELOAD");
if (e == NULL || /* any other checks that show LD_PRELOAD to not be as we want it */) {
setenv("LD_PRELOAD", ..., 1);
execvp(argv[0], argv);
}
// LD_PRELOAD is to our liking. Run the actual program.
...
}
Related
I'm currently working on an Android project where I need to load .obj file with ASSIMP on Android Platform. My way of implementing that is to use the AssetManager to load the .obj file into memory first, and then using the importer.ReadFileFromMemory() function to create the aiScene object. I've managed to import all vertex data, but I found that the texture is missing. I actually read from the ASSIMP GitHub page where it mentioned that ReadFileFromMemory() won't read contents cross file, therefore I think it is not reading the .mtl file where texture is applied. I would like to use the importer.ReadFile() function, but I have no idea on how to work with it on Android platform. Any one has suggestions?
Attached is my implementation of the loadModelFromMemory, similar as the loadModel from LearnOpenGL.
void Model::loadModelFromMemory(const void* pbuffer, size_t pLength)
{
Log::Message("Enter loadModelFromMemory", LOG_INIT);
// read file via ASSIMP
Assimp::Importer importer;
const aiScene* scene = importer.ReadFileFromMemory(pbuffer, pLength, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
// check for errors
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
{
Log::Message(strcat("ERROR::ASSIMP::", importer.GetErrorString()), LOG_ERROR);
return;
}
// process ASSIMP's root node recursively
processNode(scene->mRootNode, scene);
}
I have tried on using ReadFile but it is not working on the Android context. I also tried to use the MemoryIOWrapper provided by the ASSIMP, but have no clue on where to start.
There are different ways how to implement this.
Load the mtl- and the obj-file via memory buffers
Use the android-filesystem implementations to load assets from the asset-folder on your mobile phone. You can find our headers for that at Android File system implementations
Because there is no function malloc_trim in ndk , so I want to find a way to implement malloc_trim(0) in ndk !
A simple definition like the following should suffice:
int malloc_trim(size_t pad) { return 1; }
Better still is to see if whatever library you're compiling has a flag to disable the use of malloc_trim at all.
EDIT: According to this post, jemalloc is the default memory allocator. jemalloc uses mmap by default, not sbrk. Jemalloc automatically returns memory to the OS when certain conditions are met, so I would not bother trying to come up with a useful implementation for malloc_trim.
I want to show image (png,jpg etc) in dynamically created (as per requirement and fully through coding) TImage component, at runtime in C++ builder xe8 (not delphi). But I dont want to use opendialogbox (suggested in many web sites). I want to run this app on my android device. I tried to use LoadFromFile(), it crashes the app on android, but when I run this on windows, its running smoothly. I am just a beginner to c++ builder. So guys pls help. Thanx in advance for any kind of help.Here is what I did.
void __fastcall TForm1::TForm1(TComponent* Owner)
{
TImage* img = new TImage(this);
img->Parent = this;
img->Bitmap->LoadFromFile("D:\\res\\profile.png");
}
Did you see what is the error?
If you run the program with the provided by you code I assume the error would be that the file is not found, because there is no such directory "D:\" in android.
One way to set the path is to write a static path which points to your image. For example : "/storage/sdcard0/DCIM/Camera/MyImage.jpg";
The second way is to include the <System.IOUtils.hpp> header and to use some built-in functions like:
System::Ioutils::TPath::GetPicturesPath();
System::Ioutils::TPath::GetAlarmsPath();
You can check them out, they might be useful.
When I attempt to deploy my app using Eclipse it throws FileNotFoundException on my font, which I've now copied to both the assets/src and assets directory to be doubly sure.
I had this problem before, after succesfully integrating SDL_ttf into my Visual C++ build of the same app and transferring across to Eclipse for Android. Now I'm facing it again I thought I better write about it. The SDL_ttf source comes with a freetype folder already in place and referenced by android as external/freetype-2.4.12. DinoMage states I need to download this separately although he refers to freetype-2.4.11 being the latest. That's the only obvious difference from my VC build, apart from minor compiler intolerances.
I've got it working a bit now. I can sign the app (unsigned didn't work), disable USB debugging, and it will load the font and display a menu. From there it breaks, again, so I can't see how I'm supposed to debug it further. I'm sure I'll fix it somehow. But I'll also forget the obscura if I don't post here.
I don't know much about using the debugger with Android, but I can make suggestions otherwise.
Is your assets path really named "assetts"? If possible, I'm not sure how one would get Android and SDL to look there instead of "assets".
SDL and it's friend libs like SDL_ttf search for files local to the assets directory first and then search relative to the root directory. So I would expect that your "res/stubbornFont.ttf" will never load because it is in the resources "res" directory and SDL_ttf will not look there.
Maybe you can specify it relative to assets/, like "../res/stubbornFont.ttf", but I haven't tested that. It would work if you put the font in assets/ and loaded it as "stubbornFont.ttf".
I've think I've got closure on this.
It is possible to debug the app. By continuing it will trap several times trying to load one font. I think it stops eventually, I'm not sure. I've stepped through it from where it lands me at the throw stage. However single stepping from there begins from the synchronized statement, sorry it's Java but from my quick reference to What does 'synchronized' mean? I think this is a race condition
public final AssetFileDescriptor openFd(String fileName)
throws IOException {
synchronized (this) {
if (!mOpen) {
throw new RuntimeException("Assetmanager has been closed");
}
ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
if (pfd != null) {
return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
}
}
throw new FileNotFoundException("Asset file: " + fileName);//DEBUGGER traps here
}
You might be there all day single stepping that! It appears to perform all steps required of it and finally I land in:
public static ReadableByteChannel newChannel(InputStream inputStream) {
return new InputStreamChannel(inputStream);
}
No, not finally, lastly, there is
public static Context getContext() {
return mSingleton;
}
In the SDLActivity I extend.
That has a bunch of members I don't want to know about:
Luckily I discovered I can selectively "Disconnect" using a button in eclipse two along from debug/run. It has no keyboard shortcut and I'm not sure why but it will reconnect when I next trigger an exception. This is debugging as I know and love it in Android and Eclipse, still probably easier than GDB.
For arguments sake I've even replaced:
//TTF_Font *gFont = TTF_OpenFont( "res/stubbornFont.ttf", 160 );
with
TTF_Font *font=TTF_OpenFontRW(SDL_RWFromFile("res/stubbornFont.ttf", "rb"), 1, 160);//Same difference
UPDATE/EDIT
Here is the solution I was really looking for,
turning off uncaught exceptions in eclipse, it really is just that, Window->Preferences->Java->Debug and it's the very first box at the top for me.
I am converting someones Palm Pilot code into an Android application for them. This involves me using the NDK to read from one of their already built libraries. For this, I need to create several new functions.
void __stdcall FreeRelay(void){
RelayAPI_DataValid=0;
RelayAPI_SetBaud=0;
RelayAPI_get=0;
RelayAPI_put=0;
RelayAPI_flush=0;
RelayAPI_delay=0;
RelayAPI_initilized=0;
}
void Java_my_MainMenu_FreeRelayJava( JNIEnv * env, jobject this ) {
RelayAPI_DataValid = 0;
RelayAPI_SetBaud = 0;
RelayAPI_get = 0;
RelayAPI_put = 0;
RelayAPI_flush = 0;
RelayAPI_delay = 0;
RelayAPI_initilized = 0;
}
Now, my error is in the last line of the second method. I had originall had it spelled RelayAPI_initialized, I know that thats correct, but I'm not going through the trouble of changing all of this C code for the typo. I'll make my function fit with the old code. Anyway, I tried ndk-build and got this.
Now in between those separate ndk-build calls, I fixed the error. But it still is telling me in line 615 there is an error dealing with RelayAPI_initialized but its NOT THERE. I don't know whats going on, and I really know very little about C. I saved my files with the updated information then called ndk-build. WHAT AM I MISSING?
maybe you can grep to find if other var like RelayAPI_* are defined GLOBALLY in some c code or header file.
if not, define it, or don't set it.
it will resolve compilation error... but probably it wont work
do a clean of your build. so the party built stuff is deleted and you get a full rebuild.