Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

objtool: Fix reloc generation on big endian cross-compiles

Relocations generated in elf_rebuild_rel[a]_reloc_section() are broken
if objtool is built and run on a big endian system.

The following errors pop up during x86 cross-compilation:

x86_64-9.1.0-ld: fs/efivarfs/inode.o: bad reloc symbol index (0x2000000 >= 0x22) for offset 0 in section `.orc_unwind_ip'
x86_64-9.1.0-ld: final link failed: bad value

Convert those functions to use gelf_update_rel[a](), similar to what
elf_write_reloc() does.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Co-developed-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>

authored by

Martin Schwidefsky and committed by
Josh Poimboeuf
a1a664ec 1d509f2a

+19 -15
+19 -15
tools/objtool/elf.c
··· 855 855 { 856 856 struct reloc *reloc; 857 857 int idx = 0, size; 858 - GElf_Rel *relocs; 858 + void *buf; 859 859 860 860 /* Allocate a buffer for relocations */ 861 - size = nr * sizeof(*relocs); 862 - relocs = malloc(size); 863 - if (!relocs) { 861 + size = nr * sizeof(GElf_Rel); 862 + buf = malloc(size); 863 + if (!buf) { 864 864 perror("malloc"); 865 865 return -1; 866 866 } 867 867 868 - sec->data->d_buf = relocs; 868 + sec->data->d_buf = buf; 869 869 sec->data->d_size = size; 870 + sec->data->d_type = ELF_T_REL; 870 871 871 872 sec->sh.sh_size = size; 872 873 873 874 idx = 0; 874 875 list_for_each_entry(reloc, &sec->reloc_list, list) { 875 - relocs[idx].r_offset = reloc->offset; 876 - relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 876 + reloc->rel.r_offset = reloc->offset; 877 + reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 878 + gelf_update_rel(sec->data, idx, &reloc->rel); 877 879 idx++; 878 880 } 879 881 ··· 886 884 { 887 885 struct reloc *reloc; 888 886 int idx = 0, size; 889 - GElf_Rela *relocs; 887 + void *buf; 890 888 891 889 /* Allocate a buffer for relocations with addends */ 892 - size = nr * sizeof(*relocs); 893 - relocs = malloc(size); 894 - if (!relocs) { 890 + size = nr * sizeof(GElf_Rela); 891 + buf = malloc(size); 892 + if (!buf) { 895 893 perror("malloc"); 896 894 return -1; 897 895 } 898 896 899 - sec->data->d_buf = relocs; 897 + sec->data->d_buf = buf; 900 898 sec->data->d_size = size; 899 + sec->data->d_type = ELF_T_RELA; 901 900 902 901 sec->sh.sh_size = size; 903 902 904 903 idx = 0; 905 904 list_for_each_entry(reloc, &sec->reloc_list, list) { 906 - relocs[idx].r_offset = reloc->offset; 907 - relocs[idx].r_addend = reloc->addend; 908 - relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 905 + reloc->rela.r_offset = reloc->offset; 906 + reloc->rela.r_addend = reloc->addend; 907 + reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 908 + gelf_update_rela(sec->data, idx, &reloc->rela); 909 909 idx++; 910 910 } 911 911