xref: /openbmc/linux/arch/powerpc/kernel/module_32.c (revision ed981856)
1ed981856SPaul Mackerras /*  Kernel module help for PPC.
2ed981856SPaul Mackerras     Copyright (C) 2001 Rusty Russell.
3ed981856SPaul Mackerras 
4ed981856SPaul Mackerras     This program is free software; you can redistribute it and/or modify
5ed981856SPaul Mackerras     it under the terms of the GNU General Public License as published by
6ed981856SPaul Mackerras     the Free Software Foundation; either version 2 of the License, or
7ed981856SPaul Mackerras     (at your option) any later version.
8ed981856SPaul Mackerras 
9ed981856SPaul Mackerras     This program is distributed in the hope that it will be useful,
10ed981856SPaul Mackerras     but WITHOUT ANY WARRANTY; without even the implied warranty of
11ed981856SPaul Mackerras     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12ed981856SPaul Mackerras     GNU General Public License for more details.
13ed981856SPaul Mackerras 
14ed981856SPaul Mackerras     You should have received a copy of the GNU General Public License
15ed981856SPaul Mackerras     along with this program; if not, write to the Free Software
16ed981856SPaul Mackerras     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17ed981856SPaul Mackerras */
18ed981856SPaul Mackerras #include <linux/module.h>
19ed981856SPaul Mackerras #include <linux/moduleloader.h>
20ed981856SPaul Mackerras #include <linux/elf.h>
21ed981856SPaul Mackerras #include <linux/vmalloc.h>
22ed981856SPaul Mackerras #include <linux/fs.h>
23ed981856SPaul Mackerras #include <linux/string.h>
24ed981856SPaul Mackerras #include <linux/kernel.h>
25ed981856SPaul Mackerras #include <linux/cache.h>
26ed981856SPaul Mackerras 
27ed981856SPaul Mackerras #if 0
28ed981856SPaul Mackerras #define DEBUGP printk
29ed981856SPaul Mackerras #else
30ed981856SPaul Mackerras #define DEBUGP(fmt , ...)
31ed981856SPaul Mackerras #endif
32ed981856SPaul Mackerras 
33ed981856SPaul Mackerras LIST_HEAD(module_bug_list);
34ed981856SPaul Mackerras 
35ed981856SPaul Mackerras void *module_alloc(unsigned long size)
36ed981856SPaul Mackerras {
37ed981856SPaul Mackerras 	if (size == 0)
38ed981856SPaul Mackerras 		return NULL;
39ed981856SPaul Mackerras 	return vmalloc(size);
40ed981856SPaul Mackerras }
41ed981856SPaul Mackerras 
42ed981856SPaul Mackerras /* Free memory returned from module_alloc */
43ed981856SPaul Mackerras void module_free(struct module *mod, void *module_region)
44ed981856SPaul Mackerras {
45ed981856SPaul Mackerras 	vfree(module_region);
46ed981856SPaul Mackerras 	/* FIXME: If module_region == mod->init_region, trim exception
47ed981856SPaul Mackerras            table entries. */
48ed981856SPaul Mackerras }
49ed981856SPaul Mackerras 
50ed981856SPaul Mackerras /* Count how many different relocations (different symbol, different
51ed981856SPaul Mackerras    addend) */
52ed981856SPaul Mackerras static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num)
53ed981856SPaul Mackerras {
54ed981856SPaul Mackerras 	unsigned int i, j, ret = 0;
55ed981856SPaul Mackerras 
56ed981856SPaul Mackerras 	/* Sure, this is order(n^2), but it's usually short, and not
57ed981856SPaul Mackerras            time critical */
58ed981856SPaul Mackerras 	for (i = 0; i < num; i++) {
59ed981856SPaul Mackerras 		for (j = 0; j < i; j++) {
60ed981856SPaul Mackerras 			/* If this addend appeared before, it's
61ed981856SPaul Mackerras                            already been counted */
62ed981856SPaul Mackerras 			if (ELF32_R_SYM(rela[i].r_info)
63ed981856SPaul Mackerras 			    == ELF32_R_SYM(rela[j].r_info)
64ed981856SPaul Mackerras 			    && rela[i].r_addend == rela[j].r_addend)
65ed981856SPaul Mackerras 				break;
66ed981856SPaul Mackerras 		}
67ed981856SPaul Mackerras 		if (j == i) ret++;
68ed981856SPaul Mackerras 	}
69ed981856SPaul Mackerras 	return ret;
70ed981856SPaul Mackerras }
71ed981856SPaul Mackerras 
72ed981856SPaul Mackerras /* Get the potential trampolines size required of the init and
73ed981856SPaul Mackerras    non-init sections */
74ed981856SPaul Mackerras static unsigned long get_plt_size(const Elf32_Ehdr *hdr,
75ed981856SPaul Mackerras 				  const Elf32_Shdr *sechdrs,
76ed981856SPaul Mackerras 				  const char *secstrings,
77ed981856SPaul Mackerras 				  int is_init)
78ed981856SPaul Mackerras {
79ed981856SPaul Mackerras 	unsigned long ret = 0;
80ed981856SPaul Mackerras 	unsigned i;
81ed981856SPaul Mackerras 
82ed981856SPaul Mackerras 	/* Everything marked ALLOC (this includes the exported
83ed981856SPaul Mackerras            symbols) */
84ed981856SPaul Mackerras 	for (i = 1; i < hdr->e_shnum; i++) {
85ed981856SPaul Mackerras 		/* If it's called *.init*, and we're not init, we're
86ed981856SPaul Mackerras                    not interested */
87ed981856SPaul Mackerras 		if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
88ed981856SPaul Mackerras 		    != is_init)
89ed981856SPaul Mackerras 			continue;
90ed981856SPaul Mackerras 
91ed981856SPaul Mackerras 		/* We don't want to look at debug sections. */
92ed981856SPaul Mackerras 		if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0)
93ed981856SPaul Mackerras 			continue;
94ed981856SPaul Mackerras 
95ed981856SPaul Mackerras 		if (sechdrs[i].sh_type == SHT_RELA) {
96ed981856SPaul Mackerras 			DEBUGP("Found relocations in section %u\n", i);
97ed981856SPaul Mackerras 			DEBUGP("Ptr: %p.  Number: %u\n",
98ed981856SPaul Mackerras 			       (void *)hdr + sechdrs[i].sh_offset,
99ed981856SPaul Mackerras 			       sechdrs[i].sh_size / sizeof(Elf32_Rela));
100ed981856SPaul Mackerras 			ret += count_relocs((void *)hdr
101ed981856SPaul Mackerras 					     + sechdrs[i].sh_offset,
102ed981856SPaul Mackerras 					     sechdrs[i].sh_size
103ed981856SPaul Mackerras 					     / sizeof(Elf32_Rela))
104ed981856SPaul Mackerras 				* sizeof(struct ppc_plt_entry);
105ed981856SPaul Mackerras 		}
106ed981856SPaul Mackerras 	}
107ed981856SPaul Mackerras 
108ed981856SPaul Mackerras 	return ret;
109ed981856SPaul Mackerras }
110ed981856SPaul Mackerras 
111ed981856SPaul Mackerras int module_frob_arch_sections(Elf32_Ehdr *hdr,
112ed981856SPaul Mackerras 			      Elf32_Shdr *sechdrs,
113ed981856SPaul Mackerras 			      char *secstrings,
114ed981856SPaul Mackerras 			      struct module *me)
115ed981856SPaul Mackerras {
116ed981856SPaul Mackerras 	unsigned int i;
117ed981856SPaul Mackerras 
118ed981856SPaul Mackerras 	/* Find .plt and .init.plt sections */
119ed981856SPaul Mackerras 	for (i = 0; i < hdr->e_shnum; i++) {
120ed981856SPaul Mackerras 		if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
121ed981856SPaul Mackerras 			me->arch.init_plt_section = i;
122ed981856SPaul Mackerras 		else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
123ed981856SPaul Mackerras 			me->arch.core_plt_section = i;
124ed981856SPaul Mackerras 	}
125ed981856SPaul Mackerras 	if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
126ed981856SPaul Mackerras 		printk("Module doesn't contain .plt or .init.plt sections.\n");
127ed981856SPaul Mackerras 		return -ENOEXEC;
128ed981856SPaul Mackerras 	}
129ed981856SPaul Mackerras 
130ed981856SPaul Mackerras 	/* Override their sizes */
131ed981856SPaul Mackerras 	sechdrs[me->arch.core_plt_section].sh_size
132ed981856SPaul Mackerras 		= get_plt_size(hdr, sechdrs, secstrings, 0);
133ed981856SPaul Mackerras 	sechdrs[me->arch.init_plt_section].sh_size
134ed981856SPaul Mackerras 		= get_plt_size(hdr, sechdrs, secstrings, 1);
135ed981856SPaul Mackerras 	return 0;
136ed981856SPaul Mackerras }
137ed981856SPaul Mackerras 
138ed981856SPaul Mackerras int apply_relocate(Elf32_Shdr *sechdrs,
139ed981856SPaul Mackerras 		   const char *strtab,
140ed981856SPaul Mackerras 		   unsigned int symindex,
141ed981856SPaul Mackerras 		   unsigned int relsec,
142ed981856SPaul Mackerras 		   struct module *module)
143ed981856SPaul Mackerras {
144ed981856SPaul Mackerras 	printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n",
145ed981856SPaul Mackerras 	       module->name);
146ed981856SPaul Mackerras 	return -ENOEXEC;
147ed981856SPaul Mackerras }
148ed981856SPaul Mackerras 
149ed981856SPaul Mackerras static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
150ed981856SPaul Mackerras {
151ed981856SPaul Mackerras 	if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
152ed981856SPaul Mackerras 	    && entry->jump[1] == 0x396b0000 + (val & 0xffff))
153ed981856SPaul Mackerras 		return 1;
154ed981856SPaul Mackerras 	return 0;
155ed981856SPaul Mackerras }
156ed981856SPaul Mackerras 
157ed981856SPaul Mackerras /* Set up a trampoline in the PLT to bounce us to the distant function */
158ed981856SPaul Mackerras static uint32_t do_plt_call(void *location,
159ed981856SPaul Mackerras 			    Elf32_Addr val,
160ed981856SPaul Mackerras 			    Elf32_Shdr *sechdrs,
161ed981856SPaul Mackerras 			    struct module *mod)
162ed981856SPaul Mackerras {
163ed981856SPaul Mackerras 	struct ppc_plt_entry *entry;
164ed981856SPaul Mackerras 
165ed981856SPaul Mackerras 	DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
166ed981856SPaul Mackerras 	/* Init, or core PLT? */
167ed981856SPaul Mackerras 	if (location >= mod->module_core
168ed981856SPaul Mackerras 	    && location < mod->module_core + mod->core_size)
169ed981856SPaul Mackerras 		entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
170ed981856SPaul Mackerras 	else
171ed981856SPaul Mackerras 		entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
172ed981856SPaul Mackerras 
173ed981856SPaul Mackerras 	/* Find this entry, or if that fails, the next avail. entry */
174ed981856SPaul Mackerras 	while (entry->jump[0]) {
175ed981856SPaul Mackerras 		if (entry_matches(entry, val)) return (uint32_t)entry;
176ed981856SPaul Mackerras 		entry++;
177ed981856SPaul Mackerras 	}
178ed981856SPaul Mackerras 
179ed981856SPaul Mackerras 	/* Stolen from Paul Mackerras as well... */
180ed981856SPaul Mackerras 	entry->jump[0] = 0x3d600000+((val+0x8000)>>16);	/* lis r11,sym@ha */
181ed981856SPaul Mackerras 	entry->jump[1] = 0x396b0000 + (val&0xffff);	/* addi r11,r11,sym@l*/
182ed981856SPaul Mackerras 	entry->jump[2] = 0x7d6903a6;			/* mtctr r11 */
183ed981856SPaul Mackerras 	entry->jump[3] = 0x4e800420;			/* bctr */
184ed981856SPaul Mackerras 
185ed981856SPaul Mackerras 	DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);
186ed981856SPaul Mackerras 	return (uint32_t)entry;
187ed981856SPaul Mackerras }
188ed981856SPaul Mackerras 
189ed981856SPaul Mackerras int apply_relocate_add(Elf32_Shdr *sechdrs,
190ed981856SPaul Mackerras 		       const char *strtab,
191ed981856SPaul Mackerras 		       unsigned int symindex,
192ed981856SPaul Mackerras 		       unsigned int relsec,
193ed981856SPaul Mackerras 		       struct module *module)
194ed981856SPaul Mackerras {
195ed981856SPaul Mackerras 	unsigned int i;
196ed981856SPaul Mackerras 	Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
197ed981856SPaul Mackerras 	Elf32_Sym *sym;
198ed981856SPaul Mackerras 	uint32_t *location;
199ed981856SPaul Mackerras 	uint32_t value;
200ed981856SPaul Mackerras 
201ed981856SPaul Mackerras 	DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
202ed981856SPaul Mackerras 	       sechdrs[relsec].sh_info);
203ed981856SPaul Mackerras 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
204ed981856SPaul Mackerras 		/* This is where to make the change */
205ed981856SPaul Mackerras 		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
206ed981856SPaul Mackerras 			+ rela[i].r_offset;
207ed981856SPaul Mackerras 		/* This is the symbol it is referring to.  Note that all
208ed981856SPaul Mackerras 		   undefined symbols have been resolved.  */
209ed981856SPaul Mackerras 		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
210ed981856SPaul Mackerras 			+ ELF32_R_SYM(rela[i].r_info);
211ed981856SPaul Mackerras 		/* `Everything is relative'. */
212ed981856SPaul Mackerras 		value = sym->st_value + rela[i].r_addend;
213ed981856SPaul Mackerras 
214ed981856SPaul Mackerras 		switch (ELF32_R_TYPE(rela[i].r_info)) {
215ed981856SPaul Mackerras 		case R_PPC_ADDR32:
216ed981856SPaul Mackerras 			/* Simply set it */
217ed981856SPaul Mackerras 			*(uint32_t *)location = value;
218ed981856SPaul Mackerras 			break;
219ed981856SPaul Mackerras 
220ed981856SPaul Mackerras 		case R_PPC_ADDR16_LO:
221ed981856SPaul Mackerras 			/* Low half of the symbol */
222ed981856SPaul Mackerras 			*(uint16_t *)location = value;
223ed981856SPaul Mackerras 			break;
224ed981856SPaul Mackerras 
225ed981856SPaul Mackerras 		case R_PPC_ADDR16_HA:
226ed981856SPaul Mackerras 			/* Sign-adjusted lower 16 bits: PPC ELF ABI says:
227ed981856SPaul Mackerras 			   (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF.
228ed981856SPaul Mackerras 			   This is the same, only sane.
229ed981856SPaul Mackerras 			 */
230ed981856SPaul Mackerras 			*(uint16_t *)location = (value + 0x8000) >> 16;
231ed981856SPaul Mackerras 			break;
232ed981856SPaul Mackerras 
233ed981856SPaul Mackerras 		case R_PPC_REL24:
234ed981856SPaul Mackerras 			if ((int)(value - (uint32_t)location) < -0x02000000
235ed981856SPaul Mackerras 			    || (int)(value - (uint32_t)location) >= 0x02000000)
236ed981856SPaul Mackerras 				value = do_plt_call(location, value,
237ed981856SPaul Mackerras 						    sechdrs, module);
238ed981856SPaul Mackerras 
239ed981856SPaul Mackerras 			/* Only replace bits 2 through 26 */
240ed981856SPaul Mackerras 			DEBUGP("REL24 value = %08X. location = %08X\n",
241ed981856SPaul Mackerras 			       value, (uint32_t)location);
242ed981856SPaul Mackerras 			DEBUGP("Location before: %08X.\n",
243ed981856SPaul Mackerras 			       *(uint32_t *)location);
244ed981856SPaul Mackerras 			*(uint32_t *)location
245ed981856SPaul Mackerras 				= (*(uint32_t *)location & ~0x03fffffc)
246ed981856SPaul Mackerras 				| ((value - (uint32_t)location)
247ed981856SPaul Mackerras 				   & 0x03fffffc);
248ed981856SPaul Mackerras 			DEBUGP("Location after: %08X.\n",
249ed981856SPaul Mackerras 			       *(uint32_t *)location);
250ed981856SPaul Mackerras 			DEBUGP("ie. jump to %08X+%08X = %08X\n",
251ed981856SPaul Mackerras 			       *(uint32_t *)location & 0x03fffffc,
252ed981856SPaul Mackerras 			       (uint32_t)location,
253ed981856SPaul Mackerras 			       (*(uint32_t *)location & 0x03fffffc)
254ed981856SPaul Mackerras 			       + (uint32_t)location);
255ed981856SPaul Mackerras 			break;
256ed981856SPaul Mackerras 
257ed981856SPaul Mackerras 		case R_PPC_REL32:
258ed981856SPaul Mackerras 			/* 32-bit relative jump. */
259ed981856SPaul Mackerras 			*(uint32_t *)location = value - (uint32_t)location;
260ed981856SPaul Mackerras 			break;
261ed981856SPaul Mackerras 
262ed981856SPaul Mackerras 		default:
263ed981856SPaul Mackerras 			printk("%s: unknown ADD relocation: %u\n",
264ed981856SPaul Mackerras 			       module->name,
265ed981856SPaul Mackerras 			       ELF32_R_TYPE(rela[i].r_info));
266ed981856SPaul Mackerras 			return -ENOEXEC;
267ed981856SPaul Mackerras 		}
268ed981856SPaul Mackerras 	}
269ed981856SPaul Mackerras 	return 0;
270ed981856SPaul Mackerras }
271ed981856SPaul Mackerras 
272ed981856SPaul Mackerras int module_finalize(const Elf_Ehdr *hdr,
273ed981856SPaul Mackerras 		    const Elf_Shdr *sechdrs,
274ed981856SPaul Mackerras 		    struct module *me)
275ed981856SPaul Mackerras {
276ed981856SPaul Mackerras 	char *secstrings;
277ed981856SPaul Mackerras 	unsigned int i;
278ed981856SPaul Mackerras 
279ed981856SPaul Mackerras 	me->arch.bug_table = NULL;
280ed981856SPaul Mackerras 	me->arch.num_bugs = 0;
281ed981856SPaul Mackerras 
282ed981856SPaul Mackerras 	/* Find the __bug_table section, if present */
283ed981856SPaul Mackerras 	secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
284ed981856SPaul Mackerras 	for (i = 1; i < hdr->e_shnum; i++) {
285ed981856SPaul Mackerras 		if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
286ed981856SPaul Mackerras 			continue;
287ed981856SPaul Mackerras 		me->arch.bug_table = (void *) sechdrs[i].sh_addr;
288ed981856SPaul Mackerras 		me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
289ed981856SPaul Mackerras 		break;
290ed981856SPaul Mackerras 	}
291ed981856SPaul Mackerras 
292ed981856SPaul Mackerras 	/*
293ed981856SPaul Mackerras 	 * Strictly speaking this should have a spinlock to protect against
294ed981856SPaul Mackerras 	 * traversals, but since we only traverse on BUG()s, a spinlock
295ed981856SPaul Mackerras 	 * could potentially lead to deadlock and thus be counter-productive.
296ed981856SPaul Mackerras 	 */
297ed981856SPaul Mackerras 	list_add(&me->arch.bug_list, &module_bug_list);
298ed981856SPaul Mackerras 
299ed981856SPaul Mackerras 	return 0;
300ed981856SPaul Mackerras }
301ed981856SPaul Mackerras 
302ed981856SPaul Mackerras void module_arch_cleanup(struct module *mod)
303ed981856SPaul Mackerras {
304ed981856SPaul Mackerras 	list_del(&mod->arch.bug_list);
305ed981856SPaul Mackerras }
306ed981856SPaul Mackerras 
307ed981856SPaul Mackerras struct bug_entry *module_find_bug(unsigned long bugaddr)
308ed981856SPaul Mackerras {
309ed981856SPaul Mackerras 	struct mod_arch_specific *mod;
310ed981856SPaul Mackerras 	unsigned int i;
311ed981856SPaul Mackerras 	struct bug_entry *bug;
312ed981856SPaul Mackerras 
313ed981856SPaul Mackerras 	list_for_each_entry(mod, &module_bug_list, bug_list) {
314ed981856SPaul Mackerras 		bug = mod->bug_table;
315ed981856SPaul Mackerras 		for (i = 0; i < mod->num_bugs; ++i, ++bug)
316ed981856SPaul Mackerras 			if (bugaddr == bug->bug_addr)
317ed981856SPaul Mackerras 				return bug;
318ed981856SPaul Mackerras 	}
319ed981856SPaul Mackerras 	return NULL;
320ed981856SPaul Mackerras }
321