root/arch/unicore32/kernel/module.c

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

DEFINITIONS

This source file includes following definitions.
  1. module_alloc
  2. apply_relocate

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/arch/unicore32/kernel/module.c
   4  *
   5  * Code specific to PKUnity SoC and UniCore ISA
   6  *
   7  * Copyright (C) 2001-2010 GUAN Xue-tao
   8  */
   9 #include <linux/module.h>
  10 #include <linux/moduleloader.h>
  11 #include <linux/kernel.h>
  12 #include <linux/mm.h>
  13 #include <linux/elf.h>
  14 #include <linux/vmalloc.h>
  15 #include <linux/fs.h>
  16 #include <linux/string.h>
  17 #include <linux/gfp.h>
  18 
  19 #include <asm/pgtable.h>
  20 #include <asm/sections.h>
  21 
  22 void *module_alloc(unsigned long size)
  23 {
  24         return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
  25                                 GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
  26                                 __builtin_return_address(0));
  27 }
  28 
  29 int
  30 apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
  31                unsigned int relindex, struct module *module)
  32 {
  33         Elf32_Shdr *symsec = sechdrs + symindex;
  34         Elf32_Shdr *relsec = sechdrs + relindex;
  35         Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
  36         Elf32_Rel *rel = (void *)relsec->sh_addr;
  37         unsigned int i;
  38 
  39         for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
  40                 unsigned long loc;
  41                 Elf32_Sym *sym;
  42                 s32 offset;
  43 
  44                 offset = ELF32_R_SYM(rel->r_info);
  45                 if (offset < 0 || offset >
  46                                 (symsec->sh_size / sizeof(Elf32_Sym))) {
  47                         printk(KERN_ERR "%s: bad relocation, "
  48                                         "section %d reloc %d\n",
  49                                         module->name, relindex, i);
  50                         return -ENOEXEC;
  51                 }
  52 
  53                 sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
  54 
  55                 if (rel->r_offset < 0 || rel->r_offset >
  56                                 dstsec->sh_size - sizeof(u32)) {
  57                         printk(KERN_ERR "%s: out of bounds relocation, "
  58                                 "section %d reloc %d offset %d size %d\n",
  59                                 module->name, relindex, i, rel->r_offset,
  60                                 dstsec->sh_size);
  61                         return -ENOEXEC;
  62                 }
  63 
  64                 loc = dstsec->sh_addr + rel->r_offset;
  65 
  66                 switch (ELF32_R_TYPE(rel->r_info)) {
  67                 case R_UNICORE_NONE:
  68                         /* ignore */
  69                         break;
  70 
  71                 case R_UNICORE_ABS32:
  72                         *(u32 *)loc += sym->st_value;
  73                         break;
  74 
  75                 case R_UNICORE_PC24:
  76                 case R_UNICORE_CALL:
  77                 case R_UNICORE_JUMP24:
  78                         offset = (*(u32 *)loc & 0x00ffffff) << 2;
  79                         if (offset & 0x02000000)
  80                                 offset -= 0x04000000;
  81 
  82                         offset += sym->st_value - loc;
  83                         if (offset & 3 ||
  84                             offset <= (s32)0xfe000000 ||
  85                             offset >= (s32)0x02000000) {
  86                                 printk(KERN_ERR
  87                                        "%s: relocation out of range, section "
  88                                        "%d reloc %d sym '%s'\n", module->name,
  89                                        relindex, i, strtab + sym->st_name);
  90                                 return -ENOEXEC;
  91                         }
  92 
  93                         offset >>= 2;
  94 
  95                         *(u32 *)loc &= 0xff000000;
  96                         *(u32 *)loc |= offset & 0x00ffffff;
  97                         break;
  98 
  99                 default:
 100                         printk(KERN_ERR "%s: unknown relocation: %u\n",
 101                                module->name, ELF32_R_TYPE(rel->r_info));
 102                         return -ENOEXEC;
 103                 }
 104         }
 105         return 0;
 106 }

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