Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/unicore32/kernel/module.c
10817 views
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
25
void *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
40
void module_free(struct module *module, void *region)
41
{
42
vfree(region);
43
}
44
45
int module_frob_arch_sections(Elf_Ehdr *hdr,
46
Elf_Shdr *sechdrs,
47
char *secstrings,
48
struct module *mod)
49
{
50
return 0;
51
}
52
53
int
54
apply_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
132
int
133
apply_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
142
int
143
module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
144
struct module *module)
145
{
146
return 0;
147
}
148
149
void
150
module_arch_cleanup(struct module *mod)
151
{
152
}
153
154