diff options
author | Olivier Deprez <olivier.deprez@arm.com> | 2020-03-06 17:17:56 +0100 |
---|---|---|
committer | Olivier Deprez <olivier.deprez@arm.com> | 2020-03-23 10:19:59 +0100 |
commit | 1d2b88d430aa98961865f8be296a1b61b9ce0813 (patch) | |
tree | c3586961194fd2b0334787f6eed4abe997935c65 | |
parent | 231115da2736e7e36627a02497815f33f022cc57 (diff) | |
download | tf-a-tests-1d2b88d430aa98961865f8be296a1b61b9ce0813.tar.gz |
cactus: add symbols relocation fixup
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: Ibde8aadecf6ae6c320d01ee2acab9c3c8db3859d
-rw-r--r-- | lib/aarch64/misc_helpers.S | 115 | ||||
-rw-r--r-- | spm/cactus/aarch64/cactus_entrypoint.S | 10 | ||||
-rw-r--r-- | spm/cactus/cactus.ld.S | 25 |
3 files changed, 147 insertions, 3 deletions
diff --git a/lib/aarch64/misc_helpers.S b/lib/aarch64/misc_helpers.S index 7c9da92af..b67772152 100644 --- a/lib/aarch64/misc_helpers.S +++ b/lib/aarch64/misc_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,7 @@ #include <arch.h> #include <asm_macros.S> #include <assert_macros.S> +#include <lib/xlat_tables/xlat_tables_defs.h> .globl smc @@ -110,3 +111,115 @@ endfunc disable_mmu_icache /* Need this label for asm_read/write_sctlr_el1_or_el2 */ dead: b dead + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Offset table (GOT) and dynamic relocations + * (.rela.dyn) at runtime. + * + * This function is meant to be used when the firmware is compiled with -fpie + * and linked with -pie options. We rely on the linker script exporting + * appropriate markers for start and end of the section. For GOT, we + * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect + * __RELA_START__ and __RELA_END__. + * + * The function takes the limits of the memory to apply fixups to as + * arguments (which is usually the limits of the relocable BL image). + * x0 - the start of the fixup region + * x1 - the limit of the fixup region + * These addresses have to be page (4KB aligned). + * --------------------------------------------------------------------------- + */ +.globl fixup_gdt_reloc +func fixup_gdt_reloc + mov x6, x0 + mov x7, x1 + + /* Test if the limits are 4K aligned */ +#if ENABLE_ASSERTIONS + orr x0, x0, x1 + tst x0, #(PAGE_SIZE - 1) + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in x30. + * Assume that this function is called within a page at the start of + * fixup region. + */ + and x2, x30, #~(PAGE_SIZE - 1) + sub x0, x2, x6 /* Diff(S) = Current Address - Compiled Address */ + + adrp x1, __GOT_START__ + add x1, x1, :lo12:__GOT_START__ + adrp x2, __GOT_END__ + add x2, x2, :lo12:__GOT_END__ + + /* + * GOT is an array of 64_bit addresses which must be fixed up as + * new_addr = old_addr + Diff(S). + * The new_addr is the address currently the binary is executing from + * and old_addr is the address at compile time. + */ +1: + ldr x3, [x1] + /* Skip adding offset if address is < lower limit */ + cmp x3, x6 + b.lo 2f + /* Skip adding offset if address is >= upper limit */ + cmp x3, x7 + b.ge 2f + add x3, x3, x0 + str x3, [x1] +2: + add x1, x1, #8 + cmp x1, x2 + b.lo 1b + + /* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */ + adrp x1, __RELA_START__ + add x1, x1, :lo12:__RELA_START__ + adrp x2, __RELA_END__ + add x2, x2, :lo12:__RELA_END__ + /* + * According to ELF-64 specification, the RELA data structure is as + * follows: + * typedef struct + * { + * Elf64_Addr r_offset; + * Elf64_Xword r_info; + * Elf64_Sxword r_addend; + * } Elf64_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * 0x403 which corresponds to R_AARCH64_RELATIVE). + * r_addend is constant part of expression. + * + * Size of Elf64_Rela structure is 24 bytes. + */ +1: + /* Assert that the relocation type is R_AARCH64_RELATIVE */ +#if ENABLE_ASSERTIONS + ldr x3, [x1, #8] + cmp x3, #0x403 + ASM_ASSERT(eq) +#endif + ldr x3, [x1] /* r_offset */ + add x3, x0, x3 + ldr x4, [x1, #16] /* r_addend */ + + /* Skip adding offset if r_addend is < lower limit */ + cmp x4, x6 + b.lo 2f + /* Skip adding offset if r_addend entry is >= upper limit */ + cmp x4, x7 + b.ge 2f + + add x4, x0, x4 /* Diff(S) + r_addend */ + str x4, [x3] + +2: add x1, x1, #24 + cmp x1, x2 + b.lo 1b + + ret +endfunc fixup_gdt_reloc diff --git a/spm/cactus/aarch64/cactus_entrypoint.S b/spm/cactus/aarch64/cactus_entrypoint.S index 7d6b6b26e..4fe17e343 100644 --- a/spm/cactus/aarch64/cactus_entrypoint.S +++ b/spm/cactus/aarch64/cactus_entrypoint.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, Arm Limited. All rights reserved. + * Copyright (c) 2017-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -27,6 +27,14 @@ func cactus_entrypoint msr sctlr_el1, x0 isb + /* Relocate symbols */ +pie_fixup: + ldr x0, =pie_fixup + and x0, x0, #~(0x1000 - 1) + mov x1, #CACTUS_IMAGE_SIZE + add x1, x1, x0 + bl fixup_gdt_reloc + /* And jump to the C entrypoint. */ b cactus_main diff --git a/spm/cactus/cactus.ld.S b/spm/cactus/cactus.ld.S index a3d8e65d0..30ad0da7b 100644 --- a/spm/cactus/cactus.ld.S +++ b/spm/cactus/cactus.ld.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, Arm Limited. All rights reserved. + * Copyright (c) 2017-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -32,8 +32,20 @@ SECTIONS . = ALIGN(PAGE_SIZE); __RODATA_START__ = .; *(.rodata*) + + /* + * Keep the .got section in the RO section as it is patched + * prior to enabling the MMU and having the .got in RO is better for + * security. GOT is a table of addresses so ensure 8-byte alignment. + */ + . = ALIGN(8); + __GOT_START__ = .; + *(.got) + __GOT_END__ = .; + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; + } .data : { @@ -44,6 +56,17 @@ SECTIONS __DATA_END__ = .; } + /* + * .rela.dyn needs to come after .data for the read-elf utility to parse + * this section correctly. Ensure 8-byte alignment so that the fields of + * RELA data structure are aligned. + */ + . = ALIGN(8); + __RELA_START__ = .; + .rela.dyn . : { + } + __RELA_END__ = .; + .bss (NOLOAD) : { . = ALIGN(PAGE_SIZE); __BSS_START__ = .; |