linux/arch/arc/kernel/module.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/moduleloader.h>
  11#include <linux/kernel.h>
  12#include <linux/elf.h>
  13#include <linux/vmalloc.h>
  14#include <linux/slab.h>
  15#include <linux/fs.h>
  16#include <linux/string.h>
  17#include <asm/unwind.h>
  18
  19static inline void arc_write_me(unsigned short *addr, unsigned long value)
  20{
  21        *addr = (value & 0xffff0000) >> 16;
  22        *(addr + 1) = (value & 0xffff);
  23}
  24
  25/*
  26 * This gets called before relocation loop in generic loader
  27 * Make a note of the section index of unwinding section
  28 */
  29int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
  30                              char *secstr, struct module *mod)
  31{
  32#ifdef CONFIG_ARC_DW2_UNWIND
  33        mod->arch.unw_sec_idx = 0;
  34        mod->arch.unw_info = NULL;
  35#endif
  36        mod->arch.secstr = secstr;
  37        return 0;
  38}
  39
  40void module_arch_cleanup(struct module *mod)
  41{
  42#ifdef CONFIG_ARC_DW2_UNWIND
  43        if (mod->arch.unw_info)
  44                unwind_remove_table(mod->arch.unw_info, 0);
  45#endif
  46}
  47
  48int apply_relocate_add(Elf32_Shdr *sechdrs,
  49                       const char *strtab,
  50                       unsigned int symindex,   /* sec index for sym tbl */
  51                       unsigned int relsec,     /* sec index for relo sec */
  52                       struct module *module)
  53{
  54        int i, n, relo_type;
  55        Elf32_Rela *rel_entry = (void *)sechdrs[relsec].sh_addr;
  56        Elf32_Sym *sym_entry, *sym_sec;
  57        Elf32_Addr relocation, location, tgt_addr;
  58        unsigned int tgtsec;
  59
  60        /*
  61         * @relsec has relocations e.g. .rela.init.text
  62         * @tgtsec is section to patch e.g. .init.text
  63         */
  64        tgtsec = sechdrs[relsec].sh_info;
  65        tgt_addr = sechdrs[tgtsec].sh_addr;
  66        sym_sec = (Elf32_Sym *) sechdrs[symindex].sh_addr;
  67        n = sechdrs[relsec].sh_size / sizeof(*rel_entry);
  68
  69        pr_debug("\nSection to fixup %s @%x\n",
  70                 module->arch.secstr + sechdrs[tgtsec].sh_name, tgt_addr);
  71        pr_debug("=========================================================\n");
  72        pr_debug("r_off\tr_add\tst_value ADDRESS  VALUE\n");
  73        pr_debug("=========================================================\n");
  74
  75        /* Loop thru entries in relocation section */
  76        for (i = 0; i < n; i++) {
  77                const char *s;
  78
  79                /* This is where to make the change */
  80                location = tgt_addr + rel_entry[i].r_offset;
  81
  82                /* This is the symbol it is referring to.  Note that all
  83                   undefined symbols have been resolved.  */
  84                sym_entry = sym_sec + ELF32_R_SYM(rel_entry[i].r_info);
  85
  86                relocation = sym_entry->st_value + rel_entry[i].r_addend;
  87
  88                if (sym_entry->st_name == 0 && ELF_ST_TYPE (sym_entry->st_info) == STT_SECTION) {
  89                        s = module->arch.secstr + sechdrs[sym_entry->st_shndx].sh_name;
  90                } else {
  91                        s = strtab + sym_entry->st_name;
  92                }
  93
  94                pr_debug("   %x\t%x\t%x %x %x [%s]\n",
  95                         rel_entry[i].r_offset, rel_entry[i].r_addend,
  96                         sym_entry->st_value, location, relocation, s);
  97
  98                /* This assumes modules are built with -mlong-calls
  99                 * so any branches/jumps are absolute 32 bit jmps
 100                 * global data access again is abs 32 bit.
 101                 * Both of these are handled by same relocation type
 102                 */
 103                relo_type = ELF32_R_TYPE(rel_entry[i].r_info);
 104
 105                if (likely(R_ARC_32_ME == relo_type))   /* ME ( S + A ) */
 106                        arc_write_me((unsigned short *)location, relocation);
 107                else if (R_ARC_32 == relo_type)         /* ( S + A ) */
 108                        *((Elf32_Addr *) location) = relocation;
 109                else if (R_ARC_32_PCREL == relo_type)   /* ( S + A ) - PDATA ) */
 110                        *((Elf32_Addr *) location) = relocation - location;
 111                else
 112                        goto relo_err;
 113
 114        }
 115
 116#ifdef CONFIG_ARC_DW2_UNWIND
 117        if (strcmp(module->arch.secstr+sechdrs[tgtsec].sh_name, ".eh_frame") == 0)
 118                module->arch.unw_sec_idx = tgtsec;
 119#endif
 120
 121        return 0;
 122
 123relo_err:
 124        pr_err("%s: unknown relocation: %u\n",
 125                module->name, ELF32_R_TYPE(rel_entry[i].r_info));
 126        return -ENOEXEC;
 127
 128}
 129
 130/* Just before lift off: After sections have been relocated, we add the
 131 * dwarf section to unwinder table pool
 132 * This couldn't be done in module_frob_arch_sections() because
 133 * relocations had not been applied by then
 134 */
 135int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 136                    struct module *mod)
 137{
 138#ifdef CONFIG_ARC_DW2_UNWIND
 139        void *unw;
 140        int unwsec = mod->arch.unw_sec_idx;
 141
 142        if (unwsec) {
 143                unw = unwind_add_table(mod, (void *)sechdrs[unwsec].sh_addr,
 144                                       sechdrs[unwsec].sh_size);
 145                mod->arch.unw_info = unw;
 146        }
 147#endif
 148        return 0;
 149}
 150