我知道函数指针指向函数代码的起始地址。但有没有办法能够指向函数代码的结尾?
编辑:特别是在具有单个处理器且没有虚拟内存的嵌入式系统上。没有优化。我们的自定义处理器的gcc编译器。
我想知道我的功能的完整地址范围。
答案 0 :(得分:3)
您没有说明为什么需要此信息,但在某些嵌入式系统上,需要将单个功能从闪存复制到RAM,以便(重新)编程闪存。
通常,您将此函数放入一个新的唯一部分,根据您的链接器,您可以将此部分用纯C或汇编程序复制到新的(RAM)位置。
您还需要告诉链接器代码将从另一个地址运行,而不是放在闪存中。
在一个项目中,flash.c看起来像
#pragma define_section pram_code "pram_code.text" RWX
#pragma section pram_code begin
uint16_t flash_command(uint16_t cmd, uint16_t *addr, uint16_t *data, uint16_t cnt)
{
...
}
#pragma section pram_code end
链接器命令文件类似于
.prog_in_p_flash_ROM : AT(Fpflash_mirror) {
Fpram_start = .;
# OBJECT(Fflash_command,flash.c)
* (pram_code.text)
. = ALIGN(2);
# save data end and calculate data block size
Fpram_end = .;
Fpram_size = Fpram_end - Fpram_start;
} > .pRAM
但正如其他人所说,这是特定工具链的
答案 1 :(得分:2)
如果将函数放在其自己的特殊链接器部分中,那么您的工具链可能会提供指向链接器部分的结尾(和开头)的指针。例如,使用Green Hills Software(GHS)MULTI编译器,我相信你可以这样做:
#pragma ghs section text=".mysection"
void MyFunction(void) { }
#pragma ghs section
这将告诉链接器在.mysection中找到MyFunction的代码。然后在您的代码中,您可以声明以下指针,这些指针指向该部分的开头和结尾。 GHS链接器自动提供定义。
extern char __ghsbegin_mysection[];
extern char __ghsend_mysection[];
我不知道GCC是否支持类似的功能。
答案 2 :(得分:1)
C无法指向函数的结尾。 C编译器在编译时如何排列它发出的机器代码方面有很大的自由度。通过各种优化设置,C编译器实际上可以合并混合各种功能的机器代码的机器代码。
因为除了C编译器以外,还有链接器和加载器所做的事情,作为将各种编译的目标代码片段链接在一起然后加载也可能使用各种各样的应用程序的一部分各种共享库。
在现代操作系统和现代开发工具链的复杂运行环境中,除非语言提供了执行某项操作的特定机制,否则谨慎的做法是不要试图让自己对应用程序开放,因为应用程序突然停止工作操作环境的变化。
在大多数情况下,如果您使用静态链接库的非优化编译器设置,大多数链接器提供的符号映射将为您提供关于函数开始和结束位置的好主意。但是,您唯一可以依赖的是知道函数入口点的地址。
答案 3 :(得分:0)
在某些实现中(包括gcc),您可以执行类似的操作(但不保证并且许多实现细节可能会影响它):
int foo() {
printf("testing\n");
return 7;
}
void foo_end() { }
int sizeof_foo() {
// assumes no code size optimizations across functions
// function could be smaller than reported
// reports size, not range
return (int (*)())foo_end - foo;
}