ref: 0f3b708dce0226ffcd2a179bc9650e7f86e22f5b
parent: 7eb9101d4353ae6c5509bb0a4e65ca8b73444220
parent: e63e801e9cf2dddbdd3d95347137548db630f856
author: AntonioND <[email protected]>
date: Wed Apr 5 19:08:37 EDT 2017
Merge pull request #157 from AntonioND/an/error-undef-diff Output error message if diff of labels not defined
--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -71,5 +71,6 @@
ULONG sym_isDefined(char *tzName);
void sym_Purge(char *tzName);
ULONG sym_isConstDefined(char *tzName);
+int sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2);
#endif
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -1039,9 +1039,14 @@
| const T_OP_LOGICNE const { $$ = $1 != $3; }
| const T_OP_ADD const { $$ = $1 + $3; }
| const T_OP_SUB const { $$ = $1 - $3; }
- | T_ID T_OP_SUB T_ID { $$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3); }
+ | T_ID T_OP_SUB T_ID
+ {
+ if (sym_IsRelocDiffDefined($1, $3) == 0)
+ fatalerror("'%s - %s' not defined.", $1, $3);
+ $$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3);
+ }
| const T_OP_XOR const { $$ = $1 ^ $3; }
- | const T_OP_OR const { $$ = $1 | $3; }
+ | const T_OP_OR const { $$ = $1 | $3; }
| const T_OP_AND const { $$ = $1 & $3; }
| const T_OP_SHL const { $$ = $1 << $3; }
| const T_OP_SHR const { $$ = $1 >> $3; }
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -620,6 +620,49 @@
}
/*
+ * Check if the subtraction of two symbols is defined. That is, either both
+ * symbols are defined and the result is a constant, or both symbols are
+ * relocatable and belong to the same section.
+ *
+ * It returns 1 if the difference is defined, 0 if not.
+ */
+int
+sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2)
+{
+ /* Do nothing the first pass. */
+ if (nPass != 2)
+ return 1;
+
+ struct sSymbol *nsym1, *nsym2;
+
+ /* Do the symbols exist? */
+ if ((nsym1 = sym_FindSymbol(tzSym1)) == NULL)
+ fatalerror("Symbol \"%s\" isn't defined.", tzSym1);
+ if ((nsym2 = sym_FindSymbol(tzSym2)) == NULL)
+ fatalerror("Symbol \"%s\" isn't defined.", tzSym2);
+
+ int s1reloc = (nsym1->nType & SYMF_RELOC) != 0;
+ int s2reloc = (nsym2->nType & SYMF_RELOC) != 0;
+
+ /* Both are non-relocatable */
+ if (!s1reloc && !s2reloc) return 1;
+
+ /* One of them relocatable, the other one not. */
+ if (s1reloc ^ s2reloc) return 0;
+
+ /* Both of them are relocatable. Make sure they are defined (internal
+ * coherency with sym_AddReloc and sym_AddLocalReloc). */
+ if (!(nsym1->nType & SYMF_DEFINED))
+ fatalerror("Relocatable symbol \"%s\" isn't defined.", tzSym1);
+ if (!(nsym2->nType & SYMF_DEFINED))
+ fatalerror("Relocatable symbol \"%s\" isn't defined.", tzSym2);
+
+ /* Both of them must be in the same section for the difference to be
+ * defined. */
+ return nsym1->pSection == nsym2->pSection;
+}
+
+/*
* Export a symbol
*/
void