查找 /proc/kallsyms 调用内核函数

   有时候在做linux内核编程的时候会遇到内核模块使用一个内核符号symbolA,在编译的时候会遇到warning:

WARNING: "symbolA" [/home/sina/Debug/network/network-shell1/net.ko] undefined!

而在加载的时候则提示

 can't insmod xx.ko :unknown symbol in module or invalid parameter

内核模块中也有MODULE_LICENSE 语句。


通过内核源代码发现原来没有对内核符号 symbolA 调用 EXPORT_SYMBOL。

此时可以使用函数指针,在 /proc/kallsyms 找到内核的地址。



具体源代码如下:

int readline(char *buf,struct file *file)	
{						
						
	static	char	total[512];
	static	int	rest;			

	char	temp[128];
	int	len,i,cnt,count;
	
	cnt	= 0;				
	for (i = 0;i < rest;i ++ ){                      
		if(total[i] == '\n'){	  
			cnt ++;                                 /// 精确的定位  /proc/kallsyms  中每条项目的地址。
			break;
		}
	}

	if(cnt == 0){			                       /// 这里需要使用临时缓冲区来模拟一个seek操作
		count = file->f_op->read(file, temp, sizeof(temp), &file->f_pos);
		if(count == 0)
			return 0;			
		strncpy(total+rest,temp,count);
		rest 	+= count;
	}		
							
	len	= 0;
	while( temp[len ] = total[len ] ){		
		len ++;
		if(total[len] == '\n')
			break;
	}
	temp[len]	= '\n';
				
	buf[0]='\n';
	strncpy(buf+1,temp,len+1);
	buf[len+2] = '\0';
	
	rest	-= len+1;				
	for (i = 0;i < rest ;i ++){
		total[i] = total[i+len+1];
	}

	return 1;
}

unsigned int find_kernel_symbol(char *symbol_name, char *search_file)
{
        mm_segment_t old_fs;
        ssize_t bytes;
        struct file *file = NULL;
<span style="white-space:pre">	</span>char read_buf[500];
        char *p, tmp[20];
<span style="white-space:pre">	</span>unsigned int addr = 0;
        int i = 0;


        file = filp_open(search_file, O_RDONLY, 0);
        if (!file)
                return -1;


        if (!file->f_op->read)<span style="white-space:pre">		</span>/// ÊÇ·ñÓÐ read º¯Êý¡£
                return -1;


        old_fs = get_fs();                          /// 内核态用户态数据交换。
        set_fs(get_ds());<span style="white-space:pre">		</span>            /// 这里设置 fs ,kernel_read
<span style="white-space:pre">			</span>
<span style="white-space:pre">	</span>while ( readline(read_buf ,file ) ){
<span style="white-space:pre">		</span>p = strstr(read_buf, symbol_name);


<span style="white-space:pre">		</span>if((p != NULL) && (*(p - 1) == ' ')  && ( *(p + strlen(symbol_name))  == 0xa) ) {<span style="white-space:pre">		</span>/// 
<span style="white-space:pre">			</span>printk("the char is:0x%x\n",*(p + strlen(symbol_name)));
<span style="white-space:pre">			</span>printk("the func is:%s\n",read_buf);
                        while (*p--)
                                if (*p == '\n')
                                        break;
<span style="white-space:pre">			</span>i = 0;
                        while ( (tmp[i ++] = (*++ p) ) != ' ');
                        tmp[--i] = '\0';
                        addr = simple_strtoul(tmp, NULL, 16);
                        break;
                }
        }
        filp_close(file,NULL);
<span style="white-space:pre">	</span>set_fs(old_fs);


        return addr;
}

需要查找内核符号地址的时候可以通过  find_kernel_symbol(char *symbol_name, char *search_file)
其中 symbol_name 是符号文件,search_file 是需要寻找的文件。






你可能感兴趣的:(查找 /proc/kallsyms 调用内核函数)