天天看點

arm_linux 交叉編譯環境建立之 - gdb和gdbserver 和QT遠端調試建立環境下載下傳gdb源碼編譯 gdb編譯gdbserver部署到 arm linuxarm linux 目标闆遠端調試QT遠端調試

建立環境

cd ~/arm-linux
mkdir -p gdb/src
mkdir -p gdb/build
export SRCDIR=~/arm-linux/gdb/src
export BUILDDIR=~/arm-linux/gdb/build
export TARGET=arm-linux-gnueabi
export PREFIX=/usr/local/arm/4.8.2
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PATH:$PREFIX/bin
           

下載下傳gdb源碼

cd $SRCDIR

下載下傳版本:7.6.1

wget -c http://ftp.gnu.org/gnu/gdb/gdb-7.6.1.tar.bz2

解壓:

tar -jxvf gdb-7.6.1.tar.bz2

編譯 gdb

cd $BUILDDIR
$SRCDIR/gdb-7.6.1/configure --prefix=$PREFIX --target=$TARGET
make
           

常見錯誤:

...
/bin/bash ./libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I../../../src/gdb-7.6.1/bfd -I. -I../../../src/gdb-7.6.1/bfd -I../../../src/gdb-7.6.1/bfd/../include  -DHAVE_bfd_elf32_littlearm_vec -DHAVE_bfd_elf32_bigarm_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec  -DBINDIR='"/usr/local/arm/4.8.2/bin"'  -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Werror -g -O2 -MT opncls.lo -MD -MP -MF .deps/opncls.Tpo -c -o opncls.lo ../../../src/gdb-7.6.1/bfd/opncls.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I../../../src/gdb-7.6.1/bfd -I. -I../../../src/gdb-7.6.1/bfd -I../../../src/gdb-7.6.1/bfd/../include -DHAVE_bfd_elf32_littlearm_vec -DHAVE_bfd_elf32_bigarm_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec -DBINDIR=\"/usr/local/arm/4.8.2/bin\" -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Werror -g -O2 -MT opncls.lo -MD -MP -MF .deps/opncls.Tpo -c ../../../src/gdb-7.6.1/bfd/opncls.c -o opncls.o
In file included from ../../../src/gdb-7.6.1/bfd/opncls.c:26:0:
../../../src/gdb-7.6.1/bfd/opncls.c: In function ‘bfd_fopen’:
./bfd.h:529:65: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
 #define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE)
                                                                 ^
../../../src/gdb-7.6.1/bfd/opncls.c:263:5: note: in expansion of macro ‘bfd_set_cacheable’
     bfd_set_cacheable (nbfd, TRUE);
     ^
cc1: all warnings being treated as errors
Makefile:1607: recipe for target 'opncls.lo' failed
make[4]: *** [opncls.lo] Error 1
make[4]: Leaving directory '/home/weisf/arm-linux/build/gdb/bfd'
Makefile:1649: recipe for target 'all-recursive' failed
make[3]: *** [all-recursive] Error 1
make[3]: Leaving directory '/home/weisf/arm-linux/build/gdb/bfd'
Makefile:1135: recipe for target 'all' failed
make[2]: *** [all] Error 2
make[2]: Leaving directory '/home/weisf/arm-linux/build/gdb/bfd'
Makefile:2579: recipe for target 'all-bfd' failed
make[1]: *** [all-bfd] Error 2
make[1]: Leaving directory '/home/weisf/arm-linux/build/gdb'
Makefile:828: recipe for target 'all' failed
make: *** [all] Error 2
           

原因是比較新的編譯器如gcc4.5 以上的編譯器,對 #define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) 這樣的文法不支援,解決方法是加上忽略告警的選項 --disable-werror:

make clean
$SRCDIR/gdb-7.6.1/configure --prefix=$PREFIX --target=$TARGET --disable-werror
make
           

編譯完成後,安裝:

有錯誤提示:Makefile:370: recipe for target ‘gdb.info’ failed

但是已經安裝成功了。在/usr/local/arm/4.8.2/bin 下面能夠看到 arm-linux-gnueabi-gdb 這個檔案

$ ls /usr/local/arm/4.8.2/bin/
arm-linux-addr2line  arm-linux-gdb                arm-linux-gnueabi-gcc-4.8.2   arm-linux-gnueabi-objdump  arm-linux-objcopy
arm-linux-ar         arm-linux-gdbtui             arm-linux-gnueabi-gcc-ar      arm-linux-gnueabi-ranlib   arm-linux-objdump
arm-linux-as         arm-linux-gnueabi-addr2line  arm-linux-gnueabi-gcc-nm      arm-linux-gnueabi-readelf  arm-linux-ranlib
arm-linux-c++        arm-linux-gnueabi-ar         arm-linux-gnueabi-gcc-ranlib  arm-linux-gnueabi-run      arm-linux-readelf
arm-linux-c++filt    arm-linux-gnueabi-as         arm-linux-gnueabi-gcov        arm-linux-gnueabi-size     arm-linux-run
arm-linux-cpp        arm-linux-gnueabi-c++        arm-linux-gnueabi-gdb         arm-linux-gnueabi-strings  arm-linux-size
arm-linux-elfedit    arm-linux-gnueabi-c++filt    arm-linux-gnueabi-gprof       arm-linux-gnueabi-strip    arm-linux-strings
arm-linux-g++        arm-linux-gnueabi-cpp        arm-linux-gnueabi-ld          arm-linux-gprof            arm-linux-strip
arm-linux-gcc        arm-linux-gnueabi-elfedit    arm-linux-gnueabi-ld.bfd      arm-linux-ld               rename.sh
arm-linux-gcc-4.6.3  arm-linux-gnueabi-g++        arm-linux-gnueabi-nm          arm-linux-ld.bfd
arm-linux-gcov       arm-linux-gnueabi-gcc        arm-linux-gnueabi-objcopy     arm-linux-nm
           

編譯gdbserver

cd $BUILDDIR
mkdir gdbserver
cd gdbserver
$SRCDIR/gdb/gdbserver/configure --host=arm-linux-gnueabi --target=arm-linux-gnueabi --prefix=/usr/local/arm/4.8.2 --disable-werror
           

如果不加 --disable-werror,會報出一個錯誤:

In file included from /usr/local/arm/4.8.2/arm-linux-gnueabi/include/sys/sysinfo.h:24:0,
                 from ../../src/gdb-7.6.1/gdb/gdbserver/../common/linux-osdata.c:29:
/usr/local/arm/4.8.2/arm-linux-gnueabi/include/linux/kernel.h:720:2: error: #warning Attempt to use kernel headers from user space, see http: [-Werror=cpp]
 #warning Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders
  ^
cc1: all warnings being treated as errors
Makefile:534: recipe for target 'linux-osdata.o' failed
make: *** [linux-osdata.o] Error 1
           

用 --disable-werror 忽略這個錯誤

另外,還會報如下的錯誤:

arm-linux-gnueabi-gcc -g -O2    -I. -I../../src/gdb-7.6.1/gdb/gdbserver -I../../src/gdb-7.6.1/gdb/gdbserver/../common -I../../src/gdb-7.6.1/gdb/gdbserver/../regformats -I../../src/gdb-7.6.1/gdb/gdbserver/../../include -I../../src/gdb-7.6.1/gdb/gdbserver/../gnulib/import -Ibuild-gnulib-gdbserver/import -Wall -Wdeclaration-after-statement -Wpointer-arith -Wformat-nonliteral -Wno-char-subscripts -Wempty-body -Werror -DGDBSERVER -c -o hostio.o -MT hostio.o -MMD -MP -MF .deps/hostio.Tpo ../../src/gdb-7.6.1/gdb/gdbserver/hostio.c
../../src/gdb-7.6.1/gdb/gdbserver/hostio.c: In function ‘require_filename’:
../../src/gdb-7.6.1/gdb/gdbserver/hostio.c:67:20: error: ‘PATH_MAX’ undeclared (first use in this function)
       if (count >= PATH_MAX - 1)
                    ^
           

這是因為交叉編譯器的頭檔案中,PATH_MAX 是在 linux/limits.h 中定義的而不是 limits.h,是以,打開報錯的檔案,在 #include <limits.h> 這樣後面,新加一行 #include <linux/limits.h>

vim …/…/src/gdb-7.6.1/gdb/gdbserver/hostio.c

21 #include "server.h"
 22 #include "gdb/fileio.h"
 23 
 24 #include <fcntl.h>
 25 #include <limits.h>
 26 
 27 #include <unistd.h>
 28 /* HAOJC ADD */
 29 #include <linux/limits.h>
 30 
 31 extern int remote_debug;
 32 
           

這個同樣的錯誤,還會出現在另外一個檔案 …/…/src/gdb-7.6.1/gdb/gdbserver/thread-db.c,用同樣的方法處理它。

然後,編譯就通過了。

然後,可以安裝一下:

sudo make install

這會生成 /usr/local/arm/4.8.2/bin/arm-linux-gnueabi-gdbserver

部署到 arm linux

在主機上安裝 nfs server

sudo apt install nfs-kernel-server
           

設定服務通路配置:

sudo vim /etc/exports
添加一行:
/home/weisf/nfs *(rw,sync,no_root_squash,no_subtree_check)
           

/home/weisf/nfs 是用于共享檔案的目錄,

“*” 表示所有主機可以通路

rw - 表示可以讀和寫;

no_root_squash - 不降低root使用者的權限(不會将root使用者及所屬組都映射為匿名使用者或使用者組)

no_subtree_check - 即使輸出目錄是一個子目錄,nfs伺服器也不檢查其父目錄的權限,這樣可以提高效率。

啟動 nfs 服務:

sudo service nfs-kernel-server start
           

然後,就可以從 arm 闆上加載 nfs 實作共享了。

在arm linux 上加載 nfs 目錄

192.168.1.20 是主機IP位址

mkdir /mnt/nfs

mount -t nfs -o nolock 192.168.1.20:/home/weisf/nfs /mnt/nfs

如果想開機就加載,則建立初始化檔案 rc.local

vi /etc/rc.local
輸入:
mount -t nfs -o nolock 192.168.1.20:/home/weisf/nfs /mnt/nfs
儲存
chmod a+x /etc/rc.local
           

然後在 /etc/init.d/rc 腳本裡面調用它,在文檔的最後,加上:

#Uncomment to cause psplash to exit manually, otherwise it exits when it sees a
#if [ "x$runlevel" != "xS" ] && [ ! -x /etc/init.d/xserver-nodm ]; then
#    if type psplash-write >/dev/null 2>&1; then
#        TMPDIR=/mnt/.psplash psplash-write "QUIT" || true
#       umount /mnt/.psplash
#    fi
#fi

/etc/rc.local
           

将 gdbserver 通過 nfs 發送給arm闆

加載nfs目錄後,從主機上将gdbserver程式複制到 nfs目錄:

cp /usr/local/arm/4.8.2/bin/arm-linux-gnueabi-gdbserver /home/weisf/nfs/

從arm闆上,就可以看到:

/mnt/nfs/arm-linux-gnueabi-gdbserver

arm linux 目标闆遠端調試

主機:192.168.1.20

目标機:192.168.1.232

在主機上,編寫程式:

vim test.c

#include <stdio.h>
int func(int n)
{
    int sum=0, i;
    for (i=0; i<n; i++)
    {
        sum += i;
    }
    return sum;
}

int main(int argc, char* argv[])
{
    int i;
    long result = 0;
    for (i=0; i<=100; i++)
    {
        result += i;
    }
    printf("result[1-100] = %d \n",result);
    printf("resutl[1-225] = %d \n",func(255));
    return 0;
 }
           

在主機上編譯:

arm-linux-gcc -g test.c -o test

一定要用 -g,才可以在目标檔案中帶上調試資訊,否則不可調試。

然後,将 test 複制到 nfs:

cp test /home/weisf/nfs/

在arm闆上:

ls /mnt/nfs

可以看到 test。

執行:

[email protected]:/mnt/nfs# ./arm-linux-gnueabi-gdbserver 192.168.1.20:1234 test
Process test created; pid = 1107
Listening on port 1234
           

向 192.168.1.20 打開監聽端口 1234 來調試 test 程式。

在主機上進行調試:

[email protected]:~/work/test$ arm-linux-gnueabi-gdb test
Python Exception <type 'exceptions.ImportError'> No module named gdb: 

warning: 
Could not load the Python gdb module from `/usr/local/arm/4.8.2/share/gdb/python'.
Limited Python support is available from the _gdb module.
Suggest passing --data-directory=/path/to/gdb/data-directory.

GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/weisf/work/test/test...done.
(gdb) l
Cannot access memory at address 0x0
6	    {
7	        sum += i;
8	    }
9	    return sum;
10	}
11	 
12	int main(int argc, char* argv[])
13	{
14	    int i;
15	    long result = 0;
(gdb) b 15
Breakpoint 1 at 0x8478: file test.c, line 15.
(gdb) b func
Breakpoint 2 at 0x8410: file test.c, line 4.
(gdb) c
Continuing.
warning: Could not load shared library symbols for 2 libraries, e.g. /lib/libc.so.6.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?

Breakpoint 1, main (argc=1, argv=0xbefffbc4) at test.c:15
15	    long result = 0;
(gdb) n
16	    for (i=0; i<=100; i++)
(gdb) n
18	        result += i;
(gdb) n
16	    for (i=0; i<=100; i++)
(gdb) p result
$1 = 0
(gdb) n
18	        result += i;
(gdb) n
16	    for (i=0; i<=100; i++)
(gdb) p result
$2 = 1
(gdb) 

           

注意到有個警告:

Could not load the Python gdb module from `/usr/local/arm/4.8.2/share/gdb/python’.

Limited Python support is available from the _gdb module.

這是缺少 python 子產品,将源碼中的python 庫檔案複制過來:

cd /usr/local/arm/4.8.2/share/gdb/python/gdb
sudo cp -R ~/arm-linux/gdb/src/gdb-7.6.1/gdb/python/lib/gdb/* ./
           

QT遠端調試

在主機上,設定QT的生成檔案目錄到 nfs 目錄下,這樣可以即時與目标闆共享編譯生成的目标程式。

arm_linux 交叉編譯環境建立之 - gdb和gdbserver 和QT遠端調試建立環境下載下傳gdb源碼編譯 gdb編譯gdbserver部署到 arm linuxarm linux 目标闆遠端調試QT遠端調試

然後,執行編譯,會在 /home/weisf/nfs 目錄下生成目标程式。

在目标闆上,執行:

cd /mnt/nfs/dae/debug
 /mnt/nfs/arm-linux-gnueabi-gdbserver 192.168.1.20:1234 ./DAE-gui -qws
           

然後,在主機上qtcreator界面中,選擇 Debug -> Start Debugging -> Attach to Running Debug Server…

arm_linux 交叉編譯環境建立之 - gdb和gdbserver 和QT遠端調試建立環境下載下傳gdb源碼編譯 gdb編譯gdbserver部署到 arm linuxarm linux 目标闆遠端調試QT遠端調試

設定遠端arm闆上的位址和端口,點選OK。可以選擇 break at “main”,這樣可以執行的時候,在main入口處設定斷點暫停。

然後,就可以随意在主機上,執行各種調試操作了,設定斷點、監視變量、調用堆棧等。

arm_linux 交叉編譯環境建立之 - gdb和gdbserver 和QT遠端調試建立環境下載下傳gdb源碼編譯 gdb編譯gdbserver部署到 arm linuxarm linux 目标闆遠端調試QT遠端調試

繼續閱讀