From 6e123ccc364b8bed9c38f884666271810c37578c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Mon, 24 Apr 2017 01:39:13 +0200 Subject: [PATCH 1/3] Optimize allocation of buffers for sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of allocating 0x4000 bytes for all sections and resize them as needed, allocate 0x8000 bytes and don't let them to be resized. This is the max possible size (ROM0 when ROMX sections aren't present). Buffers are not needed for RAM sections, this patch changes the code so that it only allocates buffers for ROM sections. Signed-off-by: Antonio Niño Díaz --- include/asm/localasm.h | 2 -- src/asm/output.c | 49 ++++++++++++++++++++---------------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/include/asm/localasm.h b/include/asm/localasm.h index 4cdf7ed2..92f3eb3a 100644 --- a/include/asm/localasm.h +++ b/include/asm/localasm.h @@ -80,8 +80,6 @@ */ -#define MAXSECTIONSIZE 0x4000 - #define NAME_DB "db" #define NAME_DW "dw" #define NAME_RB "rb" diff --git a/src/asm/output.c b/src/asm/output.c index 2e7ff7eb..7ae9c585 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -17,7 +17,12 @@ #include "asm/fstack.h" #include "extern/err.h" -#define SECTIONCHUNK 0x4000 +/* + * 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); @@ -446,31 +451,19 @@ checkcodesection(SLONG size) checksection(); if (pCurrentSection->nType != SECT_ROM0 && pCurrentSection->nType != SECT_ROMX) { - errx(1, "Section '%s' cannot contain code or data (not a " - "ROM0 or ROMX)", pCurrentSection->pzName); + errx(1, "Section '%s' cannot contain code or data (not a ROM0 or ROMX)", + pCurrentSection->pzName); } if (pCurrentSection->nPC + size > MAXSECTIONSIZE) { /* - * N.B.: This check is not sufficient to ensure the section - * will fit, because there can be multiple sections of this - * type. The definitive check must be done at the linking - * stage. + * 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). + * The real check must be done at the linking stage. */ - errx(1, "Section '%s' is too big (old size %d + %d > %d)", - pCurrentSection->pzName, pCurrentSection->nPC, size, - MAXSECTIONSIZE); - } - if (((pCurrentSection->nPC % SECTIONCHUNK) > - ((pCurrentSection->nPC + size) % SECTIONCHUNK)) && - (pCurrentSection->nType == SECT_ROM0 || - pCurrentSection->nType == SECT_ROMX)) { - pCurrentSection->tData = realloc(pCurrentSection->tData, - ((pCurrentSection->nPC + size) / SECTIONCHUNK + 1) * - SECTIONCHUNK); - - if (pCurrentSection->tData == NULL) { - err(1, "Could not expand section"); - } + errx(1, "Section '%s' is too big.", pCurrentSection->pzName); } return; } @@ -580,10 +573,14 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG align pSect->charmap = NULL; pPatchSymbols = NULL; - if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) { - return (pSect); - } else - fatalerror("Not enough memory for section"); + pSect->tData = NULL; + if (secttype == SECT_ROM0 || secttype == SECT_ROMX) { + /* It is only needed to allocate memory for ROM + * sections. */ + if ((pSect->tData = malloc(MAXSECTIONSIZE)) == NULL) + fatalerror("Not enough memory for section"); + } + return (pSect); } else fatalerror("Not enough memory for sectionname"); } else From 0d3401058d83b469ef7be63d066ca9bed819735c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ni=C3=B1o=20D=C3=ADaz?= Date: Mon, 24 Apr 2017 01:29:40 +0200 Subject: [PATCH 2/3] Check max section sizes in rgblink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The max size of some section types depends on the flags passed to rgblink. Instead of doing in rgbasm some checks (for the sections with fixed size) and others in rgblink, all checks are now done in rgblink. Signed-off-by: Antonio Niño Díaz --- src/link/object.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/link/object.c b/src/link/object.c index 3a8d1a5d..9da981ac 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -169,6 +169,42 @@ obj_ReadRGBSection(FILE * f) } } + unsigned int maxsize = 0; + + /* Verify that the section isn't too big */ + switch (pSection->Type) + { + case SECT_ROM0: + maxsize = (options & OPT_TINY) ? 0x8000 : 0x4000; + break; + case SECT_ROMX: + maxsize = 0x4000; + break; + case SECT_VRAM: + case SECT_SRAM: + maxsize = 0x2000; + break; + case SECT_WRAM0: + maxsize = (options & OPT_CONTWRAM) ? 0x2000 : 0x1000; + break; + case SECT_WRAMX: + maxsize = 0x1000; + break; + case SECT_OAM: + maxsize = 0xA0; + break; + case SECT_HRAM: + maxsize = 0x7F; + break; + default: + errx(1, "Section \"%s\" has an invalid section type.", pzName); + break; + } + if (pSection->nByteSize > maxsize) { + errx(1, "Section \"%s\" is bigger than the max size for that type: 0x%X > 0x%X", + pzName, pSection->nByteSize, maxsize); + } + if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) { /* * These sectiontypes contain data... 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 3/3] 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;