IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    使用 gcc 内置接口获取当前函数的返回地址

    Hacper\'s Blog发表于 2023-05-27 09:09:15
    love 0

    作为调试目的,有时候可能需要获取当前函数的调用者信息,比如在 malloc 申请一块内存的时候,记录 caller 的地址,当发生内存泄漏或者内存破坏时,可以使用 caller 地址大致定位是哪块代码有问题。

    我们可以通过 GCC 的内置接口void * __builtin_return_address (unsigned int level) 获取当前函数的返回地址,也就是调用者。 参数 level 表示扫描的栈帧层级,0 表示返回当前函数的返回地址,1 便是当前函数的调用者的返回地址,以此类推。

    测试代码

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    void test_return(void)
    {
    	shell_printf("test return\r\n");
    	void *p =  __builtin_return_address (0);
    	shell_printf("1 %p\r\n", p);
    	p = __builtin_extract_return_addr (__builtin_return_address (0));
    	shell_printf("2 %p\r\n", p);
    }
    
    void test_return1(void)
    {
    	test_return();
    	shell_printf("test return\r\n");
    }
    
    /**
     * @brief test command
     */
    void shell_test_cmd(int argc, char *argv)
    {
    	unsigned int i;
    	shell_printf("test command:\r\n");
    	for (i = 0; i < argc; i++)
    	{
    		shell_printf("paras %d: %s\r\n", i, &(argv[(int)argv[i]]));
    	}
    	test_return1();
    	void *p = test_return1;
    	shell_printf("%p\r\n", p);
    	
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    
    nr@root:test
    test command:
    paras 0: test
    test return
    1 004EADA6
    2 004EADA6
    test return
    004EAFB0
    

    004EADA6 是 test_return 的返回地址。004EAFB0 是直接打印的函数地址,是 test_return 的入口地址。然后通过 addr2line.exe 验证这两个地址。

    1
    2
    3
    4
    5
    
    D:\workspace\QT\qt_idf\examples\shell>D:\workspace\QT\qt_idf\tools\mingw32\bin\addr2line.exe -e D:/workspace/QT/qt_idf/examples/shell/build/build_out/target/shell.exe -f 004EADA6 004EAFB0
    test_return1
    D:/workspace/QT/qt_idf/examples/shell/cmds/cmds.c:56
    test_return1
    D:/workspace/QT/qt_idf/examples/shell/cmds/cmds.c:54
    

    004EADA6 是 test_return1 中第 56 行代码位置,004EAFB0 是 test_return1 中第 54 行代码位置。

    另外,使用 addr2line.exe 还碰到出现 dwarf error: could not find abbrev number 108. 问题,原因是编译的时候没有打开调试信息,在编译配置中增加 -g3 即可解决。



沪ICP备19023445号-2号
友情链接