Search code examples
clinkergnu

how can I define a memory area to use both in my linker script and c code at compile time?


I have the following in my linker script:

...

_other_start   = ORIGIN(OTHER);
_other_end     = ORIGIN(OTHER) + LENGTH(OTHER);
_other_size    = LENGTH(OTHER);

...

/* Memories definition */
MEMORY
{
  ...
  OTHER    (rw)    : ORIGIN = 0xC000000,   LENGTH = 1MB
  ...
}

...

And I have the following C code:

void fun() {
  extern char _other_start;
  char *ptr = &_other_start
  char tmp[10];

  for(int i = 0; i < 10; i++) {
    tmp[i] = *ptr++;
  }
}

When compiling with my gcc compiler, I get the following warnging: warning: '__builtin_memcpy' reading 10 bytes from a region of size 1 [-Wstringop-overflow=]. This warning makes sense at first sight, and the only way I have to mute it is by rewriting my function as follow:

void fun() {
  extern char _other_start[10];
  char *ptr = &_other_start
  char tmp[10];

  for(int i = 0; i < 10; i++) {
    tmp[i] = *ptr++;
  }
}

My question is, can I in some way define the size of my extern char _other_start buffer at compile time with the exact same size of the memory area defined in the linker script without having to duplicate my values from the linker script in a macro? Something like that:

#define OTHER_SIZE = 1024 * 1024 // I don't want this, it's code duplication.
#define OTHER_SIZE = _other_size // I want to use the value from the linker script, but I know like that it does not work.

void fun() {
  extern char _other_start[OTHER_SIZE];
  char *ptr = &_other_start
  char tmp[10];

  for(int i = 0; i < 10; i++) {
    tmp[i] = *ptr++;
  }
}

Solution

  • You need to change the type of that pseudo object. Of course it is done when the program is linked not compiled. So you can use them runtime.

    extern char _other_start[];
    void fun() {
    
      char *ptr = _other_start;
      char tmp[10];
    
      for(int i = 0; i < 10; i++) {
        tmp[i] = *ptr++;
      }
    }
    
    extern char _other_start[];
    extern char _other_length[];
    void fun() {
    
      char (*ptr)[(size_t)_other_length] = _other_start;
      char tmp[10];
    
      for(int i = 0; i < 10; i++) {
        tmp[i] = (*ptr)[i];
      }
    }