mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
rgblink identifies patches' PC sections after reading all sections
Fixes #794
This commit is contained in:
@@ -261,7 +261,7 @@ static void readSymbol(FILE *file, struct Symbol *symbol,
|
|||||||
* @param i The number of the patch to report in errors
|
* @param i The number of the patch to report in errors
|
||||||
*/
|
*/
|
||||||
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName,
|
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName,
|
||||||
uint32_t i, struct Section *fileSections[], struct FileStackNode fileNodes[])
|
uint32_t i, struct FileStackNode fileNodes[])
|
||||||
{
|
{
|
||||||
uint32_t nodeID;
|
uint32_t nodeID;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -279,8 +279,6 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, cha
|
|||||||
tryReadlong(patch->pcSectionID, file,
|
tryReadlong(patch->pcSectionID, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
patch->pcSection = patch->pcSectionID == (uint32_t)-1 ? NULL
|
|
||||||
: fileSections[patch->pcSectionID];
|
|
||||||
tryReadlong(patch->pcOffset, file,
|
tryReadlong(patch->pcOffset, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s PC offset: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
@@ -305,6 +303,16 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, cha
|
|||||||
feof(file) ? "Unexpected end of file" : strerror(errno));
|
feof(file) ? "Unexpected end of file" : strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a patch's pcSection from its pcSectionID.
|
||||||
|
* @param patch The struct to fix
|
||||||
|
*/
|
||||||
|
static void linkPatchToPCSect(struct Patch *patch, struct Section *fileSections[])
|
||||||
|
{
|
||||||
|
patch->pcSection = patch->pcSectionID == (uint32_t)-1 ? NULL
|
||||||
|
: fileSections[patch->pcSectionID];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a section from a file.
|
* Reads a section from a file.
|
||||||
* @param file The file to read from
|
* @param file The file to read from
|
||||||
@@ -312,7 +320,7 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, cha
|
|||||||
* @param fileName The filename to report in errors
|
* @param fileName The filename to report in errors
|
||||||
*/
|
*/
|
||||||
static void readSection(FILE *file, struct Section *section, char const *fileName,
|
static void readSection(FILE *file, struct Section *section, char const *fileName,
|
||||||
struct Section *fileSections[], struct FileStackNode fileNodes[])
|
struct FileStackNode fileNodes[])
|
||||||
{
|
{
|
||||||
int32_t tmp;
|
int32_t tmp;
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
@@ -389,12 +397,9 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
malloc(sizeof(*patches) * section->nbPatches + 1);
|
malloc(sizeof(*patches) * section->nbPatches + 1);
|
||||||
|
|
||||||
if (!patches)
|
if (!patches)
|
||||||
err(1, "%s: Unable to read \"%s\"'s patches", fileName,
|
err(1, "%s: Unable to read \"%s\"'s patches", fileName, section->name);
|
||||||
section->name);
|
for (uint32_t i = 0; i < section->nbPatches; i++)
|
||||||
for (uint32_t i = 0; i < section->nbPatches; i++) {
|
readPatch(file, &patches[i], fileName, section->name, i, fileNodes);
|
||||||
readPatch(file, &patches[i], fileName, section->name,
|
|
||||||
i, fileSections, fileNodes);
|
|
||||||
}
|
|
||||||
section->patches = patches;
|
section->patches = patches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -436,13 +441,13 @@ static void linkSymToSect(struct Symbol const *symbol, struct Section *section)
|
|||||||
*/
|
*/
|
||||||
static void readAssertion(FILE *file, struct Assertion *assert,
|
static void readAssertion(FILE *file, struct Assertion *assert,
|
||||||
char const *fileName, uint32_t i,
|
char const *fileName, uint32_t i,
|
||||||
struct Section *fileSections[], struct FileStackNode fileNodes[])
|
struct FileStackNode fileNodes[])
|
||||||
{
|
{
|
||||||
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
||||||
|
|
||||||
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
||||||
|
|
||||||
readPatch(file, &assert->patch, fileName, assertName, 0, fileSections, fileNodes);
|
readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes);
|
||||||
tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s",
|
tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s",
|
||||||
fileName);
|
fileName);
|
||||||
}
|
}
|
||||||
@@ -550,7 +555,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
err(1, "%s: Couldn't create new section", fileName);
|
err(1, "%s: Couldn't create new section", fileName);
|
||||||
|
|
||||||
fileSections[i]->nextu = NULL;
|
fileSections[i]->nextu = NULL;
|
||||||
readSection(file, fileSections[i], fileName, fileSections, nodes[fileID].nodes);
|
readSection(file, fileSections[i], fileName, nodes[fileID].nodes);
|
||||||
fileSections[i]->fileSymbols = fileSymbols;
|
fileSections[i]->fileSymbols = fileSymbols;
|
||||||
if (nbSymPerSect[i]) {
|
if (nbSymPerSect[i]) {
|
||||||
fileSections[i]->symbols = malloc(nbSymPerSect[i]
|
fileSections[i]->symbols = malloc(nbSymPerSect[i]
|
||||||
@@ -568,7 +573,15 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
|
|
||||||
free(nbSymPerSect);
|
free(nbSymPerSect);
|
||||||
|
|
||||||
/* Give symbols pointers to their sections */
|
/* Give patches' PC section pointers to their sections */
|
||||||
|
for (uint32_t i = 0; i < nbSections; i++) {
|
||||||
|
if (sect_HasData(fileSections[i]->type)) {
|
||||||
|
for (uint32_t j = 0; j < fileSections[i]->nbPatches; j++)
|
||||||
|
linkPatchToPCSect(&fileSections[i]->patches[j], fileSections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give symbols' section pointers to their sections */
|
||||||
for (uint32_t i = 0; i < nbSymbols; i++) {
|
for (uint32_t i = 0; i < nbSymbols; i++) {
|
||||||
int32_t sectionID = fileSymbols[i]->sectionID;
|
int32_t sectionID = fileSymbols[i]->sectionID;
|
||||||
|
|
||||||
@@ -600,7 +613,8 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
|
|
||||||
if (!assertion)
|
if (!assertion)
|
||||||
err(1, "%s: Couldn't create new assertion", fileName);
|
err(1, "%s: Couldn't create new assertion", fileName);
|
||||||
readAssertion(file, assertion, fileName, i, fileSections, nodes[fileID].nodes);
|
readAssertion(file, assertion, fileName, i, nodes[fileID].nodes);
|
||||||
|
linkPatchToPCSect(&assertion->patch, fileSections);
|
||||||
assertion->fileSymbols = fileSymbols;
|
assertion->fileSymbols = fileSymbols;
|
||||||
assertion->next = assertions;
|
assertion->next = assertions;
|
||||||
assertions = assertion;
|
assertions = assertion;
|
||||||
|
|||||||
12
test/link/load-fragment-jr.asm
Normal file
12
test/link/load-fragment-jr.asm
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
SECTION "main", ROM0
|
||||||
|
LOAD FRAGMENT "test", SRAM
|
||||||
|
ENDL
|
||||||
|
|
||||||
|
; The RPN patch for 'jr Label' in section "alt" refers to section "test",
|
||||||
|
; but the object file puts section "test" after section "alt".
|
||||||
|
; This case needs to be handled when identifying patches' PC sections.
|
||||||
|
SECTION "alt", ROM0
|
||||||
|
LOAD FRAGMENT "test", SRAM
|
||||||
|
jr Label
|
||||||
|
Label:
|
||||||
|
ENDL
|
||||||
0
test/link/load-fragment-jr.out
Normal file
0
test/link/load-fragment-jr.out
Normal file
BIN
test/link/load-fragment-jr.out.bin
Normal file
BIN
test/link/load-fragment-jr.out.bin
Normal file
Binary file not shown.
@@ -39,7 +39,7 @@ tryCmp () {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
rgblink() {
|
rgblinkQuiet () {
|
||||||
out="$(env $RGBLINK "$@")" || return $?
|
out="$(env $RGBLINK "$@")" || return $?
|
||||||
if [[ -n "$out" ]]; then
|
if [[ -n "$out" ]]; then
|
||||||
echo "$bold${red}Linking shouldn't produce anything on stdout!$rescolors$resbold"
|
echo "$bold${red}Linking shouldn't produce anything on stdout!$rescolors$resbold"
|
||||||
@@ -55,13 +55,13 @@ for i in *.asm; do
|
|||||||
ran_flag=
|
ran_flag=
|
||||||
for flag in '-d' '-t' '-w'; do
|
for flag in '-d' '-t' '-w'; do
|
||||||
if [ -f ${i%.asm}-no${flag}.out ]; then
|
if [ -f ${i%.asm}-no${flag}.out ]; then
|
||||||
rgblink -o $gbtemp $otemp > $outtemp 2>&1
|
rgblinkQuiet -o $gbtemp $otemp > $outtemp 2>&1
|
||||||
tryDiff ${i%.asm}-no${flag}.out $outtemp
|
tryDiff ${i%.asm}-no${flag}.out $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
ran_flag=1
|
ran_flag=1
|
||||||
fi
|
fi
|
||||||
if [ -f ${i%.asm}${flag}.out ]; then
|
if [ -f ${i%.asm}${flag}.out ]; then
|
||||||
rgblink ${flag} -o $gbtemp $otemp > $outtemp 2>&1
|
rgblinkQuiet ${flag} -o $gbtemp $otemp > $outtemp 2>&1
|
||||||
tryDiff ${i%.asm}${flag}.out $outtemp
|
tryDiff ${i%.asm}${flag}.out $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
ran_flag=1
|
ran_flag=1
|
||||||
@@ -73,7 +73,7 @@ for i in *.asm; do
|
|||||||
|
|
||||||
# Other tests have several linker scripts
|
# Other tests have several linker scripts
|
||||||
find . -name "${i%.asm}*.link" | while read script; do
|
find . -name "${i%.asm}*.link" | while read script; do
|
||||||
rgblink -l $script -o $gbtemp $otemp > $outtemp 2>&1
|
rgblinkQuiet -l $script -o $gbtemp $otemp > $outtemp 2>&1
|
||||||
tryDiff ${script%.link}.out $outtemp
|
tryDiff ${script%.link}.out $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
ran_flag=1
|
ran_flag=1
|
||||||
@@ -83,7 +83,7 @@ for i in *.asm; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# The rest of the tests just links a file, and maybe checks the binary
|
# The rest of the tests just links a file, and maybe checks the binary
|
||||||
rgblink -o $gbtemp $otemp > $outtemp 2>&1
|
rgblinkQuiet -o $gbtemp $otemp > $outtemp 2>&1
|
||||||
if [ -f ${i%.asm}.out ]; then
|
if [ -f ${i%.asm}.out ]; then
|
||||||
tryDiff ${i%.asm}.out $outtemp
|
tryDiff ${i%.asm}.out $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
@@ -103,7 +103,7 @@ i="bank-const.asm"
|
|||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp bank-const/a.asm
|
$RGBASM -o $otemp bank-const/a.asm
|
||||||
$RGBASM -o $gbtemp2 bank-const/b.asm
|
$RGBASM -o $gbtemp2 bank-const/b.asm
|
||||||
rgblink -o $gbtemp $gbtemp2 $otemp > $outtemp 2>&1
|
rgblinkQuiet -o $gbtemp $gbtemp2 $otemp > $outtemp 2>&1
|
||||||
tryDiff bank-const/out.err $outtemp
|
tryDiff bank-const/out.err $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ for i in fragment-align/*; do
|
|||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp $i/a.asm
|
$RGBASM -o $otemp $i/a.asm
|
||||||
$RGBASM -o $gbtemp2 $i/b.asm
|
$RGBASM -o $gbtemp2 $i/b.asm
|
||||||
rgblink -o $gbtemp $otemp $gbtemp2 2>$outtemp
|
rgblinkQuiet -o $gbtemp $otemp $gbtemp2 2>$outtemp
|
||||||
tryDiff $i/out.err $outtemp
|
tryDiff $i/out.err $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
if [[ -f $i/out.gb ]]; then
|
if [[ -f $i/out.gb ]]; then
|
||||||
@@ -124,16 +124,16 @@ done
|
|||||||
i="high-low.asm"
|
i="high-low.asm"
|
||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp high-low/a.asm
|
$RGBASM -o $otemp high-low/a.asm
|
||||||
rgblink -o $gbtemp $otemp
|
rgblinkQuiet -o $gbtemp $otemp
|
||||||
$RGBASM -o $otemp high-low/b.asm
|
$RGBASM -o $otemp high-low/b.asm
|
||||||
rgblink -o $gbtemp2 $otemp
|
rgblinkQuiet -o $gbtemp2 $otemp
|
||||||
tryCmp $gbtemp $gbtemp2
|
tryCmp $gbtemp $gbtemp2
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
|
|
||||||
i="overlay.asm"
|
i="overlay.asm"
|
||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp overlay/a.asm
|
$RGBASM -o $otemp overlay/a.asm
|
||||||
rgblink -o $gbtemp -t -O overlay/overlay.gb $otemp > $outtemp 2>&1
|
rgblinkQuiet -o $gbtemp -t -O overlay/overlay.gb $otemp > $outtemp 2>&1
|
||||||
# This test does not trim its output with 'dd' because it needs to verify the correct output size
|
# This test does not trim its output with 'dd' because it needs to verify the correct output size
|
||||||
tryDiff overlay/out.err $outtemp
|
tryDiff overlay/out.err $outtemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
@@ -144,7 +144,7 @@ i="section-union/good.asm"
|
|||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp section-union/good/a.asm
|
$RGBASM -o $otemp section-union/good/a.asm
|
||||||
$RGBASM -o $gbtemp2 section-union/good/b.asm
|
$RGBASM -o $gbtemp2 section-union/good/b.asm
|
||||||
rgblink -o $gbtemp -l section-union/good/script.link $otemp $gbtemp2
|
rgblinkQuiet -o $gbtemp -l section-union/good/script.link $otemp $gbtemp2
|
||||||
dd if=$gbtemp count=1 bs=$(printf %s $(wc -c < section-union/good/ref.out.bin)) > $otemp 2>/dev/null
|
dd if=$gbtemp count=1 bs=$(printf %s $(wc -c < section-union/good/ref.out.bin)) > $otemp 2>/dev/null
|
||||||
tryCmp section-union/good/ref.out.bin $otemp
|
tryCmp section-union/good/ref.out.bin $otemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
@@ -153,7 +153,7 @@ i="section-union/fragments.asm"
|
|||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp section-union/fragments/a.asm
|
$RGBASM -o $otemp section-union/fragments/a.asm
|
||||||
$RGBASM -o $gbtemp2 section-union/fragments/b.asm
|
$RGBASM -o $gbtemp2 section-union/fragments/b.asm
|
||||||
rgblink -o $gbtemp $otemp $gbtemp2
|
rgblinkQuiet -o $gbtemp $otemp $gbtemp2
|
||||||
dd if=$gbtemp count=1 bs=$(printf %s $(wc -c < section-union/fragments/ref.out.bin)) > $otemp 2>/dev/null
|
dd if=$gbtemp count=1 bs=$(printf %s $(wc -c < section-union/fragments/ref.out.bin)) > $otemp 2>/dev/null
|
||||||
tryCmp section-union/fragments/ref.out.bin $otemp
|
tryCmp section-union/fragments/ref.out.bin $otemp
|
||||||
rc=$(($? || $rc))
|
rc=$(($? || $rc))
|
||||||
@@ -162,7 +162,7 @@ for i in section-union/*.asm; do
|
|||||||
startTest
|
startTest
|
||||||
$RGBASM -o $otemp $i
|
$RGBASM -o $otemp $i
|
||||||
$RGBASM -o $gbtemp2 $i -DSECOND
|
$RGBASM -o $gbtemp2 $i -DSECOND
|
||||||
if rgblink $otemp $gbtemp2 2>$outtemp; then
|
if rgblinkQuiet $otemp $gbtemp2 2>$outtemp; then
|
||||||
echo -e "${bold}${red}$i didn't fail to link!${rescolors}${resbold}"
|
echo -e "${bold}${red}$i didn't fail to link!${rescolors}${resbold}"
|
||||||
rc=1
|
rc=1
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user