]> granicus.if.org Git - llvm/commitdiff
[llvm-readobj] Fix output interleaving issue caused by using multiple streams at...
authorJordan Rupprecht <rupprecht@google.com>
Wed, 12 Jun 2019 20:16:22 +0000 (20:16 +0000)
committerJordan Rupprecht <rupprecht@google.com>
Wed, 12 Jun 2019 20:16:22 +0000 (20:16 +0000)
Summary:
Use llvm::fouts() as the default stream for outputing. No new stream
should be constructed to output at the same time.

https://bugs.llvm.org/show_bug.cgi?id=42140

Reviewers: jhenderson, grimar, MaskRay, phosek, rupprecht

Reviewed By: rupprecht

Subscribers: llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63115

Patch by Yuanfang Chen!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363198 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-readobj/check-output-order.test [new file with mode: 0644]
tools/llvm-readobj/COFFDumper.cpp
tools/llvm-readobj/ELFDumper.cpp
tools/llvm-readobj/MachODumper.cpp
tools/llvm-readobj/llvm-readobj.cpp

diff --git a/test/tools/llvm-readobj/check-output-order.test b/test/tools/llvm-readobj/check-output-order.test
new file mode 100644 (file)
index 0000000..7097d7f
--- /dev/null
@@ -0,0 +1,45 @@
+## This test checks that `--all --needed-libs` output is the same as the
+## printing order in code. One common reason the output could become
+## out-of-order is when more than one stream are printing at the same time.
+## https://bugs.llvm.org/show_bug.cgi?id=42140
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readelf --all --needed-libs %t | FileCheck %s
+
+# CHECK: ELF Header
+# CHECK:   Section header string table index
+# CHECK: There are 5 section headers, starting at offset
+# CHECK: Section Headers:
+# CHECK:   O (extra OS processing required) o (OS specific), p (processor specific)
+# CHECK: There are no relocations in this file.
+# CHECK: Symbol table '.symtab' contains 1 entries
+# CHECK:      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
+# CHECK: Dynamic section at offset
+# CHECK:   0x0000000000000000 (NULL)               0x0
+# CHECK: NeededLibraries [
+# CHECK: ]
+# CHECK: Elf file type is DYN (Shared object file)
+# CHECK: Entry point 0x0
+# CHECK: There are 1 program headers, starting at offset 64
+# CHECK: DYNAMIC
+# CHECK:  Section to Segment mapping:
+# CHECK:    None   .symtab .strtab .shstrtab
+# CHECK: There are no section groups in this file.
+
+
+--- !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
index 21ceb0028579b39bdf651fcc4a865519f1ea4a88..fbdc87a349456c835284a6546645c55408f90357 100644 (file)
@@ -1565,7 +1565,7 @@ void COFFDumper::printNeededLibraries() {
   llvm::stable_sort(Libs);
 
   for (const auto &L : Libs) {
-    outs() << "  " << L << "\n";
+    W.startLine() << L << "\n";
   }
 }
 
index 295763f879190e2cfe125d2dc54899bdac27dbd4..018cf6149634d1bfc30d3895c560b3341de75721 100644 (file)
@@ -382,13 +382,16 @@ private:
 };
 
 template <typename ELFT> class GNUStyle : public DumpStyle<ELFT> {
-  formatted_raw_ostream OS;
+  formatted_raw_ostream &OS;
 
 public:
   TYPEDEF_ELF_TYPES(ELFT)
 
   GNUStyle(ScopedPrinter &W, ELFDumper<ELFT> *Dumper)
-      : DumpStyle<ELFT>(Dumper), OS(W.getOStream()) {}
+      : DumpStyle<ELFT>(Dumper),
+        OS(static_cast<formatted_raw_ostream&>(W.getOStream())) {
+    assert (&W.getOStream() == &llvm::fouts());
+  }
 
   void printFileHeaders(const ELFO *Obj) override;
   void printGroupSections(const ELFFile<ELFT> *Obj) override;
index 5149f469aa1e4348ca6bcbc606399b784f8bf531..32a3866eb2f2fdff64f4f828f14bbe27c24572d3 100644 (file)
@@ -689,7 +689,7 @@ void MachODumper::printNeededLibraries() {
   llvm::stable_sort(Libs);
 
   for (const auto &L : Libs) {
-    outs() << "  " << L << "\n";
+    W.startLine() << L << "\n";
   }
 }
 
index 7bcdd1ef38c9bc21b1aa594a03c444d8dd27f88b..e44cbae6f856428cb69e460f861ae3cc3ac07485 100644 (file)
@@ -615,8 +615,8 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
 }
 
 /// 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));
@@ -624,9 +624,7 @@ static void dumpWindowsResourceFile(WindowsResource *WinRes) {
 
 
 /// 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<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
   if (!BinaryOrErr)
@@ -643,7 +641,7 @@ static void dumpInput(StringRef File) {
   else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
     dumpCOFFImportFile(Import, Writer);
   else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
-    dumpWindowsResourceFile(WinRes);
+    dumpWindowsResourceFile(WinRes, Writer);
   else
     reportError(File, readobj_error::unrecognized_file_format);
 
@@ -733,15 +731,16 @@ int main(int argc, const char *argv[]) {
   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());
   }