在运行时获取Linux内核函数的结束地址

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

您可能知道, /proc/kallsyms允许我们查看Linux内核的符号表,这样我们就可以看到所有导出符号的起始地址。 我们可以使用下一个函数的起始地址来计算前一个函数的结束地址吗? 如果我们不能这样做,你能以另一种方式给我build议吗?

通常,可执行文件只存储一个函数的起始地址,因为调用该函数只需要这个地址。 你将不得不推断结束地址,而不是简单地查找它。

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

 void func_a() { // do something } static void helper_function() { // do something else } void func_b() { // ... helper_function(); // ... } 

你可以得到func_afunc_b的地址,但是helper_function不会显示出来,因为什么都不需要链接到它。 如果您尝试使用func_b作为func_b的结尾(假设编译的代码中的顺序等价于源代码中的顺序,这是不能保证的),那么最终会意外地包含您不需要的代码include – 并且在将其他函数内联到func_b时可能找不到需要查找的代码。

那么,我们如何找到这些信息呢? 那么,如果你想一想 – 信息确实存在 – func_a所有路径最终都会终止(在循环中,return语句,tail调用等),可能在helper_function开始之前。

你需要解析出func_a的代码,并在其中构建所有可能的代码路径的映射。 当然,无论如何你都需要这样做来嵌入其他的函数 – 所以不必太在乎不关心函数的结束地址。

最后一个注意事项:在这个例子中,你会很难找到helper_function来知道内联,因为符号不会显示在kallsyms 。 这里的解决方案是,您可以跟踪单个函数中的call指令,以确定哪些隐藏函数存在,否则您不知道。

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