Davidebyzero / GBAGI

A fork of Brian Provinciano's Sierra AGI interpreter for the Game Boy Advance, aiming to fix its bugs
https://web.archive.org/web/20090512184610/http://www.bripro.com:80/gbagi/index.php
11 stars 1 forks source link

Build on Linux, Github Actions, linker errors #2

Open andersnm opened 3 months ago

andersnm commented 3 months ago

Not sure if this is worth it, but did some research into it. Have tried to build with a modern arm cross compiler and found some global changes that needs coordination:

After the above source fixes, it should still build on all targets like before, but fails to link with modern tools. It's possible to force the link, but then produces a binary of ~160kb (GBAGI supports max 128k).

The linker error messages point at issues in lnkscript and crt0.s, presumably they need to support newer compiler features from the last 20 years, and/or workarounds for bugs in the "ld" program that parses the lnkscript. I tried some stuff directly in the repo, but failed and have moved on to testing in a local Debian instead.

These files have a long history and exists in many versions with subtle differences. There appears to be two major branches of the lnkscript and crt0 for GBA, which also leaves two possible ways forward:

Jeff Frohweins versions

The GBAGI repo uses an older version of Jeff Frohweins lnkscript and crt0. Not maintained by the original author anymore, not anywhere centrally at least.

The main benefit of these are they support interrupts, but the drawback is they don't work as-is :). It's almost as if the SIZEOF() function in ld is broken causing overlapping sections when the code goes above a certain size. The original dev also commented on this issue in the version pulled from his site, with commented remnants from different attempts at workarounds for it - tho the problems appear to have worsened over time:

/* The linker script function "var1 += var2;" sometimes    */
/* reports incorrect values in the *.map file but the      */
/* actual value it calculates is usually, if not always,   */
/* correct. If you leave out the ". = ALIGN(4);" at the    */
/* end of each section then the return value of SIZEOF()   */
/* is sometimes incorrect and "var1 += var2;" appears to   */
/* not work as well. "var1 += var2" style functions are    */
/* avoided below as a result.                              */

(Note, the above comment only mentions issues with +=, but my results indicate same issue with plain assignments and adding)

Potential tasks:

DevKitPro's versions

DevKitPro's linkscript is based on but entirely rewritten from Frohweins version, crt0 looks to be completely different, much smaller and no longer supports interrupts. These are still actively maintained.

I've been able to link with the DevKitPro's gba_mb.ld and crt0 (=multiboot lnkscript) without errors, but not tested yet. It looks like interrupts are defered to an external library: https://github.com/devkitPro/libgba

Potential tasks:

andersnm commented 3 months ago

After spending way too much time on this, I can say relatively confidently the original lnkscript fails with overlap errors because it doesn't account for orphaned sections introduced by newer gcc/ld features.

This becomes obvious when linking with -Wl,--orphan-handling=error which prints the orphan sections.

It links successfully when all orphaned sections are dealth with, but the binary still gets too big.

I don't trust my lnkscript changes, it was a good exercise to understand how it works, but I think the best way forward is to vendor the linkscript, crt0 and interrupt code from DevKitPro and their libgba.