簡體   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