[U-Boot] [PATCH v16 04/10] arm64: Add tool to statically apply RELA relocations
Jagan Teki
jagannadh.teki at gmail.com
Sat Dec 14 06:09:06 CET 2013
On Sat, Dec 14, 2013 at 9:17 AM, <fenghua at phytium.com.cn> wrote:
> From: Scott Wood <scottwood at freescale.com>
>
> ARM64 uses the newer RELA-style relocations rather than the older REL.
> RELA relocations have an addend in the relocation struct, rather than
> expecting the loader to read a value from the location to be updated.
>
> While this is beneficial for ordinary program loading, it's problematic
> for U-Boot because the location to be updated starts out with zero,
> rather than a pre-relocation value. Since we need to be able to run C
> code before relocation, we need a tool to apply the relocations at
> build time.
>
> In theory this tool is applicable to other newer architectures (mainly
> 64-bit), but currently the only relocations it supports are for arm64,
> and it assumes a 64-bit little-endian target. If the latter limitation
> is ever to be changed, we'll need a way to tell the tool what format
> the image is in. Eventually this may be replaced by a tool that uses
> libelf or similar and operates directly on the ELF file. I've written
> some code for such an approach but libelf does not make it easy to poke
> addresses by memory address (rather than by section), and I was
> hesitant to write code to manually parse the program headers and do the
> update outside of libelf (or to iterate over sections) -- especially
> since it wouldn't get test coverage on things like binaries with
> multiple PT_LOAD segments. This should be good enough for now to let
> the manual relocation stuff be removed from the arm64 patches.
>
> Signed-off-by: Scott Wood <scottwood at freescale.com>
> Signed-off-by: David Feng <fenghua at phytium.com.cn>
> ---
> Makefile | 12 ++++
> tools/Makefile | 6 ++
> tools/relocate-rela.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 207 insertions(+)
> create mode 100644 tools/relocate-rela.c
>
> diff --git a/Makefile b/Makefile
> index 7310c4e..4a8e8c5 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -334,6 +334,17 @@ else
> BOARD_SIZE_CHECK =
> endif
>
> +# Statically apply RELA-style relocations (currently arm64 only)
> +ifneq ($(CONFIG_STATIC_RELA),)
> +# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base
> +DO_STATIC_RELA = \
> + start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \
> + end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \
> + $(obj)tools/relocate-rela $(2) $(3) $$start $$end
> +else
> +DO_STATIC_RELA =
> +endif
> +
> # Always append ALL so that arch config.mk's can add custom ones
> ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
>
> @@ -376,6 +387,7 @@ $(obj)u-boot.srec: $(obj)u-boot
>
> $(obj)u-boot.bin: $(obj)u-boot
> $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
> + $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE))
> $(BOARD_SIZE_CHECK)
>
> $(obj)u-boot.ldr: $(obj)u-boot
> diff --git a/tools/Makefile b/tools/Makefile
> index 14d94e3..6d40398 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -59,6 +59,7 @@ BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
> BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
> BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
> BIN_FILES-y += proftool(SFX)
> +BIN_FILES-$(CONFIG_STATIC_RELA) += relocate-rela$(SFX)
>
> # Source files which exist outside the tools directory
> EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
> @@ -84,6 +85,7 @@ NOPED_OBJ_FILES-y += os_support.o
> NOPED_OBJ_FILES-y += pblimage.o
> NOPED_OBJ_FILES-y += proftool.o
> NOPED_OBJ_FILES-y += ublimage.o
> +NOPED_OBJ_FILES-y += relocate-rela.o
> OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o
> OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o
> OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o
> @@ -250,6 +252,10 @@ $(obj)kwboot$(SFX): $(obj)kwboot.o
> $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
> $(HOSTSTRIP) $@
>
> +$(obj)relocate-rela$(SFX): $(obj)relocate-rela.o
> + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
> + $(HOSTSTRIP) $@
> +
> # Some of the tool objects need to be accessed from outside the tools directory
> $(obj)%.o: $(SRCTREE)/common/%.c
> $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
> diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c
> new file mode 100644
> index 0000000..93b4c39
> --- /dev/null
> +++ b/tools/relocate-rela.c
> @@ -0,0 +1,189 @@
> +/*
> + * Copyright 2013 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
> + *
> + * 64-bit and little-endian target only until we need to support a different
> + * arch that needs this.
> + */
> +
> +#include <elf.h>
> +#include <errno.h>
> +#include <inttypes.h>
> +#include <stdarg.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#ifndef R_AARCH64_RELATIVE
> +#define R_AARCH64_RELATIVE 1027
> +#endif
> +
> +static const bool debug_en;
> +
> +static void debug(const char *fmt, ...)
> +{
> + va_list args;
> +
> + va_start(args, fmt);
> + if (debug_en)
> + vprintf(fmt, args);
> +}
> +
> +static bool supported_rela(Elf64_Rela *rela)
> +{
> + uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */
> + uint32_t type = rela->r_info & mask;
> +
> + switch (type) {
> +#ifdef R_AARCH64_RELATIVE
> + case R_AARCH64_RELATIVE:
> + return true;
> +#endif
> + default:
> + fprintf(stderr, "warning: unsupported relocation type %"
> + PRIu32 " at %" PRIx64 "\n",
> + type, rela->r_offset);
> +
> + return false;
> + }
> +}
> +
> +static inline uint64_t swap64(uint64_t val)
> +{
> + return ((val >> 56) & 0x00000000000000ffULL) |
> + ((val >> 40) & 0x000000000000ff00ULL) |
> + ((val >> 24) & 0x0000000000ff0000ULL) |
> + ((val >> 8) & 0x00000000ff000000ULL) |
> + ((val << 8) & 0x000000ff00000000ULL) |
> + ((val << 24) & 0x0000ff0000000000ULL) |
> + ((val << 40) & 0x00ff000000000000ULL) |
> + ((val << 56) & 0xff00000000000000ULL);
> +}
> +
> +#if __BYTE_ORDER == __LITTLE_ENDIAN
> +static inline uint64_t be64(uint64_t val)
> +{
> + return swap64(val);
> +}
> +
> +static inline uint64_t le64(uint64_t val)
> +{
> + return val;
> +}
> +#else
> +static inline uint64_t le64(uint64_t val)
> +{
> + return swap64(val);
> +}
> +
> +static inline uint64_t be64(uint64_t val)
> +{
> + return val;
> +}
> +#endif
> +
> +static bool read_num(const char *str, uint64_t *num)
> +{
> + char *endptr;
> + *num = strtoull(str, &endptr, 16);
> + return str[0] && !endptr[0];
> +}
> +
> +int main(int argc, char **argv)
> +{
> + FILE *f;
> + int i, num;
> + uint64_t rela_start, rela_end, text_base;
> +
> + if (argc != 5) {
> + fprintf(stderr, "Statically apply ELF rela relocations\n");
> + fprintf(stderr, "Usage: %s <bin file> <text base> " \
> + "<rela start> <rela end>\n", argv[0]);
Try to avoid unnecessary line continuations at fprintf
--
Thanks,
Jagan.
--------
Jagannadha Sutradharudu Teki,
E: jagannadh.teki at gmail.com, P: +91-9676773388
Engineer - System Software Hacker
U-boot - SPI Custodian and Zynq APSOC
Ln: http://www.linkedin.com/in/jaganteki
More information about the U-Boot
mailing list