0xlab 的客製化 Android toolchain

有鑑於 Google 的 Android toolchain 開發團隊雖然活躍提交修改/貢獻到 GCC 與 binutils,但受限於 Android 原始碼釋出的慣例,總是要等待頗長的時間,才有機會使用到新的 GNU Toolchain 改善或者新功能,所以,0xlab 開發者就準備一份客製化的版本,請參考以下網址:

目前提供 gcc-4.4.3 與 gcc-4.4.4 兩個版本,前者是取自 Google Android 的原始碼分支,提供 ICF (Identical Comdat/Code Folding) 與 LIPO (Lightweight IPO) 等優化機制,而 gcc-4.4.4 的版本則是 0xlab 升級到新的程式基礎,並加入必要的修正。原始程式碼與 Toolchain 建構系統可參考 GIT: android-toolchain。不久的將來,我們將會全面移轉到 Linaro toolchain,也會一併發布 gcc-4.4 與 gcc-4.5 的 Android toolchain。

read on
Posted 張貼者: jserv 於 下午3:55 on 2010年11月16日 星期二 | 3 意見
Filed under: , , ,
 

加速 Android 的動態連結

就如人們所熟悉,Android 底層運作 Dalvik 虛擬機器,在 C Library 層面採用衍生自 NetBSD libc 的 bionic。與過往的 Java 為基礎的操作環境 (OE; Operating Environment,如 Transvirtual 的 PocketLinux / XOE) 不同的是,每個 VM instance 均為獨立的 Linux process,且由 Zygote 所「孵化」。就系統的角度來說,縱使底層對 system library 做了 prelink (透過工具 build/tools/apriori),但因語言實做的特性,需頻繁經由 JNI 去存取底層服務,也就是說,有大量的 dlopen()/dlsym() 操作,這些均無法透過 prelink 來縮減載入時間。

COSCUP 2010 的議程「打造特製的 Android Toolchain」中,小弟介紹了 0xlab 近來的幾項嘗試與改進項目,除了 GNU Toolchain (採用 gcc-4.4.4 搭配一系列的修改) 之外,就包含 Android bionic libc 與 prelink 的修改,企圖引入 DT_GNU_HASH 的機制 (也稱為 gnu hashstyle,或 gnu hash),以加速 Android 的動態連結。現在基礎工作大致完畢,陸續提交到 AOSP (Android Open Source Project) 的 Code Review,應該會納入 Android Gingerbread 以及後續的版本中。實驗平台採用 Qualcomm MSM7x25 (arm1136j-s),平均縮減 26% 的 ELF 動態連結時間,這對所有的 Android Activity (Java 程式) 與需要額外作 dlopen() 處理的系統函式庫,如 Qualcomm 的 camera HAL/service 或 Opencore/DSP,均可適用。

這過程中,讓小弟學習到頗多,從一開始的分析 (透過 oprofile 與開啟 bionic 裡頭 linker 的除錯資訊),觀察到 Android 的動態連結處理,有點類似 OpenOffice 所面臨的議題,於是嘗試引入 DT_GNU_HASH。背景知識可參考以下文獻:

gnu hashstyle 採用 Daniel J Bernstein 提出的 hash function,Jakub Jelinek 做了分析,比較原本 ELF hash:

The number of collisions in the 537403 symbols is:
name 2sym collision # 3sym collision # more than 3sym collision #
sysv 1749 5
libiberty 42
dcache 37
djb2 29
sdbm 39
djb3 31
rot 337 39 61
sax 34
fnv 40
oat 30

sysv 那項是原本的 hash function,而 djb2 則是 GNU Toolchain 採用的方案。就現有自由軟體的實做來看,包含 glibc, uClibc, dietlibc (前三者支援 GNU/Linux), FreeBSD libc 均提供 gnu hashstyle 的支援,但 Android 未正式在 bionic 提供。需留意的是,prelink 方案總是比 gnu hashstyle 帶來更快的動態連結時間,但付出的代價 (空間) 較高,而且不若後者有彈性。

read on
Posted 張貼者: jserv 於 下午9:52 on 2010年10月19日 星期二 | 4 意見
Filed under: , , , , ,
 

簡介 0xlab 新的開放原始碼專案

我們在今年八月中旬的 COSCUP 研討會中,很榮幸地向與會的朋友介紹 0xlab 若干新的開放原始碼專案,本文稍作整理回顧。0xdroid0xlab 最早的一項整合性開放原始碼專案,目的是建構於 Beagleboard 開放的硬體之上,提供 Android 的參考實做環境,經過一年多的累積,裡頭的成果被帶到不同的移動裝置中,比方說手機與 Tablet。今年二月份,有幸在 Mobile World Congress 2010 展示基於 Android 的移動裝置,Tieto 也在 TI OMAP3 平台展示 0xdroid,這些都讓我們更有信心,擴展到多元的應用。

這半年間,延續
0xdroid 的經驗,我們發展 / 貢獻以下專案:

  • 0xRobocat : 與 CATCAN 合作的專案,目的是打造一組控制伺服馬達與相關零組件的軟體框架,可提供給 Android 或 GNU/Linux 使用,以 Apache License 2.0 授權釋出。除了用於打造機器人外 (是真的可走動的 "Android"),本專案可用於 Android 裝置 (如手機) 的自動測試
  • 0xBench : 有鑑於 Android 上的系統效能評比程式,不是不完整,就是非開放原始碼,所以我們決定重新打造一個。0xBench 可從 C 函式庫/系統呼叫的層面,一路從 Dalvik VM 評測到 Android framework,仍持續擴充,並且我們提供 Web service,允許貢獻評測的結果,用互動的方式來分析。程式主體是 Apache License 2.0 授權
  • android-toolchain : 0xlab 特製的 GNU Toolchain,以 Android team 的成果為基礎,整合來自 Linaro Toolchain Working Group 的改善。這些主要是 GNU GPLv3 授權
  • Android Open Source Project (AOSP) : 提交 0xlab 過去在 TI OMAP 與 Qualcomm 72xx 平台的一些修改,經過公開的 Review 機制,慢慢整合到 AOSP
  • CyanogenMod : 社群版本的 Android,在 Nexus One, HTC Dream 等裝置有相當優越的表現,收錄若干來自 0xlab 的改良,比方說 Bluetooth HID profile
除了以上的開放原始碼專案,我們內部正進行一個基於 Android 的新型態應用,未來也會將相關的專案程式碼,以開放原始碼的形式釋出,完整的列表可參考 0xlab Projects。至於 AOSP,我們現有更改的項目是:
  • build - 調整 Android build system、修正工具程式的瑕疵
  • bionic - 提供 ARM optimizations,針對 ARMv6/ARMv7
  • PixelFlinger - 基本的 refactoring,以及 ARM 實做的改良
  • libpng / libz - 利用 GCC visibility,進一步縮減 code size
  • elfcopy - ELF 工具的調整
  • bionic / apriori / build - 支援 DT_GNU_HASH,加快動態連結的速度
  • toolchain - 加強 build system 的彈性
以上,歡迎舊雨新知給我們支持與指教,謝謝。

read on
Posted 張貼者: jserv 於 上午1:47 on 2010年9月1日 星期三 | 0 意見
Filed under: , , , , , , ,
 

0xlab 在 COSCUP 2010 的議程分享

一年一度的「COSCUP / 開源人年會」即將於八月 14 與 15 兩日舉辦,因為今年與 GNOME 亞洲峰會合辦,造成空前的盛大。0xlab 除了很榮幸能成為 COSCUP 贊助單位之外,也有四位開發者獲邀分享若干技術議程,以下摘錄 COSCUP 的演講摘要:
講題:Android Game Engine 比較

講者: walkingice (0xlab)
摘要:隨著 Android的蓬勃發展,遊戲亦如雨後春筍般冒出。避免重複造輪子,勢必要藉助現有的遊戲引擎,讓遊戲開發者可以專注在遊戲的最核心價值 — 樂趣
講題:Be "Android"
講者: tick (0xlab), matt (0xlab)

摘要:將 0xdroid 打造成為機器人平台。Robocat 是為 0xdroid 所設計的機器人控制系統,此議程將從硬體架構、系統設計、函式庫及應用程式等不同層面切入,介紹如何打造自己的 ”Android”
講題:打造特製的 Android Toolchain
講者:Jim Huang "jserv" (0xlab)

摘要:探討 0xlab 近來的實驗,從修改 Android 的 GNU Toolchain 到提供 source-to-source compiler,提出若干基於特定需求,從而發展的編譯器技術的新應用
涵蓋 Android Toolchain, Robot, Android Gaming 開發,依據慣例,屆時我們也會發布最近的成果,期待您的蒞臨指教,謝謝!

read on
Posted 張貼者: jserv 於 上午2:33 on 2010年8月2日 星期一 | 0 意見
Filed under: ,
 

在 Android/Dalvik 環境引入 precompiled class 的實驗

延續筆者去年的紀錄「當 Compiler 遇上 Mobile」,最近我們又獲得一些進展,是在 Android 的 Dalvik 虛擬機器環境中,引入 pre-compiled class 的實驗,除了可改善執行時期的效能、記憶體使用量外,另外就是避免在「反組譯並修改 Android 應用程式實例」一文可見的資訊保護議題。

其實十幾年前,在 Java 平台中就有相當多團隊提出可行的方案,而世界上第一個開放原始碼的 Kaffe 虛擬機器專案,早在 1999 年即提出實做 "Kaffe/GCJ integration",成功地將 GCJ (GCC for Java) 自 Java class/source 編譯得到的機械碼,當作 pre-compiled shared library,讓 Kaffee VM 讀取,預期可有效改善執行效能並縮減起始時間。GNU Classpath 專案主持人 Mark Wielaard 在 LWN 的文章 "GCJ - past, present, and future" 提到相關的歷史與技術背景,最早可回溯到 Cygnus solutions 時期 (RedHat 尚未併購) 的 GCJ 計畫提案 -- "A Gcc-based Java Implementation"。

為了降低實做的複雜度,筆者最早採用 LLVMIcedTea 作為系統框架,不過一直到今年春節,整體進度還是陷入膠著的狀態。現在則引入 Java2C 搭配 PGO (Profile-Guided Optimization) 與統計模型,嘗試分析運行於 Dalvik VM 的 Android activity / system server,佔用系統資源最頻繁的項目,並預先編譯 (pre-compile) 這些 class/method,居中透過 JNI (Java Native Interface) 讓 Dalvik VM 存取。不過,實務上來說,不是將所有 class/method 都編譯為原生機械碼,就會帶來效能提昇,相反地,後者往往讓系統陷入更差的效能。目前 Eclair 裡面的 Dalvik VM 雖然沒有完整的 JIT compiler,但其 fast interpreter for ARM 的確做了頗多 threaded interpreter 的改進,考量到 I-cache, paging, 與 branch prediction,若我們不思量 Java / Android Dalvik 應用程式的執行時期行為,只是一味作編譯轉換,很可能只是編譯極少被執行,或者完全不會被執行到的程式碼,因此加重執行時期的負擔,而最該被優化的部份,受限於不完整的 source-to-source 轉換,有顧此失彼的疑慮。

於是,找出系統中最該被優化的部份,並考量到正確性與相容度,就是我們的首要研究議題,筆者採用知名的 SciMark 2.0 作為量化分析的指標。以下是在 Qualcomm MSM7x25 硬體平台 (arm1136j-s) 的效能評比,ARM11 的時脈是 528 MHz,ARM Linux 版本為 2.6.29.6-0xlab:
由上可見,在 SciMark 2.0 的各項評比中,Pre-compiled class 執行效能都較 Android Dalvik fast interpreter for ARM 給予一定程度的改良,並且透過 FDO (Feedback Directed Optimization),大多可進一步給予提昇。這僅是初步的整合實驗數據,還需要更多分析與進行實做。

read on
Posted 張貼者: jserv 於 上午1:01 on 2010年5月26日 星期三 | 8 意見
Filed under: , , , , , ,
 

反組譯並修改 Android 應用程式實例

為了某個實驗的動機,我們評估反編譯 Android 應用程式的可行性,本文即是筆者的心得與實際的範例,僅供參考。就筆者的認知,目前還沒有針對 Android 的 DEX to Java source 反編譯工具,可實際處理一般的 Android 應用程式,多半要繞幾圈,還會得到不甚理想的結果,不過,smali 這個反組譯工具,已是可用了,只是得對付類似 Jasmin 語法的 Dalvik 組合語言。筆者打包了 smaliFrozen Bubble for Android,作為示範:

在 GNU/Linux 環境中,首先取得 Android SDK,這裡採用 Eclair/2.1,工具執行檔的路徑是 android-sdk-linux_86/tools,將此路徑放入 $PATH 環境變數,如此一來,就可以操作 adb, aapt, apkbuilder 一類的工具程式。筆者提供的套件已包含 Frozen Bubble 執行檔,檔名為 "FrozenBubble-orig.apk"。一旦 Android emulator 啟動後,即可安裝進去執行:(後續的操作也需要 Emulator 持續開啟)
$ adb install -r FrozenBubble-orig.apk
以下是執行畫面:
當然,沒必要讓筆者置喙談如何玩這個經典遊戲,不過我們倒是想更改原本的行為。在進行之前,我們先來複習 Android APK 的建立,參考 "How to build Android application package (.apk) from the command line using the SDK tools + continuously integrated using CruiseControl." 一文,我們可從以下圖表知悉細部的流程:

假設我們完全無法取得原始程式碼,該如何進行呢?沒錯,就透過 smali,簡化繁瑣的流程,筆者包裝為 Makefile,所以只要先解開並反組譯:
$ make extract
這時候會看到兩個目錄:
  • smali-src : 存放反組譯的程式檔輸出
  • workspace : 原本 Frozen Bubble 的 Android resource files
二話不說,當然是觀察反組譯的結果:
smali-src$ find
./org/jfedor/frozenbubble/FrozenBubble.smali
./org/jfedor/frozenbubble/R$id.smali
./org/jfedor/frozenbubble/GameView.smali
./org/jfedor/frozenbubble/SoundManager.smali
./org/jfedor/frozenbubble/LaunchBubbleSprite.smali
./org/jfedor/frozenbubble/Compressor.smali
./org/jfedor/frozenbubble/R$attr.smali
./org/jfedor/frozenbubble/BubbleFont.smali
./org/jfedor/frozenbubble/PenguinSprite.smali
./org/jfedor/frozenbubble/GameView$GameThread.smali
./org/jfedor/frozenbubble/BubbleSprite.smali./org/jfedor/frozenbubble/R$string.smali
./org/jfedor/frozenbubble/R$drawable.smali
./org/jfedor/frozenbubble/ImageSprite.smali
./org/jfedor/frozenbubble/BubbleManager.smali
./org/jfedor/frozenbubble/GameScreen.smali
./org/jfedor/frozenbubble/R.smali
./org/jfedor/frozenbubble/R$layout.smali
./org/jfedor/frozenbubble/BmpWrap.smali./org/jfedor/frozenbubble/FrozenGame.smali
./org/jfedor/frozenbubble/Sprite.smali
./org/jfedor/frozenbubble/LevelManager.smali
./org/jfedor/frozenbubble/R$raw.smali
就忠實地依據 Java package 的方式呈現,檔名結尾是 ".smali"。筆者的修改目標是,讓一開始的關卡 (Level) 從第一關直接跳躍到第五關。在 smali 原始程式碼 (注意:這完全不同於 Java 原始程式碼,而是極為貼近 Dalvik VM 所接受的 DEX 檔案的組合語言形式) 搜尋 "Level" 字眼,可發現主要的分佈就落於兩個檔案:
  • ./org/jfedor/frozenbubble/GameView$GameThread.smali
  • ./org/jfedor/frozenbubble/LevelManager.smali
前者就是 org/jfedor/frozenbubble/GameView.java 的編譯輸出,因為是 inner class,獨立編譯出 org/jfedor/frozenbubble/GameView.class$GameThread.smali,由這個 class 命名方式大概就可猜出其重要性,基本上只要能夠控制此 class 的實做,就掌握此 Android 應用程式的行為。而 class LevelManager 顧名思義,看來掌握了遊戲進行的程序控制。先觀察其 method 列表:
smali-src$ grep "\.method" org/jfedor/frozenbubble/LevelManager.smali
.method public constructor <init>([BI)V
.method private getLevel(Ljava/lang/String;)[[B
.method public getCurrentLevel()[[B
.method public getLevelIndex()I
.method public goToFirstLevel()V
.method public goToNextLevel()V.method public restoreState(Landroid/os/Bundle;)V
.method public saveState(Landroid/os/Bundle;)V
倘若我們以 "goToFirstLevel" 一類的關鍵字,在 org/jfedor/frozenbubble/GameView$GameThread.smali 檔案中搜尋,可找出有具體的呼叫行為:
smali-src$ grep -r goToFirstLevel *
org/jfedor/frozenbubble/GameView$GameThread.smali: invoke-virtual {v2}, Lorg/jfedor/frozenbubble/LevelManager;->goToFirstLevel()V
org/jfedor/frozenbubble/LevelManager.smali:.method public goToFirstLevel()V
由此更確定我們之前的猜想。其中組合語言寫為以下:
move-object/from16 v0, p0

iget-object v0, v0, Lorg/jfedor/frozenbubble/GameView$GameThread;->mLevelManager:Lorg/jfedor/frozenbubble/LevelManager;

move-object v2, v0

invoke-virtual {v2}, Lorg/jfedor/frozenbubble/LevelManager;->goToFirstLevel()V
不要被貌似複雜的語法嚇到了,基本上掌握 Java 程式語言的原則 "Everything is Object" (不過仍有提供 primitive type),組合語言仍會作 Java Object 的實體化 (instantialization),Dalvik 本身是 Register-based Virtual Machine,而扣除 static/class method 外,Java 中所有的 method invocation 多為 virtual function (對應於 C++ 的觀點,才能更具體用機械方式思考),所以組合語言的指令為 "invoke-virtual" (注意有連字號,此與 Java bytecode 不同),"{v2}" 表示第一受者的 Register,此為 Object 本體。接著,與 Java bytecode 一樣,"Lorg/jfedor/frozenbubble/LevelManager;" 就表示 Java 層面的 class "org.jfedor.frozenbubble.LevelManager",字母 "L" 即為 class 的識別,而 "->" 就很直觀了,自然是 method invocation,所以連貫來看,這一段組合語言的 Java 意思為:
objectLevelManager.goToFirstLevel();
其中 objectLevelManager 是一個 class LevelManager 的實例/實體 (instance)。倘若需要在 method invocation 時,帶入參數,那麼前述的 "{v2}" 一般會被替換為 "{v0, v1, v2, ...} 的 register 列表。關於詳細的狀況,可參考 Dalvik 非官方說明,另外 smali 的 wiki 也提供一些範例,可多加利用。

回到筆者剛剛設定的目標,我們既然知道 class org.jfedor.frozenbubble.GameView$GameThread 掌控了程式處理邏輯,自然一堆變數的傳遞、method 呼叫,都在此進行,那我們先試著用 "level" 字串去搜尋,想辦法找出常數定義,後者在 Dalvik 中,會集中保存於 constant pool 中,而 smali 的組合語言寫法大致是 "const" 開頭的宣告,端看其類型而定。以程式追蹤的目的來說,我們專注於以下兩種:
  • const-string : primitive string (不同於 java.lang.String) 表示
  • const/4 : 長度為 4 bytes (32 bit) 的整數表示
字串何其多,依據之前的推測來說,我們要找接近 "LevelManager" 字眼的組合語言程式碼,道理很明顯,從一般 Java programmer 的寫作邏輯去反推。經過一番搜尋,我們找到以下的反組譯程式碼: (位於檔案 org/jfedor/frozenbubble/GameView$GameThread.smali中)
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25 move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4 invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
在上述程式碼列表中,"Lorg/jfedor/frozenbubble/LevelManager;-><init>" 表示呼叫 class LevelManager 的 constructor,也就是 "<init>"。注意到 method invocation 方式就不同了,是 "invoke-direct",表示 class constructor,而這之前要有 "new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;" 的組合語言指令宣告。

前面談過「倘若需要在 method invocation 時,帶入參數,一般會被替換為 "{v0, v1, v2, ...} 的 register 列表」這樣的概念,我們可推知,Register v1 與 v2 就是實際上 class org.jfedor.frozenbubble.LevelManager 的 constructor 參數。就程式設計的邏輯來看,class GameView 就是依據某個流程,要求 LevelManager 去改變狀態,所以這裡的兩個參數,其實就是初始值,非常的重要。

與 Register v1 相關的組合語言指令有這幾行:(用粗體字標示)
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
顯然,Register v1 還被帶入到 android.content.Shared.Preference.getInt() method,而更早以前,其內含值被設定為 Register v3 的值,也就是常數字串 (const-string) "level",這好像與我們的焦點不同。另外,像是 Register v22 這個編號較大的 register,表示 local variable,這點需要多留意,因為 Java 程式設計的規範來說,往往會將程式切割為若干 method,而 method 實做體中,又有極多的 local variable,於是往往可從組合語言反推 Java 原始碼的型態。

那麼,看看 Register v2 吧,同樣用粗體字標示相關的指令:
const-string v3, "level"
const/4 v4, 0x0
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
這個 Register v4 的內含值 "0x0" 會指派到 Register v2 中,而讓我們似乎找到方向了,回頭看看 class org.jfedor.frozenbubble.LevelManager 的 constructor 宣告方式: (之前 grep 結果的第一行)
smali-src$ grep "\.method" org/jfedor/frozenbubble/LevelManager.smali
.method public constructor <init>([BI)V
其中 "public" 是 ACL (存取權限) 的宣告,而 constructor 的符號規範為 "<init>",注意到括號 "(" 與 ")" 裡面的兩個大寫字母,表示接受兩個參數,對應的型態為:
  • B : byte
  • I : int
在 Java 與 Dalvik virtual machine 皆以同樣的形式作宣告,看到這裡,我們實在忍不住要動手修改了,當然,一切都是實驗性質。既然一開啟遊戲,畫面就顯示 Level 1,表示 LevelManager 一開始接受的 level 參數會是 "0",然後依據 GameView 的邏輯,逐一升級或中斷遊戲進行,那麼,如果要讓遊戲一起動就是 Level 5,是不是要把內含值改為 0x4 即可?也就是 "invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V" 的 Register v2 當時內含值該為 0x4,不就任務達成了嗎?想到此,不禁會心一笑。

不過,回顧稍早 Register v2 的相關程式碼輸出,其中有兩行需要留意 (以粗體字為主):
invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
move/from16 v2, p4
"p4" 用以保存 method invocation 之後的回傳值,顯然,Register v2 受到 p4 的指派,也就是被更動為 android.content.Shared.Preference.getInt() method 的回傳值,這存在不確定性,於是,我們乾脆一口氣改掉: (修改的部份會用井字號 "#" 作註解)
# Modified from 0x0 to 0x4"
const/4 v4, 0x4
move-object/from16 v0, v25
move-object v1, v3
move v2, v4
# Modified: removed the following 2 lines
# invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences;->getInt(Ljava/lang/String;I)I
# move-result p4
new-instance v3, Lorg/jfedor/frozenbubble/LevelManager;
move-object v0, v3
move-object/from16 v1, v22
# Modified: removed the following 1 line
# move/from16 v2, p4
invoke-direct {v0, v1, v2}, Lorg/jfedor/frozenbubble/LevelManager;-><init>([BI)V
改好程式,當然要驗證,回到上一層目錄,透過 smali 提供的組譯器,重新產生 Dalvik DEX 輸出,為了簡化流程,筆者把 smali, apkbuilder, aapt, adb install 都一次整合進去,所以會直接讓 Android Emulator 生效,來看看我們的戰果吧:
注意到左下角,這表示我們成功了,完全不用取得 Java 原始程式碼,就可以作反組譯並且修改的動作。

read on
Posted 張貼者: jserv 於 下午10:08 on 2010年5月21日 星期五 | 4 意見
Filed under: , , , , , ,
 

Android Toolchain 原始程式碼尋寶

很多人從事 Android 移植,但連 Android Toolchain 都自行維護者,相對就少多了。筆者過去有幸在「台灣心」計畫中,從事建構於台灣自主 CPU 的軟體開發,嘗試從零到有,將 Android 移植到 Andes NDS32 架構,就涉及到 Toolchain 的更動。而維護 0xdroid 與對應 0xlab 的 GNU Toolchain,不免會迷失於眾多的原始程式碼,只好靜下心慢慢探索,沒想到因此挖掘到頗多「寶物」,本文簡記備忘使用。

Google 工程師 Jing Yu 於 Jan 18, 2010 提交一份修改 "Bring gcc-4.4.0 to up-to-date",讓人摸不著頭緒,不過其對於 GCC 的 architecture 更動,追加了新項目,可參見檔案 gcc-4.4.0/gcc/config/linux-grtev1.h 。以下節錄開頭註解:

/* Definitions for Linux-based GRTE (Google RunTime Environment) version 1.
Copyright (C) 2009 Free Software Foundation, Inc.
Contributed by Chris Demetriou.

This file is part of GCC.
這個以 Linux 為基礎的 GRTE 到底是什麼呢?沒獲得解答,只好在其 gcc spec 檔中探索,以下是相關的描述:
/* When GRTE links statically, it needs its NSS and resolver libraries
linked in as well. Note that when linking statically, these are
enclosed in a group by LINK_GCC_C_SEQUENCE_SPEC. */
#undef LINUX_GRTE_EXTRA_SPECS
#define LINUX_GRTE_EXTRA_SPECS \
{ "libc", "%{static:%(libc_static);:-lc}" }, \
{ "libc_p", "%{static:%(libc_p_static);:-lc_p}" }, \
{ "libc_static", \
"-lc -lnss_borg -lnss_cache -lnss_dns -lnss_files -lresolv" }, \
{ "libc_p_static", \
"-lc_p -lnss_borg_p -lnss_cache_p -lnss_dns_p -lnss_files_p -lresolv_p" },
這裡的 libc 看來是獨立的 C Library 實做,比較有趣的是 libnss 的部份。libnss 可透過外部的 module 作擴充,比方說 libnss-ldap 就是 "NSS module for using LDAP as a naming service",而前述 gcc spec 提及當進行靜態編譯時,需要將所需的 module 一併連結,那麼,這系列 libnss_ 開頭的函式庫,顯然就是 GRTE (Google RunTime Environment) 所需的基礎建設。來看看有哪些特別的:
  • libnss_borg
  • libnss_cache
或許後者可從名稱猜出一些端倪,但這個 "libnss_borg" 實在是太詭異 (Borg in Star Trek?),跟 GRTE 一樣神秘,我們只好等待 Google 大神給我們一些驚喜。

另外,Android Benchmark Suite 2.0.0 已公開釋出,可參見 benchmark.git,值得一書的是,內建了 FDO (Feedback Directed Optimization) 的編譯、測試,與效能評估機制。

read on
Posted 張貼者: jserv 於 上午11:21 on 2010年5月4日 星期二 | 0 意見
Filed under: , , , ,
 

0xdroid 正式支援 DevKit8000 開發板

沈寂的一段時間,現在 0xdroid 又恢復活躍的開發。正如稍早在 0xlab-devel 郵件討論區提及 "Return back to open source world",我們陸續將之前開發的成果,貢獻到自由軟體的世界,環繞在 0xdroid 的項目有:

  • Beagleboard 一貫的完整支援,不只是將 Android 運作起來,還要提昇整體的效能與可用性
  • 除了支援 Beagleboard 外,對 DevKit8000 也有充分的支援
  • 擴充 esuit 並整合 Android CTS (Compatibility Test Suite) Sikuli,提供涵蓋 board-level, API-level, Application-specific 的自動測試框架
  • 對 Android 為基礎的系統作全面性的功能、效能,與可靠度評比,以及整合上述的自動測試框架,以驗證量化系統的品質
在 kanru 的努力與若干網友的貢獻 (hychen, Fred, itszero) 下,現在對 DevKit8000 的支援已加入到 GIT repository,以下是執行時期的照片:
(0xdroid 的桌面與 Launcher)
(調整為直式顯示,符合原本 Android 的預期輸出假設)
目前支援 Android Donut 與 Eclair,在 0xdroid 即是 beagle-donut 與 beagle-eclair,需要搭配最新的 0xlab-kernel,對 DevKit8000 週邊做出更好的支援。以下是簡要的功能特徵描述:
  • 支援 DevKit8000 特有週邊:Ethernet, LCD panel / touchscreen, keypad
  • 提供對應的使用者介面 (UI) 設定程式,包含 Ethernet 與 Touchscrren calibration UI
  • 延續之前 0xdroid 在 TI OMAP3 平台的效能改善成果
近期內我們將會釋出新的 image installer,並持續改善 TI OMAP3 平台的 Android Eclair,而在今年的 OSDC.tw 研討會上,有個針對 0xdroid 的議程,歡迎前來指教,也希望對 0xlab 一系列開放原始碼專案有興趣的朋友,可來 0xlab-devel 郵件討論區參與討論,謝謝!

read on
Posted 張貼者: jserv 於 下午12:15 on 2010年3月10日 星期三 | 1 意見
Filed under: , , , , , ,
 
Developer at 0xlab.