diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-08-15 15:46:28 +0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-15 15:46:28 +0400 |
commit | 5aa37e4f0614e3b1f385426ce1e962e84c275bdf (patch) | |
tree | 3d8c30207989d09fde8ffb2c3c44c6b923d70062 /arch/v850/kernel/module.c | |
parent | d4c63ec060f3315653c0ae5bc3a7fe2419a2282f (diff) | |
parent | b76d69ed721e8365739c3bd5dd7891efbea88494 (diff) | |
download | linux-5aa37e4f0614e3b1f385426ce1e962e84c275bdf.tar.xz |
Merge branch 'x86/core' into x86/apic
Diffstat (limited to 'arch/v850/kernel/module.c')
-rw-r--r-- | arch/v850/kernel/module.c | 237 |
1 files changed, 0 insertions, 237 deletions
diff --git a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c deleted file mode 100644 index 64aeb3e37c52..000000000000 --- a/arch/v850/kernel/module.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * arch/v850/kernel/module.c -- Architecture-specific module functions - * - * Copyright (C) 2002,03 NEC Electronics Corporation - * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> - * Copyright (C) 2001,03 Rusty Russell - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - * Written by Miles Bader <miles@gnu.org> - * - * Derived in part from arch/ppc/kernel/module.c - */ - -#include <linux/kernel.h> -#include <linux/vmalloc.h> -#include <linux/moduleloader.h> -#include <linux/elf.h> - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt , ...) -#endif - -void *module_alloc (unsigned long size) -{ - return size == 0 ? 0 : vmalloc (size); -} - -void module_free (struct module *mod, void *module_region) -{ - vfree (module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -int module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, - struct module *mod) -{ - return 0; -} - -/* Count how many different relocations (different symbol, different - addend) */ -static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) -{ - unsigned int i, j, ret = 0; - - /* Sure, this is order(n^2), but it's usually short, and not - time critical */ - for (i = 0; i < num; i++) { - for (j = 0; j < i; j++) { - /* If this addend appeared before, it's - already been counted */ - if (ELF32_R_SYM(rela[i].r_info) - == ELF32_R_SYM(rela[j].r_info) - && rela[i].r_addend == rela[j].r_addend) - break; - } - if (j == i) ret++; - } - return ret; -} - -/* Get the potential trampolines size required of the init and - non-init sections */ -static unsigned long get_plt_size(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - int is_init) -{ - unsigned long ret = 0; - unsigned i; - - /* Everything marked ALLOC (this includes the exported - symbols) */ - for (i = 1; i < hdr->e_shnum; i++) { - /* If it's called *.init*, and we're not init, we're - not interested */ - if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) - != is_init) - continue; - - if (sechdrs[i].sh_type == SHT_RELA) { - DEBUGP("Found relocations in section %u\n", i); - DEBUGP("Ptr: %p. Number: %u\n", - (void *)hdr + sechdrs[i].sh_offset, - sechdrs[i].sh_size / sizeof(Elf32_Rela)); - ret += count_relocs((void *)hdr - + sechdrs[i].sh_offset, - sechdrs[i].sh_size - / sizeof(Elf32_Rela)) - * sizeof(struct v850_plt_entry); - } - } - - return ret; -} - -int module_frob_arch_sections(Elf32_Ehdr *hdr, - Elf32_Shdr *sechdrs, - char *secstrings, - struct module *me) -{ - unsigned int i; - - /* Find .plt and .pltinit sections */ - for (i = 0; i < hdr->e_shnum; i++) { - if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) - me->arch.init_plt_section = i; - else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) - me->arch.core_plt_section = i; - } - if (!me->arch.core_plt_section || !me->arch.init_plt_section) { - printk("Module doesn't contain .plt or .plt.init sections.\n"); - return -ENOEXEC; - } - - /* Override their sizes */ - sechdrs[me->arch.core_plt_section].sh_size - = get_plt_size(hdr, sechdrs, secstrings, 0); - sechdrs[me->arch.init_plt_section].sh_size - = get_plt_size(hdr, sechdrs, secstrings, 1); - return 0; -} - -int apply_relocate (Elf32_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relsec, - struct module *mod) -{ - printk ("Barf\n"); - return -ENOEXEC; -} - -/* Set up a trampoline in the PLT to bounce us to the distant function */ -static uint32_t do_plt_call (void *location, Elf32_Addr val, - Elf32_Shdr *sechdrs, struct module *mod) -{ - struct v850_plt_entry *entry; - /* Instructions used to do the indirect jump. */ - uint32_t tramp[2]; - - /* We have to trash a register, so we assume that any control - transfer more than 21-bits away must be a function call - (so we can use a call-clobbered register). */ - tramp[0] = 0x0621 + ((val & 0xffff) << 16); /* mov sym, r1 ... */ - tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */ - - /* Init, or core PLT? */ - if (location >= mod->module_core - && location < mod->module_core + mod->core_size) - entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; - else - entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; - - /* Find this entry, or if that fails, the next avail. entry */ - while (entry->tramp[0]) - if (entry->tramp[0] == tramp[0] && entry->tramp[1] == tramp[1]) - return (uint32_t)entry; - else - entry++; - - entry->tramp[0] = tramp[0]; - entry->tramp[1] = tramp[1]; - - return (uint32_t)entry; -} - -int apply_relocate_add (Elf32_Shdr *sechdrs, const char *strtab, - unsigned int symindex, unsigned int relsec, - struct module *mod) -{ - unsigned int i; - Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; - - DEBUGP ("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - - for (i = 0; i < sechdrs[relsec].sh_size / sizeof (*rela); i++) { - /* This is where to make the change */ - uint32_t *loc - = ((void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rela[i].r_offset); - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - Elf32_Sym *sym - = ((Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM (rela[i].r_info)); - uint32_t val = sym->st_value + rela[i].r_addend; - - switch (ELF32_R_TYPE (rela[i].r_info)) { - case R_V850_32: - /* We write two shorts instead of a long because even - 32-bit insns only need half-word alignment, but - 32-bit data writes need to be long-word aligned. */ - val += ((uint16_t *)loc)[0]; - val += ((uint16_t *)loc)[1] << 16; - ((uint16_t *)loc)[0] = val & 0xffff; - ((uint16_t *)loc)[1] = (val >> 16) & 0xffff; - break; - - case R_V850_22_PCREL: - /* Maybe jump indirectly via a PLT table entry. */ - if ((int32_t)(val - (uint32_t)loc) > 0x1fffff - || (int32_t)(val - (uint32_t)loc) < -0x200000) - val = do_plt_call (loc, val, sechdrs, mod); - - val -= (uint32_t)loc; - - /* We write two shorts instead of a long because - even 32-bit insns only need half-word alignment, - but 32-bit data writes need to be long-word - aligned. */ - ((uint16_t *)loc)[0] = - (*(uint16_t *)loc & 0xffc0) /* opcode + reg */ - | ((val >> 16) & 0xffc03f); /* offs high */ - ((uint16_t *)loc)[1] = - (val & 0xffff); /* offs low */ - break; - - default: - printk (KERN_ERR "module %s: Unknown reloc: %u\n", - mod->name, ELF32_R_TYPE (rela[i].r_info)); - return -ENOEXEC; - } - } - - return 0; -} - -void -module_arch_cleanup(struct module *mod) -{ -} |