【发布时间】:2016-04-17 19:13:55
【问题描述】:
最近,在处理一个项目时,我需要测量 C 函数的大小以便能够将其复制到其他地方,但无法找到任何“干净”的解决方案(最终,我只是想在函数末尾插入一个标签,我可以引用)。
已经为该架构编写了 LLVM 后端(虽然它可能看起来像 ARM,但实际上并非如此)并且知道它为该架构发出了汇编代码,所以我选择了以下 hack(我认为评论解释得很好):
/***************************************************************************
* if ENABLE_SDRAM_CALLGATE is enabled, this function should NEVER be called
* from C code as it will corrupt the stack pointer, since it returns before
* its epilog. this is done because clang does not provide a way to get the
* size of the function so we insert a label with inline asm to measure the
* function. in addition to that, it should not call any non-forceinlined
* functions to avoid generating a PC relative branch (which would fail if
* the function has been copied)
**************************************************************************/
void sdram_init_late(sdram_param_t* P) {
/* ... */
#ifdef ENABLE_SDRAM_CALLGATE
asm(
"b lr\n"
".globl sdram_init_late_END\n"
"sdram_init_late_END:"
);
#endif
}
它按预期工作,但需要一些汇编程序胶水代码才能调用它,这是一个非常肮脏的 hack,它之所以有效,是因为我可以假设代码生成过程的几件事。
我还考虑了其他方法,如果 LLVM 发出机器代码会更好(因为一旦我将 MC 发射器添加到我的 LLVM 后端,这种方法就会中断)。我考虑的方法涉及获取函数并搜索终止指令(可以是b lr 指令或pop ..., lr 的变体),但这也可能带来额外的复杂性(尽管它似乎比我原来的解决方案更好)。
谁能提出一种更简洁的方法来获取 C 函数的大小,而不必求助于上述那些令人难以置信的丑陋和不可靠的 hack?
【问题讨论】:
-
在 C 中使用
sizeof函数是未定义的行为。但是您可以在编译到函数部分时使用链接器来生成适当的符号。 -
用汇编语言写
sdram_init_late()合理吗?如果是这样,您将完全控制如何提供要复制的代码块的开头和结尾。 -
它当然可以用汇编语言编写,但用 C 语言编写,并与其他 SDRAM 初始化代码一起保存在同一个文件中(除了用于跳转到该函数和保存/恢复寄存器的例程)使其更易于维护。
标签: c embedded clang llvm low-level