Linux內核API sprint_symbol【轉】


轉自:https://deepinout.com/linux-kernel-api/linux-kernel-api-module-mechanism/linux-kernel-api-sprint_symbol.html

sprint_symbol函數功能描述:該函數根據一個內存中的地址address查找一個內核符號,並將該符號的基本信息,如符號名name、它在內核符號表中的偏移offset和大小size、所屬的模塊名(如果有的話)等信息連接成字符串賦值給文本緩沖區buffer。

其中所查找的內核符號可以是原本就存在於內核中的符號,也可以是位於動態插入的模塊中的符號。

sprint_symbol文件包含

#include <linux/kallsyms.h>
C

sprint_symbol函數定義

在內核源碼中的位置:linux-3.19.3/kernel/kallsyms.c

函數定義格式:

int sprint_symbol(char *buffer, unsigned long address)
C

sprint_symbol輸入參數說明

buffer:文本緩沖區,它用來記錄內核符號的信息,它是一個輸出型參數。

address:內核符號中的某一地址,為輸入型參數。

sprint_symbol返回參數說明

返回值是一個int型,它表示內核符號基本信息串的長度,即buffer所表示的字符串的長度。

sprint_symbol實例解析

編寫測試文件:sprint_symbol.c

頭文件及全局變量聲明如下:

#include <linux/module.h> #include <linux/init.h> #include <linux/kallsyms.h> MODULE_LICENSE("GPL"); static int __init sprint_symbol_init(void); static void __exit sprint_symbol_exit(void); // 符號a_symbol int a_symbol(void) { return 1; } EXPORT_SYMBOL(a_symbol);
C

模塊初始化函數:

int __init sprint_symbol_init(void) { char buffer[KSYM_SYMBOL_LEN]; //聲明一個文本緩沖區 int ret; //接收sprint_symbol( )函數返回值 unsigned long address; //表示符號地址 char * name; //模塊名字 struct module * fmodule = NULL; //指向一個模塊的指針 address = (unsigned long) __builtin_return_address(0); //當前函數的返回地址 ret = sprint_symbol( buffer , address ); printk("ret: %d\n", ret ); //輸出返回值 printk("buffer: %s\n", buffer ); //輸出文本緩沖區buffer的內容 printk("\n"); name = "test_module"; fmodule = find_module( name ); //查找模塊名為" test_module"的模塊 if( fmodule ! = NULL ) { printk("fmodule->name: %s\n", fmodule->name); //將模塊的內存起始地址賦值給address address = (unsigned long)fmodule->module_core; ret = sprint_symbol( buffer , address ); printk("ret: %d\n", ret ); printk("buffer: %s\n", buffer ); } printk("\n"); //將當前模塊中符號a_symbol的地址加上偏移量5賦值給address address = (unsigned long)a_symbol + 5; ret = sprint_symbol( buffer , address ); printk("ret: %d\n", ret ); printk("buffer: %s\n", buffer ); return 0; }
C

模塊退出函數:

void __exit sprint_symbol_exit(void) { printk("module exit ok! \n"); }
C

模塊初始化及退出函數調用:

module_init(sprint_symbol_init); module_exit(sprint_symbol_exit);
C

實例運行結果及分析:

首先編譯模塊,執行命令insmod sprint_symbol.ko插入模塊,然后執行命令dmesg -c,會出現如圖所示的結果。
Linux內核API sprint_symbol

結果分析:

測試程序中調用了find_symbol()內核函數,它的功能是根據所給的模塊名字來獲得模塊描述符指針的。

在測試程序中首先聲明一個文本緩沖區buffer,其容量為KSYM_SYMBOL_LEN,它是一個宏,在linux-3.19.3/include/linux/kallsyms.h文件中定義,是內核指定的存儲內核符號基本信息的長度。

#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN -1) \+ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN -1) + 1)
C

測試程序分成三個部分來測試函數sprint_symbol()的功能。

第一部分是將參數address賦值為__builtin_return_address(0),它指當前函數的返回地址,也即測試程序中sprint_symbol_init()的返回地址。由輸出信息可知,buffer的內容為“do_one_initcall+0xfe/0x189”,其中“do_one_initcall”為內核符號名,0xfe為address相對於該符號起始地址的偏移,0x189則為符號所占內存空間的大小。可以看到buffer中沒有關於內核模塊名的信息,這是因為do_one_initcall原本就存在於內核中,它不屬於某一通過動態加載而插入內核的模塊。而ret = 26則表示buffer緩沖區的內容為26字節。

第二部分是將參數address賦值為某一模塊的內存起始地址,該模塊通過find_symbol()函數查找得到。輸出信息中buffer的內容與第一部分的類似,只是最后增加了“[test_module]”,它是符號所屬的模塊名。

第三部分將當前模塊中符號a_symbol的地址加上偏移量5賦值給address,輸出信息與第二部分類似。這里說明一下buffer中關於該符號的偏移量0x5,它是參數address相對於符號起始地址的偏移量,如果將address賦值為a_symbol的地址,則buffer中關於符號的偏移量將為0x0。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM