From 37e0c0d89ea5432dcdc2a3d6dfd995cda4622bd6 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Wed, 3 Apr 2024 16:23:41 +0100 Subject: [PATCH 1/5] llvm-objdump/ELF: fix crash when reading dyn str table When reading the dynamic string table, llvm-objdump used to crash if the ELF was malformed, due to an erroneous consumption of error status. Instead, propogate the error status to the caller, fixing the crash, and printing a warning. Fixes #86612. --- llvm/test/tools/llvm-objdump/ELF/pr86612.test | 93 +++++++++++++++++++ llvm/tools/llvm-objdump/ELFDump.cpp | 2 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 llvm/test/tools/llvm-objdump/ELF/pr86612.test diff --git a/llvm/test/tools/llvm-objdump/ELF/pr86612.test b/llvm/test/tools/llvm-objdump/ELF/pr86612.test new file mode 100644 index 0000000000000..7250891f042cb --- /dev/null +++ b/llvm/test/tools/llvm-objdump/ELF/pr86612.test @@ -0,0 +1,93 @@ +# RUN: yaml2obj %s -o %t1 +# RUN: llvm-objdump -p %t1 | FileCheck %s +# RUN: llvm-objdump -p %t1 2>&1 >/dev/null | \ +# RUN: FileCheck %s -DFILE=%t1 --implicit-check-not=warning --check-prefix=ERROR + +# ERROR: warning: '[[FILE]]': virtual address is not in any segment: 0x474 +# CHECK: Dynamic Section: +# CHECK-NEXT: NEEDED 0xffffffffbe5a0b5f +# CHECK-NEXT: FLAGS_1 0x0000000008000000 +# CHECK-NEXT: DEBUG 0x0000000000000000 +# CHECK-NEXT: RELA 0x00000000000004e0 +# CHECK-NEXT: RELASZ 0x0000000000000090 +# CHECK-NEXT: RELAENT 0x0000000000000018 +# CHECK-NEXT: RELACOUNT 0x0000000000000004 +# CHECK-NEXT: JMPREL 0x0000000000000570 +# CHECK-NEXT: PLTRELSZ 0x0000000000000078 +# CHECK-NEXT: PLTGOT 0x0000000000003aa0 +# CHECK-NEXT: PLTREL 0x0000000000000007 +# CHECK-NEXT: SYMTAB 0x0000000000000308 +# CHECK-NEXT: SYMENT 0x0000000000000018 +# CHECK-NEXT: STRTAB 0x0000000000000474 +# CHECK-NEXT: STRSZ 0x000000000000006b +# CHECK-NEXT: GNU_HASH 0x0000000000000408 +# CHECK-NEXT: HASH 0x000000000000042c +# CHECK-NEXT: INIT_ARRAY 0x00000000000028d8 +# CHECK-NEXT: INIT_ARRAYSZ 0x0000000000000008 +# CHECK-NEXT: INIT 0x000000000000180e +# CHECK-NEXT: FINI 0x0000000000001820 +# CHECK-NEXT: VERSYM 0x00000000000003c8 +# CHECK-NEXT: VERNEED 0x00000000000003d8 +# CHECK-NEXT: VERNEEDNUM 0x0000000000000001 + +--- +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Flags: [SHF_WRITE, SHF_ALLOC] + Entries: + - Tag: DT_NEEDED + Value: 0xFFFFFFFFBE5A0B5F + - Tag: DT_FLAGS_1 + Value: 0x8000000 + - Tag: DT_DEBUG + Value: 0x0 + - Tag: DT_RELA + Value: 0x4E0 + - Tag: DT_RELASZ + Value: 0x90 + - Tag: DT_RELAENT + Value: 0x18 + - Tag: DT_RELACOUNT + Value: 0x4 + - Tag: DT_JMPREL + Value: 0x570 + - Tag: DT_PLTRELSZ + Value: 0x78 + - Tag: DT_PLTGOT + Value: 0x3AA0 + - Tag: DT_PLTREL + Value: 0x7 + - Tag: DT_SYMTAB + Value: 0x308 + - Tag: DT_SYMENT + Value: 0x18 + - Tag: DT_STRTAB + Value: 0x474 + - Tag: DT_STRSZ + Value: 0x6B + - Tag: DT_GNU_HASH + Value: 0x408 + - Tag: DT_HASH + Value: 0x42C + - Tag: DT_INIT_ARRAY + Value: 0x28D8 + - Tag: DT_INIT_ARRAYSZ + Value: 0x8 + - Tag: DT_INIT + Value: 0x180E + - Tag: DT_FINI + Value: 0x1820 + - Tag: DT_VERSYM + Value: 0x3C8 + - Tag: DT_VERNEED + Value: 0x3D8 + - Tag: DT_VERNEEDNUM + Value: 0x1 + - Tag: DT_NULL + Value: 0x0 diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index fda99bd6d33e1..c352182489107 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -68,7 +68,7 @@ static Expected getDynamicStrTab(const ELFFile &Elf) { if (Dyn.d_tag == ELF::DT_STRTAB) { auto MappedAddrOrError = Elf.toMappedAddr(Dyn.getPtr()); if (!MappedAddrOrError) - consumeError(MappedAddrOrError.takeError()); + return MappedAddrOrError.takeError(); return StringRef(reinterpret_cast(*MappedAddrOrError)); } } From fd4fc6b36750c7e7f8261a6f7569c6481eea3416 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 4 Apr 2024 11:32:28 +0100 Subject: [PATCH 2/5] objdump/test: address James' review; reduce test --- .../llvm-objdump/ELF/dynamic-malformed.test | 29 +++++- llvm/test/tools/llvm-objdump/ELF/pr86612.test | 93 ------------------- 2 files changed, 27 insertions(+), 95 deletions(-) delete mode 100644 llvm/test/tools/llvm-objdump/ELF/pr86612.test diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test index b10e4f5e44f18..e221b4608d688 100644 --- a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test +++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test @@ -12,7 +12,6 @@ FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_EXEC - Machine: EM_X86_64 Sections: - Name: .dynamic Type: SHT_DYNAMIC @@ -29,10 +28,36 @@ FileHeader: Class: ELFCLASS64 Data: ELFDATA2LSB Type: ET_EXEC - Machine: EM_X86_64 Sections: - Name: .dynamic Type: SHT_DYNAMIC Entries: - Tag: DT_SONAME Value: 1 + +# RUN: yaml2obj %s --docnum=3 -o %t.invalidaddr +# RUN: llvm-objdump -p %t.invalidaddr | FileCheck %s --check-prefix=ADDR +# RUN: llvm-objdump -p %t.invalidaddr 2>&1 >/dev/null | \ +# RUN: FileCheck %s -DFILE=%t.invalidaddr --implicit-check-not=warning --check-prefix=ADDR-ERROR + +# ADDR-ERROR: warning: '[[FILE]]': virtual address is not in any segment: 0x474 +# ADDR: Dynamic Section: +# ADDR-NEXT: NEEDED 0xffffffffbe5a0b5f +# ADDR-NEXT: STRTAB 0x0000000000000474 + +--- +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_NEEDED + Value: 0xFFFFFFFFBE5A0B5F + - Tag: DT_STRTAB + Value: 0x474 + - Tag: DT_NULL + Value: 0x0 diff --git a/llvm/test/tools/llvm-objdump/ELF/pr86612.test b/llvm/test/tools/llvm-objdump/ELF/pr86612.test deleted file mode 100644 index 7250891f042cb..0000000000000 --- a/llvm/test/tools/llvm-objdump/ELF/pr86612.test +++ /dev/null @@ -1,93 +0,0 @@ -# RUN: yaml2obj %s -o %t1 -# RUN: llvm-objdump -p %t1 | FileCheck %s -# RUN: llvm-objdump -p %t1 2>&1 >/dev/null | \ -# RUN: FileCheck %s -DFILE=%t1 --implicit-check-not=warning --check-prefix=ERROR - -# ERROR: warning: '[[FILE]]': virtual address is not in any segment: 0x474 -# CHECK: Dynamic Section: -# CHECK-NEXT: NEEDED 0xffffffffbe5a0b5f -# CHECK-NEXT: FLAGS_1 0x0000000008000000 -# CHECK-NEXT: DEBUG 0x0000000000000000 -# CHECK-NEXT: RELA 0x00000000000004e0 -# CHECK-NEXT: RELASZ 0x0000000000000090 -# CHECK-NEXT: RELAENT 0x0000000000000018 -# CHECK-NEXT: RELACOUNT 0x0000000000000004 -# CHECK-NEXT: JMPREL 0x0000000000000570 -# CHECK-NEXT: PLTRELSZ 0x0000000000000078 -# CHECK-NEXT: PLTGOT 0x0000000000003aa0 -# CHECK-NEXT: PLTREL 0x0000000000000007 -# CHECK-NEXT: SYMTAB 0x0000000000000308 -# CHECK-NEXT: SYMENT 0x0000000000000018 -# CHECK-NEXT: STRTAB 0x0000000000000474 -# CHECK-NEXT: STRSZ 0x000000000000006b -# CHECK-NEXT: GNU_HASH 0x0000000000000408 -# CHECK-NEXT: HASH 0x000000000000042c -# CHECK-NEXT: INIT_ARRAY 0x00000000000028d8 -# CHECK-NEXT: INIT_ARRAYSZ 0x0000000000000008 -# CHECK-NEXT: INIT 0x000000000000180e -# CHECK-NEXT: FINI 0x0000000000001820 -# CHECK-NEXT: VERSYM 0x00000000000003c8 -# CHECK-NEXT: VERNEED 0x00000000000003d8 -# CHECK-NEXT: VERNEEDNUM 0x0000000000000001 - ---- -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_DYN -Sections: - - Name: .dynamic - Type: SHT_DYNAMIC - Flags: [SHF_WRITE, SHF_ALLOC] - Entries: - - Tag: DT_NEEDED - Value: 0xFFFFFFFFBE5A0B5F - - Tag: DT_FLAGS_1 - Value: 0x8000000 - - Tag: DT_DEBUG - Value: 0x0 - - Tag: DT_RELA - Value: 0x4E0 - - Tag: DT_RELASZ - Value: 0x90 - - Tag: DT_RELAENT - Value: 0x18 - - Tag: DT_RELACOUNT - Value: 0x4 - - Tag: DT_JMPREL - Value: 0x570 - - Tag: DT_PLTRELSZ - Value: 0x78 - - Tag: DT_PLTGOT - Value: 0x3AA0 - - Tag: DT_PLTREL - Value: 0x7 - - Tag: DT_SYMTAB - Value: 0x308 - - Tag: DT_SYMENT - Value: 0x18 - - Tag: DT_STRTAB - Value: 0x474 - - Tag: DT_STRSZ - Value: 0x6B - - Tag: DT_GNU_HASH - Value: 0x408 - - Tag: DT_HASH - Value: 0x42C - - Tag: DT_INIT_ARRAY - Value: 0x28D8 - - Tag: DT_INIT_ARRAYSZ - Value: 0x8 - - Tag: DT_INIT - Value: 0x180E - - Tag: DT_FINI - Value: 0x1820 - - Tag: DT_VERSYM - Value: 0x3C8 - - Tag: DT_VERNEED - Value: 0x3D8 - - Tag: DT_VERNEEDNUM - Value: 0x1 - - Tag: DT_NULL - Value: 0x0 From 5509c215eecac0914a5b17183fae81d2f1d2653e Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 4 Apr 2024 17:06:55 +0100 Subject: [PATCH 3/5] dynamic-malformed.test: minor change from James' review --- llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test index e221b4608d688..05c4c58c7df07 100644 --- a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test +++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test @@ -38,7 +38,7 @@ Sections: # RUN: yaml2obj %s --docnum=3 -o %t.invalidaddr # RUN: llvm-objdump -p %t.invalidaddr | FileCheck %s --check-prefix=ADDR # RUN: llvm-objdump -p %t.invalidaddr 2>&1 >/dev/null | \ -# RUN: FileCheck %s -DFILE=%t.invalidaddr --implicit-check-not=warning --check-prefix=ADDR-ERROR +# RUN: FileCheck %s -DFILE=%t.invalidaddr --implicit-check-not=warning: --check-prefix=ADDR-ERROR # ADDR-ERROR: warning: '[[FILE]]': virtual address is not in any segment: 0x474 # ADDR: Dynamic Section: From 057e2dbea195abf32c3612dff3892d604b3adcbc Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 4 Apr 2024 19:43:12 +0100 Subject: [PATCH 4/5] llvm-objdump: fix printing order; original bug not fixed --- llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test | 7 +++---- llvm/tools/llvm-objdump/ELFDump.cpp | 9 +++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test index 05c4c58c7df07..b1e3ca17b5049 100644 --- a/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test +++ b/llvm/test/tools/llvm-objdump/ELF/dynamic-malformed.test @@ -36,12 +36,11 @@ Sections: Value: 1 # RUN: yaml2obj %s --docnum=3 -o %t.invalidaddr -# RUN: llvm-objdump -p %t.invalidaddr | FileCheck %s --check-prefix=ADDR -# RUN: llvm-objdump -p %t.invalidaddr 2>&1 >/dev/null | \ -# RUN: FileCheck %s -DFILE=%t.invalidaddr --implicit-check-not=warning: --check-prefix=ADDR-ERROR +# RUN: llvm-objdump -p %t.invalidaddr 2>&1 | \ +# RUN: FileCheck %s -DFILE=%t.invalidaddr --implicit-check-not=warning: --check-prefix=ADDR -# ADDR-ERROR: warning: '[[FILE]]': virtual address is not in any segment: 0x474 # ADDR: Dynamic Section: +# ADDR-NEXT: warning: '[[FILE]]': virtual address is not in any segment: 0x474 # ADDR-NEXT: NEEDED 0xffffffffbe5a0b5f # ADDR-NEXT: STRTAB 0x0000000000000474 diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index c352182489107..4248948e946a7 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -223,7 +223,6 @@ template void ELFDumper::printDynamicSection() { continue; std::string Str = Elf.getDynamicTagAsString(Dyn.d_tag); - outs() << format(TagFmt.c_str(), Str.c_str()); const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; @@ -232,14 +231,16 @@ template void ELFDumper::printDynamicSection() { Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER) { Expected StrTabOrErr = getDynamicStrTab(Elf); if (StrTabOrErr) { - const char *Data = StrTabOrErr.get().data(); - outs() << (Data + Dyn.d_un.d_val) << "\n"; + const char *Data = StrTabOrErr->data(); + outs() << format(TagFmt.c_str(), Str.c_str()); + outs() << Data + Dyn.getVal() << "\n"; continue; } reportWarning(toString(StrTabOrErr.takeError()), Obj.getFileName()); consumeError(StrTabOrErr.takeError()); } - outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); + outs() << format(TagFmt.c_str(), Str.c_str()); + outs() << format(Fmt, (uint64_t)Dyn.getVal()); } } From 77c600e0fe50955af4984a5ecf4cbf433db4760c Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Fri, 5 Apr 2024 11:20:26 +0100 Subject: [PATCH 5/5] ELFDump: address review; chain output --- llvm/tools/llvm-objdump/ELFDump.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 4248948e946a7..8c184fc1fbb66 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -232,15 +232,15 @@ template void ELFDumper::printDynamicSection() { Expected StrTabOrErr = getDynamicStrTab(Elf); if (StrTabOrErr) { const char *Data = StrTabOrErr->data(); - outs() << format(TagFmt.c_str(), Str.c_str()); - outs() << Data + Dyn.getVal() << "\n"; + outs() << format(TagFmt.c_str(), Str.c_str()) << Data + Dyn.getVal() + << "\n"; continue; } reportWarning(toString(StrTabOrErr.takeError()), Obj.getFileName()); consumeError(StrTabOrErr.takeError()); } - outs() << format(TagFmt.c_str(), Str.c_str()); - outs() << format(Fmt, (uint64_t)Dyn.getVal()); + outs() << format(TagFmt.c_str(), Str.c_str()) + << format(Fmt, (uint64_t)Dyn.getVal()); } }