mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-23 03:22:08 +00:00
Merge pull request #177 from AntonioND/an/section-checks
Improve section size checks and buffer handling Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
This commit is contained in:
@@ -80,8 +80,6 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MAXSECTIONSIZE 0x4000
|
|
||||||
|
|
||||||
#define NAME_DB "db"
|
#define NAME_DB "db"
|
||||||
#define NAME_DW "dw"
|
#define NAME_DW "dw"
|
||||||
#define NAME_RB "rb"
|
#define NAME_RB "rb"
|
||||||
|
|||||||
112
src/asm/output.c
112
src/asm/output.c
@@ -17,8 +17,6 @@
|
|||||||
#include "asm/fstack.h"
|
#include "asm/fstack.h"
|
||||||
#include "extern/err.h"
|
#include "extern/err.h"
|
||||||
|
|
||||||
#define SECTIONCHUNK 0x4000
|
|
||||||
|
|
||||||
void out_SetCurrentSection(struct Section * pSect);
|
void out_SetCurrentSection(struct Section * pSect);
|
||||||
|
|
||||||
struct Patch {
|
struct Patch {
|
||||||
@@ -80,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
|
||||||
*/
|
*/
|
||||||
@@ -441,39 +457,36 @@ 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 "
|
fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)",
|
||||||
"ROM0 or ROMX)", pCurrentSection->pzName);
|
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.
|
|
||||||
*/
|
|
||||||
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");
|
* 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 real check must be done at the linking stage.
|
||||||
|
*/
|
||||||
|
fatalerror("Section '%s' is too big (max size = 0x%X bytes).",
|
||||||
|
pCurrentSection->pzName, maxsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write an objectfile
|
* Write an objectfile
|
||||||
@@ -580,10 +593,15 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG align
|
|||||||
pSect->charmap = NULL;
|
pSect->charmap = NULL;
|
||||||
pPatchSymbols = NULL;
|
pPatchSymbols = NULL;
|
||||||
|
|
||||||
if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) {
|
pSect->tData = NULL;
|
||||||
return (pSect);
|
if (secttype == SECT_ROM0 || secttype == SECT_ROMX) {
|
||||||
} else
|
/* It is only needed to allocate memory for ROM
|
||||||
|
* sections. */
|
||||||
|
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);
|
||||||
} else
|
} else
|
||||||
fatalerror("Not enough memory for sectionname");
|
fatalerror("Not enough memory for sectionname");
|
||||||
} else
|
} else
|
||||||
@@ -641,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;
|
||||||
@@ -654,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++);
|
||||||
}
|
}
|
||||||
@@ -666,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);
|
||||||
}
|
}
|
||||||
@@ -684,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++);
|
||||||
}
|
}
|
||||||
@@ -697,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;
|
||||||
@@ -718,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;
|
||||||
@@ -738,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) {
|
||||||
@@ -760,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;
|
||||||
@@ -781,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) {
|
||||||
@@ -807,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");
|
||||||
@@ -835,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;
|
||||||
@@ -879,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;
|
||||||
|
|||||||
@@ -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)) {
|
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
|
||||||
/*
|
/*
|
||||||
* These sectiontypes contain data...
|
* These sectiontypes contain data...
|
||||||
|
|||||||
Reference in New Issue
Block a user