1 // SPDX-License-Identifier: GPL-2.0-or-later 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 2 /* 3 * Module kallsyms support 3 * Module kallsyms support 4 * 4 * 5 * Copyright (C) 2010 Rusty Russell 5 * Copyright (C) 2010 Rusty Russell 6 */ 6 */ 7 7 8 #include <linux/module.h> 8 #include <linux/module.h> 9 #include <linux/module_symbol.h> << 10 #include <linux/kallsyms.h> 9 #include <linux/kallsyms.h> 11 #include <linux/buildid.h> 10 #include <linux/buildid.h> 12 #include <linux/bsearch.h> 11 #include <linux/bsearch.h> 13 #include "internal.h" 12 #include "internal.h" 14 13 15 /* Lookup exported symbol in given range of ke 14 /* Lookup exported symbol in given range of kernel_symbols */ 16 static const struct kernel_symbol *lookup_expo 15 static const struct kernel_symbol *lookup_exported_symbol(const char *name, 17 16 const struct kernel_symbol *start, 18 17 const struct kernel_symbol *stop) 19 { 18 { 20 return bsearch(name, start, stop - sta 19 return bsearch(name, start, stop - start, 21 sizeof(struct kernel_s 20 sizeof(struct kernel_symbol), cmp_name); 22 } 21 } 23 22 24 static int is_exported(const char *name, unsig 23 static int is_exported(const char *name, unsigned long value, 25 const struct module *mo 24 const struct module *mod) 26 { 25 { 27 const struct kernel_symbol *ks; 26 const struct kernel_symbol *ks; 28 27 29 if (!mod) 28 if (!mod) 30 ks = lookup_exported_symbol(na 29 ks = lookup_exported_symbol(name, __start___ksymtab, __stop___ksymtab); 31 else 30 else 32 ks = lookup_exported_symbol(na 31 ks = lookup_exported_symbol(name, mod->syms, mod->syms + mod->num_syms); 33 32 34 return ks && kernel_symbol_value(ks) = 33 return ks && kernel_symbol_value(ks) == value; 35 } 34 } 36 35 37 /* As per nm */ 36 /* As per nm */ 38 static char elf_type(const Elf_Sym *sym, const 37 static char elf_type(const Elf_Sym *sym, const struct load_info *info) 39 { 38 { 40 const Elf_Shdr *sechdrs = info->sechdr 39 const Elf_Shdr *sechdrs = info->sechdrs; 41 40 42 if (ELF_ST_BIND(sym->st_info) == STB_W 41 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) { 43 if (ELF_ST_TYPE(sym->st_info) 42 if (ELF_ST_TYPE(sym->st_info) == STT_OBJECT) 44 return 'v'; 43 return 'v'; 45 else 44 else 46 return 'w'; 45 return 'w'; 47 } 46 } 48 if (sym->st_shndx == SHN_UNDEF) 47 if (sym->st_shndx == SHN_UNDEF) 49 return 'U'; 48 return 'U'; 50 if (sym->st_shndx == SHN_ABS || sym->s 49 if (sym->st_shndx == SHN_ABS || sym->st_shndx == info->index.pcpu) 51 return 'a'; 50 return 'a'; 52 if (sym->st_shndx >= SHN_LORESERVE) 51 if (sym->st_shndx >= SHN_LORESERVE) 53 return '?'; 52 return '?'; 54 if (sechdrs[sym->st_shndx].sh_flags & 53 if (sechdrs[sym->st_shndx].sh_flags & SHF_EXECINSTR) 55 return 't'; 54 return 't'; 56 if (sechdrs[sym->st_shndx].sh_flags & 55 if (sechdrs[sym->st_shndx].sh_flags & SHF_ALLOC && 57 sechdrs[sym->st_shndx].sh_type != 56 sechdrs[sym->st_shndx].sh_type != SHT_NOBITS) { 58 if (!(sechdrs[sym->st_shndx].s 57 if (!(sechdrs[sym->st_shndx].sh_flags & SHF_WRITE)) 59 return 'r'; 58 return 'r'; 60 else if (sechdrs[sym->st_shndx 59 else if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) 61 return 'g'; 60 return 'g'; 62 else 61 else 63 return 'd'; 62 return 'd'; 64 } 63 } 65 if (sechdrs[sym->st_shndx].sh_type == 64 if (sechdrs[sym->st_shndx].sh_type == SHT_NOBITS) { 66 if (sechdrs[sym->st_shndx].sh_ 65 if (sechdrs[sym->st_shndx].sh_flags & ARCH_SHF_SMALL) 67 return 's'; 66 return 's'; 68 else 67 else 69 return 'b'; 68 return 'b'; 70 } 69 } 71 if (strstarts(info->secstrings + sechd 70 if (strstarts(info->secstrings + sechdrs[sym->st_shndx].sh_name, 72 ".debug")) { 71 ".debug")) { 73 return 'n'; 72 return 'n'; 74 } 73 } 75 return '?'; 74 return '?'; 76 } 75 } 77 76 78 static bool is_core_symbol(const Elf_Sym *src, 77 static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs, 79 unsigned int shnum, 78 unsigned int shnum, unsigned int pcpundx) 80 { 79 { 81 const Elf_Shdr *sec; 80 const Elf_Shdr *sec; 82 enum mod_mem_type type; << 83 81 84 if (src->st_shndx == SHN_UNDEF || 82 if (src->st_shndx == SHN_UNDEF || 85 src->st_shndx >= shnum || 83 src->st_shndx >= shnum || 86 !src->st_name) 84 !src->st_name) 87 return false; 85 return false; 88 86 89 #ifdef CONFIG_KALLSYMS_ALL 87 #ifdef CONFIG_KALLSYMS_ALL 90 if (src->st_shndx == pcpundx) 88 if (src->st_shndx == pcpundx) 91 return true; 89 return true; 92 #endif 90 #endif 93 91 94 sec = sechdrs + src->st_shndx; 92 sec = sechdrs + src->st_shndx; 95 type = sec->sh_entsize >> SH_ENTSIZE_T << 96 if (!(sec->sh_flags & SHF_ALLOC) 93 if (!(sec->sh_flags & SHF_ALLOC) 97 #ifndef CONFIG_KALLSYMS_ALL 94 #ifndef CONFIG_KALLSYMS_ALL 98 || !(sec->sh_flags & SHF_EXECINSTR 95 || !(sec->sh_flags & SHF_EXECINSTR) 99 #endif 96 #endif 100 || mod_mem_type_is_init(type)) !! 97 || (sec->sh_entsize & INIT_OFFSET_MASK)) 101 return false; 98 return false; 102 99 103 return true; 100 return true; 104 } 101 } 105 102 106 /* 103 /* 107 * We only allocate and copy the strings neede 104 * We only allocate and copy the strings needed by the parts of symtab 108 * we keep. This is simple, but has the effec 105 * we keep. This is simple, but has the effect of making multiple 109 * copies of duplicates. We could be more sop 106 * copies of duplicates. We could be more sophisticated, see 110 * linux-kernel thread starting with 107 * linux-kernel thread starting with 111 * <73defb5e4bca04a6431392cc341112b1@localhost 108 * <73defb5e4bca04a6431392cc341112b1@localhost>. 112 */ 109 */ 113 void layout_symtab(struct module *mod, struct 110 void layout_symtab(struct module *mod, struct load_info *info) 114 { 111 { 115 Elf_Shdr *symsect = info->sechdrs + in 112 Elf_Shdr *symsect = info->sechdrs + info->index.sym; 116 Elf_Shdr *strsect = info->sechdrs + in 113 Elf_Shdr *strsect = info->sechdrs + info->index.str; 117 const Elf_Sym *src; 114 const Elf_Sym *src; 118 unsigned int i, nsrc, ndst, strtab_siz 115 unsigned int i, nsrc, ndst, strtab_size = 0; 119 struct module_memory *mod_mem_data = & << 120 struct module_memory *mod_mem_init_dat << 121 116 122 /* Put symbol section at end of init p 117 /* Put symbol section at end of init part of module. */ 123 symsect->sh_flags |= SHF_ALLOC; 118 symsect->sh_flags |= SHF_ALLOC; 124 symsect->sh_entsize = module_get_offse !! 119 symsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, symsect, 125 !! 120 info->index.sym) | INIT_OFFSET_MASK; 126 pr_debug("\t%s\n", info->secstrings + 121 pr_debug("\t%s\n", info->secstrings + symsect->sh_name); 127 122 128 src = (void *)info->hdr + symsect->sh_ 123 src = (void *)info->hdr + symsect->sh_offset; 129 nsrc = symsect->sh_size / sizeof(*src) 124 nsrc = symsect->sh_size / sizeof(*src); 130 125 131 /* Compute total space required for th 126 /* Compute total space required for the core symbols' strtab. */ 132 for (ndst = i = 0; i < nsrc; i++) { 127 for (ndst = i = 0; i < nsrc; i++) { 133 if (i == 0 || is_livepatch_mod 128 if (i == 0 || is_livepatch_module(mod) || 134 is_core_symbol(src + i, in 129 is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, 135 info->index 130 info->index.pcpu)) { 136 strtab_size += strlen( 131 strtab_size += strlen(&info->strtab[src[i].st_name]) + 1; 137 ndst++; 132 ndst++; 138 } 133 } 139 } 134 } 140 135 141 /* Append room for core symbols at end 136 /* Append room for core symbols at end of core part. */ 142 info->symoffs = ALIGN(mod_mem_data->si !! 137 info->symoffs = ALIGN(mod->data_layout.size, symsect->sh_addralign ?: 1); 143 info->stroffs = mod_mem_data->size = i !! 138 info->stroffs = mod->data_layout.size = info->symoffs + ndst * sizeof(Elf_Sym); 144 mod_mem_data->size += strtab_size; !! 139 mod->data_layout.size += strtab_size; 145 /* Note add_kallsyms() computes strtab 140 /* Note add_kallsyms() computes strtab_size as core_typeoffs - stroffs */ 146 info->core_typeoffs = mod_mem_data->si !! 141 info->core_typeoffs = mod->data_layout.size; 147 mod_mem_data->size += ndst * sizeof(ch !! 142 mod->data_layout.size += ndst * sizeof(char); >> 143 mod->data_layout.size = strict_align(mod->data_layout.size); 148 144 149 /* Put string table section at end of 145 /* Put string table section at end of init part of module. */ 150 strsect->sh_flags |= SHF_ALLOC; 146 strsect->sh_flags |= SHF_ALLOC; 151 strsect->sh_entsize = module_get_offse !! 147 strsect->sh_entsize = module_get_offset(mod, &mod->init_layout.size, strsect, 152 !! 148 info->index.str) | INIT_OFFSET_MASK; 153 pr_debug("\t%s\n", info->secstrings + 149 pr_debug("\t%s\n", info->secstrings + strsect->sh_name); 154 150 155 /* We'll tack temporary mod_kallsyms o 151 /* We'll tack temporary mod_kallsyms on the end. */ 156 mod_mem_init_data->size = ALIGN(mod_me !! 152 mod->init_layout.size = ALIGN(mod->init_layout.size, 157 __alig !! 153 __alignof__(struct mod_kallsyms)); 158 info->mod_kallsyms_init_off = mod_mem_ !! 154 info->mod_kallsyms_init_off = mod->init_layout.size; 159 !! 155 mod->init_layout.size += sizeof(struct mod_kallsyms); 160 mod_mem_init_data->size += sizeof(stru !! 156 info->init_typeoffs = mod->init_layout.size; 161 info->init_typeoffs = mod_mem_init_dat !! 157 mod->init_layout.size += nsrc * sizeof(char); 162 mod_mem_init_data->size += nsrc * size !! 158 mod->init_layout.size = strict_align(mod->init_layout.size); 163 } 159 } 164 160 165 /* 161 /* 166 * We use the full symtab and strtab which lay 162 * We use the full symtab and strtab which layout_symtab arranged to 167 * be appended to the init section. Later we 163 * be appended to the init section. Later we switch to the cut-down 168 * core-only ones. 164 * core-only ones. 169 */ 165 */ 170 void add_kallsyms(struct module *mod, const st 166 void add_kallsyms(struct module *mod, const struct load_info *info) 171 { 167 { 172 unsigned int i, ndst; 168 unsigned int i, ndst; 173 const Elf_Sym *src; 169 const Elf_Sym *src; 174 Elf_Sym *dst; 170 Elf_Sym *dst; 175 char *s; 171 char *s; 176 Elf_Shdr *symsec = &info->sechdrs[info 172 Elf_Shdr *symsec = &info->sechdrs[info->index.sym]; 177 unsigned long strtab_size; 173 unsigned long strtab_size; 178 void *data_base = mod->mem[MOD_DATA].b << 179 void *init_data_base = mod->mem[MOD_IN << 180 174 181 /* Set up to point into init section. 175 /* Set up to point into init section. */ 182 mod->kallsyms = (void __rcu *)init_dat !! 176 mod->kallsyms = (void __rcu *)mod->init_layout.base + 183 info->mod_kallsyms_init_off; 177 info->mod_kallsyms_init_off; 184 178 185 rcu_read_lock(); 179 rcu_read_lock(); 186 /* The following is safe since this po 180 /* The following is safe since this pointer cannot change */ 187 rcu_dereference(mod->kallsyms)->symtab 181 rcu_dereference(mod->kallsyms)->symtab = (void *)symsec->sh_addr; 188 rcu_dereference(mod->kallsyms)->num_sy 182 rcu_dereference(mod->kallsyms)->num_symtab = symsec->sh_size / sizeof(Elf_Sym); 189 /* Make sure we get permanent strtab: 183 /* Make sure we get permanent strtab: don't use info->strtab. */ 190 rcu_dereference(mod->kallsyms)->strtab 184 rcu_dereference(mod->kallsyms)->strtab = 191 (void *)info->sechdrs[info->in 185 (void *)info->sechdrs[info->index.str].sh_addr; 192 rcu_dereference(mod->kallsyms)->typeta !! 186 rcu_dereference(mod->kallsyms)->typetab = mod->init_layout.base + info->init_typeoffs; 193 187 194 /* 188 /* 195 * Now populate the cut down core kall 189 * Now populate the cut down core kallsyms for after init 196 * and set types up while we still hav 190 * and set types up while we still have access to sections. 197 */ 191 */ 198 mod->core_kallsyms.symtab = dst = data !! 192 mod->core_kallsyms.symtab = dst = mod->data_layout.base + info->symoffs; 199 mod->core_kallsyms.strtab = s = data_b !! 193 mod->core_kallsyms.strtab = s = mod->data_layout.base + info->stroffs; 200 mod->core_kallsyms.typetab = data_base !! 194 mod->core_kallsyms.typetab = mod->data_layout.base + info->core_typeoffs; 201 strtab_size = info->core_typeoffs - in 195 strtab_size = info->core_typeoffs - info->stroffs; 202 src = rcu_dereference(mod->kallsyms)-> 196 src = rcu_dereference(mod->kallsyms)->symtab; 203 for (ndst = i = 0; i < rcu_dereference 197 for (ndst = i = 0; i < rcu_dereference(mod->kallsyms)->num_symtab; i++) { 204 rcu_dereference(mod->kallsyms) 198 rcu_dereference(mod->kallsyms)->typetab[i] = elf_type(src + i, info); 205 if (i == 0 || is_livepatch_mod 199 if (i == 0 || is_livepatch_module(mod) || 206 is_core_symbol(src + i, in 200 is_core_symbol(src + i, info->sechdrs, info->hdr->e_shnum, 207 info->index 201 info->index.pcpu)) { 208 ssize_t ret; 202 ssize_t ret; 209 203 210 mod->core_kallsyms.typ 204 mod->core_kallsyms.typetab[ndst] = 211 rcu_dereference(mo 205 rcu_dereference(mod->kallsyms)->typetab[i]; 212 dst[ndst] = src[i]; 206 dst[ndst] = src[i]; 213 dst[ndst++].st_name = 207 dst[ndst++].st_name = s - mod->core_kallsyms.strtab; 214 ret = strscpy(s, 208 ret = strscpy(s, 215 &rcu_der 209 &rcu_dereference(mod->kallsyms)->strtab[src[i].st_name], 216 strtab_s 210 strtab_size); 217 if (ret < 0) 211 if (ret < 0) 218 break; 212 break; 219 s += ret + 1; 213 s += ret + 1; 220 strtab_size -= ret + 1 214 strtab_size -= ret + 1; 221 } 215 } 222 } 216 } 223 rcu_read_unlock(); 217 rcu_read_unlock(); 224 mod->core_kallsyms.num_symtab = ndst; 218 mod->core_kallsyms.num_symtab = ndst; 225 } 219 } 226 220 227 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 221 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 228 void init_build_id(struct module *mod, const s 222 void init_build_id(struct module *mod, const struct load_info *info) 229 { 223 { 230 const Elf_Shdr *sechdr; 224 const Elf_Shdr *sechdr; 231 unsigned int i; 225 unsigned int i; 232 226 233 for (i = 0; i < info->hdr->e_shnum; i+ 227 for (i = 0; i < info->hdr->e_shnum; i++) { 234 sechdr = &info->sechdrs[i]; 228 sechdr = &info->sechdrs[i]; 235 if (!sect_empty(sechdr) && sec 229 if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE && 236 !build_id_parse_buf((void 230 !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id, 237 sechdr 231 sechdr->sh_size)) 238 break; 232 break; 239 } 233 } 240 } 234 } 241 #else 235 #else 242 void init_build_id(struct module *mod, const s 236 void init_build_id(struct module *mod, const struct load_info *info) 243 { 237 { 244 } 238 } 245 #endif 239 #endif 246 240 >> 241 /* >> 242 * This ignores the intensely annoying "mapping symbols" found >> 243 * in ARM ELF files: $a, $t and $d. >> 244 */ >> 245 static inline int is_arm_mapping_symbol(const char *str) >> 246 { >> 247 if (str[0] == '.' && str[1] == 'L') >> 248 return true; >> 249 return str[0] == '$' && strchr("axtd", str[1]) && >> 250 (str[2] == '\0' || str[2] == '.'); >> 251 } >> 252 247 static const char *kallsyms_symbol_name(struct 253 static const char *kallsyms_symbol_name(struct mod_kallsyms *kallsyms, unsigned int symnum) 248 { 254 { 249 return kallsyms->strtab + kallsyms->sy 255 return kallsyms->strtab + kallsyms->symtab[symnum].st_name; 250 } 256 } 251 257 252 /* 258 /* 253 * Given a module and address, find the corres 259 * Given a module and address, find the corresponding symbol and return its name 254 * while providing its size and offset if need 260 * while providing its size and offset if needed. 255 */ 261 */ 256 static const char *find_kallsyms_symbol(struct 262 static const char *find_kallsyms_symbol(struct module *mod, 257 unsign 263 unsigned long addr, 258 unsign 264 unsigned long *size, 259 unsign 265 unsigned long *offset) 260 { 266 { 261 unsigned int i, best = 0; 267 unsigned int i, best = 0; 262 unsigned long nextval, bestval; 268 unsigned long nextval, bestval; 263 struct mod_kallsyms *kallsyms = rcu_de 269 struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); 264 struct module_memory *mod_mem; << 265 270 266 /* At worse, next value is at end of m 271 /* At worse, next value is at end of module */ 267 if (within_module_init(addr, mod)) 272 if (within_module_init(addr, mod)) 268 mod_mem = &mod->mem[MOD_INIT_T !! 273 nextval = (unsigned long)mod->init_layout.base + mod->init_layout.text_size; 269 else 274 else 270 mod_mem = &mod->mem[MOD_TEXT]; !! 275 nextval = (unsigned long)mod->core_layout.base + mod->core_layout.text_size; 271 << 272 nextval = (unsigned long)mod_mem->base << 273 276 274 bestval = kallsyms_symbol_value(&kalls 277 bestval = kallsyms_symbol_value(&kallsyms->symtab[best]); 275 278 276 /* 279 /* 277 * Scan for closest preceding symbol, 280 * Scan for closest preceding symbol, and next symbol. (ELF 278 * starts real symbols at 1). 281 * starts real symbols at 1). 279 */ 282 */ 280 for (i = 1; i < kallsyms->num_symtab; 283 for (i = 1; i < kallsyms->num_symtab; i++) { 281 const Elf_Sym *sym = &kallsyms 284 const Elf_Sym *sym = &kallsyms->symtab[i]; 282 unsigned long thisval = kallsy 285 unsigned long thisval = kallsyms_symbol_value(sym); 283 286 284 if (sym->st_shndx == SHN_UNDEF 287 if (sym->st_shndx == SHN_UNDEF) 285 continue; 288 continue; 286 289 287 /* 290 /* 288 * We ignore unnamed symbols: 291 * We ignore unnamed symbols: they're uninformative 289 * and inserted at a whim. 292 * and inserted at a whim. 290 */ 293 */ 291 if (*kallsyms_symbol_name(kall 294 if (*kallsyms_symbol_name(kallsyms, i) == '\0' || 292 is_mapping_symbol(kallsyms !! 295 is_arm_mapping_symbol(kallsyms_symbol_name(kallsyms, i))) 293 continue; 296 continue; 294 297 295 if (thisval <= addr && thisval 298 if (thisval <= addr && thisval > bestval) { 296 best = i; 299 best = i; 297 bestval = thisval; 300 bestval = thisval; 298 } 301 } 299 if (thisval > addr && thisval 302 if (thisval > addr && thisval < nextval) 300 nextval = thisval; 303 nextval = thisval; 301 } 304 } 302 305 303 if (!best) 306 if (!best) 304 return NULL; 307 return NULL; 305 308 306 if (size) 309 if (size) 307 *size = nextval - bestval; 310 *size = nextval - bestval; 308 if (offset) 311 if (offset) 309 *offset = addr - bestval; 312 *offset = addr - bestval; 310 313 311 return kallsyms_symbol_name(kallsyms, 314 return kallsyms_symbol_name(kallsyms, best); 312 } 315 } 313 316 314 void * __weak dereference_module_function_desc 317 void * __weak dereference_module_function_descriptor(struct module *mod, 315 318 void *ptr) 316 { 319 { 317 return ptr; 320 return ptr; 318 } 321 } 319 322 320 /* 323 /* 321 * For kallsyms to ask for address resolution. 324 * For kallsyms to ask for address resolution. NULL means not found. Careful 322 * not to lock to avoid deadlock on oopses, si 325 * not to lock to avoid deadlock on oopses, simply disable preemption. 323 */ 326 */ 324 int module_address_lookup(unsigned long addr, !! 327 const char *module_address_lookup(unsigned long addr, 325 unsigned long *size, !! 328 unsigned long *size, 326 unsigned long *offse !! 329 unsigned long *offset, 327 char **modname, !! 330 char **modname, 328 const unsigned char !! 331 const unsigned char **modbuildid, 329 char *namebuf) !! 332 char *namebuf) 330 { 333 { 331 const char *sym; !! 334 const char *ret = NULL; 332 int ret = 0; << 333 struct module *mod; 335 struct module *mod; 334 336 335 preempt_disable(); 337 preempt_disable(); 336 mod = __module_address(addr); 338 mod = __module_address(addr); 337 if (mod) { 339 if (mod) { 338 if (modname) 340 if (modname) 339 *modname = mod->name; 341 *modname = mod->name; 340 if (modbuildid) { 342 if (modbuildid) { 341 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 343 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) 342 *modbuildid = mod->bui 344 *modbuildid = mod->build_id; 343 #else 345 #else 344 *modbuildid = NULL; 346 *modbuildid = NULL; 345 #endif 347 #endif 346 } 348 } 347 349 348 sym = find_kallsyms_symbol(mod !! 350 ret = find_kallsyms_symbol(mod, addr, size, offset); 349 !! 351 } 350 if (sym) !! 352 /* Make a copy in here where it's safe */ 351 ret = strscpy(namebuf, !! 353 if (ret) { >> 354 strncpy(namebuf, ret, KSYM_NAME_LEN - 1); >> 355 ret = namebuf; 352 } 356 } 353 preempt_enable(); 357 preempt_enable(); 354 358 355 return ret; 359 return ret; 356 } 360 } 357 361 358 int lookup_module_symbol_name(unsigned long ad 362 int lookup_module_symbol_name(unsigned long addr, char *symname) 359 { 363 { 360 struct module *mod; 364 struct module *mod; 361 365 362 preempt_disable(); 366 preempt_disable(); 363 list_for_each_entry_rcu(mod, &modules, 367 list_for_each_entry_rcu(mod, &modules, list) { 364 if (mod->state == MODULE_STATE 368 if (mod->state == MODULE_STATE_UNFORMED) 365 continue; 369 continue; 366 if (within_module(addr, mod)) 370 if (within_module(addr, mod)) { 367 const char *sym; 371 const char *sym; 368 372 369 sym = find_kallsyms_sy 373 sym = find_kallsyms_symbol(mod, addr, NULL, NULL); 370 if (!sym) 374 if (!sym) 371 goto out; 375 goto out; 372 376 373 strscpy(symname, sym, 377 strscpy(symname, sym, KSYM_NAME_LEN); 374 preempt_enable(); 378 preempt_enable(); 375 return 0; 379 return 0; 376 } 380 } 377 } 381 } 378 out: 382 out: 379 preempt_enable(); 383 preempt_enable(); 380 return -ERANGE; 384 return -ERANGE; 381 } 385 } 382 386 >> 387 int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, >> 388 unsigned long *offset, char *modname, char *name) >> 389 { >> 390 struct module *mod; >> 391 >> 392 preempt_disable(); >> 393 list_for_each_entry_rcu(mod, &modules, list) { >> 394 if (mod->state == MODULE_STATE_UNFORMED) >> 395 continue; >> 396 if (within_module(addr, mod)) { >> 397 const char *sym; >> 398 >> 399 sym = find_kallsyms_symbol(mod, addr, size, offset); >> 400 if (!sym) >> 401 goto out; >> 402 if (modname) >> 403 strscpy(modname, mod->name, MODULE_NAME_LEN); >> 404 if (name) >> 405 strscpy(name, sym, KSYM_NAME_LEN); >> 406 preempt_enable(); >> 407 return 0; >> 408 } >> 409 } >> 410 out: >> 411 preempt_enable(); >> 412 return -ERANGE; >> 413 } >> 414 383 int module_get_kallsym(unsigned int symnum, un 415 int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, 384 char *name, char *modul 416 char *name, char *module_name, int *exported) 385 { 417 { 386 struct module *mod; 418 struct module *mod; 387 419 388 preempt_disable(); 420 preempt_disable(); 389 list_for_each_entry_rcu(mod, &modules, 421 list_for_each_entry_rcu(mod, &modules, list) { 390 struct mod_kallsyms *kallsyms; 422 struct mod_kallsyms *kallsyms; 391 423 392 if (mod->state == MODULE_STATE 424 if (mod->state == MODULE_STATE_UNFORMED) 393 continue; 425 continue; 394 kallsyms = rcu_dereference_sch 426 kallsyms = rcu_dereference_sched(mod->kallsyms); 395 if (symnum < kallsyms->num_sym 427 if (symnum < kallsyms->num_symtab) { 396 const Elf_Sym *sym = & 428 const Elf_Sym *sym = &kallsyms->symtab[symnum]; 397 429 398 *value = kallsyms_symb 430 *value = kallsyms_symbol_value(sym); 399 *type = kallsyms->type 431 *type = kallsyms->typetab[symnum]; 400 strscpy(name, kallsyms 432 strscpy(name, kallsyms_symbol_name(kallsyms, symnum), KSYM_NAME_LEN); 401 strscpy(module_name, m 433 strscpy(module_name, mod->name, MODULE_NAME_LEN); 402 *exported = is_exporte 434 *exported = is_exported(name, *value, mod); 403 preempt_enable(); 435 preempt_enable(); 404 return 0; 436 return 0; 405 } 437 } 406 symnum -= kallsyms->num_symtab 438 symnum -= kallsyms->num_symtab; 407 } 439 } 408 preempt_enable(); 440 preempt_enable(); 409 return -ERANGE; 441 return -ERANGE; 410 } 442 } 411 443 412 /* Given a module and name of symbol, find and 444 /* Given a module and name of symbol, find and return the symbol's value */ 413 static unsigned long __find_kallsyms_symbol_va !! 445 unsigned long find_kallsyms_symbol_value(struct module *mod, const char *name) 414 { 446 { 415 unsigned int i; 447 unsigned int i; 416 struct mod_kallsyms *kallsyms = rcu_de 448 struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); 417 449 418 for (i = 0; i < kallsyms->num_symtab; 450 for (i = 0; i < kallsyms->num_symtab; i++) { 419 const Elf_Sym *sym = &kallsyms 451 const Elf_Sym *sym = &kallsyms->symtab[i]; 420 452 421 if (strcmp(name, kallsyms_symb 453 if (strcmp(name, kallsyms_symbol_name(kallsyms, i)) == 0 && 422 sym->st_shndx != SHN_UNDEF 454 sym->st_shndx != SHN_UNDEF) 423 return kallsyms_symbol 455 return kallsyms_symbol_value(sym); 424 } 456 } 425 return 0; 457 return 0; 426 } 458 } 427 459 428 static unsigned long __module_kallsyms_lookup_ 460 static unsigned long __module_kallsyms_lookup_name(const char *name) 429 { 461 { 430 struct module *mod; 462 struct module *mod; 431 char *colon; 463 char *colon; 432 464 433 colon = strnchr(name, MODULE_NAME_LEN, 465 colon = strnchr(name, MODULE_NAME_LEN, ':'); 434 if (colon) { 466 if (colon) { 435 mod = find_module_all(name, co 467 mod = find_module_all(name, colon - name, false); 436 if (mod) 468 if (mod) 437 return __find_kallsyms !! 469 return find_kallsyms_symbol_value(mod, colon + 1); 438 return 0; 470 return 0; 439 } 471 } 440 472 441 list_for_each_entry_rcu(mod, &modules, 473 list_for_each_entry_rcu(mod, &modules, list) { 442 unsigned long ret; 474 unsigned long ret; 443 475 444 if (mod->state == MODULE_STATE 476 if (mod->state == MODULE_STATE_UNFORMED) 445 continue; 477 continue; 446 ret = __find_kallsyms_symbol_v !! 478 ret = find_kallsyms_symbol_value(mod, name); 447 if (ret) 479 if (ret) 448 return ret; 480 return ret; 449 } 481 } 450 return 0; 482 return 0; 451 } 483 } 452 484 453 /* Look for this name: can be of form module:n 485 /* Look for this name: can be of form module:name. */ 454 unsigned long module_kallsyms_lookup_name(cons 486 unsigned long module_kallsyms_lookup_name(const char *name) 455 { 487 { 456 unsigned long ret; 488 unsigned long ret; 457 489 458 /* Don't lock: we're in enough trouble 490 /* Don't lock: we're in enough trouble already. */ 459 preempt_disable(); 491 preempt_disable(); 460 ret = __module_kallsyms_lookup_name(na 492 ret = __module_kallsyms_lookup_name(name); 461 preempt_enable(); 493 preempt_enable(); 462 return ret; 494 return ret; 463 } 495 } 464 496 465 unsigned long find_kallsyms_symbol_value(struc !! 497 int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, 466 { !! 498 struct module *, unsigned long), 467 unsigned long ret; << 468 << 469 preempt_disable(); << 470 ret = __find_kallsyms_symbol_value(mod << 471 preempt_enable(); << 472 return ret; << 473 } << 474 << 475 int module_kallsyms_on_each_symbol(const char << 476 int (*fn)(v << 477 void *data) 499 void *data) 478 { 500 { 479 struct module *mod; 501 struct module *mod; 480 unsigned int i; 502 unsigned int i; 481 int ret = 0; 503 int ret = 0; 482 504 483 mutex_lock(&module_mutex); 505 mutex_lock(&module_mutex); 484 list_for_each_entry(mod, &modules, lis 506 list_for_each_entry(mod, &modules, list) { 485 struct mod_kallsyms *kallsyms; 507 struct mod_kallsyms *kallsyms; 486 508 487 if (mod->state == MODULE_STATE 509 if (mod->state == MODULE_STATE_UNFORMED) 488 continue; 510 continue; 489 511 490 if (modname && strcmp(modname, << 491 continue; << 492 << 493 /* Use rcu_dereference_sched() 512 /* Use rcu_dereference_sched() to remain compliant with the sparse tool */ 494 preempt_disable(); 513 preempt_disable(); 495 kallsyms = rcu_dereference_sch 514 kallsyms = rcu_dereference_sched(mod->kallsyms); 496 preempt_enable(); 515 preempt_enable(); 497 516 498 for (i = 0; i < kallsyms->num_ 517 for (i = 0; i < kallsyms->num_symtab; i++) { 499 const Elf_Sym *sym = & 518 const Elf_Sym *sym = &kallsyms->symtab[i]; 500 519 501 if (sym->st_shndx == S 520 if (sym->st_shndx == SHN_UNDEF) 502 continue; 521 continue; 503 522 504 ret = fn(data, kallsym 523 ret = fn(data, kallsyms_symbol_name(kallsyms, i), 505 kallsyms_symb !! 524 mod, kallsyms_symbol_value(sym)); 506 if (ret != 0) 525 if (ret != 0) 507 goto out; 526 goto out; 508 } 527 } 509 << 510 /* << 511 * The given module is found, << 512 * need to be compared. << 513 */ << 514 if (modname) << 515 break; << 516 } 528 } 517 out: 529 out: 518 mutex_unlock(&module_mutex); 530 mutex_unlock(&module_mutex); 519 return ret; 531 return ret; 520 } 532 } 521 533
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.