root/arch/m68k/kernel/module.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. apply_relocate
  2. apply_relocate_add
  3. module_finalize
  4. module_fixup

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file COPYING in the main directory of this archive
   4  * for more details.
   5  */
   6 
   7 #include <linux/moduleloader.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 }
  61 
  62 int apply_relocate_add(Elf32_Shdr *sechdrs,
  63                        const char *strtab,
  64                        unsigned int symindex,
  65                        unsigned int relsec,
  66                        struct module *me)
  67 {
  68         unsigned int i;
  69         Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
  70         Elf32_Sym *sym;
  71         uint32_t *location;
  72 
  73         DEBUGP("Applying relocate_add section %u to %u\n", relsec,
  74                sechdrs[relsec].sh_info);
  75         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
  76                 /* This is where to make the change */
  77                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
  78                         + rel[i].r_offset;
  79                 /* This is the symbol it is referring to.  Note that all
  80                    undefined symbols have been resolved.  */
  81                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
  82                         + ELF32_R_SYM(rel[i].r_info);
  83 
  84                 switch (ELF32_R_TYPE(rel[i].r_info)) {
  85                 case R_68K_32:
  86                         /* We add the value into the location given */
  87                         *location = rel[i].r_addend + sym->st_value;
  88                         break;
  89                 case R_68K_PC32:
  90                         /* Add the value, subtract its position */
  91                         *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
  92                         break;
  93                 default:
  94                         pr_err("module %s: Unknown relocation: %u\n", me->name,
  95                                ELF32_R_TYPE(rel[i].r_info));
  96                         return -ENOEXEC;
  97                 }
  98         }
  99         return 0;
 100 }
 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);
 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
 129 }

/* [<][>][^][v][top][bottom][index][help] */