1

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.

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

Andreas Walter
  • 826
  • 1
  • 10
  • 24
  • Maybe use a custom allocator and/or [specify the memory address directly](http://stackoverflow.com/questions/3030208/extern-variable-at-specific-address)? Or maybe overload operator new and provide a specific address? – wally Mar 09 '16 at 21:50
  • If the singleton object has static storage duration, then you certainly can take it's address at compile time. I don't know about the debug probe business. – eerorika Mar 09 '16 at 21:52
  • @flatmouse I know about the possibility of specifying the address and use it for some special data that is stored battery buffered. But I want to avoid doing all the memory stuff by myself. Overloading the new operator won't work, because I do not use dynamic memory. – Andreas Walter Mar 09 '16 at 21:56
  • @user2079303 I edited my question to make it more precise. Can you give me a hint, how to get the address of _instance_. – Andreas Walter Mar 09 '16 at 22:00
  • @AndreasWalter your `get` returns a copy every call. You probably intended to return a reference, right? – eerorika Mar 09 '16 at 22:05
  • @user2079303 Right, thank you! – Andreas Walter Mar 09 '16 at 22:07
  • @user2079303 I do not want to use the address inside my program. I want to modify the values from outside by directly writing to the memory. – Andreas Walter Mar 09 '16 at 22:16
  • Can you just call `get` in the debugger? – user253751 Mar 09 '16 at 22:27

4 Answers4

1

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:

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:

MyObj *obj = new ((void *)0x11220000) MyObj(args);
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • I do not want to specify the addresses for those instances by myself. I'm just interested in getting them from the binary files. – Andreas Walter Mar 09 '16 at 22:14
  • 1
    So, typically that is possible using a map-file (or some other symbol information provided by the tools). – Mats Petersson Mar 09 '16 at 22:48
  • I had a look into the map file, but could not find the proper information. But using 'nm -C' was promising. I will give it a try and report. – Andreas Walter Mar 09 '16 at 23:13
  • @AndreasWalter Even if you don't wish to specify the address, you could make the memory easier to find, by specifying your custom section and then through the linker script tell the linker to put your custom section together with the rest of the `.bss`. Then it should be easy to find it in the map file. Why not specify the address yourself though? That's how it is done in embedded systems for cases like this, period. – Lundin Mar 10 '16 at 09:09
1

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. 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. 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.

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)?

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.

Community
  • 1
  • 1
0

You can use placement-new with a buffer whose address is available at compile or link time.

#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__)));
D Krueger
  • 2,446
  • 15
  • 12
-1

Not exactly sure if this is what you're trying to do, but using "-S" with gcc will stop everything after the compile stage. 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.
  • 1
    I'm pretty sure this not what the OP is asking for. – Mats Petersson Mar 09 '16 at 22:06
  • @Mats Petersson OP asked for the address of the static variable. Wouldn't this be a way to get it? – wally Mar 09 '16 at 22:14
  • I do not think, that I can already get the address a that point. Stopping after compilation is to early. In my understanding, without linking, there is no address in memory at all. – Andreas Walter Mar 09 '16 at 22:19
  • Indeed, the compiler will not give (absolute) addresses to anything. It may contain the block-relative address of something, but that's barely helpful if there are more than one object file to link together. – Mats Petersson Mar 09 '16 at 23:17