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