18 #include <linux/module.h>
20 #include <linux/elf.h>
23 #include <linux/string.h>
24 #include <linux/kernel.h>
35 #define DEBUGP(fmt , ...)
40 static unsigned int count_relocs(
const Elf32_Rela *rela,
unsigned int num)
42 unsigned int i, r_info, r_addend, _count_relocs;
47 for (i = 0; i < num; i++)
51 r_addend != rela[i].r_addend)) {
57 #ifdef CONFIG_DYNAMIC_FTRACE
63 static int relacmp(
const void *_x,
const void *_y)
86 static void relaswap(
void *_x,
void *_y,
int size)
105 const char *secstrings,
108 unsigned long ret = 0;
113 for (i = 1; i < hdr->
e_shnum; i++) {
116 if ((
strstr(secstrings + sechdrs[i].sh_name,
".init") != 0)
121 if (
strstr(secstrings + sechdrs[i].sh_name,
".debug") != 0)
124 if (sechdrs[i].sh_type ==
SHT_RELA) {
125 DEBUGP(
"Found relocations in section %u\n", i);
126 DEBUGP(
"Ptr: %p. Number: %u\n",
127 (
void *)hdr + sechdrs[i].sh_offset,
135 sort((
void *)hdr + sechdrs[i].sh_offset,
139 ret += count_relocs((
void *)hdr
140 + sechdrs[i].sh_offset,
143 *
sizeof(
struct ppc_plt_entry);
158 for (i = 0; i < hdr->
e_shnum; i++) {
159 if (
strcmp(secstrings + sechdrs[i].sh_name,
".init.plt") == 0)
160 me->arch.init_plt_section =
i;
161 else if (
strcmp(secstrings + sechdrs[i].sh_name,
".plt") == 0)
162 me->arch.core_plt_section =
i;
164 if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
165 printk(
"Module doesn't contain .plt or .init.plt sections.\n");
170 sechdrs[me->arch.core_plt_section].
sh_size
171 = get_plt_size(hdr, sechdrs, secstrings, 0);
172 sechdrs[me->arch.init_plt_section].
sh_size
173 = get_plt_size(hdr, sechdrs, secstrings, 1);
179 if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16)
180 && entry->jump[1] == 0x398c0000 + (val & 0xffff))
191 struct ppc_plt_entry *
entry;
193 DEBUGP(
"Doing plt for call to 0x%x at 0x%x\n", val, (
unsigned int)location);
195 if (location >= mod->module_core
196 && location < mod->module_core + mod->core_size)
197 entry = (
void *)sechdrs[mod->arch.core_plt_section].
sh_addr;
199 entry = (
void *)sechdrs[mod->arch.init_plt_section].
sh_addr;
202 while (entry->jump[0]) {
207 entry->jump[0] = 0x3d800000+((val+0x8000)>>16);
208 entry->jump[1] = 0x398c0000 + (val&0xffff);
209 entry->jump[2] = 0x7d8903a6;
210 entry->jump[3] = 0x4e800420;
212 DEBUGP(
"Initialized plt for 0x%x at %p\n", val, entry);
218 unsigned int symindex,
223 Elf32_Rela *rela = (
void *)sechdrs[relsec].sh_addr;
228 DEBUGP(
"Applying ADD relocate section %u to %u\n", relsec,
229 sechdrs[relsec].sh_info);
230 for (i = 0; i < sechdrs[relsec].
sh_size /
sizeof(*rela); i++) {
232 location = (
void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
236 sym = (
Elf32_Sym *)sechdrs[symindex].sh_addr
254 *(
uint16_t *)location = (value >> 16);
262 *(
uint16_t *)location = (value + 0x8000) >> 16;
266 if ((
int)(value - (
uint32_t)location) < -0x02000000
268 value = do_plt_call(location, value,
272 DEBUGP(
"REL24 value = %08X. location = %08X\n",
274 DEBUGP(
"Location before: %08X.\n",
277 = (*(
uint32_t *)location & ~0x03fffffc)
280 DEBUGP(
"Location after: %08X.\n",
282 DEBUGP(
"ie. jump to %08X+%08X = %08X\n",
285 (*(
uint32_t *)location & 0x03fffffc)
295 printk(
"%s: unknown ADD relocation: %u\n",
301 #ifdef CONFIG_DYNAMIC_FTRACE
303 do_plt_call(module->module_core,
304 (
unsigned long)ftrace_caller,