splat icon indicating copy to clipboard operation
splat copied to clipboard

Option for generating linker script that forces matching object section addresses?

Open zZeck opened this issue 8 months ago • 0 comments

Is there any interest in a feature like this? I hacked together a change that does this unconditionally. Not sure what a good splat.yaml interface would be.

I wanted to be able to easily compare built roms and original roms without having everything shifted if one function was smaller than expected. I wanted to link in replacement functions, as long as they were equal to or smaller than the original in size. I wanted a warning if the replacement was larger.

LD's location counter "." is a relative offset in an output section. By manipulating it before each object file section is placed, we can guarantee the object section's position. Take the desired ROM position for an object file's section, and subtract from it the ROM start for the containing output section. Set the location counter to that. (I need to do more to make this work with NOLOAD sections, mainly for bss. Those sections do not have a ROM offset provided in splat.yaml, but instead a VRAM address, naturally).

An example of what my change generates:

Corresponding to:

  - name: main
    type: code
    start: 0x1000
    vram: 0x8003AD80
    subsegments:
      - [0x1000, asm]
      - [0x3E40, asm]
      - [0x4460, asm]
      - [0x6780, asm]

It produces:

   main_VRAM = ADDR(.main);
    .main 0x8003AD80 : AT(main_ROM_START) SUBALIGN(0)
    {
        FILL(0x00000000);
        main_TEXT_START = .;
        
        /*REMEMBER "." is an offset relative to start of output section (.main here).
        0x1000 - 0x1000 is 0, which is correct for the first entry. It should be right at the start of this containing output section*/
        . = 0x1000 - 0x1000;  
        build/asm/1000.s.o(.text);
        
        /*NEXT ENTRY needs to be at 0x3e40 in final.
        The output section already starts us at 0x1000 in final, and "." is an offset relative to output section start, so subtract 0x1000.
        So we will be at .main LMA 0x1000 + 0x2e40 .main relative offset = 0x3e40 in the final ROM.*/
        . = 0x3e40 - 0x1000; 
        build/asm/3E40.s.o(.text);
       
        . = 0x4460 - 0x1000;
        build/asm/4460.s.o(.text);
        . = 0x6780 - 0x1000;
        build/asm/6780.s.o(.text);

Makes it easy to compare roms in something like ImHex. You just see groups of differences instead of the entire file being off past one screw up. image

If there is interest, I will try to clean this up somehow. Suggestions? Did I miss an existing option that can do this? Is this useful more widely? Seems useful for enabling modding earlier in a project, or for keeping best effort non-matching C re-implementations around so long as the code generated was smaller than the original. I might be crazy though.

zZeck avatar May 28 '24 05:05 zZeck