Linux下coredump除錯1:使用
李遲按:
除錯是程式設計師的一項基本能力,經歷過大大小小的實戰,隨著見識的增長,只要用心留意並做總結,相信除錯的能力會越來越好。寫程式不可能沒有bug,只是bug容易不容易被發現,bug的危害大不大。筆者使用coredump除錯很多年了,也有部分的工作筆記,無奈事多人懶,一直沒有好好總結。直到最近幫同學排查bug時,才真正下定決心寫幾篇文章。本文為開篇,主要描述coredump作用及配置的一些注意事項,並給出簡單示例。
一、介紹
程式執行過程中,難免會出現這種或那種錯誤導致其異常崩潰。如果使能了coredump,則操系統在程式出現異常時生成一個檔案,一般名稱為core。該檔案有大量可以幫助我們分析程式狀態的資訊——比如可回溯函式棧幀。與gdb實時執行程式除錯不同,coredump是一種事後分析的手段。特別適合一些錯誤很難重現的程式,例如裝置執行三天後,掛掉了,可能是記憶體洩漏導致記憶體不夠用了,可能哪個模組在一個條件語句中出現了指標非法。使用gdb對coredump檔案可以分析程式崩潰之前執行的程式碼片段,可以幫助我們快速定位錯誤。
二、配置coredump
2.1 使用除錯版本
一般地,在軟體開發階段,都會使用除錯版本。亦即程式使用-g來編譯,另外要注意,不能用strip命令對生成的可執行檔案進行精簡。這一切均是為了可執行檔案保留著除錯資訊,以方便使用gdb進行呼叫。
2.2 設定ulimit
為了在程式崩潰時產生coredump檔案,要設定coredump大小。先進行檢視:
[email protected]:~# ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kb) unlimited
stack(kb) 8192
coredump(blocks) 0
memory(kb) unlimited
locked memory(kb) 64
process 545
nofiles 1024
vmemory(kb) unlimited
locks unlimited
可以看到,其中coredump一行值為0,此時無法產生coredump檔案。因此要設定其檔案為無限大,命令:
# ulimit -c unlimited
結果如下:
[email protected]:~# ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kb) unlimited
stack(kb) 8192
coredump(blocks) unlimited
memory(kb) unlimited
locked memory(kb) 64
process 545
nofiles 1024
vmemory(kb) unlimited
locks unlimited
另外,要程式執行的同一環境下執行。比如,不能在一個終端設定ulimit,而在另一個終端執行程式,這樣不能生成coredump檔案的。
為了保證coredump檔名稱的唯一性,可以用下面命令設定:
# echo 'core.%e.%s.%t' > /proc/sys/kernel/core_pattern # 設定生成的coredump檔名稱
2.3 萬一程式因段錯誤等原因崩潰,則會生成core檔案。
2.4 3、有了coredump檔案,就可以結合可執行檔案,使用gdb進行除錯了,命令形式如下:
# gdb hello core
(注:需保證編譯器一致)
三、例項演示
下面使用李遲當年參考uboot原始碼實現的命令列解析程式碼為例。
首先,程式碼編譯時必須帶-g選項。
然後,在命令列中設定core檔案:
[[email protected] creadline]$ ulimit -c unlimited
執行程式:
[[email protected] creadline]$ ./a.out
Hit any key to stop autoboot: 0
You abort.
NotAShell> print
in print ...
Segmentation fault (core dumped)
(已經產生了coredump檔案)
下面使用gdb除錯:
[[email protected] creadline]$ gdb a.out core.2896
gdb列印資訊如下:
GNU gdb Fedora (6.8-29.fc10)
Copyright (C) 2008 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 "i386-redhat-linux-gnu"...
warning: Can't read pathname for load map: Input/output error.
Reading symbols from /usr/lib/libstdc++.so.6...done.
Loaded symbols for /usr/lib/libstdc++.so.6
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
[New process 2896]
#0 0x0084d626 in memcpy () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.9-2.i686 libgcc-4.3.2-7.i386 libstdc++-4.3.2-7.i386
(gdb)
使用bt命令檢視函式呼叫的棧幀(用where命令也可以):
(gdb) bt
#0 0x0084d626 in memcpy () from /lib/libc.so.6
#1 0x08048660 in ?? ()
#2 0x08049f5d in do_print (argc=1, argv=0xbf8935dc) at my_command.c:31
#3 0x08048cc2 in run_command (cmd=0x804cca0 "print") at command.c:380
#4 0x08049e93 in readline_test ()
#5 0x08049ee6 in main ()
(gdb)
可以看到最後出現的可疑的程式碼函式為do_print,裡面使用到了memcpy,具體是哪裡,可以用frame NUM檢視棧幀。比如,檢視第2個棧幀:
(gdb) frame 2
#2 0x08049f5d in do_print (argc=1, argv=0xbf8935dc) at my_command.c:31
31 memcpy(p, buffer, 5);
(gdb)
可以看到,已經輸出了檔名稱、行號、函式等重要資訊。
至此,就可以根據資訊修改程式碼了。
下面給出錯誤函式程式碼片段:
int do_print(int argc, char * const argv[])
{
printf("in print ...\n");
char* p = NULL;
char* buffer = "hello";
memcpy(p, buffer, 5); // 注:拷貝到空指標,錯誤!!!
return 0;
}
下面在某款嵌入式平臺上進行同時的演示,這裡只給出最後gdb呼叫的過程。
[email protected]:creadline$ arm_v5t_le-gdb readline_arm readline_arm.core.11.1941
GNU gdb 6.3 (MontaVista 6.3-20.0.66.0600975 2006-07-06)
...
Core was generated by `./readline_arm'.
Program terminated with signal 11, Segmentation fault.
...
#0 0x4020f164 in memcpy ()
from /opt/mv_pro_4.0.1/montavista/pro/devkit/arm/v5t_le/target/lib/libc.so.6
(gdb) bt
#0 0x4020f164 in memcpy ()
from /opt/mv_pro_4.0.1/montavista/pro/devkit/arm/v5t_le/target/lib/libc.so.6
#1 0x0000b660 in do_print (argc=1, argv=0xbefffcd0) at my_command.c:242
#2 0x00009574 in run_command (cmd=0x16c64 "print") at command.c:380
#3 0x0000af7c in readline_test () at main.c:78
#4 0x0000b20c in main (argc=1, argv=0xbefffe64) at main.c:139
(gdb) frame 1
#1 0x0000b660 in do_print (argc=1, argv=0xbefffcd0) at my_command.c:242
242 memcpy(p, buf, 5);
(gdb)
注:行文不特別區別交叉編譯,對於交叉版本,自行補充交叉字首即可。文中“gdb”表示gdb呼叫器,在x86-linux上其檔案為gdb,而在不同的arm-linux上,檔名稱不同,如可能是arm_v5t_le-gdb,也可能是arm-linux-gdb,還可能是arm-arago-linux-gnueabi-gdb,甚至哪天李遲自己編譯了一個交叉編譯器字首為arm-latelee-,則對應偵錯程式名稱為arm-latelee-gdb。
下一篇文章將演示幾個實際中遇到過的bug的排查例項。
李遲
2016.5.31 週二 晚
相關推薦
Linux下coredump除錯1:使用
李遲按: 除錯是程式設計師的一項基本能力,經歷過大大小小的實戰,隨著見識的增長,只要用心留意並做總結,相信除錯的能力會越來越好。寫程式不可能沒有bug,只是bug容易不容易被發現,bug的危害大不大。筆者使用coredump除錯很多年了,也有部分的工作筆記,無奈事多人懶,一
(五)洞悉linux下的Netfilter&iptables:如何理解連線跟蹤機制?(1)
如何理解Netfilter中的連線跟蹤機制? 本篇我打算以一個問句開頭,因為在知識探索的道路上只有多問然後充分調動起思考的機器才能讓自己走得更遠。連線跟蹤定義很簡單:用來記錄和跟蹤連線的狀態。 問:為什麼又需要連線跟蹤功能呢? 答:因為它是狀態防火牆和NAT的實
Linux下Hadoop2.7.1集群環境的搭建(超詳細版)
目錄 hdfs cp命令 manage war 替代 share logs hadoop 本文旨在提供最基本的,可以用於在生產環境進行Hadoop、HDFS分布式環境的搭建,對自己是個總結和整理,也能方便新人學習使用。 一、基礎環境 在Linux上安裝Hadoop之前
Linux下安裝kettle7.1
kettle安裝環境:centos7kettle版本:pdi-ce-7.1.0.0-12.zip需要JDK環境為1.8需要卸載自帶JDK一、安裝JDK1.8,我的路徑是/usr/local下配置Java環境變量[[email protected] local]# vim /etc/profileex
linux下啟動mysql提示:Timeout error occurred trying to start MySQL Daemon
任務 自帶 lean linu 使用 custom 方式 files 一個 啟動 mysqld 時經過很長時間顯示 Timeout error occurred trying to start MySQL Daemon. 終端進入 mysql 時顯示 ERROR 2002
Linux下的開發工具:vim,gcc,gdb,makefile以及yum語句安裝軟體
Linux下的開發工具:vim,gcc,gdb,makefile以及yum語句安裝軟體 1. vi/vim vi/vim都是多模式編譯器,vim是vi的升級版本。vim有12個模式,在這我們先說3種模式,命令模式,插入模式,底行模式。 2. vim基本操作: $vim t
嵌入式ARM在Linux下更改除錯串列埠
By Toradex秦海 1). 簡介 在基於嵌入式ARM開發產品的時候,有時候由於ARM處理器UART數量的限制,我們需要將系統預設的除錯串列埠列印資訊關閉或者轉移到其他串列埠上面去,本文即演示更改uboot和linux kernel 除錯串列埠的過程示例。 本文所演
linux下gdb除錯檢視原始碼
GDB是GNU開源組織釋出的一個強大的UNIX下的程式除錯工具。或許,各位比較喜歡那種圖形介面方式的,像VC、BCB等IDE的除錯,但如果你是在UNIX平臺下做軟體,你會發現GDB這個除錯工具有比VC、BCB的圖形化偵錯程式更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。 &nb
Linux從0到1③:目錄結構及定位
#(一)目錄結構 centos7 Linux的一切都可以看成為一個檔案,單根的方式組織檔案(/) 各個目錄所表示的含義不同,常見的目錄含義如下: bin 普通使用者使用的命令 /bin/ls, /bin/date sbin 管理員使用的命令 /sbin/serv
Linux從0到1②:利用Xshell遠端管理
一、管理方式 1. 遠端登陸shell 兩種輸入方式: 輸入命令:效率低,適合少量的工作 Shell Script:效率高,適合完成複雜,重複性的工作 2.本地管理 開啟本地虛擬機器進行管理 注:推薦使用XShell 二、XShell
Linux從0到1:安裝Linux作業系統(超級詳細版)
分享一下安裝Linxu作業系統的流程 centos映象下載地址:https://www.centos.org/download/ 選擇DVD下載即可 安裝虛擬機器 首先自己進行Vmware workstation的安裝,開啟此軟體進行以下步驟。 在VMw
Linux安全調優1:CentOS防火墻的設置與優化
2.6 裝載 協議棧 先後 sys ip協議 ive 實現 被拒 CentOS防火墻的設置與優化 時間:2014-09-11 02:11來源:blog.csdn.net 作者:成長的小蟲 的BLOG 舉報 點擊:4908次 一、設置主機防火墻。 開放: 服務器的:we
Linux下tomcat問題1
大家好: 講述一下今天遇到的問題: Linux下部署專案,啟動tomcat,專案報初始化錯誤,經過幾次測試,本地專案執行正常,將Linux下tomcat解壓的專案放到本地測試執行也正常,看來專案沒有問題。 那tomcat啟動後,可以訪問tomca
linux 下安裝thinkphp5.1框架(使用composer安裝)
1.前提需要先安裝好composer. 接上一篇 https://www.cnblogs.com/victorcode/p/10039560.html 2.首先需要新建一個專案目錄 #mkdir data #cd data #composer create-project topthink/think
Linux下GDB除錯簡介
Linux下C/C++除錯工具gdb簡介 GDB(GNU Debugger)是Linux下的一個除錯工具,具體的功能有: - 設定斷點,使得程式碼在制定行暫停執行; - 單步除錯程式; - 檢視
linux下Mongodb叢集搭建:分片+副本集
三臺伺服器 192.168.1.40/41/42 安裝包 mongodb-linux-x86_64-amazon2-4.0.1.tgz 服務規劃 伺服器40 伺服器41 伺服器42 mongos mongos mongos config server config server
Linux下的除錯工具
隨著XP的流行,人們越來越注重軟體的前期設計、後期的實現,以及貫穿於其中的測試工作,經過這個過程出來的自然是高質量的軟體。甚至有人聲稱XP會淘汰偵錯程式!這當然是有一定道理的,然而就目前的現實來看,這還是一種理想。在日常工作中,除錯工具還是必不可少的。在Linux下,除錯工具並非只有gdb,還有很多其它除錯工
(二)洞悉linux下的Netfilter&iptables:核心中的ip_tables小覷
Netfilter框架為核心模組參與IP層資料包處理提供了很大的方便,核心的防火牆模組(ip_tables)正是通過把自己所編寫的一些鉤子函式註冊到Netfilter所監控的五個關鍵點(NF_IP_PRE_ROUTING, NF_IP_LOCAL_IN,NF_IP_FORW
Linux下列印除錯管理
#ifndef _DEBUG_MANAGE_H_ #define _DEBUG_MANAGE_H_ /* 資訊的除錯級別,數值起小級別越高 */ #define APP_EMERG "<0>" /* system is unusable */ #def
Linux下的C++程式:統計一個目錄及其內部檔案總共佔據的空間大小
統計一個目錄的大小(byte數),最簡單的辦法是在控制檯輸入命令: du -sb 目錄地址 用C++實現這個功能,是通過遞迴遍歷目錄下的檔案和子目錄達到的。需要注意的是,因為Byte數過大,單用一個整型統計Byte的數量,遇到大一些的目錄會出現溢位。因此我採用了TB、GB、MB、KB和Byte五個層級來表