From 2ac055383f4619cea09988aa79c2b4324c1bfb40 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sun, 19 Feb 2023 08:14:04 -0500 Subject: [PATCH 1/2] ld65 fix overwrite segments adding wrong padding or causing internal errors --- src/ld65/config.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ld65/config.c b/src/ld65/config.c index c22ced1ef..c101bd1c6 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -1945,6 +1945,10 @@ unsigned CfgProcess (void) /* Remember the start address before handling this segment */ unsigned long StartAddr = Addr; + /* For computing FillLevel */ + unsigned long FillLevel; + unsigned long FillAdded = 0; + /* Take note of "overwrite" segments and make sure there are no ** other segment types following them in current memory region. */ @@ -2081,14 +2085,19 @@ unsigned CfgProcess (void) /* Increment the fill level of the memory area; and, check for an ** overflow. */ - M->FillLevel = Addr + S->Seg->Size - M->Start; - if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { + FillLevel = Addr + S->Seg->Size - M->Start; + if (FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), "Segment '%s' overflows memory area '%s' by %lu byte%c", GetString (S->Name), GetString (M->Name), - M->FillLevel - M->Size, (M->FillLevel - M->Size == 1) ? ' ' : 's'); + FillLevel - M->Size, (FillLevel - M->Size == 1) ? ' ' : 's'); + } + if (FillLevel > M->FillLevel) { + /* Regular segments increase FillLevel. Overwrite segments may increase but not decrease FillLevel. */ + FillAdded = FillLevel - M->FillLevel; + M->FillLevel = FillLevel; } /* If requested, define symbols for the start and size of the @@ -2107,13 +2116,14 @@ unsigned CfgProcess (void) Addr += S->Seg->Size; /* If this segment will go out to the file, or its place - ** in the file will be filled, then increase the file size, - ** unless it's an OVERWRITE segment. + ** in the file will be filled, then increase the file size. + ** An OVERWRITE segment will only increase the size if it overlapped some of the fill area. */ if (S->Load == M && - ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0) && - (S->Flags & SF_OVERWRITE) == 0) { - M->F->Size += Addr - StartAddr; + ((S->Flags & SF_BSS) == 0 || (M->Flags & MF_FILL) != 0)) { + M->F->Size += (!(S->Flags & SF_OVERWRITE)) ? + (Addr - StartAddr) : + FillAdded; } } From 4fc19a3d4c27d193297e928171f85ab361ac2ae7 Mon Sep 17 00:00:00 2001 From: bbbradsmith Date: Sun, 19 Feb 2023 08:37:07 -0500 Subject: [PATCH 2/2] ld65 overwrite segment should pad with fill value if the desired seek position is beyond the end of the file so far --- src/ld65/bin.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ld65/bin.c b/src/ld65/bin.c index bd822cc23..15b534f66 100644 --- a/src/ld65/bin.c +++ b/src/ld65/bin.c @@ -193,8 +193,16 @@ static void BinWriteMem (BinDesc* D, MemoryArea* M) NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { - /* Seek in "overwrite" segments */ if (S->Flags & SF_OVERWRITE) { + /* Seek in "overwrite" segments. Fill if the seek position has not been reached yet. */ + unsigned long FileLength; + unsigned long SeekTarget = NewAddr - M->Start + M->FileOffs; + fseek (D->F, 0, SEEK_END); + FileLength = ftell (D->F); + if (SeekTarget > FileLength) { + WriteMult (D->F, M->FillVal, SeekTarget - FileLength); + PrintNumVal ("SF_OVERWRITE", SeekTarget - FileLength); + } fseek (D->F, NewAddr - M->Start + M->FileOffs, SEEK_SET); } else { WriteMult (D->F, M->FillVal, NewAddr-Addr);