代码之家  ›  专栏  ›  技术社区  ›  Paul Floyd

确定函数的结束地址

c
  •  0
  • Paul Floyd  · 技术社区  · 2 年前

    我知道函数指针指向函数代码的起始地址。但是,是否有任何方法也可以指向函数代码的结尾?

    编辑:特别是在具有单处理器且无虚拟内存的嵌入式系统上。也没有优化。我们的自定义处理器的gcc编译器。

    我想知道我的函数的完整地址范围。

    0 回复  |  直到 10 年前
        1
  •  4
  •   kkrambo    10 年前

    如果您将函数放在它自己的特殊链接器部分中,那么您的工具链可能会提供指向链接器部分末尾(和开头)的指针。例如,使用Green Hills Software(GHS)MULTI-compiler,我相信您可以执行以下操作:

    #pragma ghs section text=".mysection"
    void MyFunction(void) { }
    #pragma ghs section
    

    这将告诉链接器在中查找MyFunction的代码。我的部分。然后在代码中可以声明以下指针,这些指针指向节的开头和结尾。GHS链接器自动提供定义。

    extern char __ghsbegin_mysection[];
    extern char __ghsend_mysection[];
    

    我不知道GCC是否支持类似的功能。

        2
  •  3
  •   jeb    10 年前

    您没有说明为什么需要这些信息,但在某些嵌入式系统上,需要将单个功能从闪存复制到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
    

    但正如其他人所说,这是非常特定于工具链的

        3
  •  1
  •   Richard Chambers    10 年前

    C无法指向函数的结尾。C编译器在如何安排编译期间发出的机器代码方面有很大的自由度。通过各种优化设置,C编译器实际上可能会合并混合了各种函数的机器代码的机器代码。

    因为除了C编译器所做的之外,链接器和加载程序所做的也是将各种编译后的目标代码链接在一起,然后加载可能也使用各种共享库的应用程序的一部分。

    在现代操作系统和现代开发工具链的复杂运行环境中,除非该语言提供了一种特定的执行机制,否则谨慎的做法是不要想入非非地将自己留给一个由于操作环境的变化而突然停止工作的应用程序。

    在大多数情况下,如果将编译器的非优化设置与静态链接库一起使用,大多数链接器提供的符号映射将为您提供函数开始和结束位置的好主意。然而,您唯一真正可以依赖的是知道函数入口点的地址。

        4
  •  0
  •   Dwayne Towell    10 年前

    在某些实现(包括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;
    }