2 * arch/v850/kernel/module.c -- Architecture-specific module functions
4 * Copyright (C) 2002,03 NEC Electronics Corporation
5 * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
6 * Copyright (C) 2001,03 Rusty Russell
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file COPYING in the main directory of this
10 * archive for more details.
12 * Written by Miles Bader <miles@gnu.org>
14 * Derived in part from arch/ppc/kernel/module.c
17 #include <linux/kernel.h>
18 #include <linux/vmalloc.h>
19 #include <linux/moduleloader.h>
20 #include <linux/elf.h>
25 #define DEBUGP(fmt , ...)
28 void *module_alloc (unsigned long size
)
30 return size
== 0 ? 0 : vmalloc (size
);
33 void module_free (struct module
*mod
, void *module_region
)
35 vfree (module_region
);
36 /* FIXME: If module_region == mod->init_region, trim exception
40 int module_finalize (const Elf_Ehdr
*hdr
, const Elf_Shdr
*sechdrs
,
46 /* Count how many different relocations (different symbol, different
48 static unsigned int count_relocs(const Elf32_Rela
*rela
, unsigned int num
)
50 unsigned int i
, j
, ret
= 0;
52 /* Sure, this is order(n^2), but it's usually short, and not
54 for (i
= 0; i
< num
; i
++) {
55 for (j
= 0; j
< i
; j
++) {
56 /* If this addend appeared before, it's
57 already been counted */
58 if (ELF32_R_SYM(rela
[i
].r_info
)
59 == ELF32_R_SYM(rela
[j
].r_info
)
60 && rela
[i
].r_addend
== rela
[j
].r_addend
)
68 /* Get the potential trampolines size required of the init and
70 static unsigned long get_plt_size(const Elf32_Ehdr
*hdr
,
71 const Elf32_Shdr
*sechdrs
,
72 const char *secstrings
,
75 unsigned long ret
= 0;
78 /* Everything marked ALLOC (this includes the exported
80 for (i
= 1; i
< hdr
->e_shnum
; i
++) {
81 /* If it's called *.init*, and we're not init, we're
83 if ((strstr(secstrings
+ sechdrs
[i
].sh_name
, ".init") != 0)
87 if (sechdrs
[i
].sh_type
== SHT_RELA
) {
88 DEBUGP("Found relocations in section %u\n", i
);
89 DEBUGP("Ptr: %p. Number: %u\n",
90 (void *)hdr
+ sechdrs
[i
].sh_offset
,
91 sechdrs
[i
].sh_size
/ sizeof(Elf32_Rela
));
92 ret
+= count_relocs((void *)hdr
93 + sechdrs
[i
].sh_offset
,
96 * sizeof(struct v850_plt_entry
);
103 int module_frob_arch_sections(Elf32_Ehdr
*hdr
,
110 /* Find .plt and .pltinit sections */
111 for (i
= 0; i
< hdr
->e_shnum
; i
++) {
112 if (strcmp(secstrings
+ sechdrs
[i
].sh_name
, ".init.plt") == 0)
113 me
->arch
.init_plt_section
= i
;
114 else if (strcmp(secstrings
+ sechdrs
[i
].sh_name
, ".plt") == 0)
115 me
->arch
.core_plt_section
= i
;
117 if (!me
->arch
.core_plt_section
|| !me
->arch
.init_plt_section
) {
118 printk("Module doesn't contain .plt or .plt.init sections.\n");
122 /* Override their sizes */
123 sechdrs
[me
->arch
.core_plt_section
].sh_size
124 = get_plt_size(hdr
, sechdrs
, secstrings
, 0);
125 sechdrs
[me
->arch
.init_plt_section
].sh_size
126 = get_plt_size(hdr
, sechdrs
, secstrings
, 1);
130 int apply_relocate (Elf32_Shdr
*sechdrs
, const char *strtab
,
131 unsigned int symindex
, unsigned int relsec
,
138 /* Set up a trampoline in the PLT to bounce us to the distant function */
139 static uint32_t do_plt_call (void *location
, Elf32_Addr val
,
140 Elf32_Shdr
*sechdrs
, struct module
*mod
)
142 struct v850_plt_entry
*entry
;
143 /* Instructions used to do the indirect jump. */
146 /* We have to trash a register, so we assume that any control
147 transfer more than 21-bits away must be a function call
148 (so we can use a call-clobbered register). */
149 tramp
[0] = 0x0621 + ((val
& 0xffff) << 16); /* mov sym, r1 ... */
150 tramp
[1] = ((val
>> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
152 /* Init, or core PLT? */
153 if (location
>= mod
->module_core
154 && location
< mod
->module_core
+ mod
->core_size
)
155 entry
= (void *)sechdrs
[mod
->arch
.core_plt_section
].sh_addr
;
157 entry
= (void *)sechdrs
[mod
->arch
.init_plt_section
].sh_addr
;
159 /* Find this entry, or if that fails, the next avail. entry */
160 while (entry
->tramp
[0])
161 if (entry
->tramp
[0] == tramp
[0] && entry
->tramp
[1] == tramp
[1])
162 return (uint32_t)entry
;
166 entry
->tramp
[0] = tramp
[0];
167 entry
->tramp
[1] = tramp
[1];
169 return (uint32_t)entry
;
172 int apply_relocate_add (Elf32_Shdr
*sechdrs
, const char *strtab
,
173 unsigned int symindex
, unsigned int relsec
,
177 Elf32_Rela
*rela
= (void *)sechdrs
[relsec
].sh_addr
;
179 DEBUGP ("Applying relocate section %u to %u\n", relsec
,
180 sechdrs
[relsec
].sh_info
);
182 for (i
= 0; i
< sechdrs
[relsec
].sh_size
/ sizeof (*rela
); i
++) {
183 /* This is where to make the change */
185 = ((void *)sechdrs
[sechdrs
[relsec
].sh_info
].sh_addr
187 /* This is the symbol it is referring to. Note that all
188 undefined symbols have been resolved. */
190 = ((Elf32_Sym
*)sechdrs
[symindex
].sh_addr
191 + ELF32_R_SYM (rela
[i
].r_info
));
192 uint32_t val
= sym
->st_value
+ rela
[i
].r_addend
;
194 switch (ELF32_R_TYPE (rela
[i
].r_info
)) {
196 /* We write two shorts instead of a long because even
197 32-bit insns only need half-word alignment, but
198 32-bit data writes need to be long-word aligned. */
199 val
+= ((uint16_t *)loc
)[0];
200 val
+= ((uint16_t *)loc
)[1] << 16;
201 ((uint16_t *)loc
)[0] = val
& 0xffff;
202 ((uint16_t *)loc
)[1] = (val
>> 16) & 0xffff;
205 case R_V850_22_PCREL
:
206 /* Maybe jump indirectly via a PLT table entry. */
207 if ((int32_t)(val
- (uint32_t)loc
) > 0x1fffff
208 || (int32_t)(val
- (uint32_t)loc
) < -0x200000)
209 val
= do_plt_call (loc
, val
, sechdrs
, mod
);
211 val
-= (uint32_t)loc
;
213 /* We write two shorts instead of a long because
214 even 32-bit insns only need half-word alignment,
215 but 32-bit data writes need to be long-word
217 ((uint16_t *)loc
)[0] =
218 (*(uint16_t *)loc
& 0xffc0) /* opcode + reg */
219 | ((val
>> 16) & 0xffc03f); /* offs high */
220 ((uint16_t *)loc
)[1] =
221 (val
& 0xffff); /* offs low */
225 printk (KERN_ERR
"module %s: Unknown reloc: %u\n",
226 mod
->name
, ELF32_R_TYPE (rela
[i
].r_info
));
235 module_arch_cleanup(struct module
*mod
)