aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/mod/modpost.c64
1 files changed, 47 insertions, 17 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index eeaf57476820..844f84b0818a 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -451,6 +451,29 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
451 return NULL; 451 return NULL;
452} 452}
453 453
454/**
455 * Find symbol based on relocation record info.
456 * In some cases the symbol supplied is a valid symbol so
457 * return refsym. If st_name != 0 we assume this is a valid symbol.
458 * In other cases the symbol needs to be looked up in the symbol table
459 * based on section and address.
460 * **/
461static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr,
462 Elf_Sym *relsym)
463{
464 Elf_Sym *sym;
465
466 if (relsym->st_name != 0)
467 return relsym;
468 for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
469 if (sym->st_shndx != relsym->st_shndx)
470 continue;
471 if (sym->st_value == addr)
472 return sym;
473 }
474 return NULL;
475}
476
454/* 477/*
455 * Find symbols before or equal addr and after addr - in the section sec 478 * Find symbols before or equal addr and after addr - in the section sec
456 **/ 479 **/
@@ -499,8 +522,9 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
499static void warn_sec_mismatch(const char *modname, const char *fromsec, 522static void warn_sec_mismatch(const char *modname, const char *fromsec,
500 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) 523 struct elf_info *elf, Elf_Sym *sym, Elf_Rela r)
501{ 524{
502 Elf_Sym *before; 525 const char *refsymname = "";
503 Elf_Sym *after; 526 Elf_Sym *before, *after;
527 Elf_Sym *refsym;
504 Elf_Ehdr *hdr = elf->hdr; 528 Elf_Ehdr *hdr = elf->hdr;
505 Elf_Shdr *sechdrs = elf->sechdrs; 529 Elf_Shdr *sechdrs = elf->sechdrs;
506 const char *secstrings = (void *)hdr + 530 const char *secstrings = (void *)hdr +
@@ -509,29 +533,34 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
509 533
510 find_symbols_between(elf, r.r_offset, fromsec, &before, &after); 534 find_symbols_between(elf, r.r_offset, fromsec, &before, &after);
511 535
536 refsym = find_elf_symbol(elf, r.r_addend, sym);
537 if (refsym && strlen(elf->strtab + refsym->st_name))
538 refsymname = elf->strtab + refsym->st_name;
539
512 if (before && after) { 540 if (before && after) {
513 warn("%s - Section mismatch: reference to %s from %s " 541 warn("%s - Section mismatch: reference to %s:%s from %s "
514 "between '%s' (at offset 0x%lx) and '%s'\n", 542 "between '%s' (at offset 0x%llx) and '%s'\n",
515 modname, secname, fromsec, 543 modname, secname, refsymname, fromsec,
516 elf->strtab + before->st_name, 544 elf->strtab + before->st_name,
517 (long)(r.r_offset - before->st_value), 545 (long long)r.r_offset,
518 elf->strtab + after->st_name); 546 elf->strtab + after->st_name);
519 } else if (before) { 547 } else if (before) {
520 warn("%s - Section mismatch: reference to %s from %s " 548 warn("%s - Section mismatch: reference to %s:%s from %s "
521 "after '%s' (at offset 0x%lx)\n", 549 "after '%s' (at offset 0x%llx)\n",
522 modname, secname, fromsec, 550 modname, secname, refsymname, fromsec,
523 elf->strtab + before->st_name, 551 elf->strtab + before->st_name,
524 (long)(r.r_offset - before->st_value)); 552 (long long)r.r_offset);
525 } else if (after) { 553 } else if (after) {
526 warn("%s - Section mismatch: reference to %s from %s " 554 warn("%s - Section mismatch: reference to %s:%s from %s "
527 "before '%s' (at offset -0x%lx)\n", 555 "before '%s' (at offset -0x%llx)\n",
528 modname, secname, fromsec, 556 modname, secname, refsymname, fromsec,
529 elf->strtab + before->st_name, 557 elf->strtab + before->st_name,
530 (long)(before->st_value - r.r_offset)); 558 (long long)r.r_offset);
531 } else { 559 } else {
532 warn("%s - Section mismatch: reference to %s from %s " 560 warn("%s - Section mismatch: reference to %s:%s from %s "
533 "(offset 0x%lx)\n", 561 "(offset 0x%llx)\n",
534 modname, secname, fromsec, (long)r.r_offset); 562 modname, secname, fromsec, refsymname,
563 (long long)r.r_offset);
535 } 564 }
536} 565}
537 566
@@ -575,6 +604,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
575 const char *secname; 604 const char *secname;
576 r.r_offset = TO_NATIVE(rela->r_offset); 605 r.r_offset = TO_NATIVE(rela->r_offset);
577 r.r_info = TO_NATIVE(rela->r_info); 606 r.r_info = TO_NATIVE(rela->r_info);
607 r.r_addend = TO_NATIVE(rela->r_addend);
578 sym = elf->symtab_start + ELF_R_SYM(r.r_info); 608 sym = elf->symtab_start + ELF_R_SYM(r.r_info);
579 /* Skip special sections */ 609 /* Skip special sections */
580 if (sym->st_shndx >= SHN_LORESERVE) 610 if (sym->st_shndx >= SHN_LORESERVE)