^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Kernel module loader for Hexagon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/moduleloader.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define DEBUGP printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DEBUGP(fmt , ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * module_frob_arch_sections - tweak got/plt sections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * @hdr - pointer to elf header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * @sechdrs - pointer to elf load section headers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * @secstrings - symbol names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * @mod - pointer to module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char *secstrings,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Look for .plt and/or .got.plt and/or .init.plt sections */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) for (i = 0; i < hdr->e_shnum; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) DEBUGP("Section %d is %s\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) secstrings + sechdrs[i].sh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) found = i+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (strcmp(secstrings + sechdrs[i].sh_name, ".got.plt") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) found = i+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (strcmp(secstrings + sechdrs[i].sh_name, ".rela.plt") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) found = i+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* At this time, we don't support modules comiled with -shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) printk(KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "Module '%s' contains unexpected .plt/.got sections.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) mod->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* return -ENOEXEC; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * apply_relocate_add - perform rela relocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @sechdrs - pointer to section headers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @strtab - some sort of start address?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @symindex - symbol index offset or something?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @relsec - address to relocate to?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @module - pointer to module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * Perform rela relocations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int symindex, unsigned int relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct module *module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) Elf32_Sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) uint32_t *location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) uint32_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned int nrelocs = sechdrs[relsec].sh_size / sizeof(Elf32_Rela);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) Elf32_Word sym_info = sechdrs[relsec].sh_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) Elf32_Sym *sym_base = (Elf32_Sym *) sechdrs[symindex].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) void *loc_base = (void *) sechdrs[sym_info].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) DEBUGP("Applying relocations in section %u to section %u base=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) relsec, sym_info, loc_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) for (i = 0; i < nrelocs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Symbol to relocate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) sym = sym_base + ELF32_R_SYM(rela[i].r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* Where to make the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) location = loc_base + rela[i].r_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* `Everything is relative'. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) value = sym->st_value + rela[i].r_addend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) DEBUGP("%d: value=%08x loc=%p reloc=%d symbol=%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) i, value, location, ELF32_R_TYPE(rela[i].r_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) sym->st_name ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) &strtab[sym->st_name] : "(anonymous)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) switch (ELF32_R_TYPE(rela[i].r_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) case R_HEXAGON_B22_PCREL: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int dist = (int)(value - (uint32_t)location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if ((dist < -0x00800000) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) (dist >= 0x00800000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) "%s: %s: %08x=%08x-%08x %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) module->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) "R_HEXAGON_B22_PCREL reloc out of range",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) dist, value, (uint32_t)location,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) sym->st_name ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) &strtab[sym->st_name] : "(anonymous)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) DEBUGP("B22_PCREL contents: %08X.\n", *location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *location &= ~0x01ff3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *location |= 0x00003fff & dist;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *location |= 0x01ff0000 & (dist<<2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) DEBUGP("Contents after reloc: %08x\n", *location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case R_HEXAGON_HI16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) value = (value>>16) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case R_HEXAGON_LO16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *location &= ~0x00c03fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *location |= value & 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *location |= (value & 0xc000) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case R_HEXAGON_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *location = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case R_HEXAGON_32_PCREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *location = value - (uint32_t)location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case R_HEXAGON_PLT_B22_PCREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case R_HEXAGON_GOTOFF_LO16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case R_HEXAGON_GOTOFF_HI16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) printk(KERN_ERR "%s: GOT/PLT relocations unsupported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) module->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) printk(KERN_ERR "%s: unknown relocation: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) module->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ELF32_R_TYPE(rela[i].r_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }