https://www.jianshu.com/p/8686931d31f0
1、前言
從Android 4.4宣佈支持64位系統以來,各終端方案廠商逐步推出了各自的64位soc解決方案。Google爲了兼容之前32位系統的應用,在64位系統上也實現了對32位應用的支持。那麼問題就來了,在一個64位系統的Android手機上如何檢測應用是運行在32位還是64位環境?本博文將爲大家解答這個問題。
本文會分別對Android系統中的App、Native進程以及動態鏈接庫的32/64位檢測方法進行介紹。
2、檢測App
任何一個Android手機用戶對APK文件肯定不會陌生,它是一個Android應用資源的封裝文件。當你下載安裝一個App之後,從Launcher啓動該應用,系統會由Zygote分叉出一個子進程來提供App運行的虛擬機和Runtime環境。與32位系統不同的是,在64系統中會同時存在兩個Zygote進程——zygote和zygote64,分別對應32位和64位應用。所以,要進行App的32/64位檢測,只需要看它的父進程是哪個Zygote即可。
下面的例子通過App的PPID信息——2759,檢測出了終端系統中所有的64位應用,且該方式無需root權限。
$ adb shell ps |grep zygote
root 2759 1 2131692 87052 0 0000000000 S zygote64
root 2760 1 1574048 53740 0 0000000000 S zygote
$ adb shell ps|grep 2759
root 2759 1 2131692 87052 0 0000000000 S zygote64
system 3257 2759 2339956 158936 0 0000000000 S system_server
radio 3393 2759 1601272 96220 0 0000000000 S com.android.phone
u0_a85 3407 2759 1564856 88740 0 0000000000 S com.android.inputmethod.latin
u0_a20 3422 2759 1970228 167288 0 0000000000 S com.android.systemui
u0_a7 3769 2759 1548288 63384 0 0000000000 S android.ext.services
u0_a13 3958 2759 1896704 131832 0 0000000000 S com.android.launcher3
u0_a6 3989 2759 1562416 94060 0 0000000000 S android.process.acore
u0_a17 4046 2759 1563300 88504 0 0000000000 S android.process.media
u0_a28 4112 2759 1555640 82004 0 0000000000 S com.android.quicksearchbox
u0_a64 4157 2759 1554484 72944 0 0000000000 S com.android.calendar
u0_a57 4215 2759 1572160 83532 0 0000000000 S com.android.email
u0_a77 4231 2759 1554408 67192 0 0000000000 S com.android.exchange
u0_a5 4279 2759 1549136 66072 0 0000000000 S com.android.onetimeinitializer
u0_a10 4299 2759 1552472 74088 0 0000000000 S com.android.providers.calendar
u0_a94 4325 2759 1869948 112984 0 0000000000 S com.android.soundrecorder
system 4345 2759 1561180 73680 0 0000000000 S com.sprd.engineermode
u0_a15 4887 2759 1874612 106196 0 0000000000 S com.android.packageinstaller
u0_a73 5133 2759 2425904 205912 0 0000000000 S com.android.browser
3、檢測Native進程
Andorid手機開機啓動之後,init進程會啓動一些後臺守護進程。通常,這些進程會對整個Android系統起到重要作用,例如Zygote、MediaServer和ServiceManager等。因爲這些Native進程並不是通過安裝APK獲得,所以上一章節的方法在這裏並不適用。我們知道Andorid Framework層以下都是繼承自Linux,因此可以採用Linux系統的一些工具和方法來對Native進程進行32/64位系統的檢測。
方法一,通過readelf工具來分析Native進程對應的bin文件,下面以mediaserver爲例
$readelf -h mediaserver
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x1e24
Start of program headers: 52 (bytes into file)
Start of section headers: 20980 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 29
Section header string table index: 28
從上面的信息中我們看到mediaserver文件的Class字段爲ELF32,Machine字段爲ARM。由此可知,在Android 64位系統中,mediaserver運行在32位環境中。
方法二,在運行時通過打印Native進程的內存映射列表(maps)來檢測32/64位,這個方法同樣也適用於App的32/64位檢測。這裏以com.android.email爲例,從上一章節的進程列表打印可以看到,com.android.email的PID爲4215。
u0_a57 4215 2759 1572160 83532 0 0000000000 S com.android.email
然後,通過proc文件系統便可查詢到PID=4215的內存映射列表 (截取片段)
$adb root
$adb shell cat /proc/4215/maps
......
71ebcb1000-71ebcb3000 r-xp 00000000 103:15 1453 /system/lib64/libOpenSLES.so
71ebcb3000-71ebcb4000 r--p 00001000 103:15 1453 /system/lib64/libOpenSLES.so
71ebcb4000-71ebcb5000 rw-p 00002000 103:15 1453 /system/lib64/libOpenSLES.so
71ebcb5000-71ebcd5000 r--s 00000000 00:12 282 /dev/__properties__/u:object_r:logd_prop:s0
71ebcd5000-71ebcf5000 r--s 00000000 00:12 287 /dev/__properties__/u:object_r:log_tag_prop:s0
71ebcf5000-71ebcf6000 r--p 00000000 00:00 0 [anon:linker_alloc]
71ebcf6000-71ebcf7000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector]
71ebcf7000-71ebcf8000 r--p 00000000 00:00 0 [anon:linker_alloc]
71ebcf8000-71ebcf9000 rw-p 00000000 00:00 0 [anon:linker_alloc]
71ebcf9000-71ebcfb000 r-xp 00000000 103:15 1452 /system/lib64/libOpenMAXAL.so
71ebcfb000-71ebcfc000 r--p 00001000 103:15 1452 /system/lib64/libOpenMAXAL.so
71ebcfc000-71ebcfd000 rw-p 00002000 103:15 1452 /system/lib64/libOpenMAXAL.so
71ebcfd000-71ebcff000 rw-p 00000000 00:01 22281 /dev/ashmem/dalvik-indirect ref table (deleted)
71ebcff000-71ebd00000 r-xp 00000000 103:15 1565 /system/lib64/libjnigraphics.so
71ebd00000-71ebd01000 r--p 00000000 103:15 1565 /system/lib64/libjnigraphics.so
71ebd01000-71ebd02000 rw-p 00001000 103:15 1565 /system/lib64/libjnigraphics.so
71ebd02000-71ebd04000 rw-p 00000000 00:01 22280 /dev/ashmem/dalvik-indirect ref table (deleted)
71ebd04000-71ebd05000 r-xp 00000000 103:15 1644 /system/lib64/libsigchain.so
71ebd05000-71ebd06000 r--p 00000000 103:15 1644 /system/lib64/libsigchain.so
71ebd06000-71ebd07000 rw-p 00001000 103:15 1644 /system/lib64/libsigchain.so
......
從上面的打印中可以看出,com.android.email加載的動態鏈接庫均位於/system/lib64。由此便可判斷com.android.email運行於64位環境。需要注意的是這個方法要root權限才能檢測。
4、檢測動態鏈接庫(*.so文件)
如果想要對一個.so文件的進行32/64位檢測,那麼採用上一章節中的方法一就可以做到。但是,有native開發經驗的讀者應該知道,64位系統中動態鏈接庫通常會同時存在32位和64位兩個版本,它們分別位於/system/lib和/system/lib64路徑中。所以,孤立地對某一個.so文件進行32位/64位檢測並沒有現實意義,應該將其與加載該.so文件的App或Native進程作爲一個整體來分析。
5、後語
本文分別對Android系統中App、Native進程和動態鏈接庫進行32/64位檢測的方法進行了介紹,希望對大家的學習開發工作有所幫助。