简体   繁体   English

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

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

I am working on a embedded project and ask me, if it is possible to get the address of a singleton class during compile or link time. 我正在从事一个嵌入式项目,并问我,是否有可能在编译或链接时获取单例类的地址。

To create my singleton, I use the following code and would be interested in the address of instance . 要创建我的单例,我使用以下代码,并且对instance的地址感兴趣。

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

What I want to do, is of course changing the value from outside using a debug probe, but not using a real debug session. 我要做的当然是使用调试探针从外部更改值,而不是使用真正的调试会话。

Best regards Andreas 最好的问候安德烈亚斯

Without signficant knowledge of exactly what development tools, hardware architecture, etc, you are using, it's very hard to say exactly what you should do, but it's typically possible to assign certain variables to a specific data-segment or functions in a specific code-segment, and then in the linking phase assign a specific address to that segment. 如果您对所使用的开发工具,硬件架构等没有确切的了解,很难确切地说出应该做什么,但是通常可以将特定的变量分配给特定的数据段或特定代码中的功能,段,然后在链接阶段为该段分配一个特定的地址。

For example you can use the gcc section attribute : 例如,您可以使用gcc section属性

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

or 要么

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

and then use the same section name in a linker script that places it to the "right" address. 然后在链接脚本中使用相同的节名称,将其放置在“正确”的地址上。

Most (reasonable) embedded toolchains will support this in some manner, but exactly how it is done varies quite a lot. 大多数(合理的)嵌入式工具链都将以某种方式支持此功能,但是确切的实现方法却相差很多。

Another option is to use placement new : 另一种选择是使用展示位置new

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

You can use placement-new with a buffer whose address is available at compile or link time. 您可以将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__)));

Usually debug probes only see physical addresses while user applications only operate on virtual addresses, which change all the times the application is loaded, so no linker trick will work. 通常,调试探针仅会看到物理地址,而用户应用程序只能在虚拟地址上运行,而虚拟地址在应用程序加载的所有时间都会改变,因此,链接器技巧不会起作用。 You didn't say which OS you use but I guess it's Linux. 您没有说要使用哪个操作系统,但我想它是Linux。 If so, you can do something like this: reserve yourself a scratchpad memory area you know the physical address of and which is not used by the OS. 如果是这样,您可以执行以下操作:为自己保留一个暂存器存储区域,您知道该暂存器的物理地址,而OS并未使用它。 For example if your SoC has an embedded static memory, use that, if not just ask you local Linux expert how to reserve a page of RAM into the kernel memory configuration. 例如,如果您的SoC具有嵌入式静态内存,请使用它,如果不问您当地的Linux专家如何将RAM页面保留到内核内存配置中。

Then look at this article to understand how to map a physical address into the virtual memory space of your application: 然后查看本文以了解如何将物理地址映射到应用程序的虚拟内存空间:

how to access kernel space from user space(in linux)? 如何从用户空间访问内核空间(在Linux中)?

After getting the virtual address of the scratchpad area your application can read/write there whatever it wants. 获取暂存区的虚拟地址后,您的应用程序可以在其中读取/写入任何所需内容。 The debug probe will be able to to read/write into the same area with the physical address. 调试探针将能够读取/写入与物理地址相同的区域。

Not exactly sure if this is what you're trying to do, but using "-S" with gcc will stop everything after the compile stage. 不确定是否要执行此操作,但是在gcc中使用“ -S”将在编译阶段停止所有操作。 That way you can dive into the assembly code and evaluate your variables. 这样,您就可以深入汇编代码并评估变量。 Here is the man page excerpt: 这是手册页节选:

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