Using iobjmanip to process object files
Technical Note 200128
Architectures:
ARM, RH850, RL78, RX, RISCV, STM8
Component:
linker
Updated:
9/23/2020 10:58 AM
Introduction
If a version earlier than 10.6.5.1221 of the tool iobjmanip was used for manipulating an object file, variables might not be initialized correctly at startup in the resulting application.
Affected IAR Embedded Workbench versions:
IAR Embedded Workbench for Arm: All versions between 7.60 and (not including) 8.50
IAR Embedded Workbench for RH850: All versions between 1.40 and (including) 2.10
IAR Embedded Workbench for RL78: All versions between 2.21 and (including) 4.20
IAR Embedded Workbench for RX: All versions between 2.90 and (including) 4.13
IAR Embedded Workbench for RISC-V: All versions up to (but not including) 1.20
IAR Embedded Workbench for STM8: All versions between 3.10 and (including) 3.11.2
An application created using a higher version than the ones listed will not have this problem.
Discussion
__no_init compiler keyword
The compiler supports an extended keyword to C: __no_init. A variable with the __no_init attribute is not initialized during startup.
do not initialize linker directive
The IAR ILINK linker can use the directive do not initialize, that disables implicit zero initialization.
Excerpts from an example project:
=== t.c
int a; // a implicitly initialized to zero
__no_init int b; // b not initialized.
#pragma location="c-section"
int c; // c *implicitly* initialized to zero
#pragma location="d-section"
int d=0; // d *explicitly* initialized to zero
=== t.icf
include "generic_cortex.icf";
do not initialize { section c-section object t.o, section d-section object t.o};
// c will *not* be initialized
// d *will* be initialized
.iar.noinitinfo section
An ELF section .iar.noinitinfo is used for keeping track of sections that should not be initialized.
iobjmanip tool
iobjmanip is an IAR tool that is used for manipulating relocatable ELF files.
The problem
Using iobjmanip to remove a section from an object file causes the numbers for all subsequent sections to decrease by one, and changed numbering can lead to incorrect information in the .iar.noinitinfo section. Linking object files with incorrect .iar.noinitinfo sections can lead to incorrect initialization behavior.
What are the possible consequences?
1. Variables might not be initialized correctly during startup, which potentially is a serious problem.
This can happen if
- a file has:
- m > 0 __no_init sections, for example NOI_SEC_1, NOI_SEC_2, ..., NOI_SEC_m
- n > 0 initialized sections, for example I_SEC_1, I_SEC_2, ..., I_SEC_n
- iobjmanip is used to remove a section
- an initialized section, for example I_SEC_v, gets a new number that is the same as the old number for an __no_init section NOI_SEC_u
Note: It is unlikely for section numbers to match in this way, but it might happen.
2. __no_init content can be zero-initialized during startup, which is a serious problem if values must survive a reset/restart to work correctly. If the content is __no_init for other reasons (like code size or startup speed), this might not be a serious problem.
This can happen if
- a file has:
- m > 0 __no_init sections, for example NOI_SEC_1, NOI_SEC_2, ..., NOI_SEC_m
- iobjmanip is used to remove a section
- One or more NOI_SEC_u sections get new numbers that are not referenced from the .iar.noinitinfo section
Note: If the old number for a NOI_SEC_u section refers to the new number for an I_SEC_v section, this also leads to consequence 1 above.
How can I tell if this affects my project?
If you do not use iobjmanip, your code cannot be affected.
If you do not use __no_init content, your code cannot be affected.
Note: Libraries that you use (like board support libraries) can have this problem even if your code does not.
If the linker configuration file contains a do not initialize directive that matches the section that no longer has a correct .iar.noinitinfo, the section will not be initialized. If this happens, the incorrect .iar.noinitinfo section will not lead to consequence 2. Note that consequence 1 might still apply.
You can inspect object files with the ielfdump tool, located in your installation directory in the bin directory.
Run ielfdump<CpuName> object_file.o
This will output a list of sections in the object file.
Run ielfdump<CpuName> object_file.o -s .iar.noinitinfo
This will dump the contents of the .iar.noinitinfo section. It might look something like this:
Section #10 .iar.noinitinfo:
#6 .noinit
The information here is that section number 6, called .noinit, is a non-initialized section.
Now look at the list of sections:
6: .noinit nobits 0x1d5 0x320 0x4 0x3 WA
Section number 6 is nobits (ELF sections can be pbits or nobits, and only nobits sections–which typically are zero-initialized RAM– can be __no_init), so this looks good, the file does not have the problem.
If the information instead looks like this:
Section #9 .iar.noinitinfo:
#6 .iar_vfe_header
And the list of sections contains:
6: .iar_vfe_header pbits 0x18e 0x4 0x4
Then section number 6 is pbits (pbits sections cannot be __no_init) so this file has the problem, the .iar.noinitinfo section is obviously incorrect.
This manual inspection can tell if a file has the problem, but it can fail to detect problems if there are several nobits sections in the file. There is no reliable way to detect that an original file referred to one nobits section, but the modified file refers to another nobits section.
What can I do if my files have the problem?
There is an updated version of iobjmanip available (see below).
If you still have the original files from before the old version of iobjmanip processed them, you can process them again using the updated iobjmanip. This will create files that do not have the problem.
If you do not have access to the original files, you should contact whoever supplied you with them. The creator can use the updated iobjmanip to create files that do not have the problem.
If the original files are not available, you can avoid consequence 2 by using the do not initialize directive in the linker configuration file.
To avoid also consequence 1, use an updated iobjmanip to remove all .iar.noinitinfo sections.
Examples:
// the section .noinit is not initialized
do not initialize { section .noinit };
// sections named .mysec from the object file myFile.o is not initialized
do not initialize { section .mysec object myFile.o };
Empty .iar.noinitinfo sections / Further complications
iobjmanip in all affected Embedded Workbench versions (and also iobjmanip in EWARM 8.42.1, 8.42.2, and EWRISCV 1.20.1) has an additional possible issue: If the processed file contains ELF sections with the nobits property, an additional .iar.noinitinfo section is added. This added section is always empty and contains no information. Until recently this had no effect, the additional section did not affect the linking.
IAR Embedded Workbench for Arm 8.42 and IAR Embedded Workbench for RISC-V 1.20:
- have a new format for .iar.noinitinfo, which is not corrupted by section renumbering caused by removed sections.
- check that at most one .iar.noinitinfo section is present in each object file for ILINK and for iarchive.
- ILINK terminates with a fatal error
- iarchive just terminates
- include an iobjmanip that erroneously adds an empty .iar.noinitinfo section
Thus, even though the contents of .iar.noinitinfo sections are correct also after iobjmanip has removed sections, neither ILINK nor iarchive accept these files.
Iobjmanip 10.6.5.1221
This version of Iobjmanip can be downloaded here: <iobjmanip.exe>
This and later versions of iobjmanip solve the problems discussed is this text:
• It does not add additional .iar.noinitinfo sections to the output.
• It can manipulate files with both types of .iar.noinitinfo sections without corrupting them.
• It checks .iar.noinitinfo sections and warns if they seem to be incorrect.
Detecting and proving corruption
If the .iar.noinitinfo section contains the information that a section, for example NOI_SEC_u, is __no_init, but NOI_SEC_u is not nobits, the .iar.noinitinfo section is corrupt, and iobjmanip will warn and remove the corrupt section from the output (the original object file is not changed).
If all sections NOI_SEC_u are nobits, there is no evidence that the .iar.noinitinfo section is corrupt, and output will be created as usual (with an .iar.noinitinfo section, and without the warning).
Other cases of corruption
As described in the description of consequence 1 above, if the input file contains several nobits sections, the case might still be that:
- a zero-initialized section is now noinit
- a noinit section is now zero-initialized
Unfortunately. there is no way for iobjmanip to detect this.
Conclusion
iobjmanip 10.6.5.1221 will work with all versions of IAR Embedded Workbench that have this problem.
If iobjmanip is used to process files that have not already been processed with an old version of iobjmanip, the generated ELF file will not have these problems.
If an old version of iobjmanip has corrupted the contents of the .iar.noinitinfo, iobjmanip 10.6.5.1221 might be able to detect this.
In some cases, it will be able to remove an erroneous .iar.noinitinfo section, to prevent initialized content from being treated as __no_init, but it will not be able to correct an .iar.noinitinfo section for __no_init content if such information has been corrupted.
ILINK & iarchive
iarchive 10.6.5.1221 and future ILINK releases will only terminate with a fatal error when multiple .iar.noinitinfo sections are encountered if more than one such section actually contains information. If the superfluous sections contain no information, they will be ignored.