~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arc/kernel/module.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 19 static 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 /* ARC specific section quirks - before relocation loop in generic loader
 26  *
 27  * For dwarf unwinding out of modules, this needs to
 28  * 1. Ensure the .debug_frame is allocatable (ARC Linker bug: despite
 29  *    -fasynchronous-unwind-tables it doesn't).
 30  * 2. Since we are iterating thru sec hdr tbl anyways, make a note of
 31  *    the exact section index, for later use.
 32  */
 33 int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
 34                               char *secstr, struct module *mod)
 35 {
 36 #ifdef CONFIG_ARC_DW2_UNWIND
 37         int i;
 38 
 39         mod->arch.unw_sec_idx = 0;
 40         mod->arch.unw_info = NULL;
 41 
 42         for (i = 1; i < hdr->e_shnum; i++) {
 43                 if (strcmp(secstr+sechdrs[i].sh_name, ".debug_frame") == 0) {
 44                         sechdrs[i].sh_flags |= SHF_ALLOC;
 45                         mod->arch.unw_sec_idx = i;
 46                         break;
 47                 }
 48         }
 49 #endif
 50         return 0;
 51 }
 52 
 53 void module_arch_cleanup(struct module *mod)
 54 {
 55 #ifdef CONFIG_ARC_DW2_UNWIND
 56         if (mod->arch.unw_info)
 57                 unwind_remove_table(mod->arch.unw_info, 0);
 58 #endif
 59 }
 60 
 61 int apply_relocate_add(Elf32_Shdr *sechdrs,
 62                        const char *strtab,
 63                        unsigned int symindex,   /* sec index for sym tbl */
 64                        unsigned int relsec,     /* sec index for relo sec */
 65                        struct module *module)
 66 {
 67         int i, n;
 68         Elf32_Rela *rel_entry = (void *)sechdrs[relsec].sh_addr;
 69         Elf32_Sym *sym_entry, *sym_sec;
 70         Elf32_Addr relocation;
 71         Elf32_Addr location;
 72         Elf32_Addr sec_to_patch;
 73         int relo_type;
 74 
 75         sec_to_patch = sechdrs[sechdrs[relsec].sh_info].sh_addr;
 76         sym_sec = (Elf32_Sym *) sechdrs[symindex].sh_addr;
 77         n = sechdrs[relsec].sh_size / sizeof(*rel_entry);
 78 
 79         pr_debug("\n========== Module Sym reloc ===========================\n");
 80         pr_debug("Section to fixup %x\n", sec_to_patch);
 81         pr_debug("=========================================================\n");
 82         pr_debug("rela->r_off | rela->addend | sym->st_value | ADDR | VALUE\n");
 83         pr_debug("=========================================================\n");
 84 
 85         /* Loop thru entries in relocation section */
 86         for (i = 0; i < n; i++) {
 87 
 88                 /* This is where to make the change */
 89                 location = sec_to_patch + rel_entry[i].r_offset;
 90 
 91                 /* This is the symbol it is referring to.  Note that all
 92                    undefined symbols have been resolved.  */
 93                 sym_entry = sym_sec + ELF32_R_SYM(rel_entry[i].r_info);
 94 
 95                 relocation = sym_entry->st_value + rel_entry[i].r_addend;
 96 
 97                 pr_debug("\t%x\t\t%x\t\t%x  %x %x [%s]\n",
 98                         rel_entry[i].r_offset, rel_entry[i].r_addend,
 99                         sym_entry->st_value, location, relocation,
100                         strtab + sym_entry->st_name);
101 
102                 /* This assumes modules are built with -mlong-calls
103                  * so any branches/jumps are absolute 32 bit jmps
104                  * global data access again is abs 32 bit.
105                  * Both of these are handled by same relocation type
106                  */
107                 relo_type = ELF32_R_TYPE(rel_entry[i].r_info);
108 
109                 if (likely(R_ARC_32_ME == relo_type))
110                         arc_write_me((unsigned short *)location, relocation);
111                 else if (R_ARC_32 == relo_type)
112                         *((Elf32_Addr *) location) = relocation;
113                 else
114                         goto relo_err;
115 
116         }
117         return 0;
118 
119 relo_err:
120         pr_err("%s: unknown relocation: %u\n",
121                 module->name, ELF32_R_TYPE(rel_entry[i].r_info));
122         return -ENOEXEC;
123 
124 }
125 
126 /* Just before lift off: After sections have been relocated, we add the
127  * dwarf section to unwinder table pool
128  * This couldn't be done in module_frob_arch_sections() because
129  * relocations had not been applied by then
130  */
131 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
132                     struct module *mod)
133 {
134 #ifdef CONFIG_ARC_DW2_UNWIND
135         void *unw;
136         int unwsec = mod->arch.unw_sec_idx;
137 
138         if (unwsec) {
139                 unw = unwind_add_table(mod, (void *)sechdrs[unwsec].sh_addr,
140                                        sechdrs[unwsec].sh_size);
141                 mod->arch.unw_info = unw;
142         }
143 #endif
144         return 0;
145 }
146 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp