.fpc* section linked to .data, increasing size of final binary image [AVR]
Summary
Since commit 776c39dc the .fpc* section information is linked into the .data segment, taking up memory on the controller. This information is only required to supply debug information in the elf file, as far as I know.
This may be a more general issue, since the .fpc section is placed in .data for most (all?) targets. It isn't clear to me whether this information needs to be loaded as data, at least on most targets the presence of .fpc information in .data isn't much of a concern (other than general bloat of course).
System Information
- Operating system: Embedded
- Processor architecture: AVR
- Compiler version: 3.3.1 a221f2af
- Device: Microcontroller
Steps to reproduce
Compile example program:
$ ~/fpc/gitlab-cc/compiler/avr/pp -n @~/fpc/gitlab-cc/fpc.cfg -O1 -Wpattiny13 -Mobjfpc test.pas
Free Pascal Compiler version 3.3.1 [2023/02/19] for avr
Copyright (c) 1993-2023 by Florian Klaempfl and others
Target OS: Embedded
Compiling test.pas
test.pas(4,3) Note: Local variable "s" is assigned but never used
Assembling testsimavr
Linking test
9 lines compiled, 0.1 sec, 98 bytes code, 2 bytes data
1 note(s) issued
Then dump content of test.bin:
$ cat test.bin
��6�����������6�����#� �`�������������-FPC 3.3.1 [2023/02/19] for avr - Embedded
Looking at the elf headers show that the .fpc section is marked ALLOC, LOAD, DATA, thus the linker should add it to the .data section:
$ avr-objdump -h test.elf
test.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000062 00000000 00000000 00000074 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000002 00800060 00000062 000000d6 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .debug_aranges 00000042 00000000 00000000 00000101 2**0
CONTENTS, READONLY, DEBUGGING
3 .debug_info 00000710 00000000 00000000 00000143 2**0
CONTENTS, READONLY, DEBUGGING
4 .debug_abbrev 00000058 00000000 00000000 00000853 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_line 0000011f 00000000 00000000 000008ab 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_frame 00002568 00000000 00000000 000009ca 2**1
CONTENTS, READONLY, DEBUGGING
7 .fpc 00000029 00800062 00000064 000000d8 2**0
CONTENTS, ALLOC, LOAD, DATA
The problem is that the .fpc information emitted by the compiler is marked with flags "aw", for example .section .fpc.n_links,"aw"
. Thus moving the KEEP (*(.fpc .fpc.n_version .fpc.n_links))
out of the .data section of the linker script is not sufficient.
Example Project
program test;
var
s: char = '-';
begin
s := 'c';
end.
What is the current bug behavior?
The .fpc* information is stored in the .data section, taking up RAM space.
What is the expected (correct) behavior?
The .fpc* sections should be in the elf file, but not be stored in the .data section.
Possible fixes
A quick fix is to change the linker script by changing the .fpc section as follows:
diff --git a/compiler/systems/t_embed.pas b/compiler/systems/t_embed.pas
index 9b97eccaa8..79e87f61d7 100644
--- a/compiler/systems/t_embed.pas
+++ b/compiler/systems/t_embed.pas
@@ -1120,7 +1120,6 @@ procedure TlinkerEmbedded.SetDefaultInfo;
Add(' *(.rodata) /* We need to include .rodata here if gcc is used */');
Add(' *(.rodata*) /* with -fdata-sections. */');
Add(' *(.gnu.linkonce.d*)');
- add(' KEEP (*(.fpc .fpc.n_version .fpc.n_links))');
Add(' . = ALIGN(2);');
Add(' _edata = . ;');
Add(' PROVIDE (__data_end = .) ;');
@@ -1198,6 +1197,7 @@ procedure TlinkerEmbedded.SetDefaultInfo;
Add(' /* DWARF Extension. */');
Add(' .debug_macro 0 : { *(.debug_macro) }');
Add(' .debug_addr 0 : { *(.debug_addr) }');
+ Add(' .fpc (NOLOAD) : { KEEP (*(.fpc .fpc.n_version .fpc.n_links)) }');
Add('}');
end;
{$endif AVR}
A "better" fix may be to omit the "a,w" flags for .fpc* when generating the assembler code.