模块API之sprint_symbol

int sprint_symbol(char *buffer, unsigned long address)的作用是根据内存中地址address
查找这个地址对应的symbol,并加此symbol的name,offset,size等基本信息连成字符串赋值给buffer.
其使用的例子如下:
static void hist_trigger_stacktrace_print(struct seq_file *m,
					  unsigned long *stacktrace_entries,
					  unsigned int max_entries)
{
	char str[KSYM_SYMBOL_LEN];
	unsigned int spaces = 8;
	unsigned int i;

	for (i = 0; i < max_entries; i++) {
		if (stacktrace_entries[i] == ULONG_MAX)
			return;

		seq_printf(m, "%*c", 1 + spaces, ' ');
		sprint_symbol(str, stacktrace_entries[i]);
		seq_printf(m, "%s\n", str);
	}
}
其源码分析如下:
int sprint_symbol(char *buffer, unsigned long address)
{
	return __sprint_symbol(buffer, address, 0, 1);
}
继续调用__sprint_symbol,其第三个参数symbol_offset等于0,第四个参数add_offset等于1
static int __sprint_symbol(char *buffer, unsigned long address,
			   int symbol_offset, int add_offset)
{
	char *modname;
	const char *name;
	unsigned long offset, size;
	int len;
//第三个参数表示address 是否要增加一个偏移,这里赋值为0 表示不需要增加偏移 
	address += symbol_offset;
//通过kallsyms_lookup 找address对应的size,offset,modname
	name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
//如果没有找到address 对应的symbol,则返回,这时候buffer里面的内容就是几个addres。因为symbol_offset等于0
	if (!name)
		return sprintf(buffer, "0x%lx", address - symbol_offset);
// 如果name 不等于buffer 说明address 对应的symbol在模块中,将name赋值给buffer
	if (name != buffer)
		strcpy(buffer, name);
	len = strlen(buffer);
	offset -= symbol_offset;
//这里的add_offset 为1,会在buffer中以+%#lx/%#lx的格式添加offset和size
	if (add_offset)
		len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
// 如果有模块name的话,则在buffer中加上address 对应的模块的name
	if (modname)
		len += sprintf(buffer + len, " [%s]", modname);

	return len;
}


你可能感兴趣的:(kernel常用API源码分析,Linux,源码分析)