让vdsp与uclinux共舞(9):查找内核函数

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

  

 

 

 

本文适用于

ADSP-BF561

Visual DSP++ 5.0(update 6)

Bfin-uclinux-2009r1.6

 

 

欢迎转载,但请保留作者信息

 

在内核代码中随处可见EXPORT_SYMBOL,在不启用module的支持时,它们被定义为:

#define EXPORT_SYMBOL(sym)

#define EXPORT_SYMBOL_GPL(sym)

#define EXPORT_SYMBOL_GPL_FUTURE(sym)

#define EXPORT_UNUSED_SYMBOL(sym)

#define EXPORT_UNUSED_SYMBOL_GPL(sym)

也就是什么事情也不做,但是当启用MODULE的支持时(CONFIG_MODULES)它们就变成了:

/* For every exported symbol, place a struct in the __ksymtab section */

#define __EXPORT_SYMBOL(sym, sec)                  /

     extern typeof(sym) sym;                   /

     __CRC_SYMBOL(sym, sec)                    /

     static const char __kstrtab_##sym[]            /

     __attribute__((section("__ksymtab_strings"), aligned(1))) /

     = MODULE_SYMBOL_PREFIX #sym;                       /

     static const struct kernel_symbol __ksymtab_##sym  /

     __used                               /

     __attribute__((section("__ksymtab" sec), unused))  /

     = { (unsigned long)&sym, __kstrtab_##sym }

 

#define EXPORT_SYMBOL(sym)                     /

     __EXPORT_SYMBOL(sym, "")

就这样,对于每个用EXPORT_SYMBOL指定的符号,内核都将用一个kernel_symbol结构体进行描述:

struct kernel_symbol

{

     unsigned long value;

     const char *name;

};

并且这些描述信息被统一放到__ksymtab这个段中,看看vmlinux.lds.s对这个段的处理:

     __ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {      /

         VMLINUX_SYMBOL(__start___ksymtab) = .;             /

         *(__ksymtab)                         /

         VMLINUX_SYMBOL(__stop___ksymtab) = .;          /

     }                                    /

因此如果我们需要查询一个函数的地址,只要查询__start___ksymtab__stop___ksymtab之间的空间,让它们进行名称匹配就可以得到函数地址了。当我们在vdsp下查找的时候,需要从system.map中得到__start___ksymtab__stop___ksymtab这两个地址,当改变内核的编译选项时,需要相应改变这两个地址。

我们尝试查找printk,并在驱动初始化时调用它输出信息:

typedef struct _ksymbol

{

       unsigned long value;

       const char* name;

} ksymbol;

typedef (*pfcall)();

 

// 根据system map的值修改而来

#define SYMTAB_START     0x00129190

#define SYMTAB_STOP              0x0012cd18

 

unsigned long find_symbol(const char* name)

{

       ksymbol* p = (ksymbol*)SYMTAB_START;

       while(p < SYMTAB_STOP)

       {

              if(strcmp(p->name, name) == 0)

                     return p->value;

              p++;

       }

       return 0;

}

 

// 我们需要的内核函数列表

pfcall my_printk;

 

void find_my_function()

{

       // 查找我们需要的内核函数,注意下划线

       my_printk = find_symbol("_printk");

}

 

static void driver_load()

{

       find_my_function();

       if(my_printk)

       {

              my_printk("/nI AM HERE!/n");

       }

}

 

static void driver_exit()

{

}

然后在ldf文件中加上constdatabsz等各段的定义,下载运行:

让vdsp与uclinux共舞(9):查找内核函数_第1张图片

 

 

哈哈,内核很听话地输出

I AM HERE!

真乖,给你发糖吃!

 

1.1    初步总结与展望

忙乎了几天,做个初步的总结:

1、完全可以用vdsp控制uclinux内核的运行。

2vdsp无法读取vmlinux中的详细调试信息,因而无法直接对内核的其它部分做源码级的调试,一个很大的遗憾。

3、在vdsp下开发uclinux驱动是可行的,且开发调试的效率比kgdb的方式要高。

4、在vdsp下使用单步跟踪的时候,偶尔会发生VDSP总处于stepping的情况,但如果是设置断点并直接run则没有任何问题。

5、相比于将整个内核移植到vdsp下,只用vdsp开发驱动的方法要快速、简单得多,也稳定得多。因而也更具实用价值。

6、可以考虑开发一个专用于vdsp开发驱动的辅助驱动,完成内核资源的动态或者静态申请,开发完成之后辅助将之链接到内核中。

7、用VDSP开发uclinux应用程序的方法与此类似,自己改造一个类似于加载flat文件的驱动。

 

希望以后再有人问:“你这个东西有没有实用?”

可以大声回答:“当然!”

 

 

近日,我家6岁的小姑娘参加了第六届POP全国少儿英语风采大赛,拉票进行中(2011-6-15前)。

请帮忙点击新东方网站的链接:

http://popdasai.xdf.cn/toupiao.php?do=space&uid=4237

投她一票,谢谢!

2       参考资料

vdspuclinux共舞(7):在内核为驱动预留空间(2009-11-2)

vdspuclinux共舞(6):用vdsp开发驱动的设想(2009-11-2)

vdspuclinux共舞(5):加入dwarf调试信息(2009-11-2)

vdspuclinux共舞(4):加载uclinux(2009-11-2)

vdspuclinux共舞(3):boot kernel(2009-10-31)

vdspuclinux共舞(2):vdsp的影响(2009-10-31)

VDSPuclinux共舞(1):开篇(2009-10-30)

 

 

 

 

你可能感兴趣的:(让vdsp与uclinux共舞(9):查找内核函数)