I am learning about Android process execution, and lacking info about execution of native binaries.
Normally, ELF binary is parsed and loaded by Linux via exec syscall.
This call is still available to the native applications.
Java environment has its own exec which actually asks Zygote to run ActivityThread.main
Questions: will the native exec be able to load Java-based app?
if so, where does the Zygote hook into that process?
Will the Java exec be able to run native binary that is a statically linked ELF with just an entry point?
if so, can you point me to the system code that does that?
Related
I'm trying to debug an ARMv7 Android app .so with gdbserver. I've downloaded the android NDK for Mac and and pushed the gdbserver located at prebuilt/android-arm/gdbserver/gdbserver to the machine. I'm using Nox App Player v3.0 Mac version.
When attaching to the process, it produces this output:
$ adb shell gdbserver :5055 --attach 2289
Attached; pid = 2289
ptrace(regsets_fetch_inferior_registers) PID=4034: Device or resource busy
ptrace(regsets_fetch_inferior_registers) PID=4034: Function not implemented
ptrace(regsets_fetch_inferior_registers) PID=4034: Function not implemented
Warning: ptrace(regsets_store_inferior_registers): Device or resource busy
Warning: ptrace(regsets_store_inferior_registers): Function not implemented
Warning: ptrace(regsets_store_inferior_registers): Function not implemented
writing register 0: Function not implemented
Exiting
The app I tried to attach to then hangs. The rest of the emulator/phone works, and I can use the home and menu buttons to close the app. It's just the app that it tried to attach to that stops working until I restart it. I can attach to other random process numbers, even if it does complain a bit about it. Apps have this problem even if I attach while they are suspended. Checking the /data/data/ folder for the application shows that the .so the running app is using is ARMv7.
I tried using the prebuilt/android-x86/gdbserver/gdbserver version of gdbserver to see what would happen. This version loads the process fine with no hangs, and I can connect to it with the GDB the NDK provides. Of course, this also means I can't load the .so, because the gdbserver version is x86 instead of ARM. Is there any way to fix this?
Maybe you can compile the gdbserver for your target machine.
You can type uname -m for checking platform.
I have an android application that consists of a Java based APK, native executable, and native library. The apk talks to the native (root NDK c/c++) executable and library over a socket.
I'm not sure if it matters but the executable and library are compiled via cmake, and copied to be executable and then run as root. I need to get some type of debugging going with breakpoints and such, regardless of if it's directly in android studio or via command line.
You would need to run gdbserver on the device and let it attach to your executable
gdbserver comes prebuilt with ndk, usually under <ndk>/prebuilt/android-arm/gdbserver/
Copy gdbserver binary to your device, for instance to /data/local/tmp and give it executable permissions with chmod
If your executable is already running, find its PID with ps command and attach gdb to it:
gdbserver :5039 --attach <PID>
Note that 5039 is port number that is usually used for debugging with gdb, you can use your own if you like
set up a port forwarding from device to pc with
adb forward tcp:5039 tcp:5039
Run gdb locally, note that you need arm targeted gdb that comes with ndk too, usually at
<ndk>toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gdb
Attach gdb to your process
target remote :5039
And from here you need to use gdb commands that match your debugging expectations (set breakpoints, load symbols, step through etc), for examples use cheatsheet or ask in comments
I have a normal Java application I am running on DalvikVM after converting the byte code into dex code. I manually invoke the DalvikVM from the adb shell to execute it. To enable debugging, I explictly pass arguments to DalvikVM: "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y"
Using DDMS I can attach put breakpoints and trace code but DDMS's memory allocation tracker doesn't work. I tried Googling and the only relevant thing I could find was this:
Because command-line applications don't include the client-side DDM
setup, features like thread monitoring and allocation tracking will
not be available in DDMS.
Source: Basic Dalvik VM Invocation
So how do I include the client-side DDM setup? Is there any special code I need to add in order to make the application DDM aware or pass extra params to Dalvik?
I have been modifying Dalvik VM and I was wondering if there is a way that I can build only Dalvik VM from android source code.
If I can build Dalvik VM separately then how can I add the modified Dalvik VM to Android system?
Once you have done the initial build (I am assuming you have followed the steps described here: http://source.android.com/source/building.html), you can build just the Dalvik VM by doing
$ make libdvm
When the build is done, you will see some output near that looks something like
Install: out/target/product/generic/system/lib/libdvm.so
This is the newly built Dalvik VM (or more specifically, the library in which the Dalvik VM is implemented). The last part of the out path is where the installed file is expected, in this case /system/lib/libdvm.so. To install your new VM, first ensure you are root and then remount the system partition
$ adb root
adbd is already running as root
$ adb remount
remount succeeded
you can now push the new VM to the system:
$ adb push out/target/product/generic/system/lib/libdvm.so /system/lib/libdvm.so
Note that if you run the emulator, this change is not permanent, since the emulator reloads system.img each time it starts. On a device however, the change will be permanent. Also, since Android preloads a process called Zygote that is later used to fork application processes, you need to reboot the system to make the new VM be used in applications
$ adb reboot
You can actually rebuild virtually all Android components this way. The general steps are
Find Android.mk in the source tree for the component you wish to rebuild
Find the module name. In the case of the Dalvik VM, the line looks like this: LOCAL_MODULE := libdvm
make the module name, which is libdvm for Dalvik VM
The built file will be announced in the build output and start with Install:. In the case of the Dalvik VM, this is Install: out/target/product/generic/system/lib/libdvm.so
adb root and adb remount, then adb push the built file to a running Android system. The destination path is the last part of the out file path, which in the case of dalvik is /system/lib/libdvm.so
Can anyone tell me how to run ndk-gdb from within emacs using gdb-mode? I'm currently running it in a shell buffer. What I'd love to have is a way to automatically sync a source file buffer with the current pc in gdb when I break or step. Anything more, like setting breaks from source, buffers that show gdb locals etc., and key shortcuts for gdb commands would be gravy.
Background: I'm developing in GNU Emacs 23.1.90.1 (i386-apple-darwin10.5.0, NS apple-appkit-1038.35) of 2010-12-15 on OSX 10.6.6 with android-mode, using android-ndk-r5b and mixed java/c/c++ code for an android target.
Android-mode and shell (running ndk-gdb) within emacs allow me to see just about everything I need, but my setup would be more convenient if I could get a source buffer to sync with the debugger, or get the equivalent of what is described in EmacsWiki here.
FYI, I'm currently using eclipse for java side debugging and development, but finding it unstable and difficult to set up for native work, despite the availability of sequoyah, and besides, eclipse is no emacs.
[Appended]
Running M-x gdb with ndk-gdb as the gdb command (see below) results in a buffer called gud with a modeline saying "(Debugger:run [initializing...])". The buffer does not accept gdb commands, nor does it accept emacs gdb commands - (M-s, M-n etc result in <>
Output:
Current directory is /Users/jpschelter/
Android NDK installation path: /Developer/android-ndk-r5b
Using specific adb command: /Developer/android-sdk-mac_x86/platform-tools/adb
...
... ...
...
(no debugging symbols found)
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0xafd0e21c in nanosleep () from /Developer/Projects/ECS/DIGG/Projects/droid/obj/local/armeabi/libc.so
(gdb) Undefined command: "1-inferior-tty-set". Try "help".
(gdb) Undefined command: "2-gdb-set". Try "help".
(gdb) Undefined command: "3-gdb-set". Try "help".
(gdb) Undefined command: "4-file-list-exec-source-files". Try "help".
(gdb) Undefined command: "5-file-list-exec-source-file". Try "help".
(gdb) Undefined command: "6-gdb-show". Try "help".
(gdb) Undefined command: "7-stack-info-frame". Try "help".
(gdb) Undefined command: "8-thread-info". Try "help".
(gdb) Undefined command: "9-break-list". Try "help".
Buffers called *threads of*, *input/output of* and *breakpoints of* are also created, but are empty.
Browsing through the gdb-mi.el source of my emacs, and comparing to the gdb-debug-log output, it looks like gdb-mi is trying to send these parameters to a gdb executable, but gdb-server is not responding to the commands as expected?
Note that running M-x gud-gdb with the command-line for ndk-gdb seems to result in the equivalent of running ndk-gdb within a shell, so the issue seems to be within the configuration of gdb-mode in emacs.
I had the exact same problem when running gdb under emacs: the *gud* window was not responding to commands. However, ndk-gdb was working well in a shell. To make it work under the emacs gud UI, I had to modify the ndk-gdb script a bit.
On call to GDB (last line), do this:
$GDBCLIENT --annotate=3 -x `native_path $GDBSETUP`
The --annotate=3 option is mandatory for emacs gud interface, it cannot work without it (that's why *gud* was not responding).
But you're halfway. Now it will work, but only if you invoke ndk-gdb while in a buffer from a file at the root of the project (like AndroidManifest.xml). Since this is very unlikely most of the time because you are a C/C++ programmer and the sources you're working on are under the jni directory or deeper, you need to do a little more. The ndk-gdb script is a bit buggy and it will happily confuse you on this one (and gdb itself won't help much either).
Search the script for "PROJECT=$OPTION_PROJECT". You will be in a long if...else...fi clause which is in charge of finding the root of the project (if it has not been given with the --project option, though doing so WILL NOT resolve the issue I talk about, see below). After the fi, add this line:
cd $PROJECT
For some obscure reason, the script DOES NOT cd to the project root directory. This leads to very wrong behaviour when dealing with the gdb.setup file where the script assumes to be at project root. Adding this line will fix it.
Make sure you call ndk-gdb within emacs with the usual command:
(gdb "ndk-gdb ...")
Do not use gud-gdb (oddly, this is old emacs way of using gdb and has nothing to do with the nice UI you're searching for). Replace ... with your arguments, (concat ...) or anything you wish. I strongly recommend to use the --project option anyway. If you don't and you are in a buffer for a file which is out of the project, the script won't find the root. Worse, if you're in a file in another Android project, it will find the root of that project instead (maybe even copying gdb.setup and stuffs into it before failing the gdb session). So give that damn --project option. If you're using emacs desktop command set, do this:
(gdb (concat "ndk-gdb --project=" desktop-dirname ...))
(assuming your .emacs.desktop is at the root of the project, of course).
Now you can finally debug with gud UI, setting breakpoints at source level.
Note that I use emacs 23.3.1 (gdb-ui.el), so there is no need to have 24 for this to work.
Have you tried this?
Add android-sdk-mac_x86/platform-tools and android-ndk-r5b to PATH environment. After that, start gdb mode with ndk-gdb script.
M-x gdb
Run gdb (like this): ndk-gdb --verbose --start --project=your_NDK_project_dir