1 // SPDX-License-Identifier: GPL-2.0-or-later !! 1 /* Kernel module help for sparc32. 2 /* Kernel module help for powerpc. !! 2 * 3 Copyright (C) 2001, 2003 Rusty Russell IBM !! 3 * Copyright (C) 2001 Rusty Russell. 4 Copyright (C) 2008 Freescale Semiconductor !! 4 * Copyright (C) 2002 David S. Miller. >> 5 */ 5 6 6 */ << 7 #include <linux/elf.h> << 8 #include <linux/moduleloader.h> 7 #include <linux/moduleloader.h> 9 #include <linux/err.h> !! 8 #include <linux/kernel.h> 10 #include <linux/mm.h> !! 9 #include <linux/elf.h> 11 #include <linux/bug.h> !! 10 #include <linux/vmalloc.h> 12 #include <asm/module.h> !! 11 #include <linux/fs.h> 13 #include <linux/uaccess.h> !! 12 #include <linux/string.h> 14 #include <asm/firmware.h> !! 13 15 #include <linux/sort.h> !! 14 void *module_alloc(unsigned long size) 16 #include <asm/setup.h> << 17 #include <asm/sections.h> << 18 << 19 static const Elf_Shdr *find_section(const Elf_ << 20 const Elf_ << 21 const char << 22 { 15 { 23 char *secstrings; !! 16 void *ret; 24 unsigned int i; << 25 17 26 secstrings = (char *)hdr + sechdrs[hdr !! 18 /* We handle the zero case fine, unlike vmalloc */ 27 for (i = 1; i < hdr->e_shnum; i++) !! 19 if (size == 0) 28 if (strcmp(secstrings+sechdrs[ !! 20 return NULL; 29 return &sechdrs[i]; !! 21 30 return NULL; !! 22 ret = vmalloc(size); >> 23 if (!ret) >> 24 ret = ERR_PTR(-ENOMEM); >> 25 else >> 26 memset(ret, 0, size); >> 27 >> 28 return ret; 31 } 29 } 32 30 33 int module_finalize(const Elf_Ehdr *hdr, !! 31 /* Free memory returned from module_core_alloc/module_init_alloc */ 34 const Elf_Shdr *sechdrs, struc !! 32 void module_free(struct module *mod, void *module_region) 35 { 33 { 36 const Elf_Shdr *sect; !! 34 vfree(module_region); 37 int rc; !! 35 /* FIXME: If module_region == mod->init_region, trim exception >> 36 table entries. */ >> 37 } 38 38 39 rc = module_finalize_ftrace(me, sechdr !! 39 /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ 40 if (rc) !! 40 int module_frob_arch_sections(Elf_Ehdr *hdr, 41 return rc; !! 41 Elf_Shdr *sechdrs, 42 !! 42 char *secstrings, 43 /* Apply feature fixups */ !! 43 struct module *mod) 44 sect = find_section(hdr, sechdrs, "__f !! 44 { 45 if (sect != NULL) !! 45 unsigned int symidx; 46 do_feature_fixups(cur_cpu_spec !! 46 Elf32_Sym *sym; 47 (void *)sect !! 47 const char *strtab; 48 (void *)sect !! 48 int i; 49 !! 49 50 sect = find_section(hdr, sechdrs, "__m !! 50 for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) { 51 if (sect != NULL) !! 51 if (symidx == hdr->e_shnum-1) { 52 do_feature_fixups(cur_cpu_spec !! 52 printk("%s: no symtab found.\n", mod->name); 53 (void *)sect !! 53 return -ENOEXEC; 54 (void *)sect !! 54 } 55 << 56 #ifdef CONFIG_PPC64 << 57 sect = find_section(hdr, sechdrs, "__f << 58 if (sect != NULL) << 59 do_feature_fixups(powerpc_firm << 60 (void *)sect << 61 (void *)sect << 62 #endif /* CONFIG_PPC64 */ << 63 << 64 #ifdef CONFIG_PPC64_ELF_ABI_V1 << 65 sect = find_section(hdr, sechdrs, ".op << 66 if (sect != NULL) { << 67 me->arch.start_opd = sect->sh_ << 68 me->arch.end_opd = sect->sh_ad << 69 } 55 } 70 #endif /* CONFIG_PPC64_ELF_ABI_V1 */ !! 56 sym = (Elf32_Sym *)sechdrs[symidx].sh_addr; >> 57 strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr; 71 58 72 #ifdef CONFIG_PPC_BARRIER_NOSPEC !! 59 for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) { 73 sect = find_section(hdr, sechdrs, "__s !! 60 if (sym[i].st_shndx == SHN_UNDEF && 74 if (sect != NULL) !! 61 ELF32_ST_TYPE(sym[i].st_info) == STT_REGISTER) 75 do_barrier_nospec_fixups_range !! 62 sym[i].st_shndx = SHN_ABS; 76 (void *)sect !! 63 } 77 (void *)sect !! 64 return 0; 78 #endif /* CONFIG_PPC_BARRIER_NOSPEC */ !! 65 } 79 << 80 sect = find_section(hdr, sechdrs, "__l << 81 if (sect != NULL) << 82 do_lwsync_fixups(cur_cpu_spec- << 83 (void *)sect- << 84 (void *)sect- << 85 66 >> 67 int apply_relocate(Elf32_Shdr *sechdrs, >> 68 const char *strtab, >> 69 unsigned int symindex, >> 70 unsigned int relsec, >> 71 struct module *me) >> 72 { >> 73 printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n", >> 74 me->name); >> 75 return -ENOEXEC; >> 76 } >> 77 >> 78 int apply_relocate_add(Elf32_Shdr *sechdrs, >> 79 const char *strtab, >> 80 unsigned int symindex, >> 81 unsigned int relsec, >> 82 struct module *me) >> 83 { >> 84 unsigned int i; >> 85 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; >> 86 Elf32_Sym *sym; >> 87 u8 *location; >> 88 u32 *loc32; >> 89 >> 90 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { >> 91 Elf32_Addr v; >> 92 >> 93 /* This is where to make the change */ >> 94 location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr >> 95 + rel[i].r_offset; >> 96 loc32 = (u32 *) location; >> 97 /* This is the symbol it is referring to. Note that all >> 98 undefined symbols have been resolved. */ >> 99 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr >> 100 + ELF32_R_SYM(rel[i].r_info); >> 101 v = sym->st_value + rel[i].r_addend; >> 102 >> 103 switch (ELF32_R_TYPE(rel[i].r_info)) { >> 104 case R_SPARC_32: >> 105 location[0] = v >> 24; >> 106 location[1] = v >> 16; >> 107 location[2] = v >> 8; >> 108 location[3] = v >> 0; >> 109 break; >> 110 >> 111 case R_SPARC_WDISP30: >> 112 v -= (Elf32_Addr) location; >> 113 *loc32 = (*loc32 & ~0x3fffffff) | >> 114 ((v >> 2) & 0x3fffffff); >> 115 break; >> 116 >> 117 case R_SPARC_WDISP22: >> 118 v -= (Elf32_Addr) location; >> 119 *loc32 = (*loc32 & ~0x3fffff) | >> 120 ((v >> 2) & 0x3fffff); >> 121 break; >> 122 >> 123 case R_SPARC_LO10: >> 124 *loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff); >> 125 break; >> 126 >> 127 case R_SPARC_HI22: >> 128 *loc32 = (*loc32 & ~0x3fffff) | >> 129 ((v >> 10) & 0x3fffff); >> 130 break; >> 131 >> 132 default: >> 133 printk(KERN_ERR "module %s: Unknown relocation: %x\n", >> 134 me->name, >> 135 (int) (ELF32_R_TYPE(rel[i].r_info) & 0xff)); >> 136 return -ENOEXEC; >> 137 }; >> 138 } >> 139 return 0; >> 140 } >> 141 >> 142 int module_finalize(const Elf_Ehdr *hdr, >> 143 const Elf_Shdr *sechdrs, >> 144 struct module *me) >> 145 { 86 return 0; 146 return 0; >> 147 } >> 148 >> 149 void module_arch_cleanup(struct module *mod) >> 150 { 87 } 151 } 88 152
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.