August 27, 2010

為 mupdf 加上全螢幕切換功能

昨天受邀去內湖某公司作簡報,因為 OpenOffice 產生的 PDF 檔案稍大,用 evince 播放時,略為停頓一下,致使跟不上預定的節奏,有些細節就不慎忽略。回辦公室後,認真思考改良 PDF 簡報放映的方式,歸納以下軟體需求:
  • 避免太多相依性或執行時期的檔案 -- 讓任何一台裝有 GNU/Linux 的電腦都能作簡報與程式展示
  • 快速 -- 就算播放幾十 MBytes 的 PDF 檔案也順暢
  • 流暢鍵盤操作 -- 快速 zooming, 切換視角, 切換頁面,標注重點等等
  • open source -- 這還要說嗎?這年頭好多 closed source PDF viewer 根本就是 spy/ad-ware
[MuPDF] 是目前最符合上述需求的軟體,輕薄短小,而且相當快速,但缺乏最重要的功能,也就是全螢幕播放,只好自己動手改。初步的 patch 可參考 [mupdf-toggle-fullscreen.patch],只是單純的作 X11 full-screen 切換,並沒有考慮到針對螢幕解析度,重新描繪 PDF 內文的動作。在 lenovo X200 的顯示結果如下:(用 'F' 按鍵切換全螢幕)

[MuPDF] 的授權是 GNU GPLv3+。
由 jserv 發表於 4:50 PM | 迴響 (0)

August 18, 2010

演講:沒有政府補助,照樣寫自己的作業系統 -- 如何善用開放原始碼工具,加速作業系統的開發

應 ICOS 2010 之邀,小弟將在該研討會在九月 18 日 (週六) 的議程中,以「沒有政府補助,照樣寫自己的作業系統 -- 如何善用開放原始碼工具,加速作業系統的開發」之名,作為演說分享。詳情可參考 [ICOS 2010 網站] 與 [議程資訊]。

作為一位沒受過高等教育、社會最低階的軟體開發者,小弟每年練習寫一套不同的作業系統,期許自己能提昇資訊素養,雖稱不上有什麼成果,但這段歷程著實讓我體驗到開放原始碼工具的重要性,於是藉這個議程,野人獻曝一番。一如往常,每年都要發表一個 (玩具) 作業系統,今年則是將 [Orz Microkernel] 用 C 語言重寫,同樣是具體而微的系統,可作為教學研究使用。在 ICOS 2010 的議程中,小弟會探討發展這樣一個 microkernel,如何在相當有限的開發資源,善用 GNU Toolchain 搭配如 QEMU 這類強悍的工具,快速從 prototyping 到系統驗證,即便只用下班後寶貴的時間,還是能搭建一個小而美的 microkernel。

以往,我們總能以既有的資源去解決軟硬體問題,但今日我們面對五花八門的技術、日新月異的技術,許多人都亂了方寸,一味盲從,卻忘了資訊技術的提出,就是要解決既有的問題。我一直認為,唯有親身體驗一個完整系統的設計,才得以獲得成長,也才可創造更廣泛且深入的應用,無論是奠基於既有的架構抑或是重起爐灶皆是,這就是小弟這幾年多場技術演講的核心概念。期待您的參與指教,謝謝!
由 jserv 發表於 11:34 AM | 迴響 (0)

August 4, 2010

演講:打造特製的 Android Toolchain

很榮幸能連續五年,在台灣的年度盛會 [COSCUP] 研討會上,作心得分享。今年的演講議程,題目定為「打造特製的 Android Toolchain」,主要分享小弟在 [0xlab] 所作的實驗,從修改 Android 的 GNU Toolchain 到提供 source-to-source compiler,提出若干基於特定需求,從而發展的編譯器技術的新應用。時間是 Aug 15 (週日) 下午,詳細議程資訊,請參考 COSCUP 網站。

我們可發現,ARM 陣營籌組了 [Linaro] 組織,不僅有系統整合層面的 Ubuntu / Canonical,還包含像是 CodeSourcery 這樣專精於編譯器技術領域的公司投入。近期內,已建構於開放原始碼的技術上,由 CodeSourcery 與 ARM 工程師主導,由 GCC 搭配 CodeSourcery G++ 的基礎,搭建 Linaro 的 GNU Toolchain,在 Toolchain working group 有相當活躍的進展,而這些基礎建設,也讓廣大的 Ubuntu ARM 使用者受益。一直採用「半開放」開發模式的 Google Android 團隊,這半年以來,逐漸有改觀,不僅提供完整的 GIT commit log,還開放一系列 Android Toolchain 的資源。這些變化都發生在 2010 年,現在 Embedded 與 Mobile 的系統軟體開發,悄悄地引入新的模式,就如日前筆者應邀參與的 [SoC Summit] 研討會標語所說:
    "Building Compelling User Experiences in Silicon"
連編譯器技術,這種與使用者體驗,看似八竿子打不著的項目,其實也已經為我們所處的資訊生活,帶來了頗大建樹。在 COSCUP 的「打造特製的 Android Toolchain」議程中,筆者會先探討 GNU Toolchain 相關的發展,像是 gold, GCC Plugin, LTO 等等 (僅有高階的描述),再來會提及 LLVM 相關技術的應用,甚至隱藏在 Android 系統中,也有諸多與編譯器技術的項目。只要我們能掌握資訊技術的原理,往往能讓許多創新,融合到最終的產品,這也是 [0xlab] 試圖追求的目標。

依據慣例,屆時我們也會發布最近的成果,請留意 [0xlab] 開發者的動態,期待您的蒞臨指教,謝謝!
由 jserv 發表於 10:24 PM | 迴響 (0)

August 2, 2010

ptrace / SIGTRAP / int3 的關聯

最近的時間大部分投入於某個產品的研發,自然得考慮到一些議題,其中包含了 anti-hacking,順便就複習 ptrace 一類的操作,本文可視為 [以 ptrace 系統呼叫來追蹤/修改行程] 的補充,以實驗方式,觀察這些底層機制。

在 UNIX 的世界裡,作業系統提供 ptrace 系統呼叫,允許我們優雅地進行「攔截」或「追蹤」其他行程的動作,這也是 gdb 與 strace 一類系統工具背後的原理,比方說 Evan Teran 就依據如此的機制,撰寫一個 [Qt4/ptrace-based Binary Debugger]。無論是如何操作,大抵依循以下三個步驟:
  • 調用 ptrace 系統呼叫
  • 判斷 SIGTRAP 是否為監看的程式 (如 GDB) 所攔截
  • 透過硬體平台的指令,去觸發 breakpoint / SIGTRAP,進而執行特定的追蹤動作。以 x86 為例,就是 "int3" 指令
在 GNU/Linux + IA32 環境下,筆者撰寫一個小程式,試圖觸發 breakpoint,來觀察在 gdb 底下與否,有什麼變化: [hello-int3.c]
#include <stdio.h>
int main()
{
	puts("Hello");
	__asm__ __volatile__("int3");
	puts("World");
	return 0;
}
試著編譯並執行:
$ gcc -o hello-int3{,.c} -g && ./hello-int3
Hello
Trace/breakpoint trap (core dumped)
顯然,在 x86 上,這個 "int3" 的組合語言指令,觸發了 breakpoint / SIGTRAP,依據 Linux Process 預設的 signal handler,就是終止程式的執行。那麼,在 gdb 下呢?繼續作實驗:
$ gdb ./hello-int3
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/jserv/tmp/hello-int3 
Hello

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at hello-int3.c:6
6		puts("World");
(gdb) 
看來 gdb 註冊了 SIGTRAP handler,才會得知 hello-int3 執行的 Process 具體的資訊, 並依據 DWARF,查詢到停留在 C 程式的第六行 (尚未執行)。Francis Bacon 說過,最好的證明,就是練習,對資訊科技更是如此,根據稍早的觀察,我們可推論出,若要讓 Linux Process 免於被 gdb 所「騷擾」(anti-hacking 的基礎),必須在程式內適時註冊 SIGTRAP handler。筆者準備以下的驗證程式碼: [dbg-int3.c]
#include <stdio.h> 
#include <signal.h>

static volatile sig_atomic_t being_debugged = 1;
static void int3_handler(int signo) { being_debugged = 0; }

int main()
{
        signal(SIGTRAP, int3_handler);
        __asm__ __volatile__("int3");
        if (being_debugged) {
		puts("No, I don't want to serve you.");
                while (1) {
			/* endless loop */ ;
		}
        }
        puts("Yes, real routines go here.");
        return 0;
}
試著編譯並執行:
$ gcc -o dbg-int3{,.c} -g && ./dbg-int3
Yes, real routines go here.
這是平常的執行結果,因為先註冊專屬的 SIGTRAP handler,當執行 "int3" 指令,自然會去觸發,設定「此時不被 debugger 追蹤」的狀態。那在 gdb 底下執行呢?比較看看:
$ gdb ./dbg-int3 
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/jserv/tmp/dbg-int3 

Program received signal SIGTRAP, Trace/breakpoint trap.
0x08048421 in main ()
(gdb) 
GDB 告訴我們 SIGTRAP 被觸發了,這時候我們就要思考,到底 SIGTRAP handler 是不是被 GDB 給「攔截」或「改寫」過,繼續看下去:
(gdb) c
Continuing.
No, I don't want to serve you.
顯示 "No, I don't want to serve you." 一段文字後,就陷入無窮迴圈,可反推,GDB 的確會對 attached process 作 SIGTRAP handler 的攔截處理,而我們的程式則反將一軍,非暴力不合作。

另外,若不想使用 SIGTRAP handler 的機制,可直接用 ptrace 系統呼叫來檢查,改寫上述程式碼如下: [ptraceme.c]
編譯並直接在 gdb 裡面執行:
$ gcc -o ptraceme{,.c} -g && gdb ptraceme
GNU gdb (GDB) 7.1-ubuntu
...
(gdb) r
Starting program: /home/jserv/tmp/ptraceme 
No, I don't want to serve you.
同樣達成目的。需要留意的是,有一些特別的 Linux 系統,如 Google Chrome OS,也是透過上述這些常見的 anti-hacking 技倆,實現作業系統層級的 sandbox 機制。
由 jserv 發表於 2:30 AM | 迴響 (0)