aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2017-09-15 03:17:11 -0400
committerIngo Molnar <mingo@kernel.org>2017-09-15 05:31:57 -0400
commit97dab2ae7e8473a821f72a039ead0f36b12ba22d (patch)
tree5dcf8b807eab659e5ecf5831b974581a1247cfb1
parentdf968c9329f6e5cf3596a0a54adb6f749747a746 (diff)
objtool: Fix object file corruption
Arnd Bergmann reported that a randconfig build was failing with the following link error: built-in.o: member arch/x86/kernel/time.o in archive is not an object It turns out the link failed because the time.o file had been corrupted by objtool: nm: arch/x86/kernel/time.o: File format not recognized In certain rare cases, when a .o file's ORC table is very small, the .data section size doesn't change because it's page aligned. Because all the existing sections haven't changed size, libelf doesn't detect any section header changes, and so it doesn't update the section header table properly. Instead it writes junk in the section header entries for the new ORC sections. Make sure libelf properly updates the section header table by setting the ELF_F_DIRTY flag in the top level elf struct. Reported-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes: 627fce14809b ("objtool: Add ORC unwind table generation") Link: http://lkml.kernel.org/r/e650fd0f2d8a209d1409a9785deb101fdaed55fb.1505459813.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/objtool/elf.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index b4cd8bc62521..24460155c82c 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -563,6 +563,7 @@ int elf_write(struct elf *elf)
563 struct section *sec; 563 struct section *sec;
564 Elf_Scn *s; 564 Elf_Scn *s;
565 565
566 /* Update section headers for changed sections: */
566 list_for_each_entry(sec, &elf->sections, list) { 567 list_for_each_entry(sec, &elf->sections, list) {
567 if (sec->changed) { 568 if (sec->changed) {
568 s = elf_getscn(elf->elf, sec->idx); 569 s = elf_getscn(elf->elf, sec->idx);
@@ -570,13 +571,17 @@ int elf_write(struct elf *elf)
570 WARN_ELF("elf_getscn"); 571 WARN_ELF("elf_getscn");
571 return -1; 572 return -1;
572 } 573 }
573 if (!gelf_update_shdr (s, &sec->sh)) { 574 if (!gelf_update_shdr(s, &sec->sh)) {
574 WARN_ELF("gelf_update_shdr"); 575 WARN_ELF("gelf_update_shdr");
575 return -1; 576 return -1;
576 } 577 }
577 } 578 }
578 } 579 }
579 580
581 /* Make sure the new section header entries get updated properly. */
582 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
583
584 /* Write all changes to the file. */
580 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { 585 if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
581 WARN_ELF("elf_update"); 586 WARN_ELF("elf_update");
582 return -1; 587 return -1;