2014年9月15日 星期一

androidized kernel跑在linux上的眉角之二(locale)

當locale沒被設定的時候
會自動fall back到"C"
這時可能會對許多package執行造成困擾
這時候就可以用如下的命令解決
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
locale-gen en_US.UTF-8
dpkg-reconfigure locales

 
參考資料:
http://www.thomas-krenn.com/en/wiki/Perl_warning_Setting_locale_failed_in_Debian

2014年9月12日 星期五

androidized kernel跑在linux上的眉角之一(ethernet)

把一個android kernel配上linux root file system
什麼怪事都會發生
例如說
root@ubuntu:/# ping 8.8.8.8
socket: Permission denied
什麼?有沒有搞錯?permission denied?
我可是天下無敵無所不能的root耶
居然連ping都不能用
.
.
.
.
.
經過了一番google的努力後
才發現原來android的權限設置遠比原生linux還要複雜
必須要在/etc/group裡加入下列兩行
inet:x:3003:root
net_raw:x:3004:root 

root才能使用inet的功能
如果別的用戶要使用inet都必需要加到這兩個group裡面
真是太麻煩了
但!
有個一勞永逸的方法
就是把
CONFIG_ANDROID_PARANOID_NETWORK
關掉就好了
簡單吧

2014年8月29日 星期五

patch的幾種方法

有幾種常見做diff和patch的方法

1. 使用大家最愛的git

matthew@E6430:~/temp$ git log
commit 406400903bc059bedfee59b11d60f7375818a21b
Author: Matthew.Shyu
Date:   Fri Aug 29 19:59:47 2014 +0800

    add hello world

commit 619ff93b9c08a2c63d433bd67de2f4051046332f
Author: Matthew.Shyu
Date:   Fri Aug 29 19:59:09 2014 +0800

    initial commit


例如要為"add hello world"這個commit做一個patch file的時候
可以使用如下的命令
$ git format-patch 406400903bc059bedfee59b11d60f7375818a21b -1
-1 代表往前一個commit的意思

要apply patch的時候就可以
$ git apply 0001-add-hello-world.patch

或者
$ git am 0001-add-hello-world.patch

這兩個的差別在於
第一個命令只是將patch的內容加上去並不會進行commit
所以在workspace上只是以unstaging change的形式存在
第二個命令就直接將patch進行commit到log裡

2. 使用quilt
quilt是一個patch管理程式
在Debian/Ubuntu上可以使用
$ apt-get install quilt
來安裝

我們首先在source code的根目錄產生一個patches目錄
$ mkdir patches
然後新增一個patch
$ quilt new hello-world.patch
再來是將需要修改的file加到quilt中
有兩個作法
$ quilt add test.c
或直接
$ quilt edit test.c
第二個作法是將test.c加到quilt中
並使用預設的編輯器對test.c進行編輯
當改好後
$ quilt refresh
就可以檢查patches/裡的patch是否正確
如果不再修改了
則使用
$ quilt pop
這時候被修改的文件會恢復成原狀
如果要再度修改
$ quilt push hello-world.patch

3. 古老的diff/patch法
使用
$ diff -purN <orig> <new> > hello-world.patch
$ patch -p0 < hello-world.patch
p0代表不rip directory
p1代表去除一層directory
依此類推


2014年8月13日 星期三

Android與Linux常用的debug技巧

很久沒有分享心得了
今天來分享一下常用的debug技巧

當系統當機時,最常見的就是stack dump
那要怎麼利用stack dump來track down bug呢
有幾個常見的方法

1.  使用addr2line
這個方法非常好用,但只適用於自己編出來的系統
例如我們在logcat裡看到
07-30 09:52:15.289: INFO/DEBUG(28):          #00  pc 0000aea4  /system/lib/libc.so
07-30 09:52:15.289: INFO/DEBUG(28):          #01  pc 00026810  /data/data/oms.cj.yap/lib/libsdl.so
由logcat我們可以知道
這個當機發生在libc 的0xaea4行
但對應source code在哪裡呢?
這時候就可以
$ addr2line -f -e libc.so 0000aea4
<格式>
$ addr2line -f -e <path to library> <offset>

2. 直接看assembly code
那要怎麼知道哪個symbol是位於哪個library
第一個方法當然就是直接去看makefile
看library究竟包了哪些source file
但這個方法稍嫌麻煩了一點
我們可以利用nm來把symbol從library dump出來
<格式>
$ nm <library>
然後可以用objdump把source code + assembly code 用mixed format輸出
<格式>
$ objdump -dRS <path to library> > tmp

3. 除了addr2line之外,Android ndk tool也有一些很棒的工具可以使用
例如
$ adb logcat |  ndk-stack -sym <path to libraries>
$ ndk-stack -sym <path to libraries> -dump <file with crash log>

再來介紹一下gdb/gdbserver常見的技巧
在embedded system上
我們常常利用gdbserver和gdb配對進行debug
這是因為在embedded system上,通常記憶體,儲存空間,和cpu效率都是有限的
如果我們直接把gdb放到embedded system上會有幾個問題
1. 要使用gdb的話library必須要unstripped, 也就是說我們將會佔用大量的儲存空間
2. 執行gdb會耗費大量的cpu resource, 如果發生的bug與timing有關, 就會比較難以復現, 甚至於會出現其他的問題
另外gdbserver由於體積小所以更有著容易porting的好處

要開始debug時
我們先在embedded system上把gdbserver打開
# gdbserver :5039 <app>

然後在host上執行gdb
arm-linux-gdb
(gdb) target remote 192.168.0.100:5039 # 這個命令指定target的ip
(gdb) info shared # 這個命令用來確定gdb是否正確找到library的路徑, 因為使用cross compilation的關係, 所以通常default search path是不能使用的
(gdb) set solib-search-path staging/usr/lib # 用這個命令來指定library search path
(gdb) set sysroot staging # 也可以用這個命令直接指定cross compilation的root,就不用單獨指定search path了
(gdb) set logging overwrite on # 下面這幾個命令是用來把core dump儲存起來
(gdb) set logging on
(gdb) continue
(gdb) bt full
(gdb) set logging off