PageRenderTime 49ms CodeModel.GetById 15ms app.highlight 8ms RepoModel.GetById 24ms app.codeStats 0ms

/arch/unicore32/kernel/module.c

https://bitbucket.org/ndreys/linux-sunxi
C | 152 lines | 117 code | 23 blank | 12 comment | 10 complexity | 5568f205a525e224acc3c435d681b2e1 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * linux/arch/unicore32/kernel/module.c
  3 *
  4 * Code specific to PKUnity SoC and UniCore ISA
  5 *
  6 * Copyright (C) 2001-2010 GUAN Xue-tao
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License version 2 as
 10 * published by the Free Software Foundation.
 11 */
 12#include <linux/module.h>
 13#include <linux/moduleloader.h>
 14#include <linux/kernel.h>
 15#include <linux/mm.h>
 16#include <linux/elf.h>
 17#include <linux/vmalloc.h>
 18#include <linux/fs.h>
 19#include <linux/string.h>
 20#include <linux/gfp.h>
 21
 22#include <asm/pgtable.h>
 23#include <asm/sections.h>
 24
 25void *module_alloc(unsigned long size)
 26{
 27	struct vm_struct *area;
 28
 29	size = PAGE_ALIGN(size);
 30	if (!size)
 31		return NULL;
 32
 33	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
 34	if (!area)
 35		return NULL;
 36
 37	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
 38}
 39
 40void module_free(struct module *module, void *region)
 41{
 42	vfree(region);
 43}
 44
 45int module_frob_arch_sections(Elf_Ehdr *hdr,
 46			      Elf_Shdr *sechdrs,
 47			      char *secstrings,
 48			      struct module *mod)
 49{
 50	return 0;
 51}
 52
 53int
 54apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 55	       unsigned int relindex, struct module *module)
 56{
 57	Elf32_Shdr *symsec = sechdrs + symindex;
 58	Elf32_Shdr *relsec = sechdrs + relindex;
 59	Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
 60	Elf32_Rel *rel = (void *)relsec->sh_addr;
 61	unsigned int i;
 62
 63	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
 64		unsigned long loc;
 65		Elf32_Sym *sym;
 66		s32 offset;
 67
 68		offset = ELF32_R_SYM(rel->r_info);
 69		if (offset < 0 || offset >
 70				(symsec->sh_size / sizeof(Elf32_Sym))) {
 71			printk(KERN_ERR "%s: bad relocation, "
 72					"section %d reloc %d\n",
 73					module->name, relindex, i);
 74			return -ENOEXEC;
 75		}
 76
 77		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
 78
 79		if (rel->r_offset < 0 || rel->r_offset >
 80				dstsec->sh_size - sizeof(u32)) {
 81			printk(KERN_ERR "%s: out of bounds relocation, "
 82				"section %d reloc %d offset %d size %d\n",
 83				module->name, relindex, i, rel->r_offset,
 84				dstsec->sh_size);
 85			return -ENOEXEC;
 86		}
 87
 88		loc = dstsec->sh_addr + rel->r_offset;
 89
 90		switch (ELF32_R_TYPE(rel->r_info)) {
 91		case R_UNICORE_NONE:
 92			/* ignore */
 93			break;
 94
 95		case R_UNICORE_ABS32:
 96			*(u32 *)loc += sym->st_value;
 97			break;
 98
 99		case R_UNICORE_PC24:
100		case R_UNICORE_CALL:
101		case R_UNICORE_JUMP24:
102			offset = (*(u32 *)loc & 0x00ffffff) << 2;
103			if (offset & 0x02000000)
104				offset -= 0x04000000;
105
106			offset += sym->st_value - loc;
107			if (offset & 3 ||
108			    offset <= (s32)0xfe000000 ||
109			    offset >= (s32)0x02000000) {
110				printk(KERN_ERR
111				       "%s: relocation out of range, section "
112				       "%d reloc %d sym '%s'\n", module->name,
113				       relindex, i, strtab + sym->st_name);
114				return -ENOEXEC;
115			}
116
117			offset >>= 2;
118
119			*(u32 *)loc &= 0xff000000;
120			*(u32 *)loc |= offset & 0x00ffffff;
121			break;
122
123		default:
124			printk(KERN_ERR "%s: unknown relocation: %u\n",
125			       module->name, ELF32_R_TYPE(rel->r_info));
126			return -ENOEXEC;
127		}
128	}
129	return 0;
130}
131
132int
133apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
134		   unsigned int symindex, unsigned int relsec,
135		   struct module *module)
136{
137	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
138	       module->name);
139	return -ENOEXEC;
140}
141
142int
143module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
144		struct module *module)
145{
146	return 0;
147}
148
149void
150module_arch_cleanup(struct module *mod)
151{
152}