1/* Kernel module help for SH. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; either version 2 of the License, or 6 (at your option) any later version. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program; if not, write to the Free Software 15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16*/ 17#include <linux/moduleloader.h> 18#include <linux/elf.h> 19#include <linux/vmalloc.h> 20#include <linux/fs.h> 21#include <linux/string.h> 22#include <linux/kernel.h> 23 24#define DEBUGP(fmt...) 25 26void *module_alloc(unsigned long size) 27{ 28 if (size == 0) 29 return NULL; 30 return vmalloc(size); 31} 32 33 34/* Free memory returned from module_alloc */ 35void module_free(struct module *mod, void *module_region) 36{ 37 vfree(module_region); 38} 39 40/* We don't need anything special. */ 41int module_frob_arch_sections(Elf_Ehdr *hdr, 42 Elf_Shdr *sechdrs, 43 char *secstrings, 44 struct module *mod) 45{ 46 return 0; 47} 48 49#define COPY_UNALIGNED_WORD(sw, tw, align) \ 50{ \ 51 void *__s = &(sw), *__t = &(tw); \ 52 unsigned short *__s2 = __s, *__t2 = __t; \ 53 unsigned char *__s1 = __s, *__t1 = __t; \ 54 switch ((align)) \ 55 { \ 56 case 0: \ 57 *(unsigned long *) __t = *(unsigned long *) __s; \ 58 break; \ 59 case 2: \ 60 *__t2++ = *__s2++; \ 61 *__t2 = *__s2; \ 62 break; \ 63 default: \ 64 *__t1++ = *__s1++; \ 65 *__t1++ = *__s1++; \ 66 *__t1++ = *__s1++; \ 67 *__t1 = *__s1; \ 68 break; \ 69 } \ 70} 71 72int apply_relocate_add(Elf32_Shdr *sechdrs, 73 const char *strtab, 74 unsigned int symindex, 75 unsigned int relsec, 76 struct module *me) 77{ 78 unsigned int i; 79 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; 80 Elf32_Sym *sym; 81 Elf32_Addr relocation; 82 uint32_t *location; 83 uint32_t value; 84 int align; 85 86 DEBUGP("Applying relocate section %u to %u\n", relsec, 87 sechdrs[relsec].sh_info); 88 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 89 /* This is where to make the change */ 90 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 91 + rel[i].r_offset; 92 /* This is the symbol it is referring to. Note that all 93 undefined symbols have been resolved. */ 94 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 95 + ELF32_R_SYM(rel[i].r_info); 96 relocation = sym->st_value + rel[i].r_addend; 97 align = (int)location & 3; 98 99 switch (ELF32_R_TYPE(rel[i].r_info)) { 100 case R_SH_DIR32: 101 COPY_UNALIGNED_WORD (*location, value, align); 102 value += relocation; 103 COPY_UNALIGNED_WORD (value, *location, align); 104 break; 105 case R_SH_REL32: 106 relocation = (relocation - (Elf32_Addr) location); 107 COPY_UNALIGNED_WORD (*location, value, align); 108 value += relocation; 109 COPY_UNALIGNED_WORD (value, *location, align); 110 break; 111 default: 112 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 113 me->name, ELF32_R_TYPE(rel[i].r_info)); 114 return -ENOEXEC; 115 } 116 } 117 return 0; 118} 119 120int apply_relocate(Elf32_Shdr *sechdrs, 121 const char *strtab, 122 unsigned int symindex, 123 unsigned int relsec, 124 struct module *me) 125{ 126 printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", 127 me->name); 128 return -ENOEXEC; 129} 130 131int module_finalize(const Elf_Ehdr *hdr, 132 const Elf_Shdr *sechdrs, 133 struct module *me) 134{ 135 return 0; 136} 137 138void module_arch_cleanup(struct module *mod) 139{ 140} 141