Hey Community
I look for a method to export all the details of existing structures (location of the fields and padding).
The goal of this is to share variables of our software and their location with other teams, so they can validate the software by reading internal variables or modify control parameters for some other tests.
Currently I am looking the .map file in order to know where the structures and variables are located. I have an Excel file where I put all information manually about the fields of the structures, and with a macro I scan the .map file to export the base address of structs and the variables.
I would like to automatize this. Maybe there exists a configuration, so that the compiler has an output file where it is nicely visible or extractable by another script. Analyse the .map file in order to export the base address of all variables and structures should not be the problem, also not the padding between the variables / structs. But how extract the paddin and alignement inside a structure? And how extract the existing fields of a structure?
Is there a way to do/know this without looking the header files?
I know the good approach should be to define the structures in a way, to have no incertitude about the packing and padding. The problem is that this was not done at the start of the project, also not all of the team members care about such “details” as padding and alignment and the general knowledge of the compiler is not so well (me including).
Details about the system:IDE-Version:µVision V5.20.0.0Copyright (C) 2016 ARM Ltd and ARM Germany GmbH. All rights reserved.Tool Version Numbers:Toolchain: MDK-ARM Standard Cortex-M only: 2 user(s) Version: 5.20Toolchain Path: C:\Keil_v5\ARM\ARMCC\BinC Compiler: Armcc.exe V5.06 update 2 (build 183)Assembler: Armasm.exe V5.06 update 2 (build 183)Linker/Locator: ArmLink.exe V5.06 update 2 (build 183)Library Manager: ArmAr.exe V5.06 update 2 (build 183)Hex Converter: FromElf.exe V5.06 update 2 (build 183)CPU DLL: SARMCM3.DLL V5.20Dialog DLL: DARMCM1.DLL V1.14.0.0Target DLL: Segger\JL2CM3.dll V2.99.20.0Dialog DLL: TARMCM1.DLL V1.10.0.0
I do not own a copy of armcc (so can't test it yet), but from its documentation, it seems that it can produce debugging output in the dwarf format.
With gcc, "gcc -g a.c" and "objdump -dwarf=info a.out" dumps information about the types, including structures, although here we relied on objdump to parse the dwarf format for us.
There's also another, ancient format called the "stabs", which the latest gcc can emit if told to do so.
Does the output of "fromelf -d image.axf" help?
For example, a structure of 100 int sized elements
int struct1[100]={1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,0};
is displayed as:
... ** Section #2 'ER_RW' (SHT_PROGBITS) [SHF_ALLOC + SHF_WRITE] Size : 16 bytes (alignment 4) Address: 0x00008254 Data section was compressed (Original size: 400 bytes) 0x008254: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x008264: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x008274: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x008284: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x008294: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x0082a4: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x0082b4: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x0082c4: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x0082d4: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x0082e4: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x0082f4: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x008304: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x008314: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x008324: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x008334: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x008344: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x008354: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x008364: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x008374: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x008384: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x008394: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x0083a4: 01 00 00 00 02 00 00 00 03 00 00 00 01 00 00 00 ................ 0x0083b4: 02 00 00 00 03 00 00 00 01 00 00 00 02 00 00 00 ................ 0x0083c4: 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ................ 0x0083d4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
I was not able to generate this output. I only obtain compilation errors :-(. I must have a closer look where to put this option. Can you say me in which field from Keil i have to put this?
Also I am not sure if the output you showed will help. The next little example of a structure shows maybe better my need.
typedef struct { // ----- MANDATORY FIRST POSITION ------ uint8_t var_a; // ----- Other members uint16_t var_b; } my_struct_t my_struct;
Normally the compiler will put a padding byte after var_a to align var_b. That explains also the size of the structure in the .map file of 4 bytes:
my_struct 0x20000000 Data 4 global.o(.data)
If the compiler puts padding bytes outside of a structure I can see this in mi .map file ( Example here with 3 structs where he put a padding byte between the structures):
0x20000000 0x00000004 Data RW 754 .data global.o
0x20000004 0x00000005 Data RW 221 .data global.o
0x20000009 0x00000001 PAD
0x2000000a 0x0000000c Data RW 770 .data global.o
I would need something like that, to know how the structure is finally build up:
my_struct 0x20000000 Data 0 global.o(.data) my_struct.var_a 0x20000000 Data 1 global.o(.data) PAD 0x20000001 Data 1 global.o(.data) my_struct.var_b 0x20000002 Data 2 global.o(.data)
Hi again,To specify the fromelf command, use the "After build" section of the settings, similar to:As for your issue, I think I understand. The compiler will by default put each element on it's natural boundary (chars on any byte boundary, shorts on 2-byte boundary, int on 4-byte boundary (0x0, 0x4, 0x8, 0xc...)), with padding betwixt the elements if necessary.If you want to eliminate padding, you can use the packed attribute, either for the entire structure, or specific elements within that structure (ordering of elements within the struct will of course not be affected).
Hi thank you for you explanation. Finally I was able with your help to generate the same output than you showed me in the first reply. But how I thought it is not really what I need.
Ronan Synnott said:As for your issue, I think I understand. The compiler will by default put each element on it's natural boundary (chars on any byte boundary, shorts on 2-byte boundary, int on 4-byte boundary (0x0, 0x4, 0x8, 0xc...)), with padding betwixt the elements if necessary.
Yeah exactly, if I look at the structure I am able to manually determine where he puts padding to align each element on their natural boundary. That is not a problem at all. But to do it automatically is way more challenging for me. Also I want to show all members of every structure (structure type) in a file.
No I don’t want to eliminate padding at all, I will just know, every time I will compile, where the compiler puts padding without doing it manually when something in the definition of a structure changes or even when new structure types are created.
You can get a summary of this by adding --info=sizes to the linker command line (you can also specify multiple with for example --info=sizes,totals).