顯示具有 編譯 標籤的文章。 顯示所有文章
顯示具有 編譯 標籤的文章。 顯示所有文章

2015年6月1日 星期一

[Embedded] 利用 gdb script 實作 strcmp 函數

要在 gdb 內直接使用條件式中斷(Conditional breakpoint),例如:當某個字串出現時程式才進入中斷點,應該怎麼做呢?

1. 可以使用 commands 命令來設定條件式中斷
break foo
commands
if x>0
continue
else
printf "x is %d\n",x
end
end

2. 問題在於如何比較字串,以下整理網路上找到的幾種作法。若gdb版本較舊,則可能需要找尋其他方法。

方法一:使用 strcmp
(gdb) set $x = malloc(strlen("foobar") + 1)(gdb) call strcpy($x, "foobar")(gdb) break a_leg if strcmp(foo, $x) == 0

方法二:透過 python
可以直接使用下列函數 (Convenient functions) 
$_memeq(buf1buf2length)Returns one if the length bytes at the addresses given by buf1 and buf2 are equal. Otherwise it returns zero.  
$_regex(strregex)Returns one if the string str matches the regular expression regex. Otherwise it returns zero. The syntax of the regular expression is that specified by Python's regular expression support.  
$_streq(str1str2)Returns one if the strings str1 and str2 are equal. Otherwise it returns zero. 




也可以自行實作 strcmp
(gdb) define strcmp>py print cmp(gdb.execute("output $arg0", to_string=True).strip('"'), $arg1)>end(gdb) strcmp $x "hello"0

針對舊版本的 gdb,例如我所使用的 gdb 7.1,並不支援上述函數,因此需要自行實作一個 conevenient function,範例如下: 
py
class MyStrcmp (gdb.Function):
    """My Own Strcmp"""

    def __init__ (self):
        super (MyStrcmp, self).__init__ ("mystrcmp")

    def invoke (self, arg0, arg1):
        print "input '" + arg0.string() + "' and '" + arg1.string() + "'"
        if arg0.string() == arg1.string() :
            print "equal"
            return 0
        else:
            print "not equal"  
            return 1
MyStrcmp()
end
用法: 
print $mystrcmp("hello", "hello")

方法三:使用 gdb script 實作 strcmp
set var  $_isEq=0

# Yes! GDB_STRCMP, below, is a gdb function.
# Function that provides strcmp-like functionality for gdb script;
# this function will be used to match the password string provided in command line argument
# with the string argument of strcmp in program
define GDB_STRCMP
set var  $_i=0
set var  $_c1= *(unsigned char *) ($arg0 + $_i)
set var  $_c2= *(unsigned char *) ($arg1 + $_i)
while (  ($_c1 != 0x0) && ($_c2 != 0x0) && ($_c1 == $_c2) )

#printf "\n i=%d, addr1=%x(%d,%c), addr2=%x(%d,%c)", $_i, ($arg0 + $_i),$_c1, $_c1, ($arg1 + $_i), $_c2,$_c2
set  $_i++
set  $_c1= *(unsigned char *) ($arg0 + $_i)
set  $_c2= *(unsigned char *) ($arg1 + $_i)

#while end
end

if( $_c1 == $_c2)
set $_isEq=1
else
set $_isEq=0
end

#GDB_STRCMP end
end

Reference:

  1. https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html
  2. http://stackoverflow.com/questions/13961368/conditional-breakpoint-using-strcmp-in-gdb-on-mac-os-x-conflicts-with-objectiv
  3. https://sourceware.org/gdb/current/onlinedocs/gdb/Convenience-Funs.html
  4. http://stackoverflow.com/questions/7423577/how-to-compare-a-stored-string-variable-in-gdb
  5. http://www.opensourceforu.com/2011/09/modify-function-return-value-hack-part-2/

2015年3月28日 星期六

[Embedded] 使用 gdbserver 時,出現 armv5te 警告訊息

問題描述:使用 gdbserver 追蹤程式時,target 為 armv6 架構,但卻出現 armv5te 的警告訊息。

問題原因:我所使用的 tool chain arm-2009q3,預設會假設 target 為 armv5te架構

解決方法:

1. 先登入 Target 端 console,確認 cpu info 

1 # cat /proc/cpuinfo
2 Processor : ARMv6-compatible processor rev 5 (v6l)
3 BogoMIPS : 526.25
4 Features : swp half fastmult edsp java
5 CPU implementer : 0x41
6 CPU architecture: 6TEJ
7 CPU variant : 0x1
8 CPU part : 0xb36
9 CPU revision : 5
10
11 Hardware : Coconut
12 Revision : 13ec3011
13 Serial : 0000000000000000

2. 確認目前 arm-none-linux-gnueabi-gcc 的預設架構

1 $ arm-none-linux-gnueabi-gcc -Q --help=target
2 The following options are target specific:
3 -falign-arrays [disabled]
4 -mabi=
5 -mabort-on-noreturn [disabled]
6 -mapcs [disabled]
7 -mapcs-float [disabled]
8 -mapcs-frame [disabled]
9 -mapcs-reentrant [disabled]
10 -mapcs-stack-check [disabled]
11 -march= armv5te
12 -marm [enabled]
13 -mbig-endian [disabled]
14 -mcallee-super-interworking [disabled]
15 -mcaller-super-interworking [disabled]
16 -mcirrus-fix-invalid-insns [disabled]
17 -mcpu=
18 -mfix-cortex-m3-ldrd [enabled]
19 -mfix-janus-2cc [disabled]
20 -mfloat-abi=
21 -mfp16-format=
22 -mfp=
23 -mfpe [disabled]
24 -mfpe=
25 -mfpu=
26 -mglibc [enabled]
27 -mhard-float [disabled]
28 -mlittle-endian [enabled]
29 -mlong-calls [disabled]
30 -mlow-irq-latency [disabled]
31 -mmarvell-div [disabled]
32 -mpic-register=
33 -mpoke-function-name [disabled]
34 -msched-prolog [enabled]
35 -msingle-pic-base [disabled]
36 -msoft-float [disabled]
37 -mstructure-size-boundary=
38 -mthumb [disabled]
39 -mthumb-interwork [enabled]
40 -mtp=
41 -mtpcs-frame [disabled]
42 -mtpcs-leaf-frame [disabled]
43 -mtune=
44 -muclibc [disabled]
45 -mvectorize-with-neon-quad [disabled]
46 -mword-relocations [disabled]
47 -mwords-little-endian [disabled]
很明顯,若使用預設值 armv5te進行編譯,則 arm 架構不符。
3.  如何確認現在正在使用的 gdbserver 其適用的arm架構呢?
$arm-none-linux-gnueabi-readelf -A ./gdbserver
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "5TE"
  Tag_CPU_arch: v5TE
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align8_needed: Yes
  Tag_ABI_align8_preserved: Yes, except leaf SP
  Tag_ABI_enum_size: int

4 因此在重新編譯 gdbserver 時應該要指定 armv6,舉例如下:
~/gdb/gdb-7.9/gdb/gdbserver$./configure --build=i686-pc-linux-gnu --host=arm-none-linux-gnueabi  --target=arm-none-linux-gnueabi CROSS_COMPILE=arm-none-linux-gnueabi- CFLAGS='-g -O2 -march=armv6  -mtune=arm1136j-s'
編譯方式可參考此篇 。是否正確編譯成功,可透過 readelf 來檢視,如下: 
&arm-none-linux-gnueabi-readelf -A ./gdbserver
Attribute Section: aeabi
File Attributes
  Tag_CPU_name: "6"
  Tag_CPU_arch: v6
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1
  Tag_ABI_PCS_wchar_t: 4
  Tag_ABI_FP_denormal: Needed
  Tag_ABI_FP_exceptions: Needed
  Tag_ABI_FP_number_model: IEEE 754
  Tag_ABI_align8_needed: Yes
  Tag_ABI_align8_preserved: Yes, except leaf SP
  Tag_ABI_enum_size: int

5. 那麼 arm 架構不符會發生什麼問題呢?
主要是編譯成機器語言時,可能會使用不同的instruction set或call convention,可能造成執行時的錯誤。其中差異可以參考此篇討論
6. 編譯 gdb
編譯方式如下
$./configure --target=arm-none-linux-gnueabi
$ make 
不過這樣編譯出來的 gdb,在進行遠端除錯時,會出現以下錯誤訊息
"warning: Can not parse XML target description; XML support was disabled at compile time" 
手動安裝 expat,重新編譯gdb便可解決,步驟如下:
可從此處下載原始碼 http://sourceforge.net/projects/expat/files/latest/download
$ tar zxvf expat-2.1.0.tar.gz
$ cd expat-2.1.0
$ ./configure
$ make;make install 
另外支援 python script 會方便許多,因此我個人偏好使用下列這個編譯方式
$ sudo apt-get install python2.7-dev
$./configure --target=arm-none-linux-gnueabi --with-expat --with-python
$ make
註:若編譯的是 gdb-7.1,其 python 支援的功能是有限制的
http://stackoverflow.com/questions/8986589/how-to-get-output-from-gdb-execute-in-pythongdb-gdb-7-1

7. 若不使用 gdbserver,要直接編譯一個在 target system 執行的 gdb,需要先編譯 termcap,可參考下列設定

Build termcap 
./configure --build=i686-pc-linux-gnu --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf CROSS_COMPILE=arm-linux-gnueabihf- --prefix=/home/albert/tools/termcap
Build gdb 
./configure --build=i686-pc-linux-gnu --host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi CROSS_COMPILE=arm-none-linux-gnueabi- CFLAGS='-g -O2 -I/home/albert/tools/termcap/include' LDFLAGS='-static -L/home/albert/tools/termcap/lib' CPPFLAGS='-I/home/albert/tools/termcap/include'

Reference:
http://ftp.gnu.org/gnu/gdb/ 
https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
https://lists.debian.org/debian-arm/2011/11/msg00043.html
http://blog.csdn.net/a_ran/article/details/38404483
http://www.360doc.com/content/12/0312/23/532901_193884753.shtml
http://www.360doc.com/content/12/0312/23/532901_193884753.shtml
http://stackoverflow.com/questions/4381102/differences-between-arm-architectures-from-a-c-programmers-perspective
http://www.it.uom.gr/teaching/gcc_manuals/onlinedocs/gdb_35.html
http://lists.gnu.org/archive/html/bug-gnu-emacs/2001-11/msg00579.html




2012年8月26日 星期日

[LINUX] 在ubuntu環境編譯 skull 的方法

編譯LDD3書上範例 skull時,遇到了一些問題,茲記錄如下:

程式碼範例下載:http://www.oreilly.com.tw/product_linux.php?id=a184
測試機器編譯環境:Linux 3.2.0-23-generic #36-Ubuntu SMP

書上的範例是適用於 Linux 2.4/2.6 版本的,因此在 3.2.0-23 核心下編譯會造成許多錯誤訊息,以下針對scull的編譯錯誤作一整理說明。

2012年5月15日 星期二

VLC (VideoLAN Client)編譯

當測試 IP Camera上的串流媒體時,需要一個能夠調校的用戶端程式,用以調整各種參數以進行實驗。鑒於VLC 是一個開放原始碼的專案,可以讓我在原始碼的層級進行很細節的調整,因此選擇了此程式作為測試使用。


下面紀錄 VLC 的編譯過程,

一、程式碼的部份可以使用 Git 下載
git clone git:\\git.videolan.org\vlc.git