@@ -451,6 +451,29 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
451451 return NULL ;
452452}
453453
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+
454477/*
455478 * Find symbols before or equal addr and after addr - in the section sec
456479 **/
@@ -499,8 +522,9 @@ static void find_symbols_between(struct elf_info *elf, Elf_Addr addr,
499522static void warn_sec_mismatch (const char * modname , const char * fromsec ,
500523 struct elf_info * elf , Elf_Sym * sym , Elf_Rela r )
501524{
502- Elf_Sym * before ;
503- Elf_Sym * after ;
525+ const char * refsymname = "" ;
526+ Elf_Sym * before , * after ;
527+ Elf_Sym * refsym ;
504528 Elf_Ehdr * hdr = elf -> hdr ;
505529 Elf_Shdr * sechdrs = elf -> sechdrs ;
506530 const char * secstrings = (void * )hdr +
@@ -509,29 +533,34 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
509533
510534 find_symbols_between (elf , r .r_offset , fromsec , & before , & after );
511535
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+
512540 if (before && after ) {
513- warn ("%s - Section mismatch: reference to %s from %s "
514- "between '%s' (at offset 0x%lx ) and '%s'\n" ,
515- modname , secname , fromsec ,
541+ warn ("%s - Section mismatch: reference to %s:%s from %s "
542+ "between '%s' (at offset 0x%llx ) and '%s'\n" ,
543+ modname , secname , refsymname , fromsec ,
516544 elf -> strtab + before -> st_name ,
517- (long )( r .r_offset - before -> st_value ) ,
545+ (long long ) r .r_offset ,
518546 elf -> strtab + after -> st_name );
519547 } else if (before ) {
520- warn ("%s - Section mismatch: reference to %s from %s "
521- "after '%s' (at offset 0x%lx )\n" ,
522- modname , secname , fromsec ,
548+ warn ("%s - Section mismatch: reference to %s:%s from %s "
549+ "after '%s' (at offset 0x%llx )\n" ,
550+ modname , secname , refsymname , fromsec ,
523551 elf -> strtab + before -> st_name ,
524- (long )( r .r_offset - before -> st_value ) );
552+ (long long ) r .r_offset );
525553 } else if (after ) {
526- warn ("%s - Section mismatch: reference to %s from %s "
527- "before '%s' (at offset -0x%lx )\n" ,
528- modname , secname , fromsec ,
554+ warn ("%s - Section mismatch: reference to %s:%s from %s "
555+ "before '%s' (at offset -0x%llx )\n" ,
556+ modname , secname , refsymname , fromsec ,
529557 elf -> strtab + before -> st_name ,
530- (long )( before -> st_value - r .r_offset ) );
558+ (long long ) r .r_offset );
531559 } else {
532- warn ("%s - Section mismatch: reference to %s from %s "
533- "(offset 0x%lx)\n" ,
534- modname , secname , fromsec , (long )r .r_offset );
560+ warn ("%s - Section mismatch: reference to %s:%s from %s "
561+ "(offset 0x%llx)\n" ,
562+ modname , secname , fromsec , refsymname ,
563+ (long long )r .r_offset );
535564 }
536565}
537566
@@ -575,6 +604,7 @@ static void check_sec_ref(struct module *mod, const char *modname,
575604 const char * secname ;
576605 r .r_offset = TO_NATIVE (rela -> r_offset );
577606 r .r_info = TO_NATIVE (rela -> r_info );
607+ r .r_addend = TO_NATIVE (rela -> r_addend );
578608 sym = elf -> symtab_start + ELF_R_SYM (r .r_info );
579609 /* Skip special sections */
580610 if (sym -> st_shndx >= SHN_LORESERVE )
0 commit comments