From 892257ec2187e84c1610d97367ca59270bcbadda Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Thu, 24 Oct 2024 14:38:52 -0700 Subject: cbfstool: Fix segmentation fault for data segment relocation `cbfstool add-stage' crashes with a segmentation fault when generating the program binary out of a romstage ELF containing relocation within the data segment. This commit makes `parse_elf_to_xip_stage()' look for the segment to which the current relocation applies and compute the appropriate location within the program binary. This issue can be reproduced by defining a global variable with a pointer to constant data. This variable is defined within the .data section and contains a pointer to a constant which resides in the .text section. As a result, a relocation entry is generated in the ELF file. struct my_struct { const char *name; }; struct my_struct my_global = { .name = "EXAMPLE" }; void fun(void) { printk(BIOS_DEBUG, "my_global.name=%s\n", my_global.name); } TEST=global data structure with a pointer to a constant does not make cbfstool crash Change-Id: I480b4b047546c8aa4e12dfb688e0299f80283235 Signed-off-by: Jeremy Compostella Reviewed-on: https://review.coreboot.org/c/coreboot/+/84864 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner Reviewed-by: Shuo Liu Reviewed-by: Wonkyu Kim --- util/cbfstool/cbfs-mkstage.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'util/cbfstool') diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c index 2338adc7ae..a72b387c2b 100644 --- a/util/cbfstool/cbfs-mkstage.c +++ b/util/cbfstool/cbfs-mkstage.c @@ -403,11 +403,23 @@ int parse_elf_to_xip_stage(const struct buffer *input, struct buffer *output, size_t reloc_offset; uint32_t val; struct buffer in, out; + Elf64_Addr reloc = rmodctx->emitted_relocs[i]; /* The relocations represent in-program addresses of the * linked program. Obtain the offset into the program to do * the adjustment. */ - reloc_offset = rmodctx->emitted_relocs[i] - pelf->phdr->p_vaddr; + reloc_offset = 0; + for (phdr = toload; *phdr; phdr++) { + if (reloc >= (*phdr)->p_vaddr && + reloc < (*phdr)->p_vaddr + (*phdr)->p_memsz) + break; + reloc_offset += (*phdr)->p_filesz; + } + if (!*phdr) { + ERROR("Relocation outside of loadable segments\n"); + goto out; + } + reloc_offset += reloc - (*phdr)->p_vaddr; buffer_clone(&out, &boutput); buffer_seek(&out, reloc_offset); -- cgit v1.2.3