I have taken a different approach in the
Magic Lantern firmware for the Canon 5D Mark II. Instead of trying to relocate the entire firmware and worrying about finding every code reference, my approach has been to relocate to RAM just the functions that I need to change. Since I am targetting Canon dialog code that is called through a function pointer, my code is able to walk the GUI structures in RAM to find the pointer to the ROM routine and update it there. On the next redraw or event cycle the relocated code will be called instead and can execute my modified instructions.
reloc.c has the routines that do the copy and instruction fixup. The only instructions that are currently fixed are:
* B
* BL
* LDR rN, [ pc, off ]
If the B or BL or target of LDR are within the relocating region, they are not touched. Otherwise the offsets are adjusted. If the 12-bit offset of the LDR is out of range the constant value is copied from ROM into RAM in a small block of fixups.
I am detecting, but not fixing up ADD rN, pc, off instructions. For the code that I am currently targetting there are only two references that are out of range, and they related to debugging printf formats so I just NOP out the call to DebugMsg(). My plan is to fix these automatically in a newer version of the code by reserving a fixup space at the end of the allocated buffer as well.
The first proof of concept is to rewrite the portion of the DlgLiveViewApp() function that switches from 1080i HD to 480p on the HDMI port when recording is started. I have a video showing this in action: