--- elfutils/src/elflint.c +++ elfutils/src/elflint.c @@ -763,28 +763,35 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"), if (! ebl_check_special_symbol (ebl, ehdr, sym, name, destshdr)) { - if (sym->st_value - sh_addr > destshdr->sh_size) + if (sym->st_value < sh_addr + || sym->st_value - sh_addr > destshdr->sh_size) { /* GNU ld has severe bugs. When it decides to remove empty sections it leaves symbols referencing them - behind. These are symbols in .symtab. */ + behind. These are symbols in .symtab or .dynsym. */ if (!gnuld - || strcmp (section_name (ebl, idx), ".symtab") + || (strcmp (section_name (ebl, idx), ".symtab") + && (strcmp (section_name (ebl, idx), ".dynsym") + || strcmp (name, "__bss_start") != 0)) || (strcmp (name, "__preinit_array_start") != 0 && strcmp (name, "__preinit_array_end") != 0 && strcmp (name, "__init_array_start") != 0 && strcmp (name, "__init_array_end") != 0 && strcmp (name, "__fini_array_start") != 0 - && strcmp (name, "__fini_array_end") != 0)) + && strcmp (name, "__fini_array_end") != 0 + && strcmp (name, "__bss_start") != 0)) ERROR (gettext ("\ -section [%2d] '%s': symbol %zu: st_value out of bounds\n"), - idx, section_name (ebl, idx), cnt); +section [%2d] '%s': symbol [%zu] '%s': st_value[%lx] out of bounds [%lx+%lx]\n"), + idx, section_name (ebl, idx), cnt, name, + (unsigned long) sym->st_value, + (unsigned long) sh_addr, + (unsigned long) destshdr->sh_size); } else if ((sym->st_value - sh_addr + sym->st_size) > destshdr->sh_size) ERROR (gettext ("\ -section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"), - idx, section_name (ebl, idx), cnt, +section [%2d] '%s': symbol [%zu] '%s' does not fit completely in referenced section [%2d] '%s'\n"), + idx, section_name (ebl, idx), cnt, name, (int) xndx, section_name (ebl, xndx)); } }