3

我正在尝试获取内核函数的边界(例如系统调用)。现在,如果我理解正确,我可以通过阅读获得感兴趣的函数的起始地址,/proc/kallsymsSystem.map我不知道如何获得该函数的结束地址。

您可能知道,/proc/kallsyms允许我们查看 Linux 内核的符号表,以便我们可以看到所有导出符号的起始地址。我们可以用下一个函数的起始地址来计算上一个函数的结束地址吗?如果我们不能这样做,你能建议我其他方法吗?

4

1 回答 1

1

通常,可执行文件只存储函数的起始地址,因为它是调用函数所需的全部。您将不得不推断结束地址,而不是简单地查找它。

您可以尝试找到后续函数的起始地址,但这也并不总是有效。想象一下:

void func_a() {
    // do something
}

static void helper_function() {
    // do something else
}

void func_b() {
    // ...
    helper_function();
    // ...
}

您可以获得 and 的地址func_afunc_bhelper_function不会显示,因为不需要链接到它。如果您尝试使用func_b作为结尾func_a(假设编译代码中的顺序与源代码中的顺序相同,这是无法保证的),您最终会意外包含您不需要包含的代码 -并且可能找不到在将其他函数内联到func_b.

那么,我们如何找到这些信息呢?好吧,如果您考虑一下-信息确实存在-其中的所有路径func_a最终都将终止(在循环、返回语句、尾调用等中),可能在helper_function开始之前。

您需要解析其中func_a的所有可能代码路径的代码并构建一个映射。当然,无论如何,您都需要这样做才能将其他函数内联到其中 - 所以简单地不关心函数的结束地址应该不会太难。

最后一点:在这个例子中,你很难找到helper_function内联它,因为符号不会出现在kallsyms. 这里的解决方案是您可以跟踪call各个函数中的指令,以确定存在哪些您不知道的隐藏函数。

TL;DR:您只能通过解析编译后的代码来找到结束地址。无论如何,你必须解析这个,所以只做一次。

于 2016-05-28T19:26:19.407 回答