I know this question already is answered, but maybe for "the next guy" who tries to achieve the same. I did the following:
1 - disable managed linker script and move the generated linker script
2 - adjust the linker script to your needs
3 - Adjust the startup code so that stuff gets copied over and VTOR pointer points to new location
1 - disable managed linker script and add some extra variables in the linker script
Before you do anything, make sure you compiled your program so that you can steal the generated working linker scripts sitting in the Debug folder of your project.
Then afterwards, right click on project and open properties.

In the same window, adjust the location of the linker script one folder up so that it no longer sits in Debug folder (which gets nuked when you clean the app, and you would loose your changes).

Optionally, you can also merge the three generated linker scripts into one, for me it doesn't add anything to have the linker script scattered over three files. If you choose to leave them separated, you also need to fix the include paths of the 2 included linker scripts.
Then simply drag the linker script (or if you didn't merge, linker scripts) from Debug folder one folder up (in the root of the project).
2 - adjust the linker script to your needs
If you open the linker script in its new location, you'll see the part where stuff gets added to .text.

I preferred to have the vector table in its own section. That's not mandatory of course, so edit as your please. I changed it to the following:
.vector : ALIGN(4)
{
__vector_table_flash_start__ = ADDR(.vector) ;
KEEP(*(.isr_vector))
__vector_table_flash_end__ = ABSOLUTE(.) ;
. = ALIGN(4) ;
} >SRAM_ITC AT>PROGRAM_FLASH
I added this, right after the boot_hdr part.
So what we do here, is we defined some linker variables which will get the address location at the start of the vector tables, and one at the end. Nice would be to also add LOADADDR(.vector) to get the address of the part in ITC memory, but since it's 0x0 anyway I didn't bother.
PS: make sure you properly clean up the KEEP(*(.isr_vector)) from the .text section, since it has no purpose anymore there. The linker won't duplicate the vector, but it's confusing to leave in "dead code".
That's it, off to the start up code
3 - Adjust the startup code so that stuff gets copied over and VTOR pointer points to new location
This looks a bit bloated, but since the ResetHandler (aka ResetISR) is a naked attributed function, I am a bit scared to define variables on the stack. I'm a bit scared to write any code, since i don't exactly know where the limitations lie, but at least the following will do the trick
Define the extern variables, and whatever we need as stack variable, we'll just declare them globally instead.
volatile extern unsigned int __vector_table_flash_start__;
volatile extern unsigned int __vector_table_flash_end__;
unsigned int *vector_table_flash;
unsigned int *vector_table_itc;
unsigned int index;
unsigned int vector_table_size;
And then, inside the ResetISR we set some variables and copy the data from flash to ITC.
//
// Copy vector table to ram
//
vector_table_flash = const_cast<unsigned int*>(&__vector_table_flash_start__);
vector_table_itc = reinterpret_cast<unsigned int*>(0x0);
vector_table_size = static_cast<unsigned int>(&__vector_table_flash_end__ - &__vector_table_flash_start__);
for (index = 0u; index < vector_table_size; ++index)
{
vector_table_itc[index] = vector_table_flash[index];
}
The same code with some existing code to give a better idea where you should make your changes
// Volatile for ease of debugging, stuff tends to get optimized out which is annoying :). We'll nuke the volatile-ness with a const_cast (iewww).
volatile extern unsigned int __vector_table_flash_start__;
volatile extern unsigned int __vector_table_flash_end__;
// Some local variables. Not sure if this has to be global. You could make them static but meh, I didn't really care
unsigned int *vector_table_flash;
unsigned int *vector_table_itc;
unsigned int index;
unsigned int vector_table_size;
extern unsigned int __data_section_table;
extern unsigned int __data_section_table_end;
extern unsigned int __bss_section_table;
extern unsigned int __bss_section_table_end;
//*****************************************************************************
// Reset entry point for your code.
// Sets up a simple runtime environment and initializes the C/C++
// library.
//*****************************************************************************
__attribute__ ((naked, section(".after_vectors.reset")))
void ResetISR(void) {
// Disable interrupts
__asm volatile ("cpsid i");
__asm volatile ("MSR MSP, %0" : : "r" (&_vStackTop) : );
//
// Copy vector table to ram
//
vector_table_flash = const_cast<unsigned int*>(&__vector_table_flash_start__);
vector_table_itc = reinterpret_cast<unsigned int*>(0x0);
vector_table_size = static_cast<unsigned int>(&__vector_table_flash_end__ - &__vector_table_flash_start__);
for (index = 0u; index < vector_table_size; ++index)
{
__asm volatile ("nop");
vector_table_itc[index] = vector_table_flash[index];
}
Almost done... one more thing to do. If you go to the implementation of the SystemInit somewhere half way through the ResetISR function, the IDE will bring you to the generated device/system_MIMXRT_1024.cpp.
In the SystemInit function, the VTOR gets it's final location. Since we just copied the vector table to ITC, we need to set the VTOR to 0x0.
#if defined(__MCUXPRESSO)
//extern uint32_t g_pfnVectors[]; /* Vector table defined in startup code */
//SCB->VTOR = (uint32_t)g_pfnVectors;
SCB->VTOR = (uint32_t)0x0;
#endif
If you now compile, upload and start debugging, you be able to step through startup code, and eventually see the jump to main. Try any peripheral to see if the interrupt handlers still work. I fired up freertos since it relies on a hardware timer.
"It works on my board" .
Hope it helps somebody, some day