Search code examples
clinkerkeil

How to obtain addresses of structure members


I'm doing testing of a project based on Cortex-M0. The firmware is developed in C using Keil (v. 4.71.2) and ARM Linker (v. 5.03). I have read/write access to the RAM which I use to simulate failures, and I need to find out addresses of variables I need to modify.

Right now I'm using the linker map file which is very handy for scalar global variables:

myvar        0x00005978   Data      4  file1.o(.constdata)

Here I know that writing 4 bytes at address 0x00005978 will alter the variable myvar. However, I cannot apply the same approach for global structures:

mystruct     0x00020000   Data     400 file2.o(.data)

I have the start address of mystruct, however, I have troubles to access mystruct.module2.config.myvar. Since the code is still being developed, new fields are added to mystruct.module1 and the address of mystruct.module2 changes.

Is it possible to force the linker to output the addresses of individual fields in the structure?

As a workaround I declare a global variable with the address I want:

uint32_t * const myvar_ptr = &mystruct.module2.config.myvar;

Then I can find the address of myvar_ptr in the linker map and read it to obtain the address of mystruct.module2.config.myvar. However, this approach wastes 4 bytes of ROM to store each pointer, and ROM size is strictly limited, so I cannot declare 100 extra pointers targeting each field of mystruct. Is there a better way?


Solution

  • As you noted in a comment, structure alignment may be an issue. It looks like the Keil compiler does support the pack() #pragma so you can control the alignment of struct members. You can then use the .MAP file to get the starting address of the struct, and use the C include file that defines the struct to calculate the offsets of the individual members.