First let me say that for a device with MMU usually you can put your program at any address and then use the MMU to map this address to the address the program is compiled for. So it would be trivial.
Cortex M processors do not have an MMU, so it can't be done this way.
I have not tried this, but theoretically you can do the following, assuming app will be compiled for Primary Area and you want to run it from the Secondary Area
1. Do not initialize any global variables in the declaration. Rather, create a function that will initialize them and call it as soon as main starts.(avoids problem with loading initialized data to RAM)
2. Compile using the -fPIC option (Position Independent Code)
3. Vector table will still point to specific locations. So bootloader will need to calculate offset = (PrimaryArea Address - SecondaryArea Address)
4. Copy Vector table to RAM and add offset to all vectors.
5. Point VTOR to Vectors in RAM
6. Make sure the application's ResetISR will not change VTOR
This might work if function calls only use relative addresses, which may not be the case.