目前分類:tech (11)

瀏覽方式: 標題列表 簡短摘要
最近一直努力在build toolchain,在GLIBC碰到一個不知道怎麼解的bug(segfault in __libc_start_main),轉用EGLIBC,目前起來頭好壯壯。不過同事擔心會不會有什麼問題,奉命survey一下。
EGLIBC (Embedded GLIBC)一開始應該是真的因為glibc太痴肥,在embedded的system上效能不張(西元2005是沒有cortex可用的)而發起的計畫,可參見jserv寫的"EGLIBC初探"和"EGLIBC於S3C2410 ARM SoC的體驗",但是後來2009-05-05 Debian 的maintainer Aurelien 宣布Debian以後要用EGLIBC,主要原因有:

  • More friendly upstream (especially with regard to embedded architectures): “Encourage cooperation, communication, civility, and respect among developers” (as opposed to this).
  • Stable branch with fixes for important bugs (a real one, not like the GLIBC one which is left unchanged).
  • Better support for embedded architectures.
  • Support for different shells (GLIBC only supports bash).
  • Support for building with -Os.
  • Configurable components (do we really need NIS or RPC support in debian-installer?).
  • Better testsuite for optimized or biarch packages.

    其實這都只是場面話,主要的原因是GLIBC的領導人Ulrich Drepper,是個很機車的人,怎麼機車不是很清楚,不過developer對他的形容有
  • Ulrich Drepper, is.. lets say very uncooperative when it comes to patches.
  • The maintainer of glibc (Ulrich Drepper) rules with an iron fist.
  • eglibc is a goodescape from the Fearless Leader (stated with no offense, Ulrich).
  • The switch is happening because maintainer of glibc is (I've heard) an asshole. ICBW.
  • Ulrich Drepper is a moron.
  • 比較激烈一點
    對於patches和架構有他自已堅持,以致於很多patch都不了mainline,GLIBC也有很嚴格的release procedure,一次就要搞六個月有對於某些平台的人似乎是太久了,這對Debian 這個支援許多平台的分支造成很大的困擾,所以只好fork另外一個branch出來自已maintain
    至於有什麼差別呢?目前看起來沒什麼差別,EGLIBC就是一個有拉新的patch進mainline 的GLIBC,不像GLIBC六個會有一次minor release,EGLIBC import GLIBC main release 的source code,然後就一直merge patch,所有的code要從svn上checkout下來。根據官網所言
    Embedded GLIBC (EGLIBC) is a variant of the GNU C Library (GLIBC) that is designed to work well on embedded systems. EGLIBC strives to be source and binary compatible with GLIBC. EGLIBC's goals include reduced footprint, configurable components, better support for cross-compilation and cross-testing.
    沒什麼特殊要求的話,應該可以安心使用

cmchao 發表在 痞客邦 PIXNET 留言(2) 人氣()

先解釋一什麼叫 Static Code Analysis(簡稱SCT好了),顧名思義:不會動的時候分析一下code。也可以看到wikipedia的條目

這通常由自動化的工具來分析(不然,我想Code Review也算吧),主要希望能在source code 階段,發現一些邏輯上或程式相依上可以發現的潛在問題。有人會覺得這件事compiler不就會做了嗎?用gcc -Wall, 用vc /W4,開下去就幫你檢查完了。可是事實上compiler只會幫你檢查syntax是否符合語言的規範,一些邏輯上問題他不會幫你檢查,SCT就是補足這方面的不足。

舉例以C/C++來說(引用自klocwork)
Null Pointer dereference
如果 x = (11 12 13 14 16 17 18 19) ,就爆了

void foo(int* p) {
*p = 32;
}
void bar(int x) {
int* p = NULL;
if( x == 15 || x == 20 )
p = &x;
if( x > 10 && x <= 20 )
foo(p);
}


Buffer Overflow
如果 data 指向的string 大小大於32 ?

void foo(unsigned char* data) {
unsigned char value[32];
int len = (int)data [0];
memcpy(value, data + 1, len);
}


Memory Leak
嗯,多插2G ram

void foo() { malloc(32); }



除了邏輯上的問題,SCT也可以協助檢查style的問題,比如果在constructor請問intial list 來初始化成員,或功能強一的可以檢查是否符合"Effective C++"建議的條目,並提供一些統計數據讓開發者可以對自已的程式碼品值有一定的掌控度。
其實這種tool在早早以前就有,還記當時年紀小連class都不會寫的時候,跑去看圖書館看"C/C++ user journal"(停刊了,哭哭),側邊的廣告很多都是跟SCT相關。這樣的工具甘要錢,大概看了一下一套400us,但open source 界佛心來著,也提供了一套免錢的功能沒那麼強大工具,就是cppcheck
我自已是使用ubuntu,apt-get裝一下就有了,使用方法非常簡單,以我pcmanx-gtk為例,0.3.9為例

#-f 是檢查所有可能條件編譯的路徑
cppcheck --enable=all -f pcmanx-gtk/src


產生出的log大概長這樣

Checking src/appconfig.cpp: USE_DOCKLET...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::ShowTrayIcon'
Checking src/appconfig.cpp: USE_EXTERNAL...
Checking src/appconfig.cpp: USE_MOUSE...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::MouseSupport'
Checking src/appconfig.cpp: USE_PROXY...
Checking src/appconfig.cpp: USE_WGET...
[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::UseWgetFiles'
Checking src/appconfig.cpp: __GNUG__...
1/41 files checked 2% done
Checking src/autologinpage.cpp...
2/41 files checked 4% done
Checking src/configfile.cpp...
Checking src/configfile.cpp: __GNUG__...
3/41 files checked 7% done


來看看他會檢查出什麼問題,底下是我節錄+整理的
style

[src/appconfig.cpp:54]: (style) Member variable not initialized in the constructor 'CAppConfig::SocketTimeout'
[src/core/caret.cpp:32]: (style) Member variable not initialized in the constructor 'CCaret::m_GC'
[src/core/fileutil.c:29]: (style) The scope of the variable fddest can be reduced
[src/core/termview.cpp:895]: (style) Redundant condition. It is safe to deallocate a NULL pointer


possible error

[src/editfavdlg.cpp:147]: (possible error) Memory leak: dlg
[src/editfavdlg.h:50]: (possible error) Memory leak: CEditFavDlg::m_List
[src/nancy_bot/msgdata.cpp:345]: (possible error) Memory leak: vsm


分析的結果只代表有修正的可能,不代表一定有錯,以memory leak 那項來說,只有2,3是真的有問題,第1個是因為gui的程式通常把child widget的釋放交給parent去做,所以不會有free的動作,還不賴吧。
除了cppcheck,也有另一套針對C語言的SCT open source 工具 splint,但是我搞不定他的設定,有人搞定可以教我一下嘛。另外最近事業做很大的clang/llvm,也提供一套C/C++/object-c的SCT工具,裝是裝起來了,但是怎麼試都不會有檢測報告,也請用過的人教一下吧

cmchao 發表在 痞客邦 PIXNET 留言(4) 人氣()

身為一個open source 的阿宅,只有新toolchain就會很想試用看看,雖然Code Sourcery 每半年才release 一版,但有時候會需要做交插測試要換來要去。之前在晶心科技工作,在強力的toolchain team支援下,二三天就可以有一版新版,一直都缺少一個有方便的方法可以切換toolchain,想記錄一下用過的方法。
基本的工作環境假設是連到沒有sudo 權限的server(這樣本機看叫叫叫片的時候才不會lag)

方法一:設在 PATH 環境變數

export PATH=$HOME/tool/gnuarm/arm-2010q1/bin:$PATH

優點:這就是最常看到的方法 簡單,直覺,霸王硬上弓
缺點:但如果要在同一個shell下換來換去,你的PATH 就會一次次長大,而且每次都要按tab 補齊buildtype,就是none-eabi-ooxx之類的

方法二:用一個link指向現在要用的toolchain,PATH 一直都一樣

export PATH=$HOME/tool/gnuarm/cur/bin #寫在 bashrc
cd ~/tool/gnuarm/
ln -s arm-2010q1 cur

優點:看起來很厲害
缺點:每次都要砍掉重link,然後command cache 要你重新export PATH 後才有效,超蠢,可是我用了很久,忍耐度超高


方法三:在bashrc 裡寫一個小function alias toolchain

#很像這樣,看個人環境
function nds_setup()
{
if [ ! -z $1 && ! -z $2]; then
alias agcc "$2/bin/arm-$1-gcc;
alias agcc "$2/bin/arm-$1-gcc;
alias agcc "$2/bin/arm-$1-gcc;
alias agcc "$2/bin/arm-$1-gcc;
alias agcc "$2/bin/arm-$1-gcc;
fi
}

$nds_setup linux $HOME/tool/gnuarm/arm-2010q1

優點:感覺還不錯,
缺點:實際使用時,都會忘記buildtype(其實是三不五時就在改,不是說ARM),要ls 一下才知道,然後要打二個參數,累....,另外bash 的subshell 不吃alias,下給CROSS_COMPILE 就會爛掉

方法四:用wrapper 吃環境變數決定要選擇那個toolchain

#!/bin/bash
#arm-gcc

if [ ! -z $ARM_TOOLPATH ]; then
$ARM_TOOLPATH/bin/arm-$ARM_TOOLTYPE-gcc $*
fi

優點:指令固定,subshell 可以吃
缺點:還是要看一下buildtype,另外toolchain 裡含binutil 大概有20隻指令,如果每個都寫一隻,之後要改會死人,還是要設二個參數

方法五:比較厲害的wrapper
用有點像busybox的方式,把所有的命令都link到同一隻script,再由script去分辦要執行的程式是什麼,版本為何
優點:好像還不錯
缺點:不知

#!/bin/bash
#set -x

#I assume
# the wrapper command format is "arm-command",
# the origin toolchain name is "arm-what-ever-you-want-gcc
# the gcc must exist

toolname=`echo ${0##/*/} | cut -d '-' -f 2`;
tooltype=`ls $ARM_TOOLPATH/bin/arm-*-gcc`

if [ -z $ARM_TOOLPATH ]; then
echo '$ARM_TOOLPATH' is not set;
exit 1;
fi

if [ ! -e $tooltype ]; then
echo "Can't find tooltype";
exit 1;
fi

tooltype=${tooltype##*arm-}
tooltype=${tooltype%%-gcc}

realtool="$ARM_TOOLPATH/bin/arm-$tooltype-$toolname";

if [ -z $toolname ]; then
echo "Unknown ARM tool";
exit 1;
fi

if [ ! -x $realtool ]; then
"file is not executable"
exit 1;
fi

$realtool $*

cmchao 發表在 痞客邦 PIXNET 留言(4) 人氣()

由前同事bboy 介紹,vim 強大plugin trinity,比Neo 還神的三位一體,可以將vim 打造文字模式的source insight。取這個名稱的原因是他將三個不同的plugin整合起來,分別是:
  • 可以顯示宣告的 "Source Explore"
  • 利用ctags 在右邊顯示key word的 "taglist"
  • 可以顯示當前檔案目錄結構的 "NERD_tree"

  • 成果就是這樣

    Screenshot-1.png


    使用方式
    下載 trinity (含修正過的NERD_tree), Source ExploreTaglist,放到自已存plugin的地方,順道一提預設的位罝是 $HOME/.vim/plugin,不要跟我傻傻一樣一個一個source。,然後在.vimrc加入" Open and close all the three plugins on the same time
    nmap :TrinityToggleAll

    " Open and close the srcexpl.vim separately
    nmap :TrinityToggleSourceExplorer

    " Open and close the taglist.vim separately
    nmap :TrinityToggleTagList

    " Open and close the NERD_tree.vim separately
    nmap :TrinityToggleNERDTree


    開程式檔的時候按個F8就會跑出來了,不過據說Source Explorer 很吃資源,有些人會把他關掉,請視自已的狀況調整,後應該要再改成認附檔名自動啟用,我不會

cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

雖然很多人都說gcin 比較好用,但不想裝一堆有的沒有的還是用ibus吧

參考了
http://reic.twbbs.org/post/1/431
http://vicamo.blogspot.com/2009/07/boshiamy-for-ibus.html
http://tw.myblog.yahoo.com/chrysler-wrangler/article?mid=214&sc=1
http://cle.linux.org.tw/trac/wiki/GcinInstallBoshiamy

改出一個liu for ibus表格產生器,只要原本的table的準備好,一行指令幫你搞到好。
請到http://twins.ee.nctu.edu.tw/~cmchao/download/ibus_liu_gen.tbz 下載

不過如果有買無蝦米的正式版,也可以到行易公司的網站直接下載,不管是scim, gcin還是ibus,統統幫你準備好。原價1280,現在特價880,現買現賺


cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

Self host 的意思就是自已compile 自已。

clang 做為一個llvm 前端的c/c++ parser 已經在2/4可以成功的parse "clang + llvm",並經過三回合的自我優化(*)後仍可以通過所有的測試。另外clang 編譯boost(**),也只剩三個header 不能過。
以上代表clang 對C++ 的支持已經快達到一個成熟的程度。2.7版即將在3/22發表,有興趣的人可以玩看看啦。不過我好像離C++ 愈來愈遠了,哭哭

註:(*)native 的compiler 通常會跑三個stage的自我優化。就是拿生出來的執行檔再編譯自已,重覆三次才是會release 出去的版本。
(**) 話說1.42 版在2/2 號發表了,新增uuid,修了一些bug

cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

git push 原本預設的行為是沒啥問題就直接送進遠端的repo,但這是有一個潛在的風險,當遠端的repo不是bare(請看git clone --help)而遠端的使用者用正在改working tree時,會造成working tree的base異動(會發生啥事?)。大大們承認這是當初設計上的失誤,想在之後的版本上修正,但又不想像1.6.0 把 '-'拿掉搞的天怒人怨,要來個漸進式的招術

在1.6.4,當push 回一個 non-bare 的repo 時,會產生警告,但是還是讓你丟進去
在1.6.5後,預設的值是拒絕。

可以在遠端的設定檔的

receive.denyCurrentBranch # true/refuse, warn, false/ignore
receive.denyDeletes # for branch delete


加以設定

詳細可看1.6.4 releasenotes

murmur: 不知不覺git 的版本已經來到 1.6.4,ubuntu的官方package 還在 1.6.0.4,什麼時候才會更新阿 @@~


cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

C++0x 引進了一個新的標準r-value reference 號稱可以大大的增進程式的效能。上星期Visual C++ Team 發表了一篇STL Performance 談到他們運用在VS 2010 和自已的STL library 上的成果。如果以vector的insertion和reallocation來看的話,大概可以快 2 ~ 3 倍。

至於什麼是R-value reference呢?有興趣的可以看Rvalue References: C++0x Features in VC10, Part 2,不想看英文的可以參考ptt's yoco315 翻譯的中文版

cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

回別人的文順便貼一下

Q: 要怎麼更動set 中element 的內容呢?
A: Visual C++ Team Blog 昨天也有提到這個問題
請看問題三:http://0rz.tw/TNBKr
在C++98/03 中,使用者是可以任意更改元素的值,只要不要改變元素順序
但在C++0x,明確的限制了這件事

"Keys in an associative container are immutable" (N2857 23.2.4/5) and "For
[set and multiset], both iterator and const_iterator are
constant iterators"

他提出了四種解法
1 改用 map/multimap,分離key 和value
2 刪掉改一改再塞一個新的進去
3 改用 set/multiset, comparator>,多一層轉換
4 上一篇推文中提到的 mutable (作者這說很怪 weird),
const_cast (作者說這很邪惡 evil)

雖然 C++0x 都快變成C++1x了,還是要尊重一下...:P

cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

全文90% 參考Ubuntu - 建立 ARM Toolchain (Cross Compiler)
不一樣的部份就是版本比他用的更新,然後提一下碰到的問題

環境:乾淨的ubuntu 9.04

step 1:安裝額外的套件,有些名字不太對,自已改一下


build-essential (gcc glibc)
bison (binutils and gcc )
flex (binutils and gcc)
texinfo (makeinfo
libncurses5-dev ( termcap)
mpfr-dev (gcc build)
gmp-dev (gcc build)


step 2 : 下載source package,解壓縮到目錄
binutils-2.19.1
gcc-4.4.0
newlib-1.17.0
gdb-6.8


step 3 : 設定編譯環境
TARGET_DIR 和 LIB_SRC請依照你安裝位置和源始碼放位置修改

export TARGET_DIR="/usr/local/gnuarm"
export LIB_SRC="/home/maxkerr/gnuarm/newlib-1.14.0"
export MY_CONFIG="--target=arm-elf --prefix=$TARGET_DIR --enable-interwork --enable-multilib"
export GCC_CONFIG="--target=arm-elf --prefix=$TARGET_DIR --enable-interwork --enable-multilib --enable-languages=c,c++ --with-newlib --with-headers=$LIB_SRC/newlib/libc/include"
export PATH="$PATH:$TARGET_DIR/bin"


step 4 : 編譯 binutils
套用patch,一個debug function format error

cd binutils-2.19.1
mkdir build;cd build
../configure $MY_CONFIG
sudo make -j 4 all install


step 5 : 編譯 gcc part 1

cd gcc-4.4.0
mkdir build;cd build
../configure $GCC_CONFIG
sudo make all-gcc install-gcc


step 6 : 編譯 newlib

cd newlib-0.17.0
mkdir build;cd build
../configure $MY_CONFIG
make all
sudo -c
export PATH="$PATH:$TARGET_DIR/bin" (為了找到arm-elf-cc)
make install



step 7 : 編譯 gcc part 2

cd gcc-4.4.0/build
sudo make all install


step 8 : 編譯 gdb
套用修正 p1, p2, p3, p4, p5, p6,

cd gdb-6.8
mkdir build;cd build
../configure $MY_CONFIG
sudo make all install


step 9 : 設定運行環境
把 :/usr/local/gnuarm/bin 加到 /etc/environment 中 PATH 最後一個 " 之前,例如這樣:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/gnuarm/bin"

step 10 : 測試

arm-elf-cc hello.c
arm-elf-run a.out

cmchao 發表在 痞客邦 PIXNET 留言(5) 人氣()

之前jserv寫了篇很有趣的文章(Who Call Me ?),利用一些小技巧去取caller和callee 之間的information。不過每個trace 的地方都還要手動塞code,如果要在往上看再去看stack frame,我對x86實在是很不熟。


今天在寫profiling的東東想到是不是可以用instrumentation(註一)的方式來得到同樣的資訊,把whocallme 的call 塞到每個function裡。原本以為-pg(gprof)可以做得到,因為gprof本來就是利用偷塞一些code來統計資訊,但gcc似乎不允許你塞自已的function。


那有其它的方式嗎?果然gcc support -finstrument-functions這個選項,會在你所有function 前後各塞入一個function,讓user可以蒐集或輸出一些資訊



void __cyg_profile_func_enter (void *this_fn, void *call_site);
void __cyg_profile_func_exit   (void *this_fn, void *call_site);



使用方式呢?這種技巧jserv 去年已經介紹過了,請看這裡。那現在就是把他們組合起來啦,底下是patch


--- ../whocallme/whocallme.c    2008-07-30 13:57:30.000000000 +0800
+++ ../whocallme2/whocallme.c   2008-08-20 17:59:23.000000000 +0800
@@ -60,7 +60,7 @@
{
    int i;
    for (i = 0; i < table_count; i++) {
-       if (addr > fun_table[i].addr) {
+       if (addr >= fun_table[i].addr) {
            if (addr < fun_table[i + 1].addr)
                return fun_table[i].name;
        }
@@ -134,3 +134,12 @@
    qsort(fun_table, table_count, sizeof(FUN_TABLE), compare_function);
    return 0;
}
+
+#define DUMP(func, call) \
+        printf("%s: func = %s, called by = %s\n", __FUNCTION__, func, call)
+
+void __attribute__((__no_instrument_function__))__cyg_profile_func_enter(void *this_func, void *call_site)
+{
+        DUMP(find_function_by_addr((unsigned long)this_func),
+        find_function_by_addr((unsigned long)call_site));
+}


 


在編譯你自已的程式時加入 -finstrument-functions(編譯whocallme.c 的時候不用,不然每個function 都要再補上no_instrucment_function的 attribute


,然後輸出就會長成這樣,


__cyg_profile_func_enter: func = test, called by = main
__cyg_profile_func_enter: func = test_a, called by = main
__cyg_profile_func_enter: func = test_b, called by = test_a
__cyg_profile_func_enter: func = test, called by = test_b
__cyg_profile_func_enter: func = test_c, called by = test_a
__cyg_profile_func_enter: func = test_b, called by = main
__cyg_profile_func_enter: func = test, called by = test_b
__cyg_profile_func_enter: func = test_c, called by = main


註一:instrumentation 要翻成啥?,"中山山"好像不錯

cmchao 發表在 痞客邦 PIXNET 留言(0) 人氣()

找更多相關文章與討論