Conversation
|
|
||
| /* C stack size */ | ||
| .equ __stack_size, 2048 | ||
| .global __stack_size |
There was a problem hiding this comment.
Moved from amforth32.ld so that it can be overriden in mcu config.s
| include $(AMFORTH)/arm/dev/Makefile | ||
|
|
||
| LDFLAGS += -z max-page-size=4096 | ||
| LDFLAGS += -no-pie -static -z max-page-size=4096 |
There was a problem hiding this comment.
These flags don't fix anything but should be there as they indicate to the linker that the code is not meant to be relocated.
| all: config build/amforth.bin build/amforth.hex build/amforth.lst build/amforth.sal build/amforth.sym build/amforth.toc build/amforth.txt build/amforth.html | ||
| @echo INFO: Built $(TARGET) $(REVISION) using $(TC_DIR) | ||
| @$(SIZE) build/amforth.elf | ||
| @cd build && ls -l amforth.bin amforth.hex amforth.elf |
There was a problem hiding this comment.
Just to dump the interesting file sizes at the end of the build
| build/%.bin: build/%.elf | ||
| @echo "REBUILD $@" | ||
| @$(OBJCOPY) -O binary $< $@ | ||
| test `wc -c <$@` -lt 100000 |
There was a problem hiding this comment.
This checks that the bin file didn't grow over 100kb (we're averaging about 50kb atm), could make it tighter if desired, but wanted to leave some room for future growth.
| /* | ||
| This is the main AmForth flash section housing all the predefined words. | ||
| */ | ||
| amforth : |
There was a problem hiding this comment.
This part of the diff is confusing, I'm just moving the C data sections (.data, .bss, .dalign, ...) ahead of the amramres and amforth sections. The C data sections can contain bits of alignment padding even when otherwise empty and consequently cause the bin file to span the whole FLASH when allocated at the end of it.
| /* C stack size */ | ||
| __stack_size = 2048; | ||
| PROVIDE( _stack_size = __stack_size ); | ||
|
|
There was a problem hiding this comment.
Moved this to config.inc
So fortunately the CI segfault also reproduced in local Docker, and although that is not exactly a friendly debugging target either (GDB doesn't work in emulated container) I was able to deduce that the issue is that the user dictionary spaces weren't mapped as executable regions. It is possible to get the containerized process to dump the core file (need to invoke
ulimit -c unlimitedfirst), but the core file can then be analyzed using GDB outside of the container. The segfault was happening in the synthetic jump instruction we compile into DOES> words and is therefore executed in those spaces.So, how to mark the memory as executable? We need to mark the memory segments produced by the linker as executable. For that most reasonable way seems to be adding a PHDRS section to the linker file and declaring segments explicitly instead of letting the linker conjure them up, and then assigning each section to a specific segment (the :segment bit at the end of the section definitions).
Coming up with the set of segments was also a journey, because the :segment is only a hint apparently and you need to be careful about making segments span large memory areas and therefore large MemSiz value in the
make segmentsoutput below. It is very easy to end up with a large segment that contains other segments, usually you'll see the same section mapped to multiple segments in that case. What we want is to have nice tidy segments and each section mapped to exactly one of them.Below is the final arm/linux layout, note that the segments 02 and 03 containing all the forth sections are marked RWE (E = executable). amramhi is what made the tests segfault, but we also want the userdict section executable for >flash compiled words.
Another tweak in amforth32.ld is the addition of
(NOLOAD)flag to some of the sections, which marks the section as not having any content in the file. It was one of the AI recommendations to deal with the slow load problem on RV qemu, but it didn't help because the issue isn't loading things from file but zeroing out of empty memory and the (NOLOAD) doesn't really affect that. But the sections are marked correctly this way and I figured I may as well leave it there.Otherwise the actual fix is the change of the
-device loaderto use the.binfile instead of the.elffile and thus bypassing the ELF loading logic altogether:While fussing around with the segments I had to change the way the
amramhiallocation of the available RAM was done, by moving thestack_startcomputation up and using it in theamramhidefinition. This triggered a discovery of an issue on hifive which has so little RAM that there wan't enough room for both the default amount oframpool_sizeand__stack_size. To solve it I moved__stack_sizeinto config.s and reduced both in hifive's config.s so that things could actually fit.With these fixes I was able to enable the CI tests for arm/linux and things seem to be happy now.