]> Shamusworld >> Repos - rmac/commitdiff
Fix for bug #176: During AddFixup(), evaluate as much of the expression as possible... v2.1.4
authorggn <ggn.dbug@gmail.com>
Mon, 12 Oct 2020 10:16:33 +0000 (13:16 +0300)
committerShamus Hammons <jlhamm@acm.org>
Wed, 9 Jun 2021 00:25:13 +0000 (19:25 -0500)
sect.c

diff --git a/sect.c b/sect.c
index e0e47c6446aad4c4045fd64c9fa9f9523d2507ea..a9239e6e638b1cb8c808d801432a7be9b91e93f7 100644 (file)
--- a/sect.c
+++ b/sect.c
@@ -294,7 +294,7 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
        }
 
        // Allocate space for the fixup + any expression
-       FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen));
+       FIXUP * fixup = malloc(sizeof(FIXUP) + (sizeof(TOKEN) * exprlen)*2);
 
        // Store the relevant fixup information in the FIXUP
        fixup->next = NULL;
@@ -309,8 +309,53 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr)
        // Copy the passed in expression to the FIXUP, if any
        if (exprlen > 0)
        {
+               // Here we used to to a plain memcpy and punt on trying to evaluate the expression by then.
+               // As discussed in bug #176, this can lead to robustness issues because some symbols might
+               // have changed by the time we perform the relocations (think of a symbol that's SET multiple
+               // times). So instead we perform a symbol-by-symbol copy and check to see if there are any
+               // resolved symbols that can be evaluated immediately. Those, we replace with constants.
+               // Also of note: because "fixup" can be larger than what ExpressionLength() returns
+               // (due to constants taking up more space than symbols), we allocate twice as RAM as we should
+               // without expansions just to be on the safe side. The "correct" thing to do would be to
+               // modify ExpressionLength() to cater for defined symbols and return the exact amount of items.
+
                fixup->expr = (TOKEN *)((uint8_t *)fixup + sizeof(FIXUP));
-               memcpy(fixup->expr, fexpr, sizeof(TOKEN) * exprlen);
+               int i;
+               PTR dstexpr;
+               dstexpr.u32 = fixup->expr;
+               SYM *sy;
+               for (i = 0; i < exprlen; i++)
+               {
+                       if (*fexpr == SYMBOL)
+                       {
+                               sy = symbolPtr[fexpr[1]];
+                               if (sy->sattr & DEFINED && !(sy->sattr & (TDB| M56KPXYL|M6502)))
+                               {
+                                       // Only convert symbols that are defined and are absolute
+                                       *dstexpr.u32++ = CONST;
+                                       *dstexpr.u64++ = sy->svalue;
+                                       fexpr += 2;
+                                       i++;
+                               }
+                               else
+                               {
+                                       // Just copy the symbol
+                                       *dstexpr.u32++ = *fexpr++;
+                                       *dstexpr.u32++ = *fexpr++;
+                                       i++;
+                               }
+                       }
+                       else if (*fexpr == CONST || *fexpr == FCONST)
+                       {
+                               // Copy constants
+                               *dstexpr.u32++ = *fexpr++;
+                               *dstexpr.u32++ = *fexpr++;
+                               *dstexpr.u32++ = *fexpr++;
+                               i += 2;
+                       }
+                       else
+                               *dstexpr.u32++ = *fexpr++;
+               }
        }
 
        // Finally, put the FIXUP in the current section's linked list