diff options
author | Alistair Delva <adelva@google.com> | 2021-10-20 21:31:32 +0000 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-11-15 14:33:32 -0500 |
commit | 9d3d981661000d8496d3b7836f3bd55d6534dd05 (patch) | |
tree | f95003c3e313616247ed7d0b3036264d091e9b85 /tools/relocate-rela.c | |
parent | 9272805139a104c83dff8230e03e9626dd9bc195 (diff) | |
download | u-boot-9d3d981661000d8496d3b7836f3bd55d6534dd05.zip u-boot-9d3d981661000d8496d3b7836f3bd55d6534dd05.tar.gz u-boot-9d3d981661000d8496d3b7836f3bd55d6534dd05.tar.bz2 |
arm64: relocate-rela: Add support for ld.lld
Cap end of relocations by the binary size.
Linkers like to insert some auxiliary sections between .rela.dyn and
.bss_start. These sections don't make their way to the final binary, but
reloc_rela still tries to relocate them, resulting in attempted read
past the end of file.
When linking U-Boot with ld.lld, the STATIC_RELA feature (enabled by
default on arm64) breaks the build. After this patch, U-Boot can be
linked successfully with and without CONFIG_STATIC_RELA.
Originally-from: Elena Petrova <lenaptr@google.com>
Signed-off-by: Alistair Delva <adelva@google.com>
Cc: David Brazdil <dbrazdil@google.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'tools/relocate-rela.c')
-rw-r--r-- | tools/relocate-rela.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index 6a52401..f0bc548 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -63,7 +63,7 @@ int main(int argc, char **argv) { FILE *f; int i, num; - uint64_t rela_start, rela_end, text_base; + uint64_t rela_start, rela_end, text_base, file_size; if (argc != 5) { fprintf(stderr, "Statically apply ELF rela relocations\n"); @@ -87,8 +87,7 @@ int main(int argc, char **argv) return 3; } - if (rela_start > rela_end || rela_start < text_base || - (rela_end - rela_start) % sizeof(Elf64_Rela)) { + if (rela_start > rela_end || rela_start < text_base) { fprintf(stderr, "%s: bad rela bounds\n", argv[0]); return 3; } @@ -96,6 +95,21 @@ int main(int argc, char **argv) rela_start -= text_base; rela_end -= text_base; + fseek(f, 0, SEEK_END); + file_size = ftell(f); + rewind(f); + + if (rela_end > file_size) { + // Most likely compiler inserted some section that didn't get + // objcopy-ed into the final binary + rela_end = file_size; + } + + if ((rela_end - rela_start) % sizeof(Elf64_Rela)) { + fprintf(stderr, "%s: rela size isn't a multiple of Elf64_Rela\n", argv[0]); + return 3; + } + num = (rela_end - rela_start) / sizeof(Elf64_Rela); for (i = 0; i < num; i++) { |