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 <antonio_nd@outlook.com>
This commit is contained in:
Antonio Niño Díaz
2017-04-24 14:29:22 +02:00
parent 0d3401058d
commit b7810ffdb3

View File

@@ -17,13 +17,6 @@
#include "asm/fstack.h" #include "asm/fstack.h"
#include "extern/err.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); void out_SetCurrentSection(struct Section * pSect);
struct Patch { struct Patch {
@@ -85,6 +78,24 @@ out_PopSection(void)
fatalerror("No entries in the section stack"); 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 * Count the number of symbols used in this object
*/ */
@@ -446,26 +457,35 @@ checksection(void)
* this much initialized data * this much initialized data
*/ */
void void
checkcodesection(SLONG size) checkcodesection(void)
{ {
checksection(); checksection();
if (pCurrentSection->nType != SECT_ROM0 && if (pCurrentSection->nType != SECT_ROM0 &&
pCurrentSection->nType != SECT_ROMX) { 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); 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 * This check is here to trap broken code that generates
* sections that are too big and to prevent the assembler from * sections that are too big and to prevent the assembler from
* generating huge object files. The size used to check is the * generating huge object files.
* 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. * 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) { if (secttype == SECT_ROM0 || secttype == SECT_ROMX) {
/* It is only needed to allocate memory for ROM /* It is only needed to allocate memory for ROM
* sections. */ * sections. */
if ((pSect->tData = malloc(MAXSECTIONSIZE)) == NULL) ULONG sectsize = getmaxsectionsize(secttype, pzName);
if ((pSect->tData = malloc(sectsize)) == NULL)
fatalerror("Not enough memory for section"); fatalerror("Not enough memory for section");
} }
return (pSect); return (pSect);
@@ -638,7 +659,8 @@ out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank)
void void
out_AbsByte(int b) out_AbsByte(int b)
{ {
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
b &= 0xFF; b &= 0xFF;
if (nPass == 2) if (nPass == 2)
pCurrentSection->tData[nPC] = b; pCurrentSection->tData[nPC] = b;
@@ -651,7 +673,8 @@ out_AbsByte(int b)
void void
out_AbsByteGroup(char *s, int length) out_AbsByteGroup(char *s, int length)
{ {
checkcodesection(length); checkcodesection();
checksectionoverflow(length);
while (length--) while (length--)
out_AbsByte(*s++); out_AbsByte(*s++);
} }
@@ -663,13 +686,14 @@ void
out_Skip(int skip) out_Skip(int skip)
{ {
checksection(); checksection();
checksectionoverflow(skip);
if (!((pCurrentSection->nType == SECT_ROM0) if (!((pCurrentSection->nType == SECT_ROM0)
|| (pCurrentSection->nType == SECT_ROMX))) { || (pCurrentSection->nType == SECT_ROMX))) {
pCurrentSection->nPC += skip; pCurrentSection->nPC += skip;
nPC += skip; nPC += skip;
pPCSymbol->nValue += skip; pPCSymbol->nValue += skip;
} else { } else {
checkcodesection(skip); checkcodesection();
while (skip--) while (skip--)
out_AbsByte(CurrentOptions.fillchar); out_AbsByte(CurrentOptions.fillchar);
} }
@@ -681,7 +705,8 @@ out_Skip(int skip)
void void
out_String(char *s) out_String(char *s)
{ {
checkcodesection(strlen(s)); checkcodesection();
checksectionoverflow(strlen(s));
while (*s) while (*s)
out_AbsByte(*s++); out_AbsByte(*s++);
} }
@@ -694,7 +719,8 @@ out_String(char *s)
void void
out_RelByte(struct Expression * expr) out_RelByte(struct Expression * expr)
{ {
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = 0; pCurrentSection->tData[nPC] = 0;
@@ -715,7 +741,8 @@ out_RelByte(struct Expression * expr)
void void
out_AbsWord(int b) out_AbsWord(int b)
{ {
checkcodesection(2); checkcodesection();
checksectionoverflow(2);
b &= 0xFFFF; b &= 0xFFFF;
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF; pCurrentSection->tData[nPC] = b & 0xFF;
@@ -735,7 +762,8 @@ out_RelWord(struct Expression * expr)
{ {
ULONG b; ULONG b;
checkcodesection(2); checkcodesection();
checksectionoverflow(2);
b = expr->nVal & 0xFFFF; b = expr->nVal & 0xFFFF;
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
@@ -757,7 +785,8 @@ out_RelWord(struct Expression * expr)
void void
out_AbsLong(SLONG b) out_AbsLong(SLONG b)
{ {
checkcodesection(sizeof(SLONG)); checkcodesection();
checksectionoverflow(sizeof(SLONG));
if (nPass == 2) { if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF; pCurrentSection->tData[nPC] = b & 0xFF;
pCurrentSection->tData[nPC + 1] = b >> 8; pCurrentSection->tData[nPC + 1] = b >> 8;
@@ -778,7 +807,8 @@ out_RelLong(struct Expression * expr)
{ {
SLONG b; SLONG b;
checkcodesection(4); checkcodesection();
checksectionoverflow(4);
b = expr->nVal; b = expr->nVal;
if (rpn_isReloc(expr)) { if (rpn_isReloc(expr)) {
if (nPass == 2) { if (nPass == 2) {
@@ -804,7 +834,8 @@ out_PCRelByte(struct Expression * expr)
{ {
SLONG b = expr->nVal; SLONG b = expr->nVal;
checkcodesection(1); checkcodesection();
checksectionoverflow(1);
b = (b & 0xFFFF) - (nPC + 1); b = (b & 0xFFFF) - (nPC + 1);
if (nPass == 2 && (b < -128 || b > 127)) if (nPass == 2 && (b < -128 || b > 127))
yyerror("PC-relative value must be 8-bit"); yyerror("PC-relative value must be 8-bit");
@@ -832,7 +863,8 @@ out_BinaryFile(char *s)
fsize = ftell(f); fsize = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
checkcodesection(fsize); checkcodesection();
checksectionoverflow(fsize);
if (nPass == 2) { if (nPass == 2) {
SLONG dest = nPC; SLONG dest = nPC;
@@ -876,7 +908,8 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
fseek(f, start_pos, SEEK_SET); fseek(f, start_pos, SEEK_SET);
checkcodesection(length); checkcodesection();
checksectionoverflow(length);
if (nPass == 2) { if (nPass == 2) {
SLONG dest = nPC; SLONG dest = nPC;