安卓版Firefox(Fennec)的编译与调试——一铭陈刚
2017-09-05 00:20:38
张捷
  • 访问次数: 22
  • 注册日期: 2017-06-27
  • 最后登录: 2017-09-27
  • 当前积分: 182

1. 编译

可参考我原来写的https://github.com/openthos/firefox-analysis/blob/master/README.md

1.1环境搭建
目前是在ubuntu15下搭建的环境(16jdk太新,14太旧较难找到32位的libstdc++)
sudo add-apt-repository ppapenjdk-r/ppa
sudo apt-get update
sudo apt-get install yasm git python-dbus mercurial automake autoconf autoconf2.13 build-essential ccache python-dev python-pip python-setuptools unzip uuid zip zlib1g-dev openjdk-7-jdk wget libncurses5:i386 libstdc++6:i386 zlib1g:i386
mkdir /firefox
cd /firefox
curl -sf -L https://static.rust-lang.org/rustup.sh > rustup.sh
chmod +x rustup.sh
./rustup.sh
./rustup.sh --add-target=i686-linux-android

1.2源码下载
cd gecko-dev
git checkout -b r49-2016101919 remotes/origin/MOBILE4902_2016101919_RELBRANCH

1.3预处理
./mach bootstrap
选择4Firefox for android
等下载完ndk后,即可强行停止(ctrl+c),对于r49分支,必须要用此对应的ndk,高版本的工具链内部会报错,低版本的功能不全。
此时ndk的路径是/root/.mozbuild/android-ndk-r11b
然后再找一个尽可能高版本的SDK(可以选择android studio中带有的安卓SDK开发包),例如在180服务器上有一个,
cd ../
scp lh@192.168.0.180:/home/lh/wjx/sdk.tar.gz .
tar -zxvf sdk.tar.gz
解压后会在/firefox/Sdk目录下。
cd gecko-dev
vi mozconfig
增加以下内容
ac_add_options --enable-application=mobile/android
ac_add_options --target=i386-linux-android
ac_add_options --with-android-sdk="/firefox/Sdk"
ac_add_options --with-android-ndk="/root/.mozbuild/android-ndk-r11b"
mk_add_options MOZ_OBJDIR=./objdir-all
mk_add_options MOZ_MAKE_FLAGS="-j4"
关闭mozconfig,然后再。
vi mobile/android/confvars.sh
注释掉MOZ_INSTALL_TRACKING(在第49行),否则编译失败。

1.4编译打包安装
./mach build
./mach package
./mach install
大概需要1个小时左右(硬盘较快,40分钟左右;硬盘较慢,则1小时20分钟左右)。
如果是在OPENTHSO chroot ubuntu15下,则直接安装到本机,并可在开始菜单中直接运行。
参考链接
https://github.com/openthos/system-analysis/edit/master/firefox/build.md
https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build

2. 调试
可参考我原来写的https://github.com/openthos/multiwin-analysis/issues/1040

2.1假设前提:
  1、本机OPENTHOS,带有chroot ubuntu15,下载最新的OPENTHOS源码,可编译安装运行。(或者另外一台机器,有网络连接)
  2、本机同时带有chroot arch linux,安装了安卓SDK,可以启动LinuxSDK图形工具程序ddms(或者是另外一台机器可以adb shell连接)。

2.2分析工具:
  1apktool:反编译apk包,
            可以得到完整的文件目录拓扑结构。
            得到所有Java编译的中间语言代码,同时带有基本的符号表。
            得到所有的二进制库文件。
            in chroot ubuntu: apktool d *.apk -o out/
  2objdump:静态反汇编本地代码,但对于闭源应用很可能没有符号表。
            in chroot ubuntu: objdump -S *.so > *.s
  3ddmsjava调试器,动态获得进程的所有线程,以及堆栈信息。
            in chroot arch gui: ~/Android/Sdk/tools/ddms
  4gdbserver:运行端调试本地代码的代理。
            in OPENTHOS: gdbserver :1234 --attach pid  (pid 是我们要调试的进程id)
  5、交叉gdb: 工具链自带的调试器,同gdbserver配合,来调试本地代码。
            in chroot ubuntu: cd /aosp/prebuild/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
            in chroot ubuntu: ./x86_64-linux-android-gdb
  6symbolsOPENTHOS系统的带有符号表的对应的二进制动态库和二进制可执行文件。
            in chroot ubuntu: /aosp/out/target/product/x86_64/symbols/
            对于fennec,则需要把编译出的objdir-all/toolkit/library/libxul.soobjdir-all/config/external/nss/libnss3.so
                        复制到/aosp/out/target/product/x86_64/symbols/dev/ashmem/里(可能需要重新创建此目录)
  7/proc/*/maps:当前进程的内存布局。
            in chroot ubuntu: cat /proc/pid/maps > maps (pid是我们要调试的进程id)
  8logcat: 得到系统日志输出,包括我们自己打印的,并可通过grep进行过滤。
            logcat | grep tag0 | grep tag1 ...
  9file, readelf, ps, top, mount-static...
            file 可查看文件属性,所属平台,是否有符号表等。
            readelf可以读取到二进制文件的各种信息。
            pstop 可用来动态查看进程和线程以及cpu,内存等。
            mount-staticubuntu下静态编译的mount,支持--bind目录(OPENTHOS的不支持)。

2.3概要流程:
1、用symbols/system/目录下的带有符号表的可执行体替换掉/system/下对应可执行体。
      (不能全部替换,只能有针对性的替换,否则系统无法运行,因为带有调试符号的库太大了)
2、把OPENTHOS/system绑定到chroot ubuntu中,使得gdb可以搜索二进制执行体和符号表
      (例如mount-static --bind /system /data/ubuntu15/aosp/sysroot/system
3、运行所要调试的进程,得到所要调试进程的id号(ps即可)。
4、在Java层得到主线程的锁死点:在chroot arch 下,运行ddms,找到进程,主线程,堆栈。
5、调试本地代码(假设是x86 32位):
            运行gdbserver
            /usr/lib/python2.7/_sysconfigdata_nd.py/usr/lib/pythos2.7/plat-x86_64-linux-gnu/_sysconfigdata_nd.py替换
                  (否则x86_64-linux-android-gdb无法运行)
            运行./x86_64-linux-android-gdb(只能在当前目录运行)
                   target remote :1234
                   set sysroot /aosp/sysroot
                   set solib-search-path /aosp/sysroot/system/lib:/aosp/sysroot/system/lib/egl:/aosp/sysroot/dev/ashmem/
                   c

2.4分析方法:
1、列出所有线程,info threads.
2、列出线程寄存器:info registers.
3、列出线程堆栈数据: x /160x $esp, enter, enter, ...bt不好使,需要人工恢复)。
4、查找对象数据:需要对比源码或符号表,反汇编,堆栈数据等来进行反复查找。
5、查看线程关联,通过对象数据和调用栈来进行分析关联。
6、如果僵死容易复现,则可以通过在源码中加打印配合来做。
7、以上针对的是32位的不带本地代码转译的情况,对于64位同32位类似。
8、但带有本地代码转译的情况,则需要重新考虑调试方法(例如在虚拟机中加打印等)。


张捷 最后编辑, 2017-09-05 00:24:31