The AArch64 unconditional branch and branch and link instructions have a maximum range of +/- 128 Mib. This is usually enough for most programs but it is possible for very large programs or those with a linker script to exceed this range. This change adds support for range-extension thunks to AArch64.
Implementation Notes:
- I've used Thunks that can access the whole address range. There are more efficient Thunks that can be used, for example the PI thunk could use the usual ADRP addressing mode, but this would limit the range to +/- 4Gb. In an ideal world we could generate the thunks with a limited range only when we know they are in range, but this will require some changes and additional complexity in the underlying framework so I chose to keep it simple.
- The test aarch64-thunk-section-location.s is there to check that Thunks are placed roughly 128 MiB into a large Output Section, this test takes a noticeable amount of time to assemble and link, it may not be worth adding the test.
- I've not got any really large > 128 MiB AArch64 programs to test against. I've checked a small test case (absolute and with --pie) that artificially adds in large amounts of .space to check that the thunks are created and execute at runtime.
References:
- http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf The Base Procedure Call Standard (For use of interprocedural scratch registers X16 and X17)
- http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf (For relocations and information about relocations that can be range extended)
- https://developer.arm.com/products/architecture/a-profile/docs/ddi0487/ba/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile (For descriptions of instructions)