【问题标题】:Native Android GDB remote debug got SIGILL原生 Android GDB 远程调试得到 SIGILL
【发布时间】:2014-12-05 17:08:19
【问题描述】:

软件:官方 TI android 版本(源代码包),用于 AM335x 的 Jelly bean 4.2.2,(是的,arago/rowboat/TI 开发人员添加了对 vanilla aosp 的修改,但与我的问题无关。)

硬件:am335xevm_sk(基于 AM335x Cortex A8 SOC 的 TI 开发板)

我做什么:

  1. 构建系统并使用 sd 卡启动硬件。一切正常。

  2. adb 拉取 init.am335xevm.rc 文件,注释掉 rild 服务并将其推回,重启目标系统。我这样做是因为我想使用交叉调试器来远程调试 rild。

  3. 设置远程调试:adb forward tcp ports。并在目标系统上启动 gdbserver,如下:

    root@android:/ # gdbserver localhost:2345 system/bin/rild
    Process system/bin/rild created; pid = 829
    Listening on port 2345
    Remote debugging from host 127.0.0.1
    
  4. 远程调试,如:

    ma@ma-aspire:~/devkit/JB422$ PATH=$PATH:/home/ma/devkit/JB422/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin
    ma@ma-aspire:~/devkit/JB422$ arm-linux-androideabi-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:
    <xxxx://www.gnu.org/software/gdb/bugs/>. 
    (gdb) file /home/ma/devkit/JB422/out/target/product/am335xevm_sk/symbols/system/bin/rild 
    Reading symbols from /home/ma/devkit/JB422/out/target/product/am335xevm_sk/symbols/system/bin/rild...done.
    (gdb) set sysroot /home/ma/devkit/JB422/out/target/product/am335xevm_sk/symbols
    (gdb) target remote localhost:2345
    Remote debugging using localhost:2345
    __dl__start () at bionic/linker/arch/arm/begin.S:35
    35 mov r0, sp
    (gdb) n
    36 mov r1, #0
    (gdb) n
    37 bl __linker_init
    (gdb) n
    
    Program received signal SIGILL, Illegal instruction.
    0x4013a89e in __linker_init (elfdata=0xbee7bae0) at bionic/linker/linker.cpp:2030
    2030 extern "C" unsigned __linker_init(unsigned **elfdata) {
    (gdb) c
    Continuing.
    
    Program terminated with signal SIGILL, Illegal instruction.
    The program no longer exists.
    (gdb)
    

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我对低级工具链问题不是很熟悉。我用谷歌搜索了这个问题,似乎很少有人遇到同样的问题。

我下载了aosp源码(Android 4.2.2_r1,JDQ39),对比了预建的工具链和NDK内容,没有发现明显的差异。

我还尝试了最新的 NDK (r10b)。使用NDK中预建的工具链重建整个目标系统并进行调试,结果是一样的。

我也尝试生成平台设置为android-17和android-18的独立工具链,并重复上述步骤,结果相同。

我也尝试重新构建 NDK 工具链,没有任何区别。

我还尝试了更新版本的 gdbserver(在 NDK r10b 包中预建),问题仍然存在。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

但是如果我使用 NDK 工具链来调试一个简单的 hello-world 程序(动态链接 liblog),如本页所建议的:

www dot srombauts dot fr/2011/03/06/standalone-toolchain/

并进行调试,我可以进入 main(),但是在程序退出后,目标系统上的进程得到了类似的 SIGILL 终止,而不是正常退出。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我很困惑为什么会出现这种情况,因为许多开发人员使用 gdb 来调试本机代码,而 google 的平台开发人员也应该严重依赖 gdb 调试。问题似乎不太可能是由 gdb 或 gdbserver 中的错误引起的。也许它与 am335x 内核相关且特定于 am335x 内核?或者我错过了使用 gdb 的重要内容?比如说,目标架构选项?或者应该为这种本机调试指定某些编译器选项?我仔细阅读了很多关于android本地远程调试的在线文章,没有发现任何特别指出的内容。

我真的很想使用远程 GDB 来调试一些本机程序,包括 ril 和其他一些包装 HAL 库的测试用例。请帮忙!

【问题讨论】:

    标签: android native remote-debugging


    【解决方案1】:

    很抱歉,这不是答案,而是对我之前问题的补充。

    我进一步挖掘了这个问题。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    我在 android 源码树中放了一个基本的 helloworld 程序:

    #include <stdio.h>
    #include <android/log.h>
    
    #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "hello-native", __VA_ARGS__))
    
    void main(void)
    {
        printf("Hello Native Printf\n");
        LOGI("Hello Native LOGI");
    }
    

    Android.mk 文件为:

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := hello-native
    LOCAL_MODULE_TAGS := optional
    LOCAL_SRC_FILES := hello-native.c
    
    LOCAL_SHARED_LIBRARIES := liblog
    
    include $(BUILD_EXECUTABLE)
    

    然后调试失败并显示上一篇文章中提到的 SIGILL。

    但如果我使用标准的 Makefile(如 Karim Yaghmour 在他的优秀著作 Embedded Android, page 140 中提出的那样):

    #Paths and settings
    
    TARGET_PRODUCT = am335xevm_sk
    ANDROID_ROOT = /home/ma/devkit/JB422
    BIONIC_LIBC = $(ANDROID_ROOT)/bionic/libc
    PRODUCT_OUT = $(ANDROID_ROOT)/out/target/product/$(TARGET_PRODUCT)
    CROSS_COMPILE = $(ANDROID_ROOT)/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin/arm-linux-androideabi-
    
    # Tool names
    AS = $(CROSS_COMPILE)as
    AR = $(CROSS_COMPILE)ar
    CC = $(CROSS_COMPILE)gcc
    CPP = $(CC) -E
    LD = $(CROSS_COMPILE)ld
    NM = $(CROSS_COMPILE)nm
    OBJCOPY = $(CROSS_COMPILE)objcopy
    OBJDUMP = $(CROSS_COMPILE)objdump
    RANLIB = $(CROSS_COMPILE)ranlib
    READELF = $(CROSS_COMPILE)readelf
    SIZE = $(CROSS_COMPILE)size
    STRINGS = $(CROSS_COMPILE)strings
    STRIP = $(CROSS_COMPILE)strip
    
    export AS AR CC CPP LD NM OBJCOPY OBJDUMP RANLIB READELF \
    SIZE STRINGS STRIP
    
    # Build settings
    
    CFLAGS = -O0 -Wall -fno-short-enums -ggdb
    
    HEADER_OPS = -I$(BIONIC_LIBC)/include \
    -I$(BIONIC_LIBC)/arch-arm/include \
    -I$(BIONIC_LIBC)/kernel/common \
    -I$(BIONIC_LIBC)/kernel/arch-arm \
    -I$(ANDROID_ROOT)/system/core/include
    
    LDFLAGS = -nostdlib -Wl,-dynamic-linker,/system/bin/linker \
    $(PRODUCT_OUT)/obj/lib/crtbegin_dynamic.o \
    $(PRODUCT_OUT)/obj/lib/crtend_android.o \
    -L$(PRODUCT_OUT)/obj/lib -lc -ldl -llog
    
    # Installation variables
    EXEC_NAME = hello-native
    INSTALL = install
    INSTALL_DIR = $(PRODUCT_OUT)/system/bin
    
    # Files needed for the build
    OBJS = hello-native.o
    
    # Make rules
    all: hello-native
    
    .c.o:
    $(CC) $(CFLAGS) $(HEADER_OPS) -c $<
    
    hello-native: ${OBJS}
    $(CC) -o $(EXEC_NAME) ${OBJS} $(LDFLAGS)
    
    install: hello-native
    test -d $(INSTALL_DIR) || $(INSTALL) -d -m 755 $(INSTALL_DIR)
    $(INSTALL) -m 755 $(EXEC_NAME) $(INSTALL_DIR)
    
    clean:
    rm -f *.o $(EXEC_NAME) core
    distclean:
    rm -f *~
    rm -f *.o $(EXEC_NAME) core
    

    然后程序正确编译和调试。唯一的例外是程序退出时,如果我将sysroot设置为/out/target/product/am335xevm_sk/symbols,我得到了和SIGILL,但如果我不设置调试器sysroot,程序正常退出。

    它们与不同的工具链和调试器的工作方式完全相同,从原始 TI 版本,从原始或新版本 NDK,或者从 NDK 中的源代码重建。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    然后我尝试在ARM代码中编译rild,将LOCAL_ARM_MODE设置为arm,如下:

    ifeq ($(TARGET_ARCH),arm)
    
    LOCAL_SHARED_LIBRARIES += libdl
    endif # arm
    
    LOCAL_CFLAGS := -DRIL_SHLIB -O0
    LOCAL_ARM_MODE := arm
    
    LOCAL_MODULE:= rild
    LOCAL_MODULE_TAGS := optional
    
    include $(BUILD_EXECUTABLE)
    

    如果我没有将 sysroot 设置为 out/target/product/am335xevm_sk/symbols,那么程序将正确编译和调试,否则,调试器可以进入链接器并使用 SIGILL 崩溃,如前所述。

    这至少为我的需要提供了一个解决方案,但我不能相信 Android (ndk) gdb 不能处理拇指代码? gcc/gdb 设置有什么我错过的吗?还是在 Rowboat 发行版中修改了一些 gcc 选项,导致官方 gdb 工具无法正常工作?

    帮助!

    【讨论】:

    • 您好,无论如何都不是专家,但我建议创建一个简单的示例 android 应用程序,该应用程序导入一些本机代码(将一些本机代码编译到库中,然后从 Java 加载它),然后使用ndk-gdb 命令,以查看 ndk-gdb 的作用。它将 solib 路径设置为包含本机库的路径,但它也会从设备中提取一些库并将它们添加到 solib 路径中。一旦我开始使用 ndk-gdb 调试(当然也使用 adb root),我的调试工作才开始工作并且没有 SIGILL
    猜你喜欢
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2023-03-29
    • 2011-11-29
    相关资源
    最近更新 更多