linux/arch/sparc/kernel/module.c
<<
>>
Prefs
   1/* Kernel module help for sparc32.
   2 *
   3 * Copyright (C) 2001 Rusty Russell.
   4 * Copyright (C) 2002 David S. Miller.
   5 */
   6
   7#include <linux/moduleloader.h>
   8#include <linux/kernel.h>
   9#include <linux/elf.h>
  10#include <linux/vmalloc.h>
  11#include <linux/fs.h>
  12#include <linux/string.h>
  13#include <linux/ctype.h>
  14
  15void *module_alloc(unsigned long size)
  16{
  17        void *ret;
  18
  19        /* We handle the zero case fine, unlike vmalloc */
  20        if (size == 0)
  21                return NULL;
  22
  23        ret = vmalloc(size);
  24        if (!ret)
  25                ret = ERR_PTR(-ENOMEM);
  26        else
  27                memset(ret, 0, size);
  28
  29        return ret;
  30}
  31
  32/* Free memory returned from module_core_alloc/module_init_alloc */
  33void module_free(struct module *mod, void *module_region)
  34{
  35        vfree(module_region);
  36        /* FIXME: If module_region == mod->init_region, trim exception
  37           table entries. */
  38}
  39
  40/* Make generic code ignore STT_REGISTER dummy undefined symbols,
  41 * and replace references to .func with _Func
  42 */
  43int module_frob_arch_sections(Elf_Ehdr *hdr,
  44                              Elf_Shdr *sechdrs,
  45                              char *secstrings,
  46                              struct module *mod)
  47{
  48        unsigned int symidx;
  49        Elf32_Sym *sym;
  50        char *strtab;
  51        int i;
  52
  53        for (symidx = 0; sechdrs[symidx].sh_type != SHT_SYMTAB; symidx++) {
  54                if (symidx == hdr->e_shnum-1) {
  55                        printk("%s: no symtab found.\n", mod->name);
  56                        return -ENOEXEC;
  57                }
  58        }
  59        sym = (Elf32_Sym *)sechdrs[symidx].sh_addr;
  60        strtab = (char *)sechdrs[sechdrs[symidx].sh_link].sh_addr;
  61
  62        for (i = 1; i < sechdrs[symidx].sh_size / sizeof(Elf_Sym); i++) {
  63                if (sym[i].st_shndx == SHN_UNDEF) {
  64                        if (ELF32_ST_TYPE(sym[i].st_info) == STT_REGISTER)
  65                                sym[i].st_shndx = SHN_ABS;
  66                        else {
  67                                char *name = strtab + sym[i].st_name;
  68                                if (name[0] == '.') {
  69                                        name[0] = '_';
  70                                        name[1] = toupper(name[1]);
  71                                }
  72                        }
  73                }
  74        }
  75        return 0;
  76}
  77
  78int apply_relocate(Elf32_Shdr *sechdrs,
  79                   const char *strtab,
  80                   unsigned int symindex,
  81                   unsigned int relsec,
  82                   struct module *me)
  83{
  84        printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n",
  85               me->name);
  86        return -ENOEXEC;
  87}
  88
  89int apply_relocate_add(Elf32_Shdr *sechdrs,
  90                       const char *strtab,
  91                       unsigned int symindex,
  92                       unsigned int relsec,
  93                       struct module *me)
  94{
  95        unsigned int i;
  96        Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
  97        Elf32_Sym *sym;
  98        u8 *location;
  99        u32 *loc32;
 100
 101        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
 102                Elf32_Addr v;
 103
 104                /* This is where to make the change */
 105                location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr
 106                        + rel[i].r_offset;
 107                loc32 = (u32 *) location;
 108                /* This is the symbol it is referring to.  Note that all
 109                   undefined symbols have been resolved.  */
 110                sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
 111                        + ELF32_R_SYM(rel[i].r_info);
 112                v = sym->st_value + rel[i].r_addend;
 113
 114                switch (ELF32_R_TYPE(rel[i].r_info)) {
 115                case R_SPARC_32:
 116                case R_SPARC_UA32:
 117                        location[0] = v >> 24;
 118                        location[1] = v >> 16;
 119                        location[2] = v >>  8;
 120                        location[3] = v >>  0;
 121                        break;
 122
 123                case R_SPARC_WDISP30:
 124                        v -= (Elf32_Addr) location;
 125                        *loc32 = (*loc32 & ~0x3fffffff) |
 126                                ((v >> 2) & 0x3fffffff);
 127                        break;
 128
 129                case R_SPARC_WDISP22:
 130                        v -= (Elf32_Addr) location;
 131                        *loc32 = (*loc32 & ~0x3fffff) |
 132                                ((v >> 2) & 0x3fffff);
 133                        break;
 134
 135                case R_SPARC_LO10:
 136                        *loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff);
 137                        break;
 138
 139                case R_SPARC_HI22:
 140                        *loc32 = (*loc32 & ~0x3fffff) |
 141                                ((v >> 10) & 0x3fffff);
 142                        break;
 143
 144                default:
 145                        printk(KERN_ERR "module %s: Unknown relocation: %x\n",
 146                               me->name,
 147                               (int) (ELF32_R_TYPE(rel[i].r_info) & 0xff));
 148                        return -ENOEXEC;
 149                };
 150        }
 151        return 0;
 152}
 153
 154int module_finalize(const Elf_Ehdr *hdr,
 155                    const Elf_Shdr *sechdrs,
 156                    struct module *me)
 157{
 158        return 0;
 159}
 160
 161void module_arch_cleanup(struct module *mod)
 162{
 163}
 164