dwarfdump: Added macro support to llvm-dwarfdump tool.

Added "macro" option to "-debug-dump" flag, which trigger parsing and dumping of the ".debug_macinfo" section.

Differential Revision: http://reviews.llvm.org/D14294

llvm-svn: 252866
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index b3df042..7104c5f 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -10,6 +10,7 @@
   DWARFDebugInfoEntry.cpp
   DWARFDebugLine.cpp
   DWARFDebugLoc.cpp
+  DWARFDebugMacro.cpp
   DWARFDebugRangeList.cpp
   DWARFFormValue.cpp
   DWARFTypeUnit.cpp
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index ac92a63..f462485 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -127,6 +127,11 @@
     getDebugFrame()->dump(OS);
   }
 
+  if (DumpType == DIDT_All || DumpType == DIDT_Macro) {
+    OS << "\n.debug_macinfo contents:\n";
+    getDebugMacro()->dump(OS);
+  }
+
   uint32_t offset = 0;
   if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
     OS << "\n.debug_aranges contents:\n";
@@ -341,6 +346,16 @@
   return DebugFrame.get();
 }
 
+const DWARFDebugMacro *DWARFContext::getDebugMacro() {
+  if (Macro)
+    return Macro.get();
+
+  DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0);
+  Macro.reset(new DWARFDebugMacro());
+  Macro->parse(MacinfoData);
+  return Macro.get();
+}
+
 const DWARFLineTable *
 DWARFContext::getLineTableForUnit(DWARFUnit *U) {
   if (!Line)
@@ -611,6 +626,7 @@
             .Case("debug_frame", &DebugFrameSection)
             .Case("debug_str", &StringSection)
             .Case("debug_ranges", &RangeSection)
+            .Case("debug_macinfo", &MacinfoSection)
             .Case("debug_pubnames", &PubNamesSection)
             .Case("debug_pubtypes", &PubTypesSection)
             .Case("debug_gnu_pubnames", &GnuPubNamesSection)
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
new file mode 100644
index 0000000..b6555fa
--- /dev/null
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
@@ -0,0 +1,103 @@
+//===-- DWARFDebugMacro.cpp -----------------------------------------------===//

+//

+//                     The LLVM Compiler Infrastructure

+//

+// This file is distributed under the University of Illinois Open Source

+// License. See LICENSE.TXT for details.

+//

+//===----------------------------------------------------------------------===//

+

+#include "SyntaxHighlighting.h"

+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"

+#include "llvm/Support/Compiler.h"

+#include "llvm/Support/Dwarf.h"

+#include "llvm/Support/Format.h"

+#include "llvm/Support/raw_ostream.h"

+

+using namespace llvm;

+using namespace dwarf;

+using namespace syntax;

+

+void DWARFDebugMacro::dump(raw_ostream &OS) const {

+  unsigned IndLevel = 0;

+  for (const Entry &E : Macros) {

+    // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,

+    // this check handles the case of corrupted ".debug_macinfo" section.

+    if (IndLevel > 0)

+      IndLevel -= (E.Type == DW_MACINFO_end_file);

+    // Print indentation.

+    for (unsigned I = 0; I < IndLevel; I++)

+      OS << "  ";

+    IndLevel += (E.Type == DW_MACINFO_start_file);

+

+    WithColor(OS, syntax::Macro).get() << MacinfoString(E.Type);

+    switch (E.Type) {

+    default:

+      // Got a corrupted ".debug_macinfo" section (invalid macinfo type).

+      break;

+    case DW_MACINFO_define:

+    case DW_MACINFO_undef:

+      OS << " - lineno: " << E.Line;

+      OS << " macro: " << E.MacroStr;

+      break;

+    case DW_MACINFO_start_file:

+      OS << " - lineno: " << E.Line;

+      OS << " filenum: " << E.File;

+      break;

+    case DW_MACINFO_end_file:

+      break;

+    case DW_MACINFO_vendor_ext:

+      OS << " - constant: " << E.ExtConstant;

+      OS << " string: " << E.ExtStr;

+      break;

+    }

+    OS << "\n";

+  }

+}

+

+void DWARFDebugMacro::parse(DataExtractor data) {

+  uint32_t Offset = 0;

+  while (data.isValidOffset(Offset)) {

+    // A macro list entry consists of:

+    Entry E;

+    // 1. Macinfo type

+    E.Type = data.getULEB128(&Offset);

+

+    if (E.Type == 0) {

+      // Reached end of ".debug_macinfo" section.

+      return;

+    }

+

+    switch (E.Type) {

+    default:

+      // Got a corrupted ".debug_macinfo" section (invalid macinfo type).

+      // Push the corrupted entry to the list and halt parsing.

+      E.Type = DW_MACINFO_invalid;

+      Macros.push_back(E);

+      return;

+    case DW_MACINFO_define:

+    case DW_MACINFO_undef:

+      // 2. Source line

+      E.Line = data.getULEB128(&Offset);

+      // 3. Macro string

+      E.MacroStr = data.getCStr(&Offset);

+      break;

+    case DW_MACINFO_start_file:

+      // 2. Source line

+      E.Line = data.getULEB128(&Offset);

+      // 3. Source file id

+      E.File = data.getULEB128(&Offset);

+      break;

+    case DW_MACINFO_end_file:

+      break;

+    case DW_MACINFO_vendor_ext:

+      // 2. Vendor extension constant

+      E.ExtConstant = data.getULEB128(&Offset);

+      // 3. Vendor extension string

+      E.ExtStr = data.getCStr(&Offset);

+      break;

+    }

+

+    Macros.push_back(E);

+  }

+}

diff --git a/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp b/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp
index a6b4c65..4f561d0 100644
--- a/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp
+++ b/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp
@@ -27,6 +27,7 @@
     case Tag:        OS.changeColor(llvm::raw_ostream::BLUE);    break;
     case Attribute:  OS.changeColor(llvm::raw_ostream::CYAN);    break;
     case Enumerator: OS.changeColor(llvm::raw_ostream::MAGENTA); break;
+    case Macro:      OS.changeColor(llvm::raw_ostream::RED);     break;
     }
   }
 }
diff --git a/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h b/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h
index 946a313..16e6835 100644
--- a/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h
+++ b/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h
@@ -17,7 +17,7 @@
 namespace syntax {
 
 // Symbolic names for various syntax elements.
-enum HighlightColor { Address, String, Tag, Attribute, Enumerator };
+enum HighlightColor { Address, String, Tag, Attribute, Enumerator, Macro };
 
 /// An RAII object that temporarily switches an output stream to a
 /// specific color.
diff --git a/llvm/lib/Support/Dwarf.cpp b/llvm/lib/Support/Dwarf.cpp
index 5764e45..dd74038 100644
--- a/llvm/lib/Support/Dwarf.cpp
+++ b/llvm/lib/Support/Dwarf.cpp
@@ -468,6 +468,7 @@
   case DW_MACINFO_start_file:            return "DW_MACINFO_start_file";
   case DW_MACINFO_end_file:              return "DW_MACINFO_end_file";
   case DW_MACINFO_vendor_ext:            return "DW_MACINFO_vendor_ext";
+  case DW_MACINFO_invalid:               return "DW_MACINFO_invalid";
   }
   return nullptr;
 }