Ubuntu上交叉编译diagnose-tools用户态程序
交叉编译思路:使用交叉编译器aarch64-linux-gnu-gcc等,手动指定CC,LD,AR等变量,修改Makefile文件。
1.adb与交叉编译器下载
Ubuntu的apt下载中有交叉编译、adb等工具,在Ubuntu下环境会简单和整齐一点。
sudo apt-get install android-tools-adb sudo apt-cache search aarch64 # 该命令可用于查看可用的交叉编译器安装包 sudo apt-get install g++-aarch64-linux-gnu # 使用该交叉编译工具
2.依赖库编译
打开用户态Makfile可以看到,用户态程序是依赖一些库的,在顶层Makefile中,目标deps下,就是对这些库的编译。
-
顶层Makefile内容
我们要做的就是使用交叉编译的方式,把这个deps跑一遍。这部分可以看到,它编译了$(DEPS)目录下的所有库到$(DEPS)目录下,都是使用./configure,make, make install,每个的编译选项有点点不同,还有SOURCE/diagnose-tools/java_agent也是一个库的编译,使用make。下来我们就一个一个的编译。
我在每一个要编译的库下都写了一个make.sh脚本,直接执行脚本就可以编译。
2.1 zlib
make.sh
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld RANLIB=aarch64-linux-gnu-ranlib AR=aarch64-linux-gnu-ar ./configure --prefix=${DEPS} --static make make install
2.2 elfutils(libelf、libdwfl)
这个库比较麻烦,第一点它依赖于zlib库,需要加上一些编译链接选项;第二点,它不是只包含libelf,还有其他的库,其他的库有些可能依赖与运行主机例如libcpu,没办法交叉编译,直接修改Makefile删掉就好了。建议这个库一次编好后就不要重编了,每一次都要这样解决问题。
2.2.1 make.sh
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps autoreconf -ivf -I/usr/local/share/aclocal/pkg.m4 CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld RANLIB=aarch64-linux-gnu-ranlib AR=aarch64-linux-gnu-ar LDFLAGS='-L/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps/lib' CFLAGS="-g -O2 -I${DEPS}/include" ./configure --host=aarch64-linux-gnu --prefix=${DEPS} --disable-debuginfod --enable-maintainer-mode make make install
2.2.2 报错解决
2.2.2.1 缺少本地命令
需要安装这几个命令
sudo apt install flex sudo apt install bison sudo apt install gawk
2.2.2.2 缺少宏定义PKG_CHECK_MODULES导致configure语法错误
这个宏是工具pkg-config提供下的m4文件提供的。关于出现该报错的原因,参考:./configure时出现PKG_PROG_PKG_CONFIG和PKG_CHECK_MODULES报错的解决方案_configure.ac:32: error: macro pkg_prog_pkg_config _灵兮爸爸的博客-CSDN博客、PKG_CHECK_MODULES未定义_pkg_check_modules(sqlite, sqlite3 >= 3.7.7)_yin138的博客-CSDN博客
-
首先,下载pkg-config
wget https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz tar xvf pkg-config-0.29.2.tar.gz ./configure make && make install
-
然后,将生成的pkg.m4文件拷贝到configure所在目录的m4/目录下。
sudo find / -name pkg.m4 # 查找pkg.m4所在位置,我的在/usr/local/share/aclocal/pkg.m4 cp /usr/local/share/aclocal/pkg.m4 ./m4
-
重新执行./make.sh,通过,生成Makefile
2.2.2.3 libcpu问题
修改Makefile文件,删除SUBDIRS变量的libcpu项,另外,如果后面遇到哪些库因为依赖于该库而无法编译的话也删掉吧,因为对它有依赖关系,也没法编。
参考:perf支持用户态地址解析-libelf - 知乎 (zhihu.com)
2.2.2.4 libebl编译选项Werror检查问题
由于内部设置了-Werror,使所有的警告都变成了error,所以程序终止。这里可以看到在参数检查这里过不去,我们可以将-Werror选项去掉。
-
进入./libebl目录,打开Makefile.in文件,搜索到所有的-Werror,将其删掉即可。
2.3 libunwind
make.sh
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld RANLIB=aarch64-linux-gnu-ranlib AR=aarch64-linux-gnu-ar CFLAGS="-g -O2" ./configure --host=aarch64-linux-gnu --prefix=${DEPS} make make install
2.4 xz(lzma)
2.4.1 make.sh
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps autoreconf -ivf CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld RANLIB=aarch64-linux-gnu-ranlib AR=aarch64-linux-gnu-ar CFLAGS="-g -O2" ./configure --host=aarch64-linux-gnu --prefix=${DEPS} make make install
2.4.2 报错解决
2.4.2.1 autoreconf错误
apt下载autopoint。
2.4.2.2 ./configure错误
apt下载libtool。
2.5 libssh2
2.5.1 make.sh
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld RANLIB=aarch64-linux-gnu-ranlib AR=aarch64-linux-gnu-ar ./configure --host=aarch64-linux-gnu --prefix=${DEPS} --with-libssl-prefix=${DEPS} LDFLAGS='-Wl,-rpath-link,/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps/lib' make make install
2.5.2 报错解决
这是因为它也有依赖库,openssl,下载openssl库(在官网下载,一样的./configure编译)。
2.6 libperfmap.so
Makefile
all: libperfmap.so SRCS := perf-map-agent.c perf-map-file.c OBJS := perf-map-agent.o perf-map-file.o JAVA_1_X=$(shell ls /usr/lib/jvm/ | grep java-1. | grep openjdk | head -1) CC=aarch64-linux-gnu-gcc CFLAGS = -fPIC -static-libgcc -static-libstdc++ -Wall -O2 -I . -I /usr/lib/jvm/$(JAVA_1_X)/include/ -I /usr/lib/jvm/$(JAVA_1_X)/include/linux/ -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux LDFLAGS = -O2 -shared -static-libgcc -static-libstdc++ libperfmap.so: $(OBJS) $(CC) $(LDFLAGS) $^ -o $@ clean: rm -f libperfmap.so *.o
注意,这是一个动态链接,依赖于java环境,到安卓上运行的时候也需要有这个java环境才可以运行这个库。
3. 用户态Makefile改写
make.sh (根据顶层Makefile中的tool目标改写)
#!/bin/bash DEPS=/home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps make clean VENDER_LDFLAGS="-static -L${DEPS}/lib -L${DEPS}/elfutils/libdwfl/" make
Makefile
CXX := aarch64-linux-gnu-g++ VENDER_LDFLAGS ?= -L../../deps/lib CWD = $(shell pwd) DEPS := /home/yj/diagnose-tools/diagnose-tools/diagnose-tools/deps LDFLAGS = $(VENDER_LDFLAGS) -static-libgcc -static-libstdc++ -L$(CWD) -L/usr/lib64 -lunwind-aarch64 -lunwind -lelf -llzma -lz CXXFLAGS = -std=gnu++11 -c -O2 -I.. -I$(CWD)/include -I$(DEPS)/include -Wall -g -fno-omit-frame-pointer -Wno-unused-result CXXFLAGS += -DDIAG_ARM64 TARGET=diagnose-tools SRCS = $(wildcard *.cc) $(wildcard testcase/pi/*.cc) $(wildcard testcase/memcpy/*.cc) \ $(wildcard testcase/md5/*.cc) $(wildcard testcase/run_trace/*.cc) OBJS=$(SRCS:.cc=.o) all: $(TARGET) strip --strip-debug diagnose-tools $(OBJS): %.o: %.cc echo $(CXXCFLAGS) $(CXX) $(CXXFLAGS) -c $< -o $@ $(TARGET): $(OBJS) $(CXX) $(OBJS) $(LDFLAGS) -o $@ clean: rm -f $(TARGET) *.o libperfmap.so rm -f testcase/pi/*.o testcase/memcpy/*.o testcase/md5/*.o testcase/run_trace/*.o distclean: rm -f $(TARGET) *.o libperfmap.so rm -f testcase/pi/*.o testcase/memcpy/*.o testcase/md5/*.o testcase/run_trace/*.o make -C elfutils clean make -C libunwind clean make -C xz clean install: [ ! -z "$(DEST_DIR)" ] && mkdir -p $(DEST_DIR) && /bin/cp -f $(TARGET) $(DEST_DIR)
执行./make.sh即可。
4. 效果验证
adb到手机上后,运行可以看到提示信息。
5. 说明
目前只是能编通,但是具体每个功能是否在安卓上是能跑的不知道,因为毕竟用的是aarch64-linux-gnu交叉编译工具,不是ndk带的安卓编译工具,有可能存在一些接口问题。
有一些库的功能我并没有测试,因为手机没有root权限。如果后来在使用功能的时候出现了问题,也可以检验一下库的功能是否完好。