June 17, 2010

透過 libtcc 來擴充 C 語言

在「libacc : Android 2.0 內建的輕量級 C Compiler」一文,筆者提過 Fabrice Bellard 的大作 [OTCC] (Obfuscated Tiny C Compiler),而 OTCC 進一步開發則成為 [TCC] (Tiny C Compiler),這是世上最完整的迷你 C compiler 實做。如同 Fabrice Bellard 的其他作品,TCC 也提供一個驚喜,可參見 TCC 網頁的特徵描述,其中有一項:
    "With libtcc, you can use TCC as a backend for dynamic code generation."
本文就是透過 libtcc,試圖擴展 C 語言,並探討新的應用型態。

在 Ubuntu Linux 上,libtcc 是以 statically-linked library 的形式存在,安裝方式相當便利:
$ sudo apt-get install libtcc-dev
不過還需要 "libtcc1",也就是 TCC runtime library,最簡單的安裝方式就是直接安裝 TCC:
$ sudo apt-get install tcc
到底哪些檔案是必要的呢?先來看看目錄結構:
$ tree /usr/lib/tcc/
/usr/lib/tcc/
├── bcheck.o
├── include
│   ├── float.h
│   ├── stdarg.h
│   ├── stdbool.h
│   ├── stddef.h
│   ├── tcclib.h
│   └── varargs.h
└── libtcc1.a

1 directory, 8 files
可發現,"/usr/lib/tcc/libtcc1.a" 就是 runtime library,會在呼叫 libtcc 時被引入。實務上,可以不必安裝 TCC 套件,只要提供位於 "/usr/lib/tcc/" 目錄的若干檔案即可。張羅了必要的套件後,我們可展開一些實驗。筆者設定的目標是,將之前的 [qsort 與 shellcode] 程式範例,用 libtcc 適度改寫,使其成為架構在 C 語言上的 Lambda expression 實現。在我們設定的目標中,基本概念是動態時做出「匿名函式」(anonymous function) 的機制,,也就是建立特別的 function object 以供後續操作,不過因為 C 語言可直接操作記憶體與堆疊。動手寫個程式吧 (lambda-in-c.c):
編譯方式如下:
$ gcc -o lambda-in-c lambda-in-c.c -ltcc -ldl
執行驗證看看:
$ ./lambda-in-c 
1 2 3 4 5 6 7 8 9 10 
--- done ---
看來透過 libtcc 動態編譯的 "lambda" 函式實做,被帶入 qsort() 函式,並正確執行,確認其標榜的 "use TCC as a backend for dynamic code generation" 功能。那麼,如此的機制到底有什麼實務上的價值?當然不是為了動態編譯而編譯的,事實上,Mesa/3D 函式庫很早就透過 libtcc,進行動態編譯,進而產生某些特定的機械碼。可參考 XORG-6_8_0_.tar.gz 裡面的 xc/extras/Mesa/src/mesa/swrast/s_tcc.c 檔案,這是為了輔助同目錄下的 s_fragprog_to_c 檔案,以下引用其註解:
    An amusing little utility to print ARB fragment programs out as a C function. Resulting code not tested except visually.
在程式碼可見到,Mesa 動態輸出若干 Texture samplers,libtcc 給予開發者很大的彈性,能用 C 語言來作動態建立 texture 處理函式的實做。另外還有 SQL Stored Procedures,依據其定義就是:
    A stored procedure is a group of Transact-SQL statements compiled into a single execution plan.
在 MySQL 的處理中,也可透過 libtcc,詳情可參考這兩篇精彩的文章: 為何我們該搞懂進階的 Compiler 技術?為了技術突破!試想,SQL 有 Stored procedures;OpenGL 2.0 有 GLSL;JavaScript 有一堆 engine, ... 這些背後的技術,都直接與 compiler 有關,希望筆者也能持續分享探討這些美妙的技術。
由 jserv 發表於 2:05 AM | 迴響 (0)

在 GDB 透視 C 語言的字串表示法

最近從「快快樂樂學 GDB」到一系列與 C 程式語言相關的 [演講議程],探討了在執行時期,透過 GDB 一窺系統全貌的途徑。筆者的觀點是,C 程式語言就是設計來開發作業系統的用途,務必確認每個環節。UNIX 之父 Ken Thompson,不僅開創了 UNIX 若干經典的設計,也持續維護 C compiler,甚至在 Plan9 研發時,還重新翻修過整個編譯系統的設計,可參考 [A New C Compiler by Ken Thompson],顯然就是不放過任何一個技術細節。身處於 21 世紀的我們,幸福多了,有強大的 GDB 搭配開放的 GNU/Linux,而本文就在這些基礎上,談談在 GDB 透視 C 語言的字串表示法。

前文 [C-style 字串的最佳化] 提過 C 語言字串的形式,其實不過是一段保存於連續記憶體的資料,那面對稍微複雜一些的形式,我們不免會亂了方寸,這時候當然要祭出 GNU gdb 來協助。首先,我們先讓 gdb 變身為 C interpreter:
$ gdb `which gdb`
GNU gdb (GDB) 7.1-ubuntu
[...略...]
Reading symbols from /usr/bin/gdb...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x808ae03
Starting program: /usr/bin/gdb 
[Thread debugging using libthread_db enabled]

Temporary breakpoint 1, 0x0808ae03 in main ()
(gdb)
取得 gdb 的命令提示列後,就可動態作許多 C 語言版本的 eval (可對比 JavaScript 的 eval),我們接著作個實驗:
(gdb) p (char (*) [10]) &"0123456789abcdefghi"
$1 = (char (*)[10]) 0x83ca008
注意到字串 "0123456789abcdefghi" 的動態宣告方式與提取記憶體位址 (operator &) 的寫法,在 gdb 必須清楚的標示 C 語言的 type casting。我們知曉這 10 個單位的 C-style 字串陣列,被配置到自位址 0x83ca008 開始的連續記憶體,那就分別來窺探記憶體的內容:
(gdb) p ((char (*) [10]) &"0123456789abcdefghi")[0]
$2 = "0123456789"
(gdb) p ((char (*) [10]) &"0123456789abcdefghi")[1]
$3 = "abcdefghi"
當然,你也可以這麼作:(想想輸出的結果為何如此)
(gdb) p (char[]) {"abcdefghi"}
$4 = "P"
或者:
(gdb) p (const char[]) "abcdefghi"
$5 = "abcdefghi
前後比對 "char *" 與 "char[]" 對應的記憶體關聯,也可發現兩者的微妙差異,一切都經由 gdb 攤在陽光底下。
由 jserv 發表於 12:34 AM | 迴響 (0)

June 16, 2010

意義是三小,我只知道義氣

在思念某個人的時候,我總會來到那間兩人曾多次觀賞的二輪片戲院,不論究竟播映什麼,只想靜靜的沉溺在過往。只是沒想到,原本只是思念一人,在觀賞《艋舺》後,又多思念一位朋友。

時間回到 2002 年,當我決定離開成功大學後,先服兵役,為日後規劃作準備。體力狀況不好的我,新訓入營第一天就在集合場昏倒 (入伍前一日還在趕專案,徹夜沒睡),第二天則是上吐下瀉,反正一連串的事故,到了懇親會,滿頭茂密的頭髮,絲毫沒有修整過,甚至被當作女兵。在軍中休養與閒置時,拿起隨身攜帶的兩本書翻閱:老子《道德經》與家父用過的袖珍英漢辭典。當時的目標是「如果能在他人認為是浪費時間的軍旅生涯中,想辦法能做出一點事,就是很大的突破」,於是,一邊在這「夏令營」鍊體能、認識朋友外,就是用力背單字、思考老子的智慧,並且探索人生存在的策略。或許是註定要這麼另類,舉凡絕食抗議以爭取軍中改善伙食、當著長官視察的機會,反映新訓單位的諸多缺失,或者直接跟連長商量新訓的執行方式等等,總之,一開始只是想知道,到底能惡搞到什麼程度,但竟然讓人誤會我有什麼背景,而連上原本的小混混,也用不同的態度對待我。

成為中輟生以前,在某些觀點來說,我被當作「乖乖牌」,大抵是維持夠好的學業成績、擔任學校的班級幹部、獲選為模範學生,偶爾參加一些競賽,而精英教育更是讓視野狹隘,好似一定要把自己想得很偉大,才能稱上一個完整的人。還好我有機會服兵役,得以貼近這個世界的真實一面,這在前文「服兵役,作為一個轉折點] 大致提過。也不知道從什麼時候開始,那些身上滿滿刺青的鄰兵,不約而同稱呼我為「群哥」,炎炎夏日還會主動買涼水,除了偶爾去擺平一些雜事外,跟他們的交集不多。下部隊後,與弟兄的生活更密切,在極機密的單位服務,免不了無止盡的演習,輪班制度更是讓人心生絕望,當初立下「做出一點事」的心願,該如何履行呢?還好,逐漸習慣日夜交錯的排班、與聯隊同袍的感情更密切後,每天還是能挪出至少一小時可讀書、寫信,與 (紙上) 程式設計,重溫「乖乖牌」的生活。

跟一群原住民學長一同服役,是幸福的,沒有比這樣更能貼近不同的文化。值班時精力旺盛,下班後的活動,一樣都不少,在苦悶的營區中,依然能夜夜笙歌 (不過只有酒肉與吟唱)。過去不免對職業軍人有些陳見,而在深入了解他們後,不過只是機運不同罷了,每個人都有過去,如今我們都在同一條船上。原本滴酒不沾的我 (國中時,某次除夕沾了一口葡萄酒,立刻昏睡,自此對酒精拒絕往來),在學長密集的訓練下,竟然也培養了一點酒量,話匣子打開了,自然是無所不談,也對「兄弟」有更深入的理解。

    「如果你有選擇,當初會這樣作嗎?」
面對嫌疑犯,我們往往會有如此的疑惑,而,涉世未深的我,很難想像身邊的弟兄,幾年前曾過失殺人,為逃避那打打殺殺的環境,在軍中尋求一個相對的隔離。意義?我在他的談吐,逐漸知曉所謂的義氣。年紀與我相仿,但江湖硬是在他身上,烙印著顯著的痕跡。在服務的單位中,先後傳出三位義務役士兵自殺的消息,但我僥倖在這不甚人性化的工作環境,取得還不錯的「位置」,多少也與學長相挺有關。在有限的記憶中,下部隊一年半載,所有的酒錢、下酒菜,甚至外出的「餘興節目」(有女侍/女士陪伴的那種) 費用,其實我一毛錢都沒出過,每日的酒肉交際,成為軍旅生涯一項「功課」,大概可歸類為「群哥」時期。

喜愛值夜班,儘管要從晚上七點,一口氣值勤到早上六點,但除了夜航外,沒有太多急迫的任務,取而代之的,就是可以慢慢做的勤務與訓練。只要本職學能充分的話,夜班可以挪出可觀的空檔,令人欣慰的是,用這些空檔,陸續讀完三十多本書,包含大學沒有學習的課目。除了利用大夜班進修外,其他的時間可說是一面值勤,一面交際。一旦覺得精神不支時,就趕快跟弟兄談天,話題廣泛從風花雪月,到每個人的過往。每道刀痕的背後,都有獨特的意義,喔,更精確的說,那是義氣的見證。有時,在難得的休假中,這些弟兄還得結伴去幫忙討債,不免落得新舊傷痕並陳。

    「那未來呢?你要怎麼走人生的旅程?」
我們談論了未來,有如在漫漫長夜中,螢光幕上細微的雷達回波般,想法短暫的存在,又在轉眼間消逝。時間允許時,曾幫他們補習英文,或許退伍後能有用處,而以更多的故事見聞分享,作為回報。一直到那個時候,我才真心地,傾聽這世界上與自己設想不同的聲音。沉默是一種處世哲學,用得好時,又是一種藝術。多半,我隨著這些片段的故事,心境起伏著,儘管表面是沉默的,金庸不也借狐沖之口,說道:「有些事情本身我們無法控制,只好控制自己」?

能沖刷一切者,除了眼淚,就是時間。退伍後各奔東西,除了偶爾接到來電,要求協助處理經濟上的缺口外,頂多就是談談共同的兵役趣聞,隨著我在電子產業的消磨,彼此的聯繫越來越淡。後來輾轉得知,我這位「兄弟」涉入某個火拼,隨後消沉度日,幾度嘗試聯繫,至今沒有下文,只能盼望一切安好。你教了我一個顯見的道理:人生短短幾十年,不該給自己留下了什麼遺憾,應當想笑就笑、想哭就哭,該愛的時候就去愛,無謂自我壓抑,得以率性的活著,還有什麼比得上呢?又夢見了你,幾分陌生,又莫名的熟悉,拍著我的肩膀,稱兄道弟地豪邁把酒言歡。
由 jserv 發表於 1:54 PM | 迴響 (0)

June 2, 2010

演講:自己動手,豐衣足食 -- 淺談探索 Linux 系統設計之道

本週六 (June 5),小弟將在 Study-Area 台南的場次分享「自己動手,豐衣足食 -- 淺談探索 Linux 系統設計之道」的議程,著眼於 GNU/Linux 瞬息萬變得今日,作為軟體「消費者」的我們,該如何善用手頭的工具與資源,嘗試探索 Linux 系統設計的奧秘。光是 Linux Kernel,可以說無時無刻都在更新與演化,更遑論其上豐富的 GNU/FSF 高品質軟體,那我們該如何下手呢?筆者兩年前於南台科技大學,曾以「尋幽訪勝話系統--以 Linux 探索軟硬體整合設計」為講題,獲得一些意見交流,此次藉 Study-Area 活動的機會,將此講題延展為探索 Linux 系統設計,同樣仍強調自己動手的途徑。

本議程試圖簡介 Linux 核心的經典設計,並以軟體的觀點,探訪與週邊硬體互動的機制,比方說從 /proc 與 /sys 等虛擬檔案系統上的資訊,對照硬體環境,試圖找出關聯性,進而將這些「鑰匙」串連,建構我們的知識庫。以下節錄 Study-Area 的 [演講公告]:
  • 主題:自己動手,豐衣足食 -- 淺談探索 Linux 系統設計之道
  • 議程大綱:
    • 毛主席:自己動手,豐衣足食
    • 源碼之前了無秘密:重返 Linux 核心設計概念
    • 羅塞達碑石 (Rosetta Stone):Linux 如何建立軟硬體關聯
    • Linux 驅動程式架構與發展
    • 尋幽訪勝自己來
  • 時間: 2010年06月05日 (星期六) / 下午 14:00 ~ 17:30
  • 地點:崑山科技大學-資科學院i5401i5(資訊管5館)4(4F)01教室
  • 報名網址: http://www.study-area.org/samc/registry/add/48
另外,這裡一併回答若干大學院校的詢問,如果貴實驗室 / 貴單位對這一類的系統層面議程有興趣,諸如編譯器技術技術、作業系統,或者驅動程式架構等等,都歡迎指教,這裡可斟酌安排。
由 jserv 發表於 8:21 PM | 迴響 (0)