Android C Library: Bionic 成長計畫

7,354 views
7,221 views

Published on

本議程主要探討 Android 的 C Library : Bionic , bionic 與一般 Linux 所使用的 C Library 有所不同,為達到輕薄短小, 因此相較下缺少部份功能的實做, 本議程將探討 bionic 何處尚可改善以及發表我們對於 bionic 所改善的部份, 其中改善包含 bionic 中的 Dynamic Linker 及對於 Profiling 的支援.

Published in: Technology, Education
1 Comment
10 Likes
Statistics
Notes
No Downloads
Views
Total views
7,354
On SlideShare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
176
Comments
1
Likes
10
Embeds 0
No embeds

No notes for slide

Android C Library: Bionic 成長計畫

  1. 1. Android C Library: Bionic 成長計畫Kito Cheng ( 程皇嘉 )Developer, 0xlab kito@0xlab.org April 14, 2012 / OSDC
  2. 2. Rights to copy © Copyright 2012 0xlab http://0xlab.org/ contact@0xlab.org Attribution – ShareAlike 3.0 Corrections, suggestions, contributions You are free and translations are welcome!to copy, distribute, display, and perform the workto make derivative works Latest update: Mar 21, 2012to make commercial use of the work Under the following conditions Attribution. You must give the original author credit. Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.For any reuse or distribution, you must make clear to others thelicense terms of this work.Any of these conditions can be waived if you get permission from thecopyright holder. Your fair use and other rights are in no way affected by the above. License text: http://creativecommons.org/licenses/by-sa/3.0/legalcode
  3. 3. 簡短自我介紹 博班菸酒生 @ 熱血工讀生 @天大地大台科大 0xlab
  4. 4. 簡短自我介紹
  5. 5. 成長計畫 ?
  6. 6. 成長計畫 !
  7. 7. 可解讀 GNU- style 成長計畫 ! hash 的帥氣墨鏡具備 S/L 大法的 時間魔法陣 針對 JNI 量測效 能 強化版 8-bit 的機械錶 prelink map
  8. 8. 可解讀 GNU- stylehash 的帥氣墨鏡
  9. 9. GNU-Style HashGNU-Style Hash 是啥 ?
  10. 10. GNU-Style HashGNU-Style Hash 是啥 ?先來看看他是用在哪 !
  11. 11. 程式啟動流程執行檔讀入記憶體 libc/libm/ libdvm... 在更新符號的時候需要大量的符號查找操載入相關動態函式庫 更新符號位址(Relocation) printf, sin, cos, ... 開始執行 !
  12. 12. 程式載入範例libc libfoo prog 使用到 libc 跟 libfoo 的東西 prog
  13. 13. 程式載入範例strtoumax foo statfs bar wcsncmp ogcdlmallopt orz printf ... ... ox1ab strtoul getutent libc 及 libfoo 各自提供這堆符號 ( 函數 / libc libfoo prog 使用到 libc 跟 libfoo 的東西 prog
  14. 14. 程式載入範例 strtoumax foo statfs bar wcsncmp ogc dlmallopt orz printf ... ... ox1ab strtoul getutent libc 及 libfoo 各自提供這堆符號 ( 函數 / libc libfoo prog 使用到 libc 跟 libfoo 的東西 prog假設 prog 只有使用到 printf, foo, bar 這 3 個函數
  15. 15. 程式載入範例 strtoumax foo statfs bar wcsncmp ogc dlmallopt orz printf ... ... ox1ab strtoul getutent libc libfoo 只用到 3 個符號 , 但在這個例子需要查找 5 次符號 prog假設 prog 只有使用到 printf, foo, bar 這 3 個函數
  16. 16. 程式載入範例 strtoumax foo statfs bar wcsncmp ogc dlmallopt orz printf ... ... ox1ab strtoul 查找符號次數 : O(n*m) getutent n : 相依的函數庫數目 m : 符號數 libc libfoo 只用到 3 個符號 , 但在這個例子需要查找 5 次符號 prog假設 prog 只有使用到 printf, foo, bar 這 3 個函數
  17. 17. GNU-Style Hash GNU-Style Hash則是可以加速這個查詢過程的方法之一 !
  18. 18. GNU-Style Hash GNU-Style Hash則是可以加速這個查詢過程的方法之一 ! 原本 ELF 中就有採用 Hash 來加速查找速度 , 但不盡理想
  19. 19. GNU-Style Hash elf 預設的 hash 方法name 2sym collision # 3sym collision # 3+sym collision #sysv 1749 5libiberty 42dcache 37 gnu-style hash 的方法djb2 29sdbm 39djb3 31rot 337 39 61sax 34fnv 40oat 30 原本 ELF 中就有採用 Hash 來加速查找速度 , 但不盡理想Experiment by Jakub Jelinekhttp://cygwin.com/ml/libc-alpha/2006-06/msg00098.html
  20. 20. GNU-Style HashBit array v H = {x, y, z} = hash functions 並且使用 bloom filter 來進一步加速整體查找流程 !
  21. 21. GNU-Style HashBit array v H = {x, y, z} = hash functions 並且使用 bloom filter 來進一步加速整體查找流程 ! 號稱可以加速 50% 的載入時間 !
  22. 22. GNU-Style hash 背後的故事 ...
  23. 23. GNU-Style Hash所以在 Android 使用則有些地方要注意 ... 某些傢伙自帶 Dynamic Linker 所以不支援 ex: Unity 3D, B2G... 因此必須要採用向後相容方案 , 新舊的 hash table 都要放 ,-Wl,--hash-style=both 但 gold 有 bug, 所以最好用 bfd 的 linker... http://sourceware.org/bugzilla/show_bug.cgi? id=13597
  24. 24. 強化版 8-bitprelink map
  25. 25. No prelink in ICS Android 太貪吃 所以 prelink map 掉 了
  26. 26. No prelink in ICS The speedup that it afforded in the early days of Android is now nullified by the speed of hardware, as well as by the presence of Zygote The space savings that come with prelinking are no longer important either. Prelinking reduces the effectiveness of Address- Space-Layout Randomization. Since it is not part of the gcc suite, the prelinker needs to be maintained separately. 官方說法Git log fromhttps://github.com/android/platform_build/commit/b375e71d306f2fd356b9b356b636e568c4581fa1
  27. 27. No prelink in ICS 硬體進步跟 Zygote 機制 , Prelink 加速跟沒有一樣 只省一丁點空間 , 現在記憶體大又便宜 Prelink 後 Address-Space-Layout Randomization 效果會變弱 不是 GNU toolchain 的東西 , 要維護很麻煩 官方說法 ( 白話版 )Git log fromhttps://github.com/android/platform_build/commit/b375e71d306f2fd356b9b356b636e568c4581fa1
  28. 28. No prelink in ICS但 prelink 對於開機時間還是有影響阿阿
  29. 29. No prelink in ICS但 prelink 對於開機時間還是有影響阿阿事實上 Prelink 在 ICS 可以撿回來用
  30. 30. 程式啟動流程執行檔讀入記憶體 libc/libm/ libdvm... 在更新符號的時候需要大量的符號查找操載入相關動態函式庫 更新符號位址(Relocation) printf, sin, cos, ... 開始執行 !
  31. 31. 程式啟動流程 Prelink 就是把這邊要找的東西統統都先作掉 一勞永逸執行檔讀入記憶體 libc/libm/ libdvm... 在更新符號的時候需要大量的符號查找操載入相關動態函式庫 更新符號位址(Relocation) printf, sin, cos, ... 開始執行 !
  32. 32. int bar() { return 100;} 做個實驗int foo () { printf(“foo”); return bar();} libc libfoo 本實驗中假設已經有一個建好的且 prelink 過後的 libc.so
  33. 33. int bar() { return 100;} 做個實驗int foo () { # arm-eabi-objdump libfoo.so -R printf(“foo”); return bar(); libfoo.so: file format elf32-} littlearm DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 000010e8 R_ARM_JUMP_SLOT printf libc 000010ec R_ARM_JUMP_SLOT __cxa_finalize 00000424 R_ARM_RELATIVE *ABS* 0000100c R_ARM_RELATIVE *ABS* libfoo objdump -R 可檢視 Relocation Record, libfoo.so 共有四個 R
  34. 34. int bar() { return 100;} 做個實驗int foo () { # arm-eabi-objdump libfoo.so -R printf(“foo”); return bar(); libfoo.so: file format elf32-} littlearm DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 000010e8 R_ARM_JUMP_SLOT printf libc 000010ec R_ARM_JUMP_SLOT __cxa_finalize 00000424 R_ARM_RELATIVE *ABS* 0000100c R_ARM_RELATIVE *ABS* libfoo 一個 *ABS* 是 bar 的位址 另一個是系統用的
  35. 35. int bar() { return 100;} 做個實驗int foo () { # apriori --locals-only printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} libc 接著對 libfoo.so 進行 prelink libfoo apriori 在 out/host/linux-x86/bin/ prelink map 在 build/core --locals-only(-l) 指定進行 local prelink
  36. 36. int bar() { return 100;} 做個實驗int foo () { # apriori --locals-only printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} build/tools/apriori/prelinkmap.c(183): libc library libfoo.so not in prelink map 出現錯誤 , 抱怨在 prelink map 找不到 libfoo.. libfoo
  37. 37. Prelink Map# core system librarieslibdl.so 0xAFF00000 # [<64K]libc.so 0xAFD00000 # [~2M]libstdc++.so 0xAFC00000 # [<64K]libm.so 0xAFB00000 # [~1M]liblog.so 0xAFA00000 # [<64K]libcutils.so 預先分配每個動態函式庫的基底位址 (Base 0xAF900000 # [~1M]libthread_db.so 0xAF800000 # [<64K]libz.so 0xAF700000 # [~1M] 的函式庫都要加進來 要 Prelinklibevent.so 0xAF600000 # [???]libssl.so 0xAF400000 # [~2M]libcrypto.so 0xAF000000 # [~4M]libsysutils.so 0xAEF00000 # [~1M]# bluetoothliba2dp.so 0xAEE00000 # [~1M]audio.so 0xAED00000 # [~1M]input.so 0xAEC00000 # [~1M]…liblept.so 0x9CA00000 # [~5M]
  38. 38. Prelink Map# core system librarieslibdl.so 0xAFF00000 # [<64K]libc.so 0xAFD00000 # [~2M]libstdc++.so 0xAFC00000 # [<64K]libm.so 0xAFB00000 # [~1M]liblog.so 0xAFA00000 # [<64K]libcutils.so 預先分配每個動態函式庫的基底位址 (Base 0xAF900000 # [~1M]libthread_db.so 0xAF800000 # [<64K]libz.so 0xAF700000 # [~1M] 的函式庫都要加進來 要 Prelinklibevent.so 0xAF600000 # [???]libssl.so 0xAF400000 # [~2M]libcrypto.so 0xAF000000 # [~4M]libsysutils.so 0xAEF00000 # [~1M]# bluetooth 把 libfoo 加進來liba2dp.so 0xAEE00000 # [~1M]audio.so 0xAED00000 # [~1M]input.so 0xAEC00000 # [~1M]…liblept.so 0x9CA00000 # [~5M]libfoo 0x9C900000
  39. 39. int bar() { return 100;} 做個實驗int foo () { # apriori --locals-only printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} libc 加入 Prelink Map 後就可以順利進行 Prelink 了 libfoo
  40. 40. int bar() { return 100;} 做個實驗int foo () { # arm-eabi-objdump prelinked/libfoo.so -R printf(“foo”); return bar(); libfoo.so: file format elf32-littlearm} DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 000010e8 R_ARM_JUMP_SLOT printf 000010ec R_ARM_JUMP_SLOT __cxa_finalize libc 可以發現只剩下兩個 Relocation 了 ! libfoo
  41. 41. int bar() { return 100; } 做個實驗 int foo () { # arm-eabi-objdump prelinked/libfoo.so -R printf(“foo”); return bar(); libfoo.so: file format elf32-littlearm } DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE 000010e8 R_ARM_JUMP_SLOT printf 000010ec R_ARM_JUMP_SLOT __cxa_finalize libcoo.so 的 Base Address 在 prelink map 中固定 , 而事實上處理 Relocatio libfoo
  42. 42. int bar() { return 100;} 做個實驗int foo () { # apriori --locals-only printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} libc 回顧剛才的參數有個— locals-only, 通常有 local 就有相對的 global libfoo
  43. 43. int bar() { return 100;} 做個實驗int foo () { # apriori printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} build/tools/apriori/main.c(195): There are command-line-option errors. libc 但直接拔掉該參數會跟你抱怨參數錯誤 ... libfoo
  44. 44. int bar() { return 100;} 做個實驗int foo () { # apriori printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} build/tools/apriori/main.c(195): There are command-line-option errors. libc 不明原因在 apriori 的 global prelink 的部份程式沒有完成 , 但 libfoo
  45. 45. int bar() { return 100;} 做個實驗int foo () { # apriori printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); libfoo.so --output prelinked/libfoo.so} libc 所以接下來的實驗請記得先去 0xdroid 撿 patch 散落在下面三個地方 : libfoo build/ external/elfutils/ external/elfcopy/
  46. 46. int bar() { return 100;} 做個實驗int foo () { # apriori --inc-global-prelink printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); -L /system/lib } libfoo.so --output prelinked/libfoo.so libc patch 打上後把參數加上 --inc-global-prelink -L < 其他函數庫的路徑 > libfoo 就會開始進行 Incremental Global Prelink!
  47. 47. int bar() { return 100; } 做個實驗 int foo () { # apriori --inc-global-prelink printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); -L /system/lib } libfoo.so --output prelinked/libfoo.so # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS (none) Incremental libfoo Global Prelink 完後就沒有任何 Relocation 要處Local Prelink 再去處理 Global Prelink 的漸進方式 , 故命名之 , 因此輸
  48. 48. int bar() { return 100; } 做個實驗 int foo () { # apriori --inc-global-prelink printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); -L /system/lib } libfoo.so --output prelinked/libfoo.so # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS (none)nk 的過程中 , 會試著搜索外部的符號 , 如果找的到且該函式庫也 Prelink 過 , libfoo
  49. 49. int bar() { return 100; } 做個實驗 int foo () { # apriori --inc-global-prelink printf(“foo”); --prelinkmap prelink-linux-arm.map return bar(); -L /system/lib } libfoo.so --output prelinked/libfoo.so # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS (none)nk 的過程中 , 會試著搜索外部的符號 , 如果找的到且該函式庫也 Prelink 過 , libfoo以發現 , 不在 Prelink Map 的函式庫事實上也是可以處理掉部份的 Relocation!
  50. 50. int bar() { return 100; } 做個實驗 int foo () { printf(“foo”); return bar(); } libc libfoo現在為了實驗目的將 libfoo 從 prelink map 中驅逐出境並且加上 LOCAL_PRELINK_MODULE := false來建置
  51. 51. int bar() { return 100;} 做個實驗int foo () { # apriori --partial-global-prelink printf(“foo”); -L /system/lib return bar(); libfoo.so --output prelinked/libfoo.so} libc 接著加上新的參數 --partial-global-prelink 來進行 Partial Glo libfoo
  52. 52. int bar() { return 100;} 做個實驗int foo () { # apriori --partial-global-prelink printf(“foo”); -L /system/lib return bar(); libfoo.so --output prelinked/libfoo.so} # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS 00000424 R_ARM_RELATIVE *ABS* 0000100c R_ARM_RELATIVE *ABS* libfoo 來自 libc 符號的 Relocation 都 Prelink 掉了 !
  53. 53. int bar() { return 100; } 做個實驗 int foo () { # apriori --partial-global-prelink printf(“foo”); -L /system/lib return bar(); libfoo.so --output prelinked/libfoo.so } # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS 00000424 R_ARM_RELATIVE *ABS* 0000100c R_ARM_RELATIVE *ABS* libfoo進行 Prelink 後符號的位址都已經固定且已知 , 因此即使 libfoo 沒有分配 Base
  54. 54. int bar() { return 100; } 做個實驗 int foo () { # apriori --partial-global-prelink printf(“foo”); -L /system/lib return bar(); libfoo.so --output prelinked/libfoo.so } # arm-eabi-objdump prelinked/libfoo.so -R libc libfoo.so: file format elf32-littlearm DYNAMIC RELOCATION RECORDS 00000424 R_ARM_RELATIVE *ABS* 0000100c R_ARM_RELATIVE *ABS* libfoo進行 Prelink 後符號的位址都已經固定且已知 , 因此即使 libfoo 沒有分配 Base 這個機制命名為 Partial Global Prelink
  55. 55. Prelink 家族大評比
  56. 56. 針對 JNI 量測效 能 的機械錶
  57. 57. Aprof : Android Profiler
  58. 58. Aprof : Android Profiler針對 JNI 部份客製化類似於常見的 gprof 工具Sample BasedInstrumentation Based
  59. 59. Aprof : Android Profiler
  60. 60. Aprof : Android ProfilerSample Based 定期查看程式跑到哪Instrumentation Based 每次函數被呼叫時會紀錄
  61. 61. Aprof : Android Profiler% cumulative self self totaltime time time calls ms/call ms/call name99.52 2170 2140 2178309 0 0 fib0.00 2170 0 1 0 217 main0.32 0 20 0 0 0 write0.16 0 10 0 0 0 memcpyCall graph (explanation follows)-------------------------------------------------------------Image : fooCumulative time : 2170 msSelf time : 2140 ms Function % time cumulative self Count Call by fib 2170 2140 100.00 2170 0 1 main 100.00 2170 2140 2178308 fib main 2170 0 100.00 2170 0 1 __libc_init-------------------------------------------------------------Image : fooCumulative time : 2170 msSelf time : 30 ms write 0 20 memcpy 0 10
  62. 62. Aprof : Android Profiler
  63. 63. 具備 S/L 大法 的 時間魔法陣
  64. 64. Checkpoint
  65. 65. Checkpoint保存使用狀態 !
  66. 66. Checkpoint之後直接從上次保存 的狀態回覆
  67. 67. 現存的 Checkpoint 工具CryoPID http://cryopid.berlios.de/BLCR https://ftg.lbl.gov/projects/Checkpoint Restart/DMTCP http://dmtcp.sourceforge.net/
  68. 68. DMTCP支援大部分 OS 功能 檔案 , 網路 , Shared Memory, SysV IPC...純 user-space checkpoint 實作架構良好易於擴充且開發活耀 ! C++-based
  69. 69. DMTCP for Android預計可有效減少開機時間所有遊戲都可以跟模擬器一樣隨時存檔讀檔 (誤
  70. 70. DMTCP for Android但 Android 上有許多特殊的機制 Logger, binder, ashmem, wakelock...目前尚在進行中
  71. 71. 成長計畫 !
  72. 72. http://0xlab.org

×