Android: debug shared library - android

I'd like to debug android NDK application, more precisely - I want to check what arguments (r4 - r8 r1 - r4 registers) are passed to function from shared library in apk.
What I have tried:
I've run gdbserver :1234 --attach on the device
I've run arm-linux-androideabi-gdb from ndk package by Google on the PC
I've set solib-search-path and written target remote :1234
So far, so good. Now I try to set breakpoint (break <function name>) (function name from
objdump), but I get repond: Cannot access memory at address <...>. info shared says the library is loaded, Does it mean I can't set breakpoint there? Or am I doing something wrong?

The ndk-build skript does much more then you would expect.
One of the things it to copy both the gdbserver, a file called gbd.setup and the generated .so into a hidden folder called .obj/armei/
There you will have to add the libraries you would like to debug because the symbols are referencing them.
The libraries are copied from the device to your PC by some adb shell pull - commands.
I wrote an article about the topic at: http://www.professional-android-development.com/articles/android-ndk-large-c-projects
When placing the libraries into the right folder, you can set your breakpoints.
Still, for some internal reasons, they can fail.
In this case run ndk-gdb --start (the first try will also fail), enforce the application to close and rerun ndk-gdb --start (this time not forcing the application to close).

"Cannot access memory at address <...>" usually means there is a mismatch between the .so file on your PC and the .so file that is on Android. Did you recompile and reinstall?
Btw, what is the reason you're not using "ndk-gdb"? That's a script (part of the NDK) that takes care of all the gory details for you.

Related

Android ART - Usage of .oat file in /dalvik-cache/?

while playing around with Android ART and the "native" code file .oat/.elf which is created at the app installation process, I did notice something odd.
For my understanding, if the device is using ART (Android >= 5.0), the app will start with the compiled oat file (/data/dalvik-cache/arm64/).
Thats why I was kinda surprised when checking the used fd's of an app and did not find the file there. Only the normal apk (/data/app//base.apk) is listed there.
Check this output of my "ls -l /proc/PID/fd"
So I thought maybe it's just not listed there. So I did exchange the oat file of that app by myself by compiling another classes.dex with the dex2oat tool.
So even after changing the file, the app starts normally without any strange messages or errors (also in logcat).
What is the explanation for this? What is the detailed process Android does when starting an app under ART?
I hope someone can clear that up for me. Thanks a lot.
Based on #Paschalis comment, I investigated here and the oat file is indeed memory mapped on Android 5.0 devices (emulator):
a6af4000-a6af9000 r--p 00000000 1f:01 7366 /data/dalvik-cache/x86/data#app#my.app.works-1#base.apk#classes.dex
Check via:
cat /proc/<PID>/maps | grep dex
Sadly this isn't true anymore for Android 6.0 devices (Nexus 5 & arm-Emulator).
The odex file is within the /data/app/<APP>/oat/<ARCHITECTURE>/ folder as 'base.odex`
/data/app/app.app.works-1/oat/arm/base.odex
I still haven't found a valid reference for this, it is based on experiments and observations

How to tell where a shared library is loaded in process address space?

I'm trying to debug a shared library to which I have the source code and debugging symbols for using gdb.
I do not have debugging symbols or code for the process that actually uses this shared library (I compile it myself, so I can have everything, but the resulting binary is stripped, to simulate a situation where I don't have the code).
The process prints the address for target function foo I'm trying to debug, to test that gdb knows the right location for symbols from the shared library. foo exists the my shared library.
My method of printing it is adding the following line to the binary that uses my shared library:
printf("%p\n", foo)
...and to add complexity, this is an Android system I'm debugging remotely.
The scenario I'm trying follows:
On target:
root#phone:/proc/23806 # gdbserver --attach :5555 23806
Attached; pid = 23806
Listening on port 5555
Remote debugging from host 127.0.0.1
On host:
[build#build-machine shared]$ /home/build/shared/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7/bin/arm-eabi-gdb
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
For bug reporting instructions, please see:
(gdb) target remote :5555
Remote debugging using :5555
0xb6f17fa0 in ?? ()
(gdb) add-symbol-file out/target/product/armv7-a-neon/symbols/system/lib/libShared.so
The address where out/target/product/armv7-a-neon/symbols/system/lib/libShared.so has been loaded is missing
Now I know what I need - the relocated .text section of this shared library in the process address space, but I have no idea how to find it.
I tried /proc/23806/smaps:
root#phone:/proc/23806 # cat maps | grep Shared
b6ea0000-b6edb000 r-xp 00000000 b3:10 3337 /system/lib/libShared.so
b6edc000-b6ede000 r--p 0003b000 b3:10 3337 /system/lib/libShared.so
b6ede000-b6edf000 rw-p 0003d000 b3:10 3337 /system/lib/libShared.so
And the .text section is located at 0x0003ff00 in the .so file:
[build#build-machine shared]$ objdump -h out/target/product/armv7-a-neon/symbols/system/lib/libShared.so | grep text
7 .text 0002835c 00003ff0 00003ff0 00003ff0 2**3
So now I'm supposed to have the address where my shared library is located:
0xb6ea0000+0x00003ff0=0xb6ea3ff0 (where the library is loaded+.text offset from the beginning)
So I did:
(gdb) add-symbol-file out/target/product/armv7-a-neon/symbols/system/lib/libShared.so 0xb6ea3ff0
add symbol table from file "out/target/product/armv7-a-neon/symbols/system/lib/libShared.so" at
.text_addr = 0xb6ea3ff0
(y or n) y
Now I tried setting a breakpoint for the foo function from my shared library:
(gdb) b F10
Breakpoint 1 at 0xb6ea41de: file frameworks/native/test/shared/src/shared, line 122.
And it doesn't match the value from my binary which was 0xb6ea4217 (printed on the screen).
It appears I did not provide the correct memory location for the shared library, but I'm clueless why.
Any help is appreciated!
Okay, so after scratching my head on this one on and off for some time now, I finally discovered what went wrong.
The solution came from a different angle, I recently had to debug some code I had partial sources for, so I did hybrid source/assembly debugging and noticed that when debugging the source, things start to skew - I can't use next instruction as it will crash - but when I debug instructions everything works great!
I then added and compiled the following short code in the AOSP tree:
int main(int argc, char** argv)
{
int first,second;
first=1;
second=2;
return first+second;
}
And, as expected, it would not debug properly (assembly debugging works, source debugging does not).
Then I noticed argc has been OPTIMIZED OUT!
So... what really happened here was a compiler optimization that prevents debugging of source code as there is no 1:1 relations between the generated instructions and the actual source. Since I left the default build flags in the hands of the AOSP build script, I got these weird debugging issues...
Thanks #EmpyloyedRussian for the assistance!
Your best bet is to run (gdb) x/10i 0xb6ea41de and (gdb) x/10i 0xb6ea4217.
I am guessing that either GDB, or your program prints the address of the PLT entry, and not the real address of foo.
P.S. Your method of calling add-symbol-file appears to be correct.

execute permissions on fuse/fat filesystem

've successfully cross compiled ruby for android and everything goes ok in the emulator.
but while i'm testing these funny things on my device ( Nexus4 ) i noticed that /sdcard ( or /storage/emulated/0 ) is a fuse mount with no execution permissions.
how can i execute something on the sdcard?
i saw that on linux you can pass it as argument to the linker, in android this does not work, /system/bin/linker want a pointer to a special struct, i believe that i can write a small c program that create that structure and run the linker to execute a readable program.
but what about shared libraries? ruby load tens of shared libraries ( everytime you have a require ), i bet that execute permissions are required for loading shared libraries.
moving the executable to /data/data/my.app.name/files/ or any other place is not a solution, my binaries are very fat ( statically linked ) and users should be free to specify any location where storing them.
thanks in advance for any help.

Analyzing coredump from java app on android

I have a core dump from dalvik process (it was com.android.browser).
I definitely know, that process was terminated somewhere in JNI module.
Also, I have all debug symbols for that device. But I can't invoke gdb for this coredump.
I'm trying like this:
arm-eabi-gdb ../symbols/system/bin/dalvikvm android.browser_5879_1354575922.core
but gdb says:
warning: core file may not match specified executable file.
.....
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
Core was generated by `com.android.browser'
Program terminated with signal 11, Segmentation fault.
so (gdb) info sharedlibrary displays nothing:
No shared libraries loaded at this time.
How to properly load coredump for dalvikvm process?
Ok, answer was to provide app_process as image name:
arm-eabi-gdb symbols/system/bin/app_process android.browser_5879_1354575922.core

Eclipse & Seqoyah - Tries to connect to gdbserver before application is launched on device

I've setup my Eclipse to debug the Native side of my application using Eclipse & Seqoyah and added the appropriate C/C++ Application Debug Configuration.
The problem is it seems that Eclipse is trying to initiate a connection with the applications GDB server even before it launches it. I'm not to sure how to change the order in which Eclipse tries to do things with Debug Configurations. Any help would be appreciated (as always).
http://wiki.eclipse.org/Sequoyah/ndk_guide
31-gdb-set confirm off
31^done
(gdb)
32-gdb-set width 0
32^done
(gdb)
33-gdb-set height 0
33^done
(gdb)
34-interpreter-exec console echo
34^done
(gdb)
35-gdb-show prompt
35^done,value="(gdb) "
(gdb)
36-gdb-set auto-solib-add on
36^done
(gdb)
37-gdb-set stop-on-solib-events 0
37^done
(gdb)
38-gdb-set stop-on-solib-events 1
38^done
(gdb)
39-target-select remote localhost:5039
&"Remote communication error: Connection reset by peer.\n"
39^error,msg="Remote communication error: Connection reset by peer."
(gdb)
40-gdb-exit
40^exit
Remote communication error: Connection reset by peer.
I managed to solve this one.
There should be two Debug Configurations available to your Java / C++ Native project. The first is for the Java side of things and the second is for the C++ side of things.
Make sure you have setup your environment according to: http://wiki.eclipse.org/Sequoyah/ndk_guide
Set a breakpoint just after the JNI Shared library is added or in your Activities onCreate.
Debug your application using its default debug configuration.
In a shell navigate to your project directory and issue $NDK/ndk-gdb (where $NDK is the location of your Android Native Development Kit).
Debug your application using its Native debugger that you created in the Sequoyah guide.
If all goes well you should be able to step into JNI code and when your application crashes, see where in your source it crashed.
I've not yet found a way to setup through the actual source yet, if anyone does please post here.

Categories

Resources