I have a native C++ app which is supposed to run on an Android device. The application crashes at the startup, most likely when calling a function from a linked library. I am trying to debug it with gdb, but I can't succeed.
I am starting gdbserver on the Android device on some arbitrarily picked port (2000):
shell#msm8996: gdbserver :2000 my_app
Process my_app created; pid = 3420
Listening on port 2000
Now I am trying to attach to this process on my Host system (Windows 7) with gdb that was provided in Android-NDK.
C:\> gdb
(gdb) attach 3420
Can't attach to process.
(gdb) target remote :2000
:2000: The system tried to join a drive to a directory on a joined drive.
What is the problem?
EDIT:
Prior to running gdb I forwarded the port 2000 using adb:
adb forward tcp:2000 tcp:2000
This at least helped me to establish some communication, but:
(gdb) target remote :2000
Remote debugging using :2000
warning: Architecture rejected target-supplied description
Remote 'g' packet reply is too long: 00000000000000000000000000000...
On the device side:
Listening on port 2000
Remote debugging from host 127.0.0.1
readchar: Got EOF
Remote side has terminated connection. GDBserver will reopen the connection.
Listening on port 2000
You are most probably using different architecture / version of gdb. When you start the gdb, it displays a line like (I am showing what my GDB shows):
This GDB was configured as "--host=x86_64-linux-gnu
--target=arm-Linux-android"
Check if this matches with your phone's architecture.
Downloading the correct GDB version may solve your problem.
Related
I've been trying to setup ADB remote debugging for Qt.
Scenario:
Remote development server with QT
Local laptop with connected phone
Solution:
I tunnel all the traffic on port 5037 (default adb port) through a Remote Port Forwarding SSH session. Works Fine.
The commands I execute:
# Kill old adb server.
devhost$ adb kill-server
# Activate adb server on client
laptop$ adb start-server
# Start ssh tunnel. Hide/minimize this window not to close it by accident
laptop$ ssh -XC -R 5037:localhost:5037 <your devhost machine>
QT on dev. server detects the mobile, attempts to the deploy.
The app gets deployed. The result FEELS GOOD. ~~With dev server in another country. It's optic fiber all the way from server right to my desk... But not so fast...
When all of the sudden QT shouts about being unable to connect with localhost:5039
5039? What is it needed for? I tried tunelling 5039 but I'm basically in a blind-spot. The error is gone but the app is stuck at waiting for debugger and no further messages from QT no errors.
Nothing. It just hangs indefinitely.
On the mobile there's the standard waiting for debugger msg at the bottom. (Note: the app got deployed by qt and launched).
Ideas?
The only informative message within log is:
W ActivityThread: Application org.qtproject.APPNAME is waiting for the debugger on port 8100...
8100? now what is that? Is that supposed to be taken care of by ADB/QT or what
I can see all the logcat events on dev-server while the app on mobile 'keeps waiting' ..browser entire logcat log. the only sensible message regarding debugging is that the app keeps waiting on and on.
Local debugging of same app through USB works FINE.
The remote server is able to compile deplay and launch the app on mobile phone, however dubugging is an exercise in futility due to the described behaviour.
I have noticed that during debugging attempts, adb on local laptop keeps opening new ports and listening on these. what the heck is going on here?
On the contrary, when debugging over USB, 5037 is the only port used everything works and adb does not go into the new-port-creation frenzy.
I've trawled through many of the answers here regarding socket access via native code on Android, and others regarding socket access for "androidTest" instrumented tests, but none are able to fully explain some odd behaviour I'm seeing.
Android Studio 2.3.3 on Windows 10, NDK 15.1.x, build tools 25.0.3. Building with Cmake. I am porting some native code over to Android intended to be distributed as a library that is wrapped in a Java JNI-based API. This part seems to be working fine; at least I can debug and log into the native code and see where things go wrong.
I've created a few instrumented tests to exercise the JNI, but it looks like the native side does not have access to sockets, even if the test app that Android Studio wraps up for your intrumented tests does (i.e., it has the INTERNET permission applied, and I can see that it is part of the pushed manifest of the test app. I also applied the ACCESS_NETWORK_STATE perm in a fit of pique.)
That is, parts of the library know how to set up and use TCP sockets (datagram and stream; in this case stream) and resolve DNS, which fails (This might be a bug in my port, since the device itself still seems to resolve DNS based on the adb shell output below). If I test with an IP address it retries until it fails. Each call to socket() returns an ERRNO of 11 EAGAIN ("Try again").
If I use the adb shell to login to the device under test over USB, I can ping and use curl, etc. But, as soon as I run-as as the test app I am no longer allowed to use any network device.
shell#venice:/data/data/org.clvrmnky.library.test $ ping www.example.com
PING www.example.com (93.184.216.34) 56(84) bytes of data.
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
ping: sendmsg: Operation not permitted
^C
--- www.example.com ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2004ms
1|shell#venice:/data/data/org.clvrmnky.library.test $ ping -I wlan0 www.example.com
ping: SO_BINDTODEVICE: Operation not permitted
2|shell#venice:/data/data/org.clvrmnky.library.test $ curl -4 --verbose www.example.com/
* Trying 93.184.216.34...
* connect to 93.184.216.34 port 80 failed: Connection timed out
* Failed to connect to www.example.com port 80: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to www.example.com port 80: Connection timed out
7|shell#venice:/data/data/org.clvrmnky.library.test $
I won't paste it here, but wlan0 (and others) exists and is UP with a valid, reachable IP address. It is "Link encap:UNSPEC" which I admit I don't fully grok.
I'm making an assumption that the app failing on the successive socket calls and the inability to bind to a network device in and use it in an adb shell are related in some manner, but if someone has a reason why this may not be so, please let me know.
I've tried:
Invoking the test methods in a background thread, just in case the instrumented tests were running in the test app main thread.
Setting the StrictMode thread policy to permitAll() in the #Before clause of the test class.
Running with and without the INTERNET permission set in the test manifest. Without this permission it reaches the native code, but fails much earlier in the initialization. I'd have to dig into my notes to fetch more details about that. I assume that I need this permission. (Side note: if I enable INTERNET then the remote debugger can no longer attach to the device, so I can debug via logs only.)
It looks like instrumented tests, at least as of this writing, do not support access to raw sockets through the NDK. The .test app that is auto-created seemed to have everything it needed in the manifest (I checked base.apk right from the device).
Once a DemoApp was created with identical manifest settings I was able to open sockets, connect to them, do name lookups, etc. Furthermore, I was able to access the network via adb shell when running as ("run-as") the DemoApp.
There is still something strange going on, as I created a separate JNI app that opens sockets, and hacked an instrumented test against that. At least briefly adb shell running as ext.other.app.test did have internet access.
I am trying to remotely debug a pure C program on an Android device.
The Android device (target) is connected via USB to a host machine.
What I did was:
Copied from the target the following files:
/system/lib, /vendor/lib, /system/bin/app_process, and /system/bin/linker.
Target:
Copied gdbserver from NDK to the target device
Sent the exe that I want to debug
runned gdb server on target using ./gdbserver :5039 exec
this basically executes the process, and gets a pid
Host:
enabled the port adb forward tcp:5039 tcp:5039
runned: arm-eabi-gcc exec.
Then in gdb:
set solib-search-path ..., with the libraries that I pulled earlier from the target
target remote :5039
The arm-eabi-gcc can connect to the remote process, and even continue(c) the execution. However, I cannot set breakpoints. If I do, I get the following error:
Cannot access memory at address xxx.
Am I missing something here?
Thank you.
So, at host, in gdb shell, before specifying the remote's target port, I should type shared. This command loads the shared symbols.
Also, for compiling, I used -ggdb.
I'm porting an Linux C++ application to Android NDK and my app invokes ping to the shell to see the status of another machine for logging purposes. On my android port this fails for localhost:
# ping -c 10 localhost
ping: unknown host localhost
If I give another web address that appears to send, but no response is seen:
# ping -c 1 google.com
PING google.com (74.125.239.136) 56(84) bytes of data.
--- google.com ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Is localhost expected to work on Android to refer back to the android itself (not the host machine running the emulator as discussed here)? If not, is there some other way that will work?
Is ping expected to work on the Android emulator for Mac OSX or must I do something to allow the emulator to see the network fully?
I have built a binary excutable from pure C++ code and it prompts time error when running on android device.
How can I debug the pure native code for android? It seems that the existing methods are not for pure native code.
Step 1: Put the gdbserver and your unstripped native binary executable (suppose it is named testexec) on the android emulator. E.g. you can put it under folder /data/data/test. And use chmod command to add permissions to them.
Step2: Start gdb debugger. And this step consists of following sub-steps:
Step 2.1: Start gdb debugger of the emulator by typing command on your host machine terminal:
adb shell /data/data/test/gdbserver 10.0.2.2:1234 /data/data/test/testexec
The emulator will then listen on port 1234.
Step 2.2: Connect the gdb debugger of the local machine with the gdbserver of the emulator:
telnet localhost 5554
It will prompt:
Android Console: type 'help' for a list of commands
OK
Then input:
redir add tcp:1234:1234
to enable data redirection and then type
exit
Step2.3: Start the gdb debugger of the local machine. Input:
arm-linux-androideabi-gdb.exe YOUR_ EXECUTABLE_PATH_ON_LOCAL_MACHINE\testexec
After that, input
target remote localhost:1234
to connect to the gdbserver.
Finally, enjoy your debugging!
Android supports the use of GDB. However, I should note that if by "pure C++" you mean that there is no Java at all in the application, this is technically not allowed (although you can definitely do it). See the NDK page.