[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