你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

Tools / 获取 c 文件函数名的几种方法

[复制链接]
gaosmile 发布时间:2020-8-2 10:23
Tools / 获取 c 文件函数名的几种方法

目录:

1. 方法1: grep 配合正则表达式
2. 方法2: nm 类的调试工具
3. 方法3: 开源软件 ctags
4. 使用 list function 的方法简单分析 Linux Input 子系统
5. 相关参考


1. 方法1: grep 配合正则表达式

1) private 函数:

$ grep -E '^(\w+ )?\w+ (\w+ )?\w+( )?\(.*)' SDL_events.c -o | sort | grep static | sort
static int SDL_AddEvent(SDL_Event *event)
static int SDLCALL SDL_GobbleEvents(void *unused)
static int SDL_CutEvent(int spot)
static int SDL_StartEventThread(Uint32 flags)
static void SDL_StopEventThread(void)

2) public 函数:

$ grep -E '^(\w+ )?\w+ (\w+ )?\w+( )?\(.*)' SDL_events.c -o | sort | grep -v static | sort
int SDL_PollEvent (SDL_Event *event)
...
int SDL_WaitEvent (SDL_Event *event)
SDL_EventFilter SDL_GetEventFilter(void)
Uint32 SDL_EventThreadID(void)
Uint8 SDL_EventState (Uint8 type, int state)
void SDL_Lock_EventThread(void)
...
void SDL_Unlock_EventThread(void)

3) 优点:

  • 通用性强,基本所有的 Linux 系统都会有 grep 命令;

  • 可以看到函数的完整定义;


4) 缺点:

  • 某些情景下无法完全匹配所有的函数定义,例如将函数定义分 2 行来写的情况。

2. 方法2: nm 类的调试工具

1) 什么是 nm?

nm 用于检查二进制文件 (包括库,编译后的目标模块,共享目标文件,和独立可执行文件),并显示这些文件的内容,或存储在其中的元信息,特别是符号表。

输出格式:

  • 默认按符号字母序排序;

  • 大写字母表示全局性,小写字母表示局部性;

  • U 表示此符号未定义,C 表示此符号是公共的,T/t 表示此符号在代码段中,D/d 的表示此符号在初始化数据段中,B/b 表示此符号在BSS数据段中;


另外,objdump -t 和 readelf -s 也可以查看目标文件的符号表。

2) 例子:
下面的例子展示了变量和函数在全局、局部、外部、静态、自动和初始化的不同情况下的不同符号类型。

全局/静态 变量:

int global_var;
int global_var_init = 26;

static int static_var;
static int static_var_init = 25;

extern int extern_var;
extern int extern_function(int);

静态函数:

static int static_function(int x, int y)
{
int local_automatic_var;

local_automatic_var = x + y;
return local_automatic_var;
}

全局函数:

int global_function(int p)
{
static int local_static_var;
static int local_static_var_init=5;

local_static_var = static_function(local_static_var_init, p);
return local_static_var;
}

int main(int argc, char** argv)
{
static_var = 1;

global_var = global_function(2);
extern_var = extern_function(3);
return 0;
}

#ifdef __cplusplus
extern "C"
#endif
void non_mangled_function(void)
{
// I do nothing
}

3) private 函数:

$ gcc -c c_obj.c
$ nm c_obj.o | grep " t " | cut -d' ' -f3
static_function

4) public 函数:

$ gcc -c c_obj.c
$ nm c_obj.o | grep " T " | cut -d' ' -f3
global_function
main
non_mangled_function

5) 优点:

  • 可以看到整个文件的所有调试信息,不仅仅是函数列表;

  • 同时适用于C 和 C++;

  • 呈现的是编译后的结果,更加准确可靠,例如不用关心源码中宏定义是否打开。


6) 缺点:

  • 只能对编译后的目标文件进行查看;

  • 目标文件如果被 strip 后,则无法使用该方法。

  • 无法看到完整的函数定义;



3. 方法3: 开源软件 Ctags

1) 什么是 ctags?
Ctags 是一个用于从程序源代码树产生索引文件(或tag文件),从而便于文本编辑器来实现快速定位的实用工具。在产生的 tag 文件中,每一个 tag 的入口指向了一个编程语言的对象。这个对象可以是变量定义、函数、类或其他的物件

Ctags 支持下列的编程语言:
汇编,AWK, ASP, BETA, Bourne/Korn/Zsh Shell, C, C++, COBOL, Eiffel, Fortran, Java, Lisp, Lua, Make, Pascal, Perl, PHP, Python, REXX, Ruby, S-Lang, Scheme, Tcl, Vim, and YACC。

2) private 函数:

$ ctags -x SDL_events.c | grep function | tr -s ' ' | cut -d' ' -f5- | grep static | sort

static int SDL_AddEvent(SDL_Event *event)
static int SDLCALL SDL_GobbleEvents(void *unused)
static int SDL_CutEvent(int spot)
static int SDL_StartEventThread(Uint32 flags)
static void SDL_StopEventThread(void)

3) public 函数:

$ ctags -x SDL_events.c | grep function | tr -s ' ' | cut -d' ' -f5- | grep -v static | sort

int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action,
int SDL_PollEvent (SDL_Event *event)
...
int SDL_WaitEvent (SDL_Event *event)
SDL_EventFilter SDL_GetEventFilter(void)
...
void SDL_Lock_EventThread(void)
...
void SDL_Unlock_EventThread(void)

4) 优点:

  • 支持多语言;

  • 可以看到函数的完整定义;

  • Ctags 不是编译器也不是预处理器,它的解析能力是有限的;


5) 缺点:

  • 分2行定义的函数无法完整显示:
    int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action,

6) 我有必要了解 ctags 的内部实现吗?

  • 并不十分清楚 Ctags 使用何种技术来解析内容,估计包括正则表达式、词法分析、语法分析。日后如果工作对上述知识点有需求的话,应该也是一个很不错的学习资料,暂时不深入学习,

4. 使用 list function 的方法简单分析 Linux Input 子系统

先是发散思维,Linux input 的整体框架大致如下:

微信图片_20200802102223.png
linux-input-overview

然后慢慢专注在自己关心的内容上,例如我想多了解一下input core的内容,我就去查看它提供了什么 API:

$ ctags -x input.c | grep function | tr -s ' ' | cut -d' ' -f5- | grep -v static
struct input_dev *devm_input_allocate_device(struct device *dev)
void input_alloc_absinfo(struct input_dev *dev)
struct input_dev *input_allocate_device(void)
...
void input_free_device(struct input_dev *dev)
void input_free_minor(unsigned int minor)
...
bool input_match_device_id(const struct input_dev *dev,
int input_open_device(struct input_handle *handle)
int input_register_device(struct input_dev *dev)
int input_register_handle(struct input_handle *handle)
int input_register_handler(struct input_handler *handler)
void input_release_device(struct input_handle *handle)
...
void input_unregister_device(struct input_dev *dev)
void input_unregister_handle(struct input_handle *handle)
void input_unregister_handler(struct input_handler *handler)

然后就可以重点去阅读上述函数了。


5. 相关参考
  • nm wiki

  • Ctags wiki


收藏 评论0 发布时间:2020-8-2 10:23

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版