1#include <linux/moduleloader.h> 2#include <linux/elf.h> 3#include <linux/vmalloc.h> 4#include <linux/fs.h> 5#include <linux/string.h> 6#include <linux/kernel.h> 7 8#define DEBUGP(fmt...) 9 10void *module_alloc(unsigned long size) 11{ 12 if (size == 0) 13 return NULL; 14 return vmalloc(size); 15} 16 17 18/* Free memory returned from module_alloc */ 19void module_free(struct module *mod, void *module_region) 20{ 21 vfree(module_region); 22} 23 24/* We don't need anything special. */ 25int module_frob_arch_sections(Elf_Ehdr *hdr, 26 Elf_Shdr *sechdrs, 27 char *secstrings, 28 struct module *mod) 29{ 30 return 0; 31} 32 33int apply_relocate(Elf32_Shdr *sechdrs, 34 const char *strtab, 35 unsigned int symindex, 36 unsigned int relsec, 37 struct module *me) 38{ 39 printk(KERN_ERR "module %s: RELOCATION unsupported\n", 40 me->name); 41 return -ENOEXEC; 42} 43 44int apply_relocate_add(Elf32_Shdr *sechdrs, 45 const char *strtab, 46 unsigned int symindex, 47 unsigned int relsec, 48 struct module *me) 49{ 50 unsigned int i; 51 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 52 53 DEBUGP("Applying relocate section %u to %u\n", relsec, 54 sechdrs[relsec].sh_info); 55 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 56 /* This is where to make the change */ 57 uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr 58 + rela[i].r_offset); 59 /* This is the symbol it is referring to. Note that all 60 undefined symbols have been resolved. */ 61 Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 62 + ELF32_R_SYM(rela[i].r_info); 63 uint32_t v = sym->st_value + rela[i].r_addend; 64 65 switch (ELF32_R_TYPE(rela[i].r_info)) { 66 case R_H8_DIR24R8: 67 loc = (uint32_t *)((uint32_t)loc - 1); 68 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); 69 break; 70 case R_H8_DIR24A8: 71 if (ELF32_R_SYM(rela[i].r_info)) 72 *loc += v; 73 break; 74 case R_H8_DIR32: 75 case R_H8_DIR32A16: 76 *loc += v; 77 break; 78 case R_H8_PCREL16: 79 v -= (unsigned long)loc + 2; 80 if ((Elf32_Sword)v > 0x7fff || 81 (Elf32_Sword)v < -(Elf32_Sword)0x8000) 82 goto overflow; 83 else 84 *(unsigned short *)loc = v; 85 break; 86 case R_H8_PCREL8: 87 v -= (unsigned long)loc + 1; 88 if ((Elf32_Sword)v > 0x7f || 89 (Elf32_Sword)v < -(Elf32_Sword)0x80) 90 goto overflow; 91 else 92 *(unsigned char *)loc = v; 93 break; 94 default: 95 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 96 me->name, ELF32_R_TYPE(rela[i].r_info)); 97 return -ENOEXEC; 98 } 99 } 100 return 0; 101 overflow: 102 printk(KERN_ERR "module %s: relocation offset overflow: %08x\n", 103 me->name, rela[i].r_offset); 104 return -ENOEXEC; 105} 106 107int module_finalize(const Elf_Ehdr *hdr, 108 const Elf_Shdr *sechdrs, 109 struct module *me) 110{ 111 return 0; 112} 113 114void module_arch_cleanup(struct module *mod) 115{ 116} 117