Index: include/llvm/DebugInfo/DIContext.h =================================================================== --- include/llvm/DebugInfo/DIContext.h +++ include/llvm/DebugInfo/DIContext.h @@ -112,6 +112,7 @@ DIDT_LineDwo, DIDT_Loc, DIDT_LocDwo, + DIDT_Macro, DIDT_Ranges, DIDT_Pubnames, DIDT_Pubtypes, Index: include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFContext.h +++ include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" @@ -45,6 +46,7 @@ std::unique_ptr Aranges; std::unique_ptr Line; std::unique_ptr DebugFrame; + std::unique_ptr Macro; DWARFUnitSection DWOCUs; std::vector> DWOTUs; @@ -161,6 +163,9 @@ /// Get a pointer to the parsed frame information object. const DWARFDebugFrame *getDebugFrame(); + /// Get a pointer to the parsed DebugMacro object. + const DWARFDebugMacro *getDebugMacro(); + /// Get a pointer to a parsed line table corresponding to a compile unit. const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); @@ -184,6 +189,7 @@ virtual const DWARFSection &getLineSection() = 0; virtual StringRef getStringSection() = 0; virtual StringRef getRangeSection() = 0; + virtual StringRef getMacinfoSection() = 0; virtual StringRef getPubNamesSection() = 0; virtual StringRef getPubTypesSection() = 0; virtual StringRef getGnuPubNamesSection() = 0; @@ -232,6 +238,7 @@ DWARFSection LineSection; StringRef StringSection; StringRef RangeSection; + StringRef MacinfoSection; StringRef PubNamesSection; StringRef PubTypesSection; StringRef GnuPubNamesSection; @@ -268,6 +275,7 @@ const DWARFSection &getLineSection() override { return LineSection; } StringRef getStringSection() override { return StringSection; } StringRef getRangeSection() override { return RangeSection; } + StringRef getMacinfoSection() override { return MacinfoSection; } StringRef getPubNamesSection() override { return PubNamesSection; } StringRef getPubTypesSection() override { return PubTypesSection; } StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } Index: include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h @@ -0,0 +1,51 @@ +//===-- DWARFDebugMacro.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H +#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Dwarf.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugMacro { + /// A single macro entry within a macro list. + struct Entry { + /// The type of the macro entry. + uint32_t Type; + /// The source line where the macro is defined. + unsigned Line; + + /// The string (name, value) of the macro entry. + StringRef MacroStr; + // An unsigned integer indicating the identity of the source file. + uint16_t File; + }; + + typedef SmallVector MacroList; + + /// A list of all the macro entries in the debug_macinfo section. + MacroList Macros; + +public: + DWARFDebugMacro() {} + /// Print the macro list found within the debug_macinfo section. + void dump(raw_ostream &OS) const; + /// Parse the debug_macinfo section accessible via the 'data' parameter. + void parse(DataExtractor data); +}; + +} + +#endif Index: lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- lib/DebugInfo/DWARF/CMakeLists.txt +++ lib/DebugInfo/DWARF/CMakeLists.txt @@ -10,6 +10,7 @@ DWARFDebugInfoEntry.cpp DWARFDebugLine.cpp DWARFDebugLoc.cpp + DWARFDebugMacro.cpp DWARFDebugRangeList.cpp DWARFFormValue.cpp DWARFTypeUnit.cpp Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -126,6 +126,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"; @@ -322,6 +327,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) @@ -592,6 +607,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) Index: lib/DebugInfo/DWARF/DWARFDebugMacro.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -0,0 +1,99 @@ +//===-- DWARFDebugLoc.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/ErrorHandling.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) { + 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: llvm_unreachable("Invalid macinfo type"); + case DW_MACINFO_define: + case dwarf::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: + // FIXME: DW_MACINFO_vendor_ext is not supported. + break; + } + OS << "\n"; + } +} + +void DWARFDebugMacro::parse(DataExtractor data) { + uint32_t Offset = 0; + // A macro list entry consists of: + while (data.isValidOffset(Offset)) { + + if (data.getData().data()[Offset] == '\0') { + // Reached end of ".debug_macinfo" section. + // Skip the '\0' byte and stop parsing. + (void)data.getU8(&Offset); + break; + } + + Entry E; + // 1. Macinfo type + E.Type = data.getULEB128(&Offset); + + switch (E.Type) { + default: + llvm::errs() << "error: Invalid macinfo type\n"; + return; + case DW_MACINFO_define: + case DW_MACINFO_undef: + // 2. Source line + E.Line = (unsigned)data.getULEB128(&Offset); + // 3. Macro string + E.MacroStr = data.getCStr(&Offset); + break; + case DW_MACINFO_start_file: + // 2. Source line + E.Line = (unsigned)data.getULEB128(&Offset); + // 3. Source file id + E.File = (uint16_t)data.getULEB128(&Offset); + break; + case DW_MACINFO_end_file: + break; + case DW_MACINFO_vendor_ext: + // DW_MACINFO_vendor_ext is not supported. + // Just skip it (read and ignore). + (void)data.getULEB128(&Offset); + (void)data.getCStr(&Offset); + break; + } + + Macros.push_back(E); + } +} + Index: lib/DebugInfo/DWARF/SyntaxHighlighting.h =================================================================== --- lib/DebugInfo/DWARF/SyntaxHighlighting.h +++ 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. Index: lib/DebugInfo/DWARF/SyntaxHighlighting.cpp =================================================================== --- lib/DebugInfo/DWARF/SyntaxHighlighting.cpp +++ 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; } } } Index: test/DebugInfo/Inputs/dwarfdump-macro-cmd.h =================================================================== --- test/DebugInfo/Inputs/dwarfdump-macro-cmd.h +++ test/DebugInfo/Inputs/dwarfdump-macro-cmd.h @@ -0,0 +1 @@ +#define M4 Value4 Index: test/DebugInfo/Inputs/dwarfdump-macro.h =================================================================== --- test/DebugInfo/Inputs/dwarfdump-macro.h +++ test/DebugInfo/Inputs/dwarfdump-macro.h @@ -0,0 +1,5 @@ + + + +#undef M1 +#define M1 NewValue1 Index: test/DebugInfo/Inputs/dwarfdump-macro.cc =================================================================== --- test/DebugInfo/Inputs/dwarfdump-macro.cc +++ test/DebugInfo/Inputs/dwarfdump-macro.cc @@ -0,0 +1,11 @@ +#define M1 Value1 +#include "dwarfdump-macro.h" +#define M2(x, y) ((x)+(y)* Value2) + +// Built with GCC +// $ mkdir -p /tmp/dbginfo +// $ cp dwarfdump-macro.cc /tmp/dbginfo +// $ cp dwarfdump-macro.h /tmp/dbginfo +// $ cp dwarfdump-macro-cmd.h /tmp/dbginfo +// $ cd /tmp/dbginfo +// $ g++ -c -g3 -O0 -DM3=Value3 -include dwarfdump-macro-cmd.h dwarfdump-macro.cc -o Index: test/DebugInfo/debugmacinfo.test =================================================================== --- test/DebugInfo/debugmacinfo.test +++ test/DebugInfo/debugmacinfo.test @@ -0,0 +1,27 @@ +RUN: llvm-dwarfdump -debug-dump=macro %p/Inputs/dwarfdump-macro.o \ +RUN: | FileCheck %s -check-prefix TEST_MACINFO +RUN: llvm-dwarfdump -debug-dump=line %p/Inputs/dwarfdump-macro.o \ +RUN: | FileCheck %s -check-prefix TEST_LINE + + +; This test verifies that llvm-dwarfdump tools know how to read .debug_macinfo +; section. It also checks that the file numbers fits with those in the +; .debug_line section. +TEST_MACINFO: .debug_macinfo contents: +TEST_MACINFO: DW_MACINFO_define - lineno: 0 macro: M3 Value3 +TEST_MACINFO: DW_MACINFO_start_file - lineno: 0 filenum: 1 +TEST_MACINFO: DW_MACINFO_start_file - lineno: 0 filenum: 2 +TEST_MACINFO: DW_MACINFO_define - lineno: 1 macro: M4 Value4 +TEST_MACINFO: DW_MACINFO_end_file +TEST_MACINFO: DW_MACINFO_define - lineno: 1 macro: M1 Value1 +TEST_MACINFO: DW_MACINFO_start_file - lineno: 2 filenum: 3 +TEST_MACINFO: DW_MACINFO_undef - lineno: 4 macro: M1 +TEST_MACINFO: DW_MACINFO_define - lineno: 5 macro: M1 NewValue1 +TEST_MACINFO: DW_MACINFO_end_file +TEST_MACINFO: DW_MACINFO_define - lineno: 3 macro: M2(x,y) ((x)+(y)* Value2) +TEST_MACINFO: DW_MACINFO_end_file + +TEST_LINE: .debug_line contents: +TEST_LINE: file_names[ 1] 0 0x00000000 0x00000000 dwarfdump-macro.cc +TEST_LINE: file_names[ 2] 1 0x00000000 0x00000000 dwarfdump-macro-cmd.h +TEST_LINE: file_names[ 3] 0 0x00000000 0x00000000 dwarfdump-macro.h Index: tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -60,6 +60,7 @@ clEnumValN(DIDT_Loc, "loc", ".debug_loc"), clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"), clEnumValN(DIDT_Frames, "frames", ".debug_frame"), + clEnumValN(DIDT_Macro, "macro", ".debug_macinfo"), clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"), clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"), clEnumValN(DIDT_Pubtypes, "pubtypes", ".debug_pubtypes"),