^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* Kernel module help for SH.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) SHcompact version by Kaz Kojima and Paul Mundt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) SHmedia bits:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) Copyright 2004 SuperH (UK) Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) Author: Richard Curnow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) Based on the sh version, and on code from the sh64-specific parts of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) modutils, originally written by Richard Curnow and Ben Gaster.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/moduleloader.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/dwarf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int apply_relocate_add(Elf32_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const char *strtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned int symindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct module *me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) Elf32_Sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) Elf32_Addr relocation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) uint32_t *location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) uint32_t value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) pr_debug("Applying relocate section %u to %u\n", relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) sechdrs[relsec].sh_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* This is where to make the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) + rel[i].r_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* This is the symbol it is referring to. Note that all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) undefined symbols have been resolved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) + ELF32_R_SYM(rel[i].r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) relocation = sym->st_value + rel[i].r_addend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) switch (ELF32_R_TYPE(rel[i].r_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case R_SH_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case R_SH_DIR32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) value = get_unaligned(location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) value += relocation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) put_unaligned(value, location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case R_SH_REL32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) relocation = (relocation - (Elf32_Addr) location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) value = get_unaligned(location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) value += relocation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) put_unaligned(value, location);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case R_SH_IMM_LOW16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *location = (*location & ~0x3fffc00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ((relocation & 0xffff) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case R_SH_IMM_MEDLOW16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *location = (*location & ~0x3fffc00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) (((relocation >> 16) & 0xffff) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case R_SH_IMM_LOW16_PCREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) relocation -= (Elf32_Addr) location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *location = (*location & ~0x3fffc00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ((relocation & 0xffff) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) case R_SH_IMM_MEDLOW16_PCREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) relocation -= (Elf32_Addr) location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *location = (*location & ~0x3fffc00) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) (((relocation >> 16) & 0xffff) << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) printk(KERN_ERR "module %s: Unknown relocation: %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) me->name, ELF32_R_TYPE(rel[i].r_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int module_finalize(const Elf_Ehdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) const Elf_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct module *me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ret |= module_dwarf_finalize(hdr, sechdrs, me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) void module_arch_cleanup(struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) module_dwarf_cleanup(mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }