diff --git a/llvm/test/tools/llvm-readobj/check-output-order.test b/llvm/test/tools/llvm-readobj/check-output-order.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/check-output-order.test @@ -0,0 +1,35 @@ +## This test checks that `--needed-libs` output is after that of +## `--dynamic-table` since it is the printing order in code. One common reason +## the output could become out-of-order when more than one stream are printing +## at the same time. +## https://bugs.llvm.org/show_bug.cgi?id=42140 + +## TODO: Add a --all-debug option for llvm-readobj to turn on literally every +## option, then copy the output of `llvm-readobj --all-debug` and paste +## it into the CHECK line here. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-readelf --needed-libs --dynamic-table %t | FileCheck %s + +# CHECK: Dynamic section at offset 0x1b8 contains 1 entries: +# CHECK-NEXT: Tag Type Name/Value +# CHECK-NEXT: 0x0000000000000000 (NULL) 0x0 +# CHECK-NEXT: NeededLibraries [ +# CHECK-NEXT: ] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_NULL + Value: 0 +ProgramHeaders: + - Type: PT_DYNAMIC + Sections: + - Section: .dynamic diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -1565,7 +1565,7 @@ llvm::stable_sort(Libs); for (const auto &L : Libs) { - outs() << " " << L << "\n"; + W.startLine() << L << "\n"; } } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -382,13 +382,14 @@ }; template class GNUStyle : public DumpStyle { - formatted_raw_ostream OS; + formatted_raw_ostream &OS; public: TYPEDEF_ELF_TYPES(ELFT) GNUStyle(ScopedPrinter &W, ELFDumper *Dumper) - : DumpStyle(Dumper), OS(W.getOStream()) {} + : DumpStyle(Dumper), + OS(static_cast(W.getOStream())) {} void printFileHeaders(const ELFO *Obj) override; void printGroupSections(const ELFFile *Obj) override; diff --git a/llvm/tools/llvm-readobj/MachODumper.cpp b/llvm/tools/llvm-readobj/MachODumper.cpp --- a/llvm/tools/llvm-readobj/MachODumper.cpp +++ b/llvm/tools/llvm-readobj/MachODumper.cpp @@ -689,7 +689,7 @@ llvm::stable_sort(Libs); for (const auto &L : Libs) { - outs() << " " << L << "\n"; + W.startLine() << L << "\n"; } } diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -609,8 +609,8 @@ } /// Dumps \a WinRes, Windows Resource (.res) file; -static void dumpWindowsResourceFile(WindowsResource *WinRes) { - ScopedPrinter Printer{outs()}; +static void dumpWindowsResourceFile(WindowsResource *WinRes, + ScopedPrinter &Printer) { WindowsRes::Dumper Dumper(WinRes, Printer); if (auto Err = Dumper.printData()) reportError(WinRes->getFileName(), std::move(Err)); @@ -618,9 +618,7 @@ /// Opens \a File and dumps it. -static void dumpInput(StringRef File) { - ScopedPrinter Writer(outs()); - +static void dumpInput(StringRef File, ScopedPrinter &Writer) { // Attempt to open the binary. Expected> BinaryOrErr = createBinary(File); if (!BinaryOrErr) @@ -637,7 +635,7 @@ else if (COFFImportFile *Import = dyn_cast(&Binary)) dumpCOFFImportFile(Import, Writer); else if (WindowsResource *WinRes = dyn_cast(&Binary)) - dumpWindowsResourceFile(WinRes); + dumpWindowsResourceFile(WinRes, Writer); else reportError(File, readobj_error::unrecognized_file_format); @@ -727,15 +725,16 @@ if (opts::InputFilenames.empty()) opts::InputFilenames.push_back("-"); - llvm::for_each(opts::InputFilenames, dumpInput); + ScopedPrinter Writer(fouts()); + for (const std::string &I : opts::InputFilenames) + dumpInput(I, Writer); if (opts::CodeViewMergedTypes) { - ScopedPrinter W(outs()); if (opts::CodeViewEnableGHash) - dumpCodeViewMergedTypes(W, CVTypes.GlobalIDTable.records(), + dumpCodeViewMergedTypes(Writer, CVTypes.GlobalIDTable.records(), CVTypes.GlobalTypeTable.records()); else - dumpCodeViewMergedTypes(W, CVTypes.IDTable.records(), + dumpCodeViewMergedTypes(Writer, CVTypes.IDTable.records(), CVTypes.TypeTable.records()); }