shithub: rgbds

Download patch

ref: b7810ffdb3dcb5b4f4f412a0d50c5e08e146257a
parent: 0d3401058d83b469ef7be63d066ca9bed819735c
author: Antonio Niño Díaz <[email protected]>
date: Mon Apr 24 10:29:22 EDT 2017

Check for section overflows in rgbasm

When allocating a section, allocate only the max possible size for that
type (only applies to ROM0 and ROMX).

When finding an overflow, in any kind of section, output an error with
the location of the line of code that caused the overflow.

Signed-off-by: Antonio Niño Díaz <[email protected]>

--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -17,13 +17,6 @@
 #include "asm/fstack.h"
 #include "extern/err.h"
 
-/*
- * Size allocated for code sections. This is the max size for any ROM section
- * (which corresponds to a ROM0 section when the tiny flag is used in rgblink.
- * RAM sections don't need to allocate any memory.
- */
-#define MAXSECTIONSIZE	0x8000
-
 void out_SetCurrentSection(struct Section * pSect);
 
 struct Patch {
@@ -85,6 +78,24 @@
 		fatalerror("No entries in the section stack");
 }
 
+ULONG
+getmaxsectionsize(ULONG secttype, char * sectname)
+{
+	switch (secttype)
+	{
+		case SECT_ROM0:  return 0x8000; /* If ROMX sections not used. */
+		case SECT_ROMX:  return 0x4000;
+		case SECT_VRAM:  return 0x2000;
+		case SECT_SRAM:  return 0x2000;
+		case SECT_WRAM0: return 0x2000; /* If WRAMX sections not used. */
+		case SECT_WRAMX: return 0x1000;
+		case SECT_OAM:   return 0xA0;
+		case SECT_HRAM:  return 0x7F;
+		default: break;
+	}
+	errx(1, "Section \"%s\" has an invalid section type.", sectname);
+}
+
 /*
  * Count the number of symbols used in this object
  */
@@ -446,26 +457,35 @@
  * this much initialized data
  */
 void
-checkcodesection(SLONG size)
+checkcodesection(void)
 {
 	checksection();
 	if (pCurrentSection->nType != SECT_ROM0 &&
 	    pCurrentSection->nType != SECT_ROMX) {
-		errx(1, "Section '%s' cannot contain code or data (not a ROM0 or ROMX)",
+		fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)",
 		     pCurrentSection->pzName);
 	}
-	if (pCurrentSection->nPC + size > MAXSECTIONSIZE) {
+}
+
+/*
+ * Check if the section has grown too much.
+ */
+void
+checksectionoverflow(ULONG delta_size)
+{
+	ULONG maxsize = getmaxsectionsize(pCurrentSection->nType,
+					  pCurrentSection->pzName);
+
+	if (pCurrentSection->nPC + delta_size > maxsize) {
 		/*
 		 * This check is here to trap broken code that generates
 		 * sections that are too big and to prevent the assembler from
-		 * generating huge object files. The size used to check is the
-		 * biggest possible section in a GB (a ROM0 section when ROMX
-		 * sections aren't used).
+		 * generating huge object files.
 		 * The real check must be done at the linking stage.
 		 */
-		errx(1, "Section '%s' is too big.", pCurrentSection->pzName);
+		fatalerror("Section '%s' is too big (max size = 0x%X bytes).",
+			pCurrentSection->pzName, maxsize);
 	}
-	return;
 }
 
 /*
@@ -577,7 +597,8 @@
 			if (secttype == SECT_ROM0 || secttype == SECT_ROMX) {
 				/* It is only needed to allocate memory for ROM
 				 * sections. */
-				if ((pSect->tData = malloc(MAXSECTIONSIZE)) == NULL)
+				ULONG sectsize = getmaxsectionsize(secttype, pzName);
+				if ((pSect->tData = malloc(sectsize)) == NULL)
 					fatalerror("Not enough memory for section");
 			}
 			return (pSect);
@@ -638,7 +659,8 @@
 void
 out_AbsByte(int b)
 {
-	checkcodesection(1);
+	checkcodesection();
+	checksectionoverflow(1);
 	b &= 0xFF;
 	if (nPass == 2)
 		pCurrentSection->tData[nPC] = b;
@@ -651,7 +673,8 @@
 void
 out_AbsByteGroup(char *s, int length)
 {
-	checkcodesection(length);
+	checkcodesection();
+	checksectionoverflow(length);
 	while (length--)
 		out_AbsByte(*s++);
 }
@@ -663,6 +686,7 @@
 out_Skip(int skip)
 {
 	checksection();
+	checksectionoverflow(skip);
 	if (!((pCurrentSection->nType == SECT_ROM0)
 		|| (pCurrentSection->nType == SECT_ROMX))) {
 		pCurrentSection->nPC += skip;
@@ -669,7 +693,7 @@
 		nPC += skip;
 		pPCSymbol->nValue += skip;
 	} else {
-		checkcodesection(skip);
+		checkcodesection();
 		while (skip--)
 			out_AbsByte(CurrentOptions.fillchar);
 	}
@@ -681,7 +705,8 @@
 void
 out_String(char *s)
 {
-	checkcodesection(strlen(s));
+	checkcodesection();
+	checksectionoverflow(strlen(s));
 	while (*s)
 		out_AbsByte(*s++);
 }
@@ -694,7 +719,8 @@
 void
 out_RelByte(struct Expression * expr)
 {
-	checkcodesection(1);
+	checkcodesection();
+	checksectionoverflow(1);
 	if (rpn_isReloc(expr)) {
 		if (nPass == 2) {
 			pCurrentSection->tData[nPC] = 0;
@@ -715,7 +741,8 @@
 void
 out_AbsWord(int b)
 {
-	checkcodesection(2);
+	checkcodesection();
+	checksectionoverflow(2);
 	b &= 0xFFFF;
 	if (nPass == 2) {
 		pCurrentSection->tData[nPC] = b & 0xFF;
@@ -735,7 +762,8 @@
 {
 	ULONG b;
 
-	checkcodesection(2);
+	checkcodesection();
+	checksectionoverflow(2);
 	b = expr->nVal & 0xFFFF;
 	if (rpn_isReloc(expr)) {
 		if (nPass == 2) {
@@ -757,7 +785,8 @@
 void
 out_AbsLong(SLONG b)
 {
-	checkcodesection(sizeof(SLONG));
+	checkcodesection();
+	checksectionoverflow(sizeof(SLONG));
 	if (nPass == 2) {
 		pCurrentSection->tData[nPC] = b & 0xFF;
 		pCurrentSection->tData[nPC + 1] = b >> 8;
@@ -778,7 +807,8 @@
 {
 	SLONG b;
 
-	checkcodesection(4);
+	checkcodesection();
+	checksectionoverflow(4);
 	b = expr->nVal;
 	if (rpn_isReloc(expr)) {
 		if (nPass == 2) {
@@ -804,7 +834,8 @@
 {
 	SLONG b = expr->nVal;
 
-	checkcodesection(1);
+	checkcodesection();
+	checksectionoverflow(1);
 	b = (b & 0xFFFF) - (nPC + 1);
 	if (nPass == 2 && (b < -128 || b > 127))
 		yyerror("PC-relative value must be 8-bit");
@@ -832,7 +863,8 @@
 	fsize = ftell(f);
 	fseek(f, 0, SEEK_SET);
 
-	checkcodesection(fsize);
+	checkcodesection();
+	checksectionoverflow(fsize);
 
 	if (nPass == 2) {
 		SLONG dest = nPC;
@@ -876,7 +908,8 @@
 
 	fseek(f, start_pos, SEEK_SET);
 
-	checkcodesection(length);
+	checkcodesection();
+	checksectionoverflow(length);
 
 	if (nPass == 2) {
 		SLONG dest = nPC;