diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/mod/modpost.c | 64 |
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 | * **/ | ||
461 | static 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, | |||
499 | static void warn_sec_mismatch(const char *modname, const char *fromsec, | 522 | static 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) |