On Sat, Dec 14, 2013 at 9:17 AM, <feng...@phytium.com.cn> wrote: > From: Scott Wood <scottw...@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 <scottw...@freescale.com> > Signed-off-by: David Feng <feng...@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.t...@gmail.com, P: +91-9676773388 Engineer - System Software Hacker U-boot - SPI Custodian and Zynq APSOC Ln: http://www.linkedin.com/in/jaganteki _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot