From b7810ffdb3dcb5b4f4f412a0d50c5e08e146257a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Mon, 24 Apr 2017 14:29:22 +0200 Subject: [PATCH] Check for section overflows in rgbasm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/asm/output.c | 89 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/src/asm/output.c b/src/asm/output.c index 7ae9c585..4bc1ae9e 100644 --- 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 @@ out_PopSection(void) 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 @@ checksection(void) * 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 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG align 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 @@ out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank) void out_AbsByte(int b) { - checkcodesection(1); + checkcodesection(); + checksectionoverflow(1); b &= 0xFF; if (nPass == 2) pCurrentSection->tData[nPC] = b; @@ -651,7 +673,8 @@ out_AbsByte(int b) void out_AbsByteGroup(char *s, int length) { - checkcodesection(length); + checkcodesection(); + checksectionoverflow(length); while (length--) out_AbsByte(*s++); } @@ -663,13 +686,14 @@ void out_Skip(int skip) { checksection(); + checksectionoverflow(skip); if (!((pCurrentSection->nType == SECT_ROM0) || (pCurrentSection->nType == SECT_ROMX))) { pCurrentSection->nPC += skip; nPC += skip; pPCSymbol->nValue += skip; } else { - checkcodesection(skip); + checkcodesection(); while (skip--) out_AbsByte(CurrentOptions.fillchar); } @@ -681,7 +705,8 @@ out_Skip(int skip) void out_String(char *s) { - checkcodesection(strlen(s)); + checkcodesection(); + checksectionoverflow(strlen(s)); while (*s) out_AbsByte(*s++); } @@ -694,7 +719,8 @@ out_String(char *s) 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 @@ out_RelByte(struct Expression * expr) void out_AbsWord(int b) { - checkcodesection(2); + checkcodesection(); + checksectionoverflow(2); b &= 0xFFFF; if (nPass == 2) { pCurrentSection->tData[nPC] = b & 0xFF; @@ -735,7 +762,8 @@ out_RelWord(struct Expression * expr) { ULONG b; - checkcodesection(2); + checkcodesection(); + checksectionoverflow(2); b = expr->nVal & 0xFFFF; if (rpn_isReloc(expr)) { if (nPass == 2) { @@ -757,7 +785,8 @@ out_RelWord(struct Expression * expr) 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 @@ out_RelLong(struct Expression * expr) { SLONG b; - checkcodesection(4); + checkcodesection(); + checksectionoverflow(4); b = expr->nVal; if (rpn_isReloc(expr)) { if (nPass == 2) { @@ -804,7 +834,8 @@ out_PCRelByte(struct Expression * expr) { 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 @@ out_BinaryFile(char *s) fsize = ftell(f); fseek(f, 0, SEEK_SET); - checkcodesection(fsize); + checkcodesection(); + checksectionoverflow(fsize); if (nPass == 2) { SLONG dest = nPC; @@ -876,7 +908,8 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length) fseek(f, start_pos, SEEK_SET); - checkcodesection(length); + checkcodesection(); + checksectionoverflow(length); if (nPass == 2) { SLONG dest = nPC;