內核與用戶態打印堆棧信息

1、內核

在想查看的函數中使用dump_stack()函數即可
如:想查看sa6155_tdm_snd_startup函數被調用的情況,可以在sa6155_tdm_snd_startup函數中加入dump_stack(),編譯運行即可看到,類似如下信息。

6,19566,192668180,-;Call trace:
6,19567,192668200,-; dump_backtrace+0x0/0x1f4
6,19568,192668207,-; show_stack+0x20/0x2c
6,19569,192668223,-; __dump_stack+0x20/0x28
6,19570,192668228,-; dump_stack+0x80/0xbc
6,19571,192668246,-; sa6155_tdm_snd_startup+0x6c/0x1c4 [machine_dlkm]
6,19572,192668254,-; soc_pcm_open+0x188/0x780
6,19573,192668259,-; dpcm_be_dai_startup+0x124/0x2a0
6,19574,192668265,-; soc_compr_open_fe+0x148/0x308
6,19575,192668273,-; snd_compr_open+0x150/0x204
6,19576,192668279,-; snd_open+0x11c/0x14c
6,19577,192668285,-; chrdev_open+0xbc/0x1b8
6,19578,192668290,-; do_dentry_open+0x144/0x300
6,19579,192668295,-; vfs_open+0x58/0x84
6,19580,192668301,-; path_openat+0x85c/0x1098
6,19581,192668306,-; do_filp_open+0x80/0xfc
6,19582,192668310,-; do_sys_open+0x13c/0x24c
6,19583,192668315,-; compat_SyS_openat+0x38/0x48
6,19584,192668320,-; el0_svc_naked+0x34/0x38

2、用戶態

函數定義

      #include <execinfo.h>

       int backtrace(void **buffer, int size);

       char **backtrace_symbols(void *const *buffer, int size);

       void backtrace_symbols_fd(void *const *buffer, int size, int fd);

函數說明

backtrace()函數用來獲取程序中當前函數的回溯信息,即一系列的函數調用關係,獲取到的信息被放在參數buffer中。buffer是一個數組指針,數組的每個元素保存着每一級被調用函數的返回地址。參數size指定了buffer中可存放的返回地址的數量。如果函數實際的回溯層級數大於size,則buffer中只能存放最近的函數調用關係,所以,想要得到完整的回溯信息,就要確保size參數足夠大。
backtrace()函數的返回值爲buffer中的條目數量,這個值不一定等於size,因爲如果爲得到完整回溯信息而將size設置的足夠大,則該函數的返回值爲buffer中實際得到的返回地址數量。

通過backtrace()函數得到buffer之後,backtrace_symbols()可以將其中的返回地址都對應到具體的函數名,參數size爲buffer中的條目數。backtrace_symbols()函數可以將每一個返回值都翻譯成“函數名+函數內偏移量+函數返回值”,這樣就可以更直觀的獲得函數的調用關係。
經過翻譯後的函數回溯信息放到backtrace_symbols()的返回值中,如果失敗則返回NULL。需要注意,返回值本身是在backtrace_symbols()函數內部進行malloc的,所以必須在後續顯式地free掉。

backtrace_symbols_fd()的buffer和size參數和backtrace_symbols()函數相同,只是它翻譯後的函數回溯信息不是放到返回值中,而是一行一行的放到文件描述符fd對應的文件中。

#include <execinfo.h>

/*在想查看的函數中使用user_dump_stack()函數即可*/
 
void
user_dump_stack(void)
{
   int j, nptrs;
#define SIZE 100
   void *buffer[100];
   char **strings;
 
   nptrs = backtrace(buffer, SIZE);
   printf("backtrace() returned %d addresses\n", nptrs);
 
   /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
	  would produce similar output to the following: */
 
   strings = backtrace_symbols(buffer, nptrs);
   if (strings == NULL) {
	   perror("backtrace_symbols");
	   exit(EXIT_FAILURE);
   }
 
   for (j = 0; j < nptrs; j++)
	   printf("%s\n", strings[j]);
 
   free(strings);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章