简体   繁体   中英

Wrong Virtual Memory Address if section is not defined in the linker script

I want to insert an array of bytes in a binary, but in a particular section, so I can update this section later using objcopy .

Step 1 - Failure

If I declare the array by doing volatile const __attribute__((section(".pub_key"))) uint8_t pub_key_start[10] = "10 characters" when I objdump the generated elf file I can see the following:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
...
6 .pub_key      00000018  20000674  08039e04  00040674  2**2
...

Notice that VMA and LMA are different. When I run the binary, effectively the address of the symbol pub_key_start is 0x20000674 , but that address is not accessible. The actual data is in 0x08039e04 .

Step 2 - Success

However, if I define a section in the linker script such as:

.pub_key :
  {
    . = ALIGN(4);

    _pub_key_sec_start = .;
    *(.pub_key)
    *(.pub_key*)
    _pub_key_sec_end = .;

    . = ALIGN(4);
  } >SOME_REGION

after building and using egain objdump with the elf file, I obtain:

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
...
  6 .pub_key      00000018  08039e04  08039e04  00049e04  2**2
...

Notice that, now, VMA and LMA are the same.

If now I debug with gdb , I can confirm that the address of the symbol pub_key_start is 0x08039e04 , and I can access the array as usual ( pub_key_start[n] ).

Why does this happen?

What are the exact implications of defining a section in the linker script instead of don't do it?

First, you appear to be using something like an ARM part (maybe an STM32?) where flash is at 0x08000000 and RAM is at 0x20000000.

In your first case, what you have effectively (if perhaps unintentionally) specified is the fairly usual storage of initialized data in RAM, and the C startup routine should be copying the initialization for it from flash to RAM for use. If you are not seeing it in RAM, likely there's either a problem with the copy routine (missing from custom start files?) or else you are looking with the debugger before that has run.

Unless you setup your linker script otherwise, you may find that this is how all initialized global data (such as that defined in source files) in your program is handled.

In the second case, you are specifying data which is accessed directly from flash.

Note that things like the Cortex-M processors have quasi-Harvard data paths optimized for data access to RAM (and code access to flash), while doing data access to flash is supported it can incur arbitration overhead. Of course many parts also have limited RAM, so copying initialized but constant data to RAM may use resources better saved for things which actually need to be modified at runtime.

Finally to address a specific nitpick:

When I run the binary, effectively the address of the symbol pub_key_start is 0x20000674, but that address is not accessible. The actual data is in 0x08039e04.

That is incorrect - address 0x20000674 is accessible (ie, trying to do so does not cause a fault), it merely does not (yet) contain the data you expect it to. That would be distinct from trying to access an address which is actually not accessible (such as many cases of de-referencing a pointer that was never remotely valid and points where nothing exists) which will typically fault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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