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