Bug/Feature Wish: Strange warning and selecting the entry point (micro controller support, section order): -u vs -e
I have been quite successful with mold in bare metal systems. I am also quite happy to not having to write magic linker scripts. In those systems you want to create a raw binary that starts with a structure that contains addresses to the interrupt service routines and usually an address that gives you the starting point of the stack. In the past it was considered common sense to mark the "reset" service routine as entry point, I think it makes more sense to select the whole initial structure, to ensure that all of the necessary functions would be added.
I.e. on a STM32H7432 I use:
arm-none-eabi-g++ -mthumb -mcpu=cortex-m7 -march=armv7e-m -mfpu=fpv5-d16 -mfloat-abi=hard \
-ffunction-sections -fdata-sections -fstack-usage -MMD -MP -gdwarf-4 -Os -g3 -nostartfiles --specs=nano.specs\
--specs=nosys.specs -Wl,--icf=all -Wl,--relocatable-merge-sections -Wl,--no-undefined -lstdc++ -lsupc++ \
-Wl,-u,vector_table -Wl,-e,vector_table -Wl,--gc-sections -Wl,--nmagic -Wl,--no-omagic -Wl,--Bno-symbolic -Wl,--static\
-Wl,--stats -Wl,--start-stop -Wl,--image-base=0x24000000 -Wl,--physical-image-base=0x8000000 \
-Wl,--section-align=TEXT=8 -Wl,--section-align=BSS=8 -Wl,--section-align=RODATA=8 -Wl,--section-align=DATA=8
"-Wl,--section-order==0x8000000 isr_vec TEXT RODATA =0x30000000 .data_sram1 =0x20000000 .data_dtcm =0x20018000 !__start_stack =0x20020000 !__stop_stack =0x24000000 DATA BSS" -fuse-ld=mold ...
I want to point towards the -e vector_table and -u vector_table parameters. This is an array of addresses of functions. It uses [[gnu::section("isr_vec")]] so that I can order it in the section order parameter:
[[gnu::section("isr_vec")]] VectorAddress vector_table[] = {
(VectorAddress)(&__stop_stack),
reset_handler,
nmi_handler,
hard_fault_handerl,
....
};
With the above I do get the desired behavior, but I still get a warning: mold: warning: entry symbol is not defined: vector_table.
According to objdump vector_table is found and placed at 0x800000.
Am I mis-using the entry point parameter?
Thank you for sharing your experience with embedded programming in mold! The lack of feedback is a critical issue when building features for embedded programming, so I'm glad you are using it.
Regarding the warning message about the entry point address, I believe your vector_table is defined as a local symbol. There are several ways to fix this, as follows:
- Currently, neither
-enor-uhas any effect on your program when that warning message is displayed, so you could simply delete these options from the command line, or - define vector_table as a global symbol.
vector_table is not a subject of garbage collection because it's defined in a section whose name is a valid C identifier (i.e. isr_vec, not .isr_vec or something.)
Ok will give this a try.
I think there are one or two other features inside --section-order that would be great. But I do feel bad for requesting them, but rather obliged to donate them:
- the ability to mark user defined sections as uninitialized, to have them placed in memory but not contribute to the final binary size (PS: this one was simpler than I expected)
- address size checks similar to the memory region feature of linker scripts: --section-order=" =0x2400000 DATA BSS <0x2402000 " - then warn or fail if contents of the section that ordered right before the "<ADDR" token exceed the given address
As to the second point, would it be sufficient if --section-order="=0x2400000 DATA BSS =0x2402000" issued a warning like “the address is rewound from 0x2403ffff to 0x2402000”?
Oh of course - havent thought about that!
the --zero-to-bss change works great. With that I discovered a few symbols that are constant and zero for ever. These previously .rodata symbols get moved to the BSS group:
diff --git a/src/passes.cc b/src/passes.cc
index 3c322828..6ca45140 100644
--- a/src/passes.cc
+++ b/src/passes.cc
@@ -2525,7 +2525,7 @@ void sort_output_sections_regular(Context<E> &ctx) {
template <typename E>
static std::string_view get_section_order_group(Chunk<E> &chunk) {
- if (chunk.shdr.sh_type == SHT_NOBITS)
+ if (chunk.shdr.sh_type == SHT_NOBITS && (chunk.shdr.sh_flags & SHF_WRITE))
return "BSS";
if (chunk.shdr.sh_flags & SHF_EXECINSTR)
return "TEXT";
diff --git a/test/zero-to-bss.sh b/test/zero-to-bss.sh
index a809e358..a7818930 100755
--- a/test/zero-to-bss.sh
+++ b/test/zero-to-bss.sh
@@ -5,6 +5,7 @@ cat <<EOF | $CC -o $t/a.o -c -xc -
#include <stdio.h>
__attribute__((section(".zero"))) char zero[256];
+char const stay_in_rodata[256];
int main() {
printf("Hello world\n");
So the above keeps them in the RODATA group and keeps them inside the binary as zeros. Yeah this is kind of opposite to the initial motivation. For this project it does not matter either way. I was then trying to rename the symbols to "rodata.zero" to give the user more control.
Then I wondered why those "zeros" do not get folded by ICF. Maybe ICF could also merge read-only NOBITS symbols..
Read-only BSS is an odd concept because reading from such section will always returns 0 at any time, so they don't have to be in memory at all. So maybe --zero-to-bss should work only for writable sections. For the same reason, I believe you don't generally want to merge read-only BSS sections because such sections should not exist in normal circumstances.
Exactly but we magically created that now :). Hence the suggestion above - to keep the original .rodata-NOBITS away from BSS.
How about the above change?
Sorry for the delay. Yes perfect!
On the other topic I tried to make this change: https://github.com/APokorny/mold/tree/feat/detect-overlapping-section-intervals
But warnings are triggered twice i.e:
#include <stdint.h>
#include <stdio.h>
__attribute__((section(".dmastuff"))) char ex[1024];
__attribute__((section(".dmastuff"))) int32_t foo;
__attribute__((section(".dmastuff2"))) char ex2[1024];
int main() {
printf("Hello world\n");
}
gcc -B. -o testi test.o -fuse-ld=mold -Wl,--image-base=0x5000 -Wl,--section-order='=0x1000 .dmastuff =0x1010 =0x4000 .dmastuff2 =0x5000 TEXT RODATA BSS DATA 0x6000 '
mold: warning: : symbols ordered to 0x1000 exceed 0x1010 up to 0x1404
mold: warning: : symbols ordered to 0x1000 exceed 0x1010 up to 0x1404
I see that it gets re-run, but I dont understand why in this case.
I believe it's because the function to layout sections actually runs twice. I can add a warning for you. Besides showing the warning twice, did it work as you expected?
How about the above change?
Yeah this works for me. As of now - I am not missing anything in terms of bare metal / embedded systems support. I will convert another project next week and see how that goes, but I dont expect any troubles.
Thanks a lot!
I give a try in documenting that feature.
--section-order was undocumented because there's no user. I'll add a description of that command line flag to our man page.