^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/moduleloader.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.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(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define DEBUGP(fmt, ...) no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
^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) #ifdef CONFIG_MODULES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) int apply_relocate(Elf32_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) const char *strtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned int symindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) unsigned int relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct module *me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) Elf32_Sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) uint32_t *location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) DEBUGP("Applying relocate section %u to %u\n", relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) sechdrs[relsec].sh_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* This is where to make the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) + rel[i].r_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* This is the symbol it is referring to. Note that all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) undefined symbols have been resolved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) + ELF32_R_SYM(rel[i].r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) switch (ELF32_R_TYPE(rel[i].r_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case R_68K_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* We add the value into the location given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *location += sym->st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case R_68K_PC32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Add the value, subtract its position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *location += sym->st_value - (uint32_t)location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) pr_err("module %s: Unknown relocation: %u\n", me->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ELF32_R_TYPE(rel[i].r_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int apply_relocate_add(Elf32_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) const char *strtab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int symindex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct module *me)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) Elf32_Sym *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) uint32_t *location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) DEBUGP("Applying relocate_add section %u to %u\n", relsec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) sechdrs[relsec].sh_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* This is where to make the change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) + rel[i].r_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* This is the symbol it is referring to. Note that all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) undefined symbols have been resolved. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) + ELF32_R_SYM(rel[i].r_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) switch (ELF32_R_TYPE(rel[i].r_info)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case R_68K_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* We add the value into the location given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *location = rel[i].r_addend + sym->st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case R_68K_PC32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Add the value, subtract its position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) pr_err("module %s: Unknown relocation: %u\n", me->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ELF32_R_TYPE(rel[i].r_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int module_finalize(const Elf_Ehdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) const Elf_Shdr *sechdrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #endif /* CONFIG_MODULES */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) void module_fixup(struct module *mod, struct m68k_fixup_info *start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct m68k_fixup_info *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #ifdef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct m68k_fixup_info *fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) for (fixup = start; fixup < end; fixup++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) switch (fixup->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case m68k_fixup_memoffset:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *(u32 *)fixup->addr = m68k_memoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case m68k_fixup_vnode_shift:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *(u16 *)fixup->addr += m68k_virt_to_node_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }