【问题标题】:How to verify that a function X() is getting called from function Y() not from function Z()? [closed]如何验证函数 X() 是从函数 Y() 而不是从函数 Z() 调用的? [关闭]
【发布时间】:2017-02-12 16:21:40
【问题描述】:

您能否提供任何示例如何验证函数 X() 是从函数 Y() 而不是从函数 Z() 调用的?

使用“C”或汇编语言?

提前致谢。

更新:02-03-2015

  1. 假设内核源代码有很多驱动程序调用相同的函数,例如 SPI(串行外围接口)和 GPIO(通用输入输出)的驱动程序源代码正在调用相同的函数,例如“bzero()”。

    void bzero(void *s, size_t n);

  2. 我要测试SPI和GPIO驱动(驱动代码不能修改)。为此,我编写了测试驱动程序。我只能调用从我的测试驱动程序公开的函数。

    uint8_t SPI_read_write(uint8_t byte_out, char *s) // 函数1 { bzero(s,sizeof(struct_global1)); 返回字节输入; }

    uint8_t GPIO_read_write(uint8_t byte_out, char *s)// 函数2 { bzero(s,sizeof(struct_global2)); 返回字节输入; }

    int main()// 测试驱动 { SPI_read_write(arg1,arg2);// 当我从测试驱动调用这个函数时,它会调用 bzero
    }

  3. 函数 SPI_read_write() 和 GPIO_read_write() 函数都调用“bzero”函数。 我需要确保仅在任何实例中从 SPI_read_write() 函数调用“bzero”。

2017 年 4 月 15 日更新

我不知道哪条线不清楚?一些函数 fun1() 可以从 N 个其他函数中调用。如何确定哪个函数调用了 fun1()?

可能和栈、链接寄存器有关……

【问题讨论】:

  • 使其成为与X 相同的翻译单元中的静态函数。如果Y 也在那里,那么你就不走运了。但坦率地说,我认为这是(字面意思)XY Problem
  • 您可以使用调试器检查它,例如来自 Code::blocks 的内置调试器。
  • 使用__builtin_return_address检查它?
  • 确实是 XY 问题。如果调用链很重要(间接调用呢?),你的代码就被设计破坏了。
  • 你必须知道每个函数的地址是什么,然后沿着栈往上走,检查栈帧。

标签: c gcc assembly lynxos


【解决方案1】:

无法确定调用您的函数的函数的名称。这完全是设计使然,因为函数旨在提供一种抽象,该抽象封装了独立于调用站点的计算或活动。因此,如果您想知道哪个函数正在调用您的函数,调用者需要提供此信息。

C99 兼容的编译器提供了一种方法来确定当前函数的名称,可用于传递给目标函数,如下所示:

#define X() x(__func__)

void x(const char* caller) {
    printf("x() is called from %s()\n", caller);
}
void y() {
    X();
}
void z() {
    X();
}

以上印刷品

x() is called from y()
x() is called from z()

Demo.

【讨论】:

  • 什么是 GNU 特有的?您正在使用 __func__,它是 C99 及更高版本中的预定义标识符。也就是说,没有什么可以阻止用户写void Z(void) { X("Y"); },其中关于调用Y 的函数的谎言。
  • @JonathanLeffler 非常感谢您的评论。
【解决方案2】:
 #include <execinfo.h>
 #include <stdio.h>

 void print_function(void *p) {
    char cmd[128];
    FILE *fp;
    snprintf(cmd, sizeof(cmd), "addr2line -e %s -f %p", "print_caller", p);
    fp = popen(cmd, "r");
    if (fp) {
        char buf[128];
        while (fgets(buf, sizeof(buf), fp)) {
           printf("%s", buf);
        }
    }
 }

 void Y() 
{
    print_function(__builtin_return_address(0));
}

void X()
{
    Y();
}

int main()
{
   X();
   return 0;
}

 $ gcc -g -o print_caller print_caller.c
 $ ./print_caller
 X
 /home/viswesn/print_caller.c:24

我还建议您查看BACKTRACE() 的手册页,它可以让您更深入地了解如何查看在进入当前函数之前调用的函数。

【讨论】:

  • 谢谢。在这里,您正在编写自己的函数。随叫随到。那么,在那种情况下,我可以放一个调试消息来查看哪个函数调用了哪个函数?对吗?
  • 实际上..在我的情况下,我无法修改任何功能。这是拇指规则。我可以调用函数 X() 或函数 Y() 但不允许编辑。
猜你喜欢
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多