如何调试Android / GDB / Qt问题?

时间:2016-04-13 08:55:18

标签: android c++ qt debugging android-ndk

我用Qt开发了一款Android应用程序已有好几个月了。我曾经能够在Qt Creator中调试没有问题,但现在调试器无法启动。部署过程有效 - 可以从设备GUI启动应用程序。

示例项目构建并可以正常调试。

我正在使用NDK 10e,因为后来有任何东西混淆了Creator,它告诉我Qt人没有使用最近的版本。

我有最新版本的SDK,在OS X上开发。

调试器日志窗口以此结束:

~"Loaded symbols for /Users/tjdaniel/projects/qt/5.6.0/plugins/sensors/libqtsensors_android.so\n"
~"Reading symbols from /Users/tjdaniel/projects/build/localization/android/Debug/liblocalization.so..."
sReading /Users/tjdaniel/projects/build/localization/android/Debug/liblocalization.so......

dHANDLE GDB ERROR: The gdb process was ended forcefully
dGDB PROCESS FINISHED, status 1, exit code 11
dNOTE: ENGINE ILL ******

以下是adb logcat的输出:

W/linker  (12790): libqtforandroid.so: unused DT entry: type 0x1d arg 0x8d9a
W/linker  (12790): Unsupported flags DT_FLAGS_1=0x81
I/Qt      (12790): qt start
W/linker  (12790): libqandroidbearer.so: unused DT entry: type 0x1d arg 0x174f
W/linker  (12790): Unsupported flags DT_FLAGS_1=0x81
W/linker  (12790): libqtmedia_android.so: unused DT entry: type 0x1d arg 0x51da
W/linker  (12790): Unsupported flags DT_FLAGS_1=0x81
W/linker  (12790): libqtsensors_android.so: unused DT entry: type 0x1d arg 0x1076
W/linker  (12790): Unsupported flags DT_FLAGS_1=0x81
I/Qt      (12790): Sensors start
W/linker  (12790): liblocalization.so: unused DT entry: type 0x1d arg 0x29f5f4
D/        (12790): (null):0 ((null)): QML debugging is enabled. Only use this in a safe environment.
I/Qt JAVA (12790): DEBUGGER: extra parameters: Bundle[{debug_ping=true, gdbserver_socket=/data/data/org.qtproject.example.localization/debug-socket, qml_debug=true, gdbserver_command=/data/data/org.qtproject.example.localization/lib/libgdbserver.so --multi +/data/data/org.qtproject.example.localization/debug-socket, qmljsdebugger=port:56956,block,services:DebugMessages,QmlDebugger,V8Debugger,QmlInspector, ping_socket=org.qtproject.example.localization.ping_pong_socket}]
I/Qt JAVA (12790): DEBUGGER: removing gdb socket /data/data/org.qtproject.example.localization/debug-socket
I/Qt JAVA (12790): DEBUGGER: starting /data/data/org.qtproject.example.localization/lib/libgdbserver.so --multi +/data/data/org.qtproject.example.localization/debug-socket
I/Qt JAVA (12790): DEBUGGER: gdbserver started
I/Qt JAVA (12790): DEBUGGER: waiting for socket at /data/data/org.qtproject.example.localization/debug-socket, attempt 0
I/Qt JAVA (12790): DEBUGGER: waiting for socket at /data/data/org.qtproject.example.localization/debug-socket, attempt 1
I/Qt JAVA (12790): DEBUGGER: socket ok
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Debug socket accepted
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/Qt JAVA (12790): DEBUGGER: Waiting for debug socket connect
I/Qt JAVA (12790): DEBUGGER: go to sleep
I/ConfigService( 1968): onDestroy
W/ActivityManager(  845): Launch timeout has expired, giving up wake lock!

关于如何调试这个的任何建议?无法使用调试器正在扼杀我。我已经擦除并重新安装了与Qt相关的一切......没有运气。

3 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,而且使用的SDK工具并不是QT的良好支持。安装25.2.5工具后,就像说here一样。

答案 1 :(得分:0)

我遇到了同样的问题,截至今天,我发现的唯一方法是在AndroidManifest.xml中将Target android SDK设置为API 23(Android 6)或更低版本

答案 2 :(得分:0)

我有同样的问题XD:

  1. 确保双方(此AppIDE)不会被任何一方阻止 防火墙。
  2. 确保在IDE连接到GNU调试服务器之前,您的应用程序不会退出
  3. 以下是Qt调试服务器源(xd/DebugServer.java)的独立版本:

    package xd;
    
    //beaware: before call to "xd.DebugServer.start();" Gdb Server:
    //  Ensure all native libraries you want debug break in are loaded
    //  just add to class that calls "start" static initalizer sample:
    //      static { System.loadLibrary("tun2http"); } //this may load "libs/armeabi-v7a/libtun2http.so"
    //  Ensure both sides (this App and IDE) are NOT blocked by any firewall
    //
    //you can ignore signals using below (but may need to change SIG33):
    //handle SIG33 nostop noprint noignore pass
    
    import android.util.Log;
    import android.content.pm.PackageManager;
    import android.content.pm.ApplicationInfo;
    import android.net.LocalServerSocket;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.DataOutputStream;
    
    public class DebugServer {
        public static final String TAG = "XD_GDB"; // string used for Log.x (the colon helps cut out false positives)
        private static Process m_debuggerProcess = null; // debugger process
    
        private static void debugLog(String msg) {
            Log.i(TAG, msg);
        }
    
        //do not use this or IDE will fail to connect to debug server
        public static String flushLog() {
            try {
                String command = "logcat -d";
    
                Process process = Runtime.getRuntime().exec(command);
                BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
                StringBuilder log=new StringBuilder();
                String line = "";
                while ((line = bufferedReader.readLine()) != null) {
                    log.append(line + System.lineSeparator());
                }
                //process.waitFor();
                bufferedReader.close();
                return log.toString();
            } catch (IOException e) {
                 // Handle Exception
            }
            return "";
        }
    
        private static class DebugWaitRunnable implements Runnable {
    
            public DebugWaitRunnable(String pingPongSocket) throws  IOException {
                socket = new LocalServerSocket(pingPongSocket);
            }
    
            public boolean wasFailure;
            private LocalServerSocket socket;
    
            public void run() {
                final int napTime = 200; // milliseconds between file accesses
                final int timeOut = 5000; // ms until we give up on ping and pong
                final int maxAttempts = timeOut / napTime;
    
                try {
                    android.net.LocalSocket connectionFromClient = socket.accept();
                    debugLog("Debug socket accepted");
                    BufferedReader inFromClient =
                            new BufferedReader(new InputStreamReader(connectionFromClient.getInputStream()));
                    DataOutputStream outToClient = new DataOutputStream(connectionFromClient.getOutputStream());
                    outToClient.writeBytes("" + android.os.Process.myPid());
    
                    for (int i = 0; i < maxAttempts; i++) {
                        String clientData = inFromClient.readLine();
                        debugLog("Incoming socket " + clientData);
                        if (!clientData.isEmpty())
                            break;
    
                        if (connectionFromClient.isClosed()) {
                            wasFailure = true;
                            break;
                        }
                        Thread.sleep(napTime);
                    }
                } catch (IOException ioEx) {
                    ioEx.printStackTrace();
                    wasFailure = true;
                    Log.e(TAG,"Can't start debugger" + ioEx.getMessage());
                } catch (InterruptedException interruptEx) {
                    wasFailure = true;
                    Log.e(TAG,"Can't start debugger" + interruptEx.getMessage());
                }
            }
    
            public void shutdown() throws IOException
            {
                wasFailure = true;
                try {
                    socket.close();
                } catch (IOException ignored) { }
            }
        };
    
    //beaware: before call to "start" Gdb Server:
    //  Ensure all native libraries you want debug break in are loaded
    //  just add to class that calls "xd.DebugServer.start();" static initalizer sample:
    //      static { System.loadLibrary("tun2http"); } //this may load "libs/armeabi-v7a/libtun2http.so"
    //  Ensure both sides (this App and IDE) are NOT blocked by any firewall
        public static boolean start(android.app.Activity activity) {
        try {
            //System.loadLibrary("gnustl_shared");
    
            final int napTime = 200; // milliseconds between file accesses
            final int timeOut = 30000; // ms until we give up on ping and pong
            final int maxAttempts = timeOut / napTime;
    
            PackageManager pm = activity.getPackageManager();
            ApplicationInfo appInfo = pm.getApplicationInfo(
                activity.getPackageName(), android.content.pm.PackageManager.GET_CONFIGURATIONS
            );
    
            final String packagePath = appInfo.dataDir + "/";
            //using constant '"/data/data/"' instate of 'appInfo.dataDir+"/"' since that does not work old code was "extras.getString("gdbserver_socket");"
            final String gdbserverSocket = "/data/data/" + appInfo.packageName + "/debug-socket";
            final String gdbserverCommand = packagePath + "lib/libgdbserver.so --multi +" + gdbserverSocket;
    
            debugLog("removing gdb socket " + gdbserverSocket);
            new File(gdbserverSocket).delete();
    
            debugLog("starting " + gdbserverCommand);
            m_debuggerProcess = Runtime.getRuntime().exec(gdbserverCommand);
            debugLog("gdbserver started");
    
            int i;
            for (i = 0; i < maxAttempts; ++i) {
                debugLog("waiting for socket at " + gdbserverSocket + ", attempt " + i);
                File file = new File(gdbserverSocket);
                if (file.exists()) {
                    file.setReadable(true, false);
                    file.setWritable(true, false);
                    file.setExecutable(true, false);
                    break;
                }
                Thread.sleep(napTime);
            }
    
            if (i == maxAttempts) {
                debugLog("time out when waiting for debug socket");
                return false;
            }
    
            debugLog("socket ok");
    
            final String pingSocket = appInfo.packageName + ".ping_pong_socket";
            debugLog("pingSocket: " + pingSocket);
            DebugWaitRunnable runnable = new DebugWaitRunnable(pingSocket);
            Thread waitThread = new Thread(runnable);
            waitThread.start();
    
            debugLog("Waiting for debug socket connect");
            for (i = 0; i < maxAttempts && waitThread.isAlive(); ++i) {
                if(i % 10 == 0)
                    debugLog("Waiting attempt: " + i);
                Thread.sleep(napTime);
            }
    
            if (i == maxAttempts) {
                debugLog("time out when waiting for ping socket");
                runnable.shutdown();
                return false;
            }
    
            if (runnable.wasFailure) {
                debugLog("Could not connect to debug client");
                return false;
            } else {
                debugLog("Got pid acknowledgment");
            }
    
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        }
    
        public static void stop(android.app.Activity activity) {
            if (m_debuggerProcess != null)
                m_debuggerProcess.destroy();
            System.exit(0);// FIXME remove it or find a better way
        }
    } //class GdbServer