We have a multi-app bootloader. The application starts with bootloader.uvprojx and then switches to one of the two applications namely: fw2000 and fw3000. So we have 3 binaries/executables on our controller at following addresses of the flash program/code memory space: bootloader at 0x0, fw2000 at 0x2000 and fw3000 at 0x3000 . fw2000 and fw3000 are the same code but these two app firmwares here are compiled using absolute ROM addresses to create fw2000.bin and fw3000.bin. This is done in Keil by setting the address in "Options for target"->"Target"->"IROM1:" -> "Start" address to respective start address .
We have this architecture to update firmware. For that creating bin/hex specific to absolute address is not desirable.
Is there a way to compile a fwXXXX which can be relocatable at both the addresses? Such that, fwXXXX is compiled and the .bin ot .hex can be written at any address (in this case 0x2000 or 0x3000).
The source level debugger should work if a) the right project file is loaded, and b) it's at the address the linker created it. The disassembly view should work regardless, and should be adequate to diagnose what's happening. Use the .MAP file to navigate if you need too.
I'd augment that with output via USART or SWV channels, and by having an effective Hard Fault handler, and other diagnostics, so I could see what was happening internally.
If you built all your firmware with the assumption they load at zero, then you'd fix up the vector table so that the ODD code address had +0x2000 and +0x3000 added to them respectively if you wrote them at 0x2000 and 0x3000 instead of 0x0000
I'd also walk the code generated by the compiler/linker until I was comfortable that it was actually address independent. Believe me people get very irritated if you commit bad code to a Masked ROM, even if it's the tool chain's fault, they can't fire, shout or throw things at the tools. You learn to understand how the processor and the tools function.