侯 Sir说:“源码之下,了无秘密。” 但有些秘密还是要搞起来了看得更真切,仅从静态代码的体位很难体会到运动时的妙处。因此环境搭好了,下一步就是调试。gdbserver搭配gdb的调试环境走得很顺利,可是mmm出的C代码总是没有debugging symbol。在调研原因的过程中倒是熟悉了一些工具的用法,值得记录。

首先,关于mmm的代码,它是写在build/envsetup.sh中的函数,内部是对make的简单封装:指定要编译的模块,该函数会进入Android源码根目录,将指定模块的.mk文件传给make进行编译、链接。网上有对它的详细分析。

期初,我创建了external/helloworld,并在其下放了helloworld.c和Android.mk,执行

$ mmm external/helloworld
$ make snod

把生成的helloworld可执行文件打包到emulator的/system/bin里。当dbg提示(no debugging symbols found),我的第一反应是应该修改Android.mk文件,添加-g编译参数:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := helloworld
LOCAL_CFLAGS += -g -O0
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)

可是没有任何效果,gdb还是那么提示。我怀疑是gdb的版本不匹配,我是用的是Mac平台,gdb是这么用的:

$ ./prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-gdb
(gdb) file out/target/product/generic/system/bin/helloworld
Reading symbols from out/target/product/generic/system/bin/helloworld...(no debugging symbols found)...done.

怎么验证helloworld中是否存在调试符号表呢?能干这事的工具还挺多,我用了三个:

  • objdump工具,它可以用来反汇编binary文件,加参数-t显示symbol table:
$ ./prebuilts/gcc/darwin-x86/x86/x86_64-linux-android-4.9/bin/x86_64-linux-android-objdump -t out/target/product/generic/system/bin/helloworld
  • nm工具,它可以列出目标文件中的各种符号:
$ ./prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-nm  out/target/product/generic/system/bin/helloworld
  • readelf工具,它可以解析elf格式的文件:
$ ./prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-readelf -a out/target/product/generic/system/bin/helloworld

Linux下的工具真是好强大,而且在prebuilts/gcc下面都有对应的版本。不过这些强大的工具一致表明刚刚make出来的binary确实没有调试信息!

我又怀疑到自己的编译环境,难道是我的cc工具有问题?在.mk文件下添加如下输出,看$(CC)是啥:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
$(warning $(CC))
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := helloworld
LOCAL_CFLAGS += -O2 -fno-inline
LOCAL_SRC_FILES := $(call all-subdir-c-files)
include $(BUILD_EXECUTABLE)

输出的结果就是cc,再使用cc -g helloworld.c看生成的a.out文件是有调试信息的!

网上不少文章都提到不要在LOCAL_CFLAGS中加入优化/调试级别的参数:

Try not to change the optimization/debugging level in your Android.mk, this can be handled automatically for you by specifying the appropriate information in your Application.mk, and will let the NDK generate useful data files used during debugging.

这让我更加疑惑,这种纯C文件没有Application.mk怎么办呢?

晚上跟宋大侠一起review过程的时候,大侠关注到mmm最后有这么一段文字:

原来犯了个弱智错误,mmm说得很清楚:它同时生成了多个版本的helloworld,其中有原始版本,也有被阉割掉调试信息的strip版本,那么用于打包到system.img中的是不是阉割版?

赶快挨个验明正身:

$ ./prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-nm out/target/product/generic/obj/EXECUTABLES/helloworld_intermediates/LINKED/helloworld

00003e90 d _DYNAMIC
00003fc8 d _GLOBAL_OFFSET_TABLE_
00000df8 t _Unwind_Complete
00000eac t _Unwind_DeleteException
00000e74 t _Unwind_GetLanguageSpecificData
00000e90 t _Unwind_GetRegionStart
00000c88 t _Unwind_RaiseException
00000dfc t _Unwind_Resume
000009c0 t _Unwind_VRS_Get
............

果然是这样。所以不建议在LOCAL_CFLAGS中指定优化/调试等级。

Android源码树中C代码的编译的更多相关文章

  1. 编译android源码官方教程(2)建立编译环境「linux & mac osx」

    https://source.android.com/source/initializing.html Establishing a Build Environment IN THIS DOCUMEN ...

  2. 编译android源码官方教程(4)开始编译

    Preparing to Build IN THIS DOCUMENT Obtain proprietary binaries Download proprietary binaries Extrac ...

  3. android.mk android源码编译

    http://www.cnblogs.com/chenbin7/archive/2013/01/05/2846863.html Android.mk简单分析 2013-01-05 22:51 by . ...

  4. 在Mac mini上编译Android源码

    参考文章 1.Android 6.0 源代码编译实践 2.编译Android源码致命错误解决方案 实践过程 1.Mac下安装Ubuntu双系统 (1)Ubuntu版本:Ubuntu 15.10 注:实 ...

  5. 深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)

    2.3编译Android源码 Android源码体积非常庞大,由Dalvik虚拟机.Linux内核.编译系统.框架代码.Android定制C库.测试套件.系统应用程序等部分组成,在编译Android源 ...

  6. Android源码下载和编译过程

    这是我在编译android源码时整理记录的编译步骤和错误解决方法,期间参考了一些网上的博客和教程. 第一步: 安装ubuntu12.04,分配一盘空间50G,2G内存.如果分配1G内存编译时将报错.( ...

  7. 【转】在Ubuntu下编译Android源码并运行Emulator

    原文网址:http://www.mcuos.com/thread-4553-1-1.html 建立编译环境 1.在VirtualBox上安装Ubuntu 2.安装JDK   $ sudo apt-ge ...

  8. 【转】Linux(ubuntu14.04)上编译Android4.4源码的环境搭建及编译全过程

    原文网址:http://jileniao.net/linux-android-building.html sublime text让我伤心.本来很信任sublime text的自动保存功能,之前使用一 ...

  9. 一次编译Android源码实验

    注意,本文只供参考,是老文章 1.必要的软件环境 sudo apt-get install build-essential sudo apt-get install make sudo apt-get ...

随机推荐

  1. 在<img src="..." title="..."> 中使title的内容换行的方法

    在<img src="..." title="...">中要使TITILE的内容换行,不能使用html标签,只能用ASCII码,方法如下: < ...

  2. ASP.NET MVC5中View显示Html

    @Html.Raw(Model.Name) @(new HtmlString(Model.Name));

  3. GWT 中实现“CSS Sprite”

    近段时间在弄GWT这一块,开发中遇到的一些不错的方法或者技巧,在此做个分享和记录,有不同见解可发表意见  互相切磋. 在web开发中,必然涉及到网页中的图片,本地浏览网页,要下载在服务器端的图片,然后 ...

  4. vijos1906:联合权值

    描述 无向连通图 G 有 n 个点,n-1 条边.点从 1 到 n 依次编号,编号为 i 的点的权值为 WiWi, 每条边的长度均为 1.图上两点(u, v)的距离定义为 u 点到 v 点的最短距离. ...

  5. Java 8新增的日期、时间格式器

    一 获取DateTimeFormatter对象的三种方式 直接使用静态常量创建DateTimeFormatter格式器 使用代码不同风格的枚举值来创建DateTimeFormatter格式器 根据模式 ...

  6. XXXAction-validation.xml文件中报错:Referenced file Contains errors

    我们需要引用与验证器配置相关的dtd文件,这个文件可以在xwork-core-2.3.1.2.jar下找到(xwork-validator-1.0.3.dtd) 网上有很多处理办法,如下所示: 1.直 ...

  7. select *和select 全部

    select *和select 全部字段 在查询上效果是一样的,速度也是一样的. 不过理论上来说select *反而会快点. 因为 1.select 全部字段在数据传输上消耗会更多,如果几百个字段这个 ...

  8. composer update的错误使用以及如何更新composer.lock文件

    用composer update装包是错误的. 安装包标准的方法应该是 require ,或者手动写 compose.json 文件,然后 composer install .如果只是需要更新 com ...

  9. spring读取classpath目录下的配置文件通过表达式去注入属性值.txt

    spring读取配置文件: 1. spring加载配置文件: <context:property-placeholder location="classpath:config/syst ...

  10. Android中的文件读写总结

    在Android中,文件主要分为两大类,内部存储和外部存储 内部存储的文件是程序私有的,分为普通文件和Cache文件 外部文件也可以是私有的,也可以是共有的,这要根据文件的目录位置来决定 共有文件可以 ...