1 /* 2 * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 3 * Copyright (C) 2007-2009 PetaLogix 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/module.h> 11 #include <linux/moduleloader.h> 12 #include <linux/kernel.h> 13 #include <linux/elf.h> 14 #include <linux/vmalloc.h> 15 #include <linux/slab.h> 16 #include <linux/fs.h> 17 #include <linux/string.h> 18 19 #include <asm/pgtable.h> 20 21 void *module_alloc(unsigned long size) 22 { 23 void *ret; 24 ret = (size == 0) ? NULL : vmalloc(size); 25 pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret); 26 return ret; 27 } 28 29 void module_free(struct module *module, void *region) 30 { 31 pr_debug("module_free(%s,%08lx)\n", module->name, 32 (unsigned long)region); 33 vfree(region); 34 } 35 36 int module_frob_arch_sections(Elf_Ehdr *hdr, 37 Elf_Shdr *sechdrs, 38 char *secstrings, 39 struct module *mod) 40 { 41 return 0; 42 } 43 44 int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, 45 unsigned int symindex, unsigned int relsec, struct module *module) 46 { 47 printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", 48 module->name); 49 return -ENOEXEC; 50 } 51 52 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, 53 unsigned int symindex, unsigned int relsec, struct module *module) 54 { 55 56 unsigned int i; 57 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 58 Elf32_Sym *sym; 59 unsigned long int *location; 60 unsigned long int value; 61 #if __GNUC__ < 4 62 unsigned long int old_value; 63 #endif 64 65 pr_debug("Applying add relocation section %u to %u\n", 66 relsec, sechdrs[relsec].sh_info); 67 68 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 69 70 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + 71 rela[i].r_offset; 72 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + 73 ELF32_R_SYM(rela[i].r_info); 74 value = sym->st_value + rela[i].r_addend; 75 76 switch (ELF32_R_TYPE(rela[i].r_info)) { 77 78 /* 79 * Be careful! mb-gcc / mb-ld splits the relocs between the 80 * text and the reloc table. In general this means we must 81 * read the current contents of (*location), add any offset 82 * then store the result back in 83 */ 84 85 case R_MICROBLAZE_32: 86 #if __GNUC__ < 4 87 old_value = *location; 88 *location = value + old_value; 89 90 pr_debug("R_MICROBLAZE_32 (%08lx->%08lx)\n", 91 old_value, value); 92 #else 93 *location = value; 94 #endif 95 break; 96 97 case R_MICROBLAZE_64: 98 #if __GNUC__ < 4 99 /* Split relocs only required/used pre gcc4.1.1 */ 100 old_value = ((location[0] & 0x0000FFFF) << 16) | 101 (location[1] & 0x0000FFFF); 102 value += old_value; 103 #endif 104 location[0] = (location[0] & 0xFFFF0000) | 105 (value >> 16); 106 location[1] = (location[1] & 0xFFFF0000) | 107 (value & 0xFFFF); 108 #if __GNUC__ < 4 109 pr_debug("R_MICROBLAZE_64 (%08lx->%08lx)\n", 110 old_value, value); 111 #endif 112 break; 113 114 case R_MICROBLAZE_64_PCREL: 115 #if __GNUC__ < 4 116 old_value = (location[0] & 0xFFFF) << 16 | 117 (location[1] & 0xFFFF); 118 value -= old_value; 119 #endif 120 value -= (unsigned long int)(location) + 4; 121 location[0] = (location[0] & 0xFFFF0000) | 122 (value >> 16); 123 location[1] = (location[1] & 0xFFFF0000) | 124 (value & 0xFFFF); 125 pr_debug("R_MICROBLAZE_64_PCREL (%08lx)\n", 126 value); 127 break; 128 129 case R_MICROBLAZE_32_PCREL_LO: 130 pr_debug("R_MICROBLAZE_32_PCREL_LO\n"); 131 break; 132 133 case R_MICROBLAZE_64_NONE: 134 pr_debug("R_MICROBLAZE_NONE\n"); 135 break; 136 137 case R_MICROBLAZE_NONE: 138 pr_debug("R_MICROBLAZE_NONE\n"); 139 break; 140 141 default: 142 printk(KERN_ERR "module %s: " 143 "Unknown relocation: %u\n", 144 module->name, 145 ELF32_R_TYPE(rela[i].r_info)); 146 return -ENOEXEC; 147 } 148 } 149 return 0; 150 } 151 152 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, 153 struct module *module) 154 { 155 return 0; 156 } 157 158 void module_arch_cleanup(struct module *mod) 159 { 160 } 161