1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * OpenRISC module.c !! 2 * This file is subject to the terms and conditions of the GNU General Public 4 * !! 3 * License. See the file COPYING in the main directory of this archive 5 * Linux architectural port borrowing liberall !! 4 * for more details. 6 * others. All original copyrights apply as p << 7 * declaration. << 8 * << 9 * Modifications for the OpenRISC architecture << 10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@s << 11 */ 5 */ 12 6 13 #include <linux/moduleloader.h> 7 #include <linux/moduleloader.h> 14 #include <linux/elf.h> 8 #include <linux/elf.h> >> 9 #include <linux/vmalloc.h> >> 10 #include <linux/fs.h> >> 11 #include <linux/string.h> >> 12 #include <linux/kernel.h> >> 13 >> 14 #if 0 >> 15 #define DEBUGP(fmt, ...) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) >> 16 #else >> 17 #define DEBUGP(fmt, ...) no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) >> 18 #endif >> 19 >> 20 #ifdef CONFIG_MODULES >> 21 >> 22 int apply_relocate(Elf32_Shdr *sechdrs, >> 23 const char *strtab, >> 24 unsigned int symindex, >> 25 unsigned int relsec, >> 26 struct module *me) >> 27 { >> 28 unsigned int i; >> 29 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; >> 30 Elf32_Sym *sym; >> 31 uint32_t *location; >> 32 >> 33 DEBUGP("Applying relocate section %u to %u\n", relsec, >> 34 sechdrs[relsec].sh_info); >> 35 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { >> 36 /* This is where to make the change */ >> 37 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr >> 38 + rel[i].r_offset; >> 39 /* This is the symbol it is referring to. Note that all >> 40 undefined symbols have been resolved. */ >> 41 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr >> 42 + ELF32_R_SYM(rel[i].r_info); >> 43 >> 44 switch (ELF32_R_TYPE(rel[i].r_info)) { >> 45 case R_68K_32: >> 46 /* We add the value into the location given */ >> 47 *location += sym->st_value; >> 48 break; >> 49 case R_68K_PC32: >> 50 /* Add the value, subtract its position */ >> 51 *location += sym->st_value - (uint32_t)location; >> 52 break; >> 53 default: >> 54 pr_err("module %s: Unknown relocation: %u\n", me->name, >> 55 ELF32_R_TYPE(rel[i].r_info)); >> 56 return -ENOEXEC; >> 57 } >> 58 } >> 59 return 0; >> 60 } 15 61 16 int apply_relocate_add(Elf32_Shdr *sechdrs, 62 int apply_relocate_add(Elf32_Shdr *sechdrs, 17 const char *strtab, 63 const char *strtab, 18 unsigned int symindex, 64 unsigned int symindex, 19 unsigned int relsec, 65 unsigned int relsec, 20 struct module *me) 66 struct module *me) 21 { 67 { 22 unsigned int i; 68 unsigned int i; 23 Elf32_Rela *rel = (void *)sechdrs[rels 69 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 24 Elf32_Sym *sym; 70 Elf32_Sym *sym; 25 uint32_t *location; 71 uint32_t *location; 26 uint32_t value; << 27 72 28 pr_debug("Applying relocate section %u !! 73 DEBUGP("Applying relocate_add section %u to %u\n", relsec, 29 sechdrs[relsec].sh_info); !! 74 sechdrs[relsec].sh_info); 30 for (i = 0; i < sechdrs[relsec].sh_siz 75 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 31 /* This is where to make the c 76 /* This is where to make the change */ 32 location = (void *)sechdrs[sec 77 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 33 + rel[i].r_offset; 78 + rel[i].r_offset; 34 << 35 /* This is the symbol it is re 79 /* This is the symbol it is referring to. Note that all 36 undefined symbols have been 80 undefined symbols have been resolved. */ 37 sym = (Elf32_Sym *)sechdrs[sym 81 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 38 + ELF32_R_SYM(rel[i].r 82 + ELF32_R_SYM(rel[i].r_info); 39 value = sym->st_value + rel[i] << 40 83 41 switch (ELF32_R_TYPE(rel[i].r_ 84 switch (ELF32_R_TYPE(rel[i].r_info)) { 42 case R_OR1K_32: !! 85 case R_68K_32: 43 *location = value; !! 86 /* We add the value into the location given */ 44 break; !! 87 *location = rel[i].r_addend + sym->st_value; 45 case R_OR1K_LO_16_IN_INSN: !! 88 break; 46 *((uint16_t *)location !! 89 case R_68K_PC32: 47 break; !! 90 /* Add the value, subtract its position */ 48 case R_OR1K_HI_16_IN_INSN: !! 91 *location = rel[i].r_addend + sym->st_value - (uint32_t)location; 49 *((uint16_t *)location << 50 break; << 51 case R_OR1K_INSN_REL_26: << 52 value -= (uint32_t)loc << 53 value >>= 2; << 54 value &= 0x03ffffff; << 55 value |= *location & 0 << 56 *location = value; << 57 break; << 58 case R_OR1K_AHI16: << 59 /* Adjust the operand << 60 value += 0x8000; << 61 *((uint16_t *)location << 62 break; << 63 case R_OR1K_SLO16: << 64 /* Split value lower 1 << 65 value = ((value & 0xf8 << 66 *location = (*location << 67 break; 92 break; 68 default: 93 default: 69 pr_err("module %s: Unk !! 94 pr_err("module %s: Unknown relocation: %u\n", me->name, 70 me->name, ELF32 !! 95 ELF32_R_TYPE(rel[i].r_info)); 71 break; !! 96 return -ENOEXEC; 72 } 97 } 73 } 98 } >> 99 return 0; >> 100 } 74 101 >> 102 int module_finalize(const Elf_Ehdr *hdr, >> 103 const Elf_Shdr *sechdrs, >> 104 struct module *mod) >> 105 { >> 106 module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end); 75 return 0; 107 return 0; >> 108 } >> 109 >> 110 #endif /* CONFIG_MODULES */ >> 111 >> 112 void module_fixup(struct module *mod, struct m68k_fixup_info *start, >> 113 struct m68k_fixup_info *end) >> 114 { >> 115 #ifdef CONFIG_MMU >> 116 struct m68k_fixup_info *fixup; >> 117 >> 118 for (fixup = start; fixup < end; fixup++) { >> 119 switch (fixup->type) { >> 120 case m68k_fixup_memoffset: >> 121 *(u32 *)fixup->addr = m68k_memoffset; >> 122 break; >> 123 case m68k_fixup_vnode_shift: >> 124 *(u16 *)fixup->addr += m68k_virt_to_node_shift; >> 125 break; >> 126 } >> 127 } >> 128 #endif 76 } 129 } 77 130
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.