diff --git a/src/include/memlayout.h b/src/include/memlayout.h index bf830b7d24..424a28a20a 100644 --- a/src/include/memlayout.h +++ b/src/include/memlayout.h @@ -31,7 +31,7 @@ #define SYMBOL(name, addr) \ SET_COUNTER(name, addr) \ - _##name = .; + _##name = ABSOLUTE(.); #define REGION(name, addr, size, expected_align) \ SYMBOL(name, addr) \ @@ -40,8 +40,8 @@ SYMBOL(e##name, addr + size) #define ALIAS_REGION(name, alias) \ - _##alias = _##name; \ - _e##alias = _e##name; + _##alias = ABSOLUTE(_##name); \ + _e##alias = ABSOLUTE(_e##name); \ /* Declare according to SRAM/DRAM ranges in SoC hardware-defined address map. */ #define SRAM_START(addr) SYMBOL(sram, addr) @@ -92,7 +92,7 @@ #if ENV_DECOMPRESSOR #define DECOMPRESSOR(addr, sz) \ SYMBOL(decompressor, addr) \ - _edecompressor = _decompressor + sz; \ + _edecompressor = ABSOLUTE(_decompressor + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(decompressor exceeded its allotted size! (sz))); \ INCLUDE "decompressor/lib/program.ld" @@ -112,7 +112,7 @@ #if ENV_BOOTBLOCK #define BOOTBLOCK(addr, sz) \ SYMBOL(bootblock, addr) \ - _ebootblock = _bootblock + sz; \ + _ebootblock = ABSOLUTE(_bootblock + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(Bootblock exceeded its allotted size! (sz))); \ INCLUDE "bootblock/lib/program.ld" @@ -124,7 +124,7 @@ #if ENV_ROMSTAGE #define ROMSTAGE(addr, sz) \ SYMBOL(romstage, addr) \ - _eromstage = _romstage + sz; \ + _eromstage = ABSOLUTE(_romstage + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(Romstage exceeded its allotted size! (sz))); \ INCLUDE "romstage/lib/program.ld" @@ -136,7 +136,7 @@ #if ENV_RAMSTAGE #define RAMSTAGE(addr, sz) \ SYMBOL(ramstage, addr) \ - _eramstage = _ramstage + sz; \ + _eramstage = ABSOLUTE(_ramstage + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(Ramstage exceeded its allotted size! (sz))); \ INCLUDE "ramstage/lib/program.ld" @@ -160,7 +160,7 @@ #if ENV_SEPARATE_VERSTAGE #define VERSTAGE(addr, sz) \ SYMBOL(verstage, addr) \ - _everstage = _verstage + sz; \ + _everstage = ABSOLUTE(_verstage + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(Verstage exceeded its allotted size! (sz))); \ INCLUDE "verstage/lib/program.ld" @@ -179,7 +179,7 @@ #if ENV_POSTCAR #define POSTCAR(addr, sz) \ SYMBOL(postcar, addr) \ - _epostcar = _postcar + sz; \ + _epostcar = ABSOLUTE(_postcar + sz); \ _ = ASSERT(_eprogram - _program <= sz, \ STR(Aftercar exceeded its allotted size! (sz))); \ INCLUDE "postcar/lib/program.ld" diff --git a/tests/Makefile.inc b/tests/Makefile.inc index 56d557879e..a10e9bf73b 100644 --- a/tests/Makefile.inc +++ b/tests/Makefile.inc @@ -48,6 +48,10 @@ TEST_CFLAGS += -I$(cmockasrc)/include TEST_LDFLAGS = -L$(cmockaobj)/src -lcmocka -Wl,-rpath=$(cmockaobj)/src TEST_LDFLAGS += -Wl,--gc-sections +# Some memlayout symbols don't work with userspace relocation -- disable it. +TEST_CFLAGS += -fno-pie -fno-pic +TEST_LDFLAGS += -no-pie + # Extra attributes for unit tests, declared per test attributes:= srcs cflags mocks stage diff --git a/util/cbfstool/rmodule.c b/util/cbfstool/rmodule.c index 429bbf37fb..258a4d8803 100644 --- a/util/cbfstool/rmodule.c +++ b/util/cbfstool/rmodule.c @@ -72,7 +72,7 @@ static int valid_reloc_arm(Elf64_Rela *rel) /* Only these 6 relocations are expected to be found. */ return (type == R_ARM_ABS32 || type == R_ARM_THM_PC22 || - type == R_ARM_THM_JUMP24 || type == R_ARM_V4BX || + type == R_ARM_THM_JUMP24 || type == R_ARM_V4BX || type == R_ARM_CALL || type == R_ARM_JUMP24); } @@ -137,6 +137,19 @@ static const struct arch_ops reloc_ops[] = { }, }; +static int relocation_for_absolute_symbol(struct rmod_context *ctx, Elf64_Rela *r) +{ + Elf64_Sym *s = &ctx->pelf.syms[ELF64_R_SYM(r->r_info)]; + + if (s->st_shndx == SHN_ABS) { + DEBUG("Omitting relocation for absolute symbol: %s\n", + &ctx->strtab[s->st_name]); + return 1; + } + + return 0; +} + /* * Relocation processing loops. */ @@ -172,6 +185,9 @@ static int for_each_reloc(struct rmod_context *ctx, struct reloc_filter *f, return -1; } + if (relocation_for_absolute_symbol(ctx, r)) + continue; + /* Allow the provided filter to have precedence. */ if (f != NULL) { filter_emit = f->filter(f, r); @@ -341,7 +357,7 @@ int rmodule_collect_relocations(struct rmod_context *ctx, static int populate_sym(struct rmod_context *ctx, const char *sym_name, Elf64_Addr *addr, - int nsyms, const char *strtab, int optional) + int nsyms, int optional) { int i; Elf64_Sym *syms; @@ -351,7 +367,7 @@ populate_sym(struct rmod_context *ctx, const char *sym_name, Elf64_Addr *addr, for (i = 0; i < nsyms; i++) { if (syms[i].st_name == 0) continue; - if (strcmp(sym_name, &strtab[syms[i].st_name])) + if (strcmp(sym_name, &ctx->strtab[syms[i].st_name])) continue; DEBUG("%s -> 0x%llx\n", sym_name, (long long)syms[i].st_value); *addr = syms[i].st_value; @@ -371,7 +387,6 @@ populate_sym(struct rmod_context *ctx, const char *sym_name, Elf64_Addr *addr, static int populate_rmodule_info(struct rmod_context *ctx) { int i; - const char *strtab; struct parsed_elf *pelf; Elf64_Ehdr *ehdr; int nsyms; @@ -379,23 +394,6 @@ static int populate_rmodule_info(struct rmod_context *ctx) pelf = &ctx->pelf; ehdr = &pelf->ehdr; - /* Obtain the string table. */ - strtab = NULL; - for (i = 0; i < ehdr->e_shnum; i++) { - if (ctx->pelf.strtabs[i] == NULL) - continue; - /* Don't use the section headers' string table. */ - if (i == ehdr->e_shstrndx) - continue; - strtab = buffer_get(ctx->pelf.strtabs[i]); - break; - } - - if (strtab == NULL) { - ERROR("No string table found.\n"); - return -1; - } - /* Determine number of symbols. */ nsyms = 0; for (i = 0; i < ehdr->e_shnum; i++) { @@ -406,18 +404,16 @@ static int populate_rmodule_info(struct rmod_context *ctx) break; } - if (populate_sym(ctx, "_rmodule_params", &ctx->parameters_begin, - nsyms, strtab, 1)) + if (populate_sym(ctx, "_rmodule_params", &ctx->parameters_begin, nsyms, 1)) return -1; - if (populate_sym(ctx, "_ermodule_params", &ctx->parameters_end, - nsyms, strtab, 1)) + if (populate_sym(ctx, "_ermodule_params", &ctx->parameters_end, nsyms, 1)) return -1; - if (populate_sym(ctx, "_bss", &ctx->bss_begin, nsyms, strtab, 0)) + if (populate_sym(ctx, "_bss", &ctx->bss_begin, nsyms, 0)) return -1; - if (populate_sym(ctx, "_ebss", &ctx->bss_end, nsyms, strtab, 0)) + if (populate_sym(ctx, "_ebss", &ctx->bss_end, nsyms, 0)) return -1; return 0; @@ -425,7 +421,7 @@ static int populate_rmodule_info(struct rmod_context *ctx) static int add_section(struct elf_writer *ew, struct buffer *data, const char *name, - Elf64_Addr addr, Elf64_Word size) + Elf64_Addr addr, Elf64_Word size) { Elf64_Shdr shdr; int ret; @@ -452,7 +448,7 @@ add_section(struct elf_writer *ew, struct buffer *data, const char *name, static int write_elf(const struct rmod_context *ctx, const struct buffer *in, - struct buffer *out) + struct buffer *out) { int ret; int bit64; @@ -658,6 +654,22 @@ int rmodule_init(struct rmod_context *ctx, const struct buffer *elfin) else ctx->xdr = &xdr_le; + /* Obtain the string table. */ + for (i = 0; i < pelf->ehdr.e_shnum; i++) { + if (pelf->strtabs[i] == NULL) + continue; + /* Don't use the section headers' string table. */ + if (i == pelf->ehdr.e_shstrndx) + continue; + ctx->strtab = buffer_get(pelf->strtabs[i]); + break; + } + + if (ctx->strtab == NULL) { + ERROR("No string table found.\n"); + return -1; + } + if (find_program_segment(ctx)) goto out; diff --git a/util/cbfstool/rmodule.h b/util/cbfstool/rmodule.h index a62562b98f..ec0971e27e 100644 --- a/util/cbfstool/rmodule.h +++ b/util/cbfstool/rmodule.h @@ -29,6 +29,8 @@ struct rmod_context { struct parsed_elf pelf; /* Program segment. */ Elf64_Phdr *phdr; + /* Symbol string table. */ + char *strtab; /* Collection of relocation addresses fixup in the module. */ Elf64_Xword nrelocs;