繁体   English   中英

我可以在gcc的编译或链接期间获取单例的地址吗?

[英]Can I get the address of a singleton during compile or link time from gcc?

我正在从事一个嵌入式项目,并问我,是否有可能在编译或链接时获取单例类的地址。

要创建我的单例,我使用以下代码,并且对instance的地址感兴趣。

class A
{
    public:
    static A& get()
    {
        static A instance;
        return instance;
}:

我要做的当然是使用调试探针从外部更改值,而不是使用真正的调试会话。

最好的问候安德烈亚斯

如果您对所使用的开发工具,硬件架构等没有确切的了解,很难确切地说出应该做什么,但是通常可以将特定的变量分配给特定的数据段或特定代码中的功能,段,然后在链接阶段为该段分配一个特定的地址。

例如,您可以使用gcc section属性

int init_data __attribute__ ((section ("INITDATA")));

要么

MyObj obj __attribute__((section ("BATTERY_BACKED")));

然后在链接脚本中使用相同的节名称,将其放置在“正确”的地址上。

大多数(合理的)嵌入式工具链都将以某种方式支持此功能,但是确切的实现方法却相差很多。

另一种选择是使用展示位置new

MyObj *obj = new ((void *)0x11220000) MyObj(args);

您可以将new-placement与其地址在编译或链接时可用的缓冲区一起使用。

#include <new>

extern unsigned char placeA[];

class A {
public:
    static A& get()
    {
        static A *p_instance;
        if(!p_instance) {
            p_instance = new(placeA) A();
        }
        return *p_instance;
    }
};

unsigned char placeA[sizeof(A)] __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));

通常,调试探针仅会看到物理地址,而用户应用程序只能在虚拟地址上运行,而虚拟地址在应用程序加载的所有时间都会改变,因此,链接器技巧不会起作用。 您没有说要使用哪个操作系统,但我想它是Linux。 如果是这样,您可以执行以下操作:为自己保留一个暂存器存储区域,您知道该暂存器的物理地址,而OS并未使用它。 例如,如果您的SoC具有嵌入式静态内存,请使用它,如果不问您当地的Linux专家如何将RAM页面保留到内核内存配置中。

然后查看本文以了解如何将物理地址映射到应用程序的虚拟内存空间:

如何从用户空间访问内核空间(在Linux中)?

获取暂存区的虚拟地址后,您的应用程序可以在其中读取/写入任何所需内容。 调试探针将能够读取/写入与物理地址相同的区域。

不确定是否要执行此操作,但是在gcc中使用“ -S”将在编译阶段停止所有操作。 这样,您就可以深入汇编代码并评估变量。 这是手册页节选:

If you only want some of the stages of compilation, you can use -x (or
filename suffixes) to tell gcc where to start,
and one of the options -c, -S, or -E to say where gcc is to stop.  Note that
some combinations (for example, -x cpp-output -E) instruct gcc to do nothing at all.

-c  Compile or assemble the source files, but do not link.  The linking stage simply is not done.  The ultimate
    output is in the form of an object file for each source file.

    By default, the object file name for a source file is made by replacing the suffix .c, .i, .s, etc., with .o.

    Unrecognized input files, not requiring compilation or assembly, are ignored.

-S  Stop after the stage of compilation proper; do not assemble.  The output is in the form of an assembler code file
    for each non-assembler input file specified.

    By default, the assembler file name for a source file is made by replacing the suffix .c, .i, etc., with .s.

    Input files that don't require compilation are ignored.

-E  Stop after the preprocessing stage; do not run the compiler proper.  The output is in the form of preprocessed
    source code, which is sent to the standard output.

    Input files which don't require preprocessing are ignored.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM