Index: include/lldb/Symbol/CompileUnit.h =================================================================== --- include/lldb/Symbol/CompileUnit.h +++ include/lldb/Symbol/CompileUnit.h @@ -11,6 +11,7 @@ #define liblldb_CompUnit_h_ #include "lldb/lldb-enumerations.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Function.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/ModuleChild.h" @@ -250,6 +251,9 @@ LineTable* GetLineTable (); + DebugMacros* + GetDebugMacros (); + //------------------------------------------------------------------ /// Get the compile unit's support file list. /// @@ -344,6 +348,9 @@ void SetLineTable(LineTable* line_table); + void + SetDebugMacros(const DebugMacrosSP &debug_macros); + //------------------------------------------------------------------ /// Set accessor for the variable list. /// @@ -437,6 +444,7 @@ ///< compile unit. FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations. std::unique_ptr m_line_table_ap; ///< Line table that will get parsed on demand. + DebugMacrosSP m_debug_macros_sp; ///< Debug macros that will get parsed on demand. lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. bool m_is_optimized; /// eLazyBoolYes if this compile unit was compiled with optimization. @@ -448,7 +456,8 @@ flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? flagsParsedLanguage = (1u << 4), ///< Have we parsed the language already? - flagsParsedImportedModules = (1u << 5) ///< Have we parsed the imported modules already? + flagsParsedImportedModules = (1u << 5), ///< Have we parsed the imported modules already? + flagsParsedDebugMacros = (1u << 6) ///< Have we parsed the debug macros already? }; DISALLOW_COPY_AND_ASSIGN (CompileUnit); Index: include/lldb/Symbol/DebugMacros.h =================================================================== --- /dev/null +++ include/lldb/Symbol/DebugMacros.h @@ -0,0 +1,142 @@ +//===-- DebugMacros.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DebugMacros_h_ +#define liblldb_DebugMacros_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +class DebugMacros; +typedef std::shared_ptr DebugMacrosSP; + +class DebugMacroEntry +{ +public: + enum EntryType + { + DEFINE, + UNDEF, + START_FILE, + END_FILE, + INDIRECT + }; + +public: + static DebugMacroEntry * + NewDefineEntry(uint64_t line, const char *str); + + static DebugMacroEntry * + NewUndefEntry(uint64_t line, const char *str); + + static DebugMacroEntry * + NewStartFileEntry(uint64_t line, const char *file_name); + + static DebugMacroEntry * + NewEndFileEntry(); + + static DebugMacroEntry * + NewIndirectEntry(const DebugMacrosSP &debug_macros_sp); + + ~DebugMacroEntry() { } + + EntryType + GetType() const + { + return m_type; + } + + uint64_t + GetLineNumber() const + { + return m_line; + } + + ConstString + GetMacroString() const + { + return m_str; + } + + ConstString + GetFileName() const + { + return m_file; + } + + DebugMacros * + GetIndirectDebugMacros() const + { + return m_debug_macros_sp.get(); + } + +private: + DebugMacroEntry(EntryType type, + uint64_t line, + const char *str, + const char *file_name); + + DebugMacroEntry(EntryType type, + const DebugMacrosSP &debug_macros_sp); + + EntryType m_type; + uint64_t m_line; + ConstString m_str; + ConstString m_file; + DebugMacrosSP m_debug_macros_sp; +}; + +typedef std::unique_ptr DebugMacroEntryUP; + +class DebugMacros +{ +public: + DebugMacros() { } + + ~DebugMacros() {} + + void + AddMacroEntry(DebugMacroEntry *entry) + { + m_macro_entries.push_back(DebugMacroEntryUP(entry)); + } + + size_t + GetNumMacroEntries() const + { + return m_macro_entries.size(); + } + + DebugMacroEntry * + GetMacroEntryAtIndex(const size_t index) const + { + if (index < m_macro_entries.size()) + return m_macro_entries[index].get(); + else + return NULL; + } + +private: + DISALLOW_COPY_AND_ASSIGN(DebugMacros); + + std::vector m_macro_entries; +}; + +} // namespace lldb_private + +#endif // liblldb_DebugMacros_h_ Index: include/lldb/Symbol/SymbolFile.h =================================================================== --- include/lldb/Symbol/SymbolFile.h +++ include/lldb/Symbol/SymbolFile.h @@ -123,6 +123,7 @@ virtual lldb::LanguageType ParseCompileUnitLanguage (const SymbolContext& sc) = 0; virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0; virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0; + virtual bool ParseCompileUnitDebugMacros (const SymbolContext& sc) = 0; virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0; virtual bool ParseImportedModules (const SymbolContext &sc, std::vector &imported_modules) = 0; virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0; Index: include/lldb/Symbol/SymbolVendor.h =================================================================== --- include/lldb/Symbol/SymbolVendor.h +++ include/lldb/Symbol/SymbolVendor.h @@ -62,6 +62,9 @@ ParseCompileUnitLineTable (const SymbolContext& sc); virtual bool + ParseCompileUnitDebugMacros (const SymbolContext& sc); + + virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files); Index: include/lldb/lldb-enumerations.h =================================================================== --- include/lldb/lldb-enumerations.h +++ include/lldb/lldb-enumerations.h @@ -603,6 +603,7 @@ eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, + eSectionTypeDWARFDebugMacro, eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, Index: packages/Python/lldbsuite/test/expression_command/macros/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/macros/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +DEBUG_INFO_FLAG = -g3 + + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/macros/TestMacros.py @@ -0,0 +1,85 @@ +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class TestMacros(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureClang("clang does not emit .debug_macro[.dwo] sections.") + def test_expr_with_macros(self): + self.build() + + # Get main source file + src_file = "main.cpp" + src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(src_file_spec.IsValid(), "Main source file") + + # Get the path of the executable + cwd = os.getcwd() + exe_file = "a.out" + exe_path = os.path.join(cwd, exe_file) + + # Load the executable + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target.IsValid(), VALID_TARGET) + + # Set breakpoints + bp1 = target.BreakpointCreateBySourceRegex("Break 1", src_file_spec) + self.assertTrue(bp1.IsValid() and bp1.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + process = target.LaunchSimple(None, None, self.get_process_working_directory()) + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + + # Get the thread of the process + self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + result = frame.EvaluateExpression("MACRO_1") + self.assertTrue(result.IsValid() and result.GetValue() == "100", "MACRO_1 = 100") + + result = frame.EvaluateExpression("MACRO_2") + self.assertTrue(result.IsValid() and result.GetValue() == "200", "MACRO_2 = 200") + + result = frame.EvaluateExpression("ONE") + self.assertTrue(result.IsValid() and result.GetValue() == "1", "ONE = 1") + + result = frame.EvaluateExpression("TWO") + self.assertTrue(result.IsValid() and result.GetValue() == "2", "TWO = 2") + + result = frame.EvaluateExpression("THREE") + self.assertTrue(result.IsValid() and result.GetValue() == "3", "THREE = 3") + + result = frame.EvaluateExpression("FOUR") + self.assertTrue(result.IsValid() and result.GetValue() == "4", "FOUR = 4") + + result = frame.EvaluateExpression("HUNDRED") + self.assertTrue(result.IsValid() and result.GetValue() == "100", "HUNDRED = 100") + + result = frame.EvaluateExpression("THOUSAND") + self.assertTrue(result.IsValid() and result.GetValue() == "1000", "THOUSAND = 1000") + + result = frame.EvaluateExpression("MILLION") + self.assertTrue(result.IsValid() and result.GetValue() == "1000000", "MILLION = 1000000") + + result = frame.EvaluateExpression("MAX(ONE, TWO)") + self.assertTrue(result.IsValid() and result.GetValue() == "2", "MAX(ONE, TWO) = 2") + + result = frame.EvaluateExpression("MAX(THREE, TWO)") + self.assertTrue(result.IsValid() and result.GetValue() == "3", "MAX(THREE, TWO) = 3") + + # Get the thread of the process + thread.StepOver() + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + result = frame.EvaluateExpression("MACRO_2") + self.assertTrue(result.GetError().Fail(), "Printing MACRO_2 fails") + + result = frame.EvaluateExpression("FOUR") + self.assertTrue(result.GetError().Fail(), "Printing FOUR fails") Index: packages/Python/lldbsuite/test/expression_command/macros/macro1.h =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/macros/macro1.h @@ -0,0 +1,7 @@ + +#include "macro2.h" + +#define ONE 1 +#define TWO 2 +#define THREE 3 +#define FOUR 4 Index: packages/Python/lldbsuite/test/expression_command/macros/macro2.h =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/macros/macro2.h @@ -0,0 +1,8 @@ +#define HUNDRED 100 +#define THOUSAND 1000 +#define MILLION 1000000 + +#define MAX(a, b)\ +((a) > (b) ?\ + (a):\ + (b)) Index: packages/Python/lldbsuite/test/expression_command/macros/main.cpp =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/macros/main.cpp @@ -0,0 +1,15 @@ +#include "macro1.h" + +#define MACRO_1 100 +#define MACRO_2 200 + +int +main () +{ + int a = MACRO_1 + MACRO_2; // Break 1 + + #undef MACRO_2 + #undef FOUR + + return a; +} Index: packages/Python/lldbsuite/test/make/Makefile.rules =================================================================== --- packages/Python/lldbsuite/test/make/Makefile.rules +++ packages/Python/lldbsuite/test/make/Makefile.rules @@ -182,7 +182,9 @@ LIMIT_DEBUG_INFO_FLAGS += -flimit-debug-info endif -CFLAGS ?= -g -O0 -fno-builtin +DEBUG_INFO_FLAG ?= -g + +CFLAGS ?= $(DEBUG_INFO_FLAG) -O0 -fno-builtin ifeq "$(OS)" "Darwin" CFLAGS += $(ARCHFLAG) $(ARCH) $(FRAMEWORK_INCLUDES) $(CFLAGS_EXTRAS) -I$(LLDB_BASE_DIR)include else Index: source/Expression/ExpressionSourceCode.cpp =================================================================== --- source/Expression/ExpressionSourceCode.cpp +++ source/Expression/ExpressionSourceCode.cpp @@ -12,6 +12,8 @@ #include "lldb/Core/StreamString.h" #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/ExecutionContext.h" @@ -57,6 +59,92 @@ } )"; +namespace { + +class AddMacroState +{ +public: + AddMacroState(const uint32_t main_file_line) : m_main_file_line(main_file_line) { } + + void + StartFile(uint64_t line) + { + m_start_lines.push_back(line); + } + + void + EndFile() + { + m_start_lines.pop_back(); + } + + // An entry is valid if it occurs before the current line in + // the main file. + bool + IsValidEntry(uint64_t line) + { + // If there are more than 1 files in the statestack, then it means that + // the entry is coming from an include file. It is valid. + if (m_start_lines.size() != 1) + return true; + + if (m_start_lines[0] == 0) + { + if (line >= m_main_file_line) + return false; + } + + return true; + } + +private: + std::vector m_start_lines; + uint32_t m_main_file_line; +}; + +void +AddMacros(const DebugMacros *dm, AddMacroState &state, StreamString &stream) +{ + if (dm == NULL) + return; + + for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) + { + DebugMacroEntry *entry = dm->GetMacroEntryAtIndex(i); + uint64_t line; + + switch (entry->GetType()) + { + case DebugMacroEntry::DEFINE: + if (state.IsValidEntry(entry->GetLineNumber())) + stream.Printf("#define %s\n", entry->GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::UNDEF: + if (state.IsValidEntry(entry->GetLineNumber())) + stream.Printf("#undef %s\n", entry->GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::START_FILE: + line = entry->GetLineNumber(); + if (state.IsValidEntry(line)) + state.StartFile(entry->GetLineNumber()); + else + return; + break; + case DebugMacroEntry::END_FILE: + state.EndFile(); + break; + case DebugMacroEntry::INDIRECT: + AddMacros(entry->GetIndirectDebugMacros(), state, stream); + break; + } + } +} + +} // anonymous namespace bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const { @@ -120,6 +208,24 @@ } } + + StreamString debug_macros_stream; + debug_macros_stream << ""; // Start with an empty string. + if (StackFrame *frame = exe_ctx.GetFramePtr()) + { + const SymbolContext &sc = frame->GetSymbolContext( + lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); + + if (sc.comp_unit && sc.line_entry.IsValid()) + { + DebugMacros *dm = sc.comp_unit->GetDebugMacros(); + if (dm) + { + AddMacroState state(sc.line_entry.line); + AddMacros(dm, state, debug_macros_stream); + } + } + } if (m_wrap) { @@ -135,8 +241,9 @@ StreamString wrap_stream; - wrap_stream.Printf("%s\n%s\n%s\n%s\n", + wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(), + debug_macros_stream.GetData(), g_expression_prefix, target_specific_defines, m_prefix.c_str()); Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1772,6 +1772,7 @@ static ConstString g_sect_name_dwarf_debug_line (".debug_line"); static ConstString g_sect_name_dwarf_debug_loc (".debug_loc"); static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo"); + static ConstString g_sect_name_dwarf_debug_macro (".debug_macro"); static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames"); static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes"); static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges"); @@ -1780,6 +1781,7 @@ static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo"); static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo"); static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo"); + static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo"); static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo"); static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo"); static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo"); @@ -1827,6 +1829,7 @@ else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine; else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc; else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo; + else if (name == g_sect_name_dwarf_debug_macro) sect_type = eSectionTypeDWARFDebugMacro; else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames; else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes; else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges; @@ -1835,6 +1838,7 @@ else if (name == g_sect_name_dwarf_debug_abbrev_dwo) sect_type = eSectionTypeDWARFDebugAbbrev; else if (name == g_sect_name_dwarf_debug_info_dwo) sect_type = eSectionTypeDWARFDebugInfo; else if (name == g_sect_name_dwarf_debug_line_dwo) sect_type = eSectionTypeDWARFDebugLine; + else if (name == g_sect_name_dwarf_debug_macro_dwo) sect_type = eSectionTypeDWARFDebugMacro; else if (name == g_sect_name_dwarf_debug_loc_dwo) sect_type = eSectionTypeDWARFDebugLoc; else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr; else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets; Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1369,6 +1369,7 @@ case eSectionTypeDWARFDebugLine: case eSectionTypeDWARFDebugLoc: case eSectionTypeDWARFDebugMacInfo: + case eSectionTypeDWARFDebugMacro: case eSectionTypeDWARFDebugPubNames: case eSectionTypeDWARFDebugPubTypes: case eSectionTypeDWARFDebugRanges: Index: source/Plugins/SymbolFile/DWARF/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -12,6 +12,7 @@ DWARFDebugInfo.cpp DWARFDebugInfoEntry.cpp DWARFDebugLine.cpp + DWARFDebugMacro.cpp DWARFDebugMacinfo.cpp DWARFDebugMacinfoEntry.cpp DWARFDebugPubnames.cpp Index: source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -0,0 +1,66 @@ +//===-- 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 SymbolFileDWARF_DWARFDebugMacro_h_ +#define SymbolFileDWARF_DWARFDebugMacro_h_ + +#include + +#include "lldb/lldb-types.h" +#include "lldb/Symbol/DebugMacros.h" +#include "llvm/Support/Dwarf.h" + +namespace lldb_private +{ + +class DWARFDataExtractor; + +} // namespace lldb_private + +class SymbolFileDWARF; + +enum DWARFMacroHeaderFlagMask +{ + MACRO_HEADER_OFFSET_SIZE_MASK = 0x1, + MACRO_HEADER_DEBUG_LINE_OFFSET_MASK = 0x2, + MACRO_HEADER_OPCODE_OPERANDS_TABLE_MASK = 0x4 +}; + +class DWARFDebugMacroOperandTable +{ +public: + class Entry + { + public: + uint8_t opcode_number; + uint64_t operand_count; + std::vector operand_forms; + }; + +public: + uint8_t entry_count; + std::map entry_map; // Mapping from opcode number to its entry. + + static DWARFDebugMacroOperandTable * + ReadOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); +}; + +class DWARFDebugMacroEntry +{ +public: + static void + ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, + const lldb_private::DWARFDataExtractor &debug_str_data, + const bool offset_is_64_bit, + lldb::offset_t *sect_offset, + SymbolFileDWARF *sym_file_dwarf, + lldb_private::DebugMacrosSP &debug_macros_sp); +}; + +#endif // SymbolFileDWARF_DWARFDebugMacro_h_ Index: source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -0,0 +1,109 @@ +//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugMacro.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Symbol/DebugMacros.h" + +#include "DWARFDataExtractor.h" + +using namespace lldb_private; + +DWARFDebugMacroOperandTable * +DWARFDebugMacroOperandTable::ReadOperandTable(const DWARFDataExtractor &debug_macro_data, + lldb::offset_t *offset) +{ + DWARFDebugMacroOperandTable *tbl = new DWARFDebugMacroOperandTable(); + + tbl->entry_count = debug_macro_data.GetU8(offset); + for (uint8_t i = 0; i < tbl->entry_count; i++) + { + DWARFDebugMacroOperandTable::Entry entry; + + entry.opcode_number = debug_macro_data.GetU8(offset); + entry.operand_count = debug_macro_data.GetULEB128(offset); + + for (uint64_t j = 0; j < entry.operand_count; j++) + { + llvm::dwarf::Form form = static_cast(debug_macro_data.GetU8(offset)); + entry.operand_forms.push_back(form); + } + + tbl->entry_map.emplace(entry.opcode_number, entry); + } + + return tbl; +} + +void +DWARFDebugMacroEntry::ReadMacroEntries(const DWARFDataExtractor &debug_macro_data, + const DWARFDataExtractor &debug_str_data, + const bool offset_is_64_bit, + lldb::offset_t *offset, + SymbolFileDWARF *sym_file_dwarf, + DebugMacrosSP &debug_macros_sp) +{ + llvm::dwarf::MacroEntryType type = static_cast(debug_macro_data.GetU8(offset)); + while (type != 0) + { + lldb::offset_t new_offset, str_offset; + uint64_t line; + const char *macro_str; + + switch (type) + { + case DW_MACRO_define: + case DW_MACRO_undef: + line = debug_macro_data.GetULEB128(offset); + macro_str = debug_macro_data.GetCStr(offset); + if (type == DW_MACRO_define) + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewUndefEntry(line, macro_str)); + break; + case DW_MACRO_define_indirect: + case DW_MACRO_undef_indirect: + line = debug_macro_data.GetULEB128(offset); + if (offset_is_64_bit) + str_offset = debug_macro_data.GetU64(offset); + else + str_offset = debug_macro_data.GetU32(offset); + macro_str = debug_str_data.GetCStr(&str_offset); + if (type == DW_MACRO_define_indirect) + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewDefineEntry(line, macro_str)); + else + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewUndefEntry(line, macro_str)); + break; + case DW_MACRO_start_file: + line = debug_macro_data.GetULEB128(offset); + // For now we just skip over the file name offset as we do not use it anywhere. + debug_macro_data.GetULEB128(offset); + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewStartFileEntry(line, NULL)); + break; + case DW_MACRO_end_file: + // This operation has no operands. + debug_macros_sp->AddMacroEntry(DebugMacroEntry::NewEndFileEntry()); + break; + case DW_MACRO_transparent_include: + if (offset_is_64_bit) + new_offset = debug_macro_data.GetU64(offset); + else + new_offset = debug_macro_data.GetU32(offset); + debug_macros_sp->AddMacroEntry( + DebugMacroEntry::NewIndirectEntry(sym_file_dwarf->ParseDebugMacros(&new_offset))); + break; + default: + // TODO: Add support for other standard operations. + // TODO: Provide mechanism to hook handling of non-standard/extension operands. + return; + } + type = static_cast(debug_macro_data.GetU8(offset)); + } +} Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -28,6 +28,7 @@ #include "lldb/Core/RangeMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -124,6 +125,9 @@ ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; bool + ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override; + + bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files) override; @@ -248,6 +252,7 @@ const lldb_private::DWARFDataExtractor& get_debug_frame_data (); const lldb_private::DWARFDataExtractor& get_debug_info_data (); const lldb_private::DWARFDataExtractor& get_debug_line_data (); + const lldb_private::DWARFDataExtractor& get_debug_macro_data (); const lldb_private::DWARFDataExtractor& get_debug_loc_data (); const lldb_private::DWARFDataExtractor& get_debug_ranges_data (); const lldb_private::DWARFDataExtractor& get_debug_str_data (); @@ -302,6 +307,9 @@ bool Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); + lldb_private::DebugMacrosSP + ParseDebugMacros(lldb::offset_t *offset); + static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die); @@ -530,6 +538,7 @@ DWARFDataSegment m_data_debug_frame; DWARFDataSegment m_data_debug_info; DWARFDataSegment m_data_debug_line; + DWARFDataSegment m_data_debug_macro; DWARFDataSegment m_data_debug_loc; DWARFDataSegment m_data_debug_ranges; DWARFDataSegment m_data_debug_str; @@ -549,6 +558,10 @@ std::unique_ptr m_apple_namespaces_ap; std::unique_ptr m_apple_objc_ap; std::unique_ptr m_global_aranges_ap; + + typedef std::map DebugMacrosMap; + DebugMacrosMap m_debug_macros_map; + ExternalTypeModuleMap m_external_type_modules; NameToDIE m_function_basename_index; // All concrete functions NameToDIE m_function_fullname_index; // All concrete functions Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -39,6 +39,7 @@ #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/DebugMacros.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TypeSystem.h" @@ -58,6 +59,7 @@ #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugLine.h" +#include "DWARFDebugMacro.h" #include "DWARFDebugPubnames.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" @@ -436,6 +438,7 @@ m_data_debug_frame (), m_data_debug_info (), m_data_debug_line (), + m_data_debug_macro (), m_data_debug_loc (), m_data_debug_ranges (), m_data_debug_str (), @@ -709,6 +712,12 @@ } const DWARFDataExtractor& +SymbolFileDWARF::get_debug_macro_data() +{ + return GetCachedSectionData (eSectionTypeDWARFDebugMacro, m_data_debug_macro); +} + +const DWARFDataExtractor& SymbolFileDWARF::get_debug_loc_data() { return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc); @@ -1204,6 +1213,73 @@ return false; } +lldb_private::DebugMacrosSP +SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) +{ + auto iter = m_debug_macros_map.find(*offset); + if (iter != m_debug_macros_map.end()) + return iter->second; + + const DWARFDataExtractor &debug_macro_data = get_debug_macro_data(); + if (debug_macro_data.GetByteSize() == 0) + return DebugMacrosSP(); + + lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros()); + m_debug_macros_map[*offset] = debug_macros_sp; + + // Read the header. + + // Skip over the version field in header. + debug_macro_data.GetU16(offset); + uint8_t flags = debug_macro_data.GetU8(offset); + bool offset_bit_size_64 = flags & MACRO_HEADER_OFFSET_SIZE_MASK ? true : false; + + uint64_t debug_line_offset = 0; + if (flags & MACRO_HEADER_DEBUG_LINE_OFFSET_MASK) + { + if (offset_bit_size_64) + debug_line_offset = debug_macro_data.GetU64(offset); + else + debug_line_offset = debug_macro_data.GetU32(offset); + } + + // Skip over the operand table. + std::unique_ptr opr_tbl_ap; + if (flags & MACRO_HEADER_OPCODE_OPERANDS_TABLE_MASK) + { + opr_tbl_ap.reset(DWARFDebugMacroOperandTable::ReadOperandTable(debug_macro_data, offset)); + } + + DWARFDebugMacroEntry::ReadMacroEntries( + debug_macro_data, get_debug_str_data(), offset_bit_size_64, offset, this, debug_macros_sp); + + return debug_macros_sp; +} + +bool +SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc) +{ + assert (sc.comp_unit); + + DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + if (dwarf_cu == NULL) + return false; + + const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); + if (!dwarf_cu_die) + return false; + + lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET); + if (sect_offset == DW_INVALID_OFFSET) + return false; + + sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); + + return true; +} + size_t SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc, Block *parent_block, Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -63,6 +63,7 @@ lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override; size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override; bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; + bool ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override; bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override; bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector &imported_modules) override; size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -707,6 +707,15 @@ } bool +SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros (const SymbolContext& sc) +{ + SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); + if (oso_dwarf) + return oso_dwarf->ParseCompileUnitDebugMacros (sc); + return false; +} + +bool SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) { SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); Index: source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h =================================================================== --- source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -69,6 +69,9 @@ ParseCompileUnitLineTable(const lldb_private::SymbolContext& sc) override; bool + ParseCompileUnitDebugMacros(const lldb_private::SymbolContext& sc) override; + + bool ParseCompileUnitSupportFiles(const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override; Index: source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp =================================================================== --- source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -253,6 +253,12 @@ } bool +SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc) +{ + return false; +} + +bool SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files) { return false; Index: source/Symbol/CMakeLists.txt =================================================================== --- source/Symbol/CMakeLists.txt +++ source/Symbol/CMakeLists.txt @@ -10,6 +10,7 @@ CompilerType.cpp CompileUnit.cpp CompactUnwindInfo.cpp + DebugMacros.cpp Declaration.cpp DWARFCallFrameInfo.cpp Function.cpp Index: source/Symbol/CompileUnit.cpp =================================================================== --- source/Symbol/CompileUnit.cpp +++ source/Symbol/CompileUnit.cpp @@ -268,6 +268,37 @@ m_line_table_ap.reset(line_table); } +DebugMacros* +CompileUnit::GetDebugMacros() +{ + if (m_debug_macros_sp.get() == nullptr) + { + if (m_flags.IsClear(flagsParsedDebugMacros)) + { + m_flags.Set(flagsParsedDebugMacros); + SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); + if (symbol_vendor) + { + SymbolContext sc; + CalculateSymbolContext(&sc); + symbol_vendor->ParseCompileUnitDebugMacros(sc); + } + } + } + + return m_debug_macros_sp.get(); +} + +void +CompileUnit::SetDebugMacros(const DebugMacrosSP &debug_macros_sp) +{ + if (debug_macros_sp.get() == nullptr) + m_flags.Clear(flagsParsedDebugMacros); + else + m_flags.Set(flagsParsedDebugMacros); + m_debug_macros_sp = debug_macros_sp; +} + VariableListSP CompileUnit::GetVariableList(bool can_create) { Index: source/Symbol/DebugMacros.cpp =================================================================== --- /dev/null +++ source/Symbol/DebugMacros.cpp @@ -0,0 +1,57 @@ +//===-- DebugMacros.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/DebugMacros.h" + +using namespace lldb_private; + +DebugMacroEntry::DebugMacroEntry(EntryType type, + uint64_t line, + const char *str, + const char *file_name) + : m_type(type), + m_line(line), + m_str(str), + m_file(file_name) +{ } + +DebugMacroEntry::DebugMacroEntry(EntryType type, + const DebugMacrosSP &debug_macros_sp) + : m_type(type), m_debug_macros_sp(debug_macros_sp) +{ } + +DebugMacroEntry * +DebugMacroEntry::NewDefineEntry(uint64_t line, const char *str) +{ + return new DebugMacroEntry(DebugMacroEntry::DEFINE, line, str, NULL); +} + +DebugMacroEntry * +DebugMacroEntry::NewUndefEntry(uint64_t line, const char *str) +{ + return new DebugMacroEntry(DebugMacroEntry::UNDEF, line, str, NULL); +} + +DebugMacroEntry * +DebugMacroEntry::NewStartFileEntry(uint64_t line, const char *file_name) +{ + return new DebugMacroEntry(DebugMacroEntry::START_FILE, line, NULL, file_name); +} + +DebugMacroEntry * +DebugMacroEntry::NewEndFileEntry() +{ + return new DebugMacroEntry(DebugMacroEntry::END_FILE, 0, NULL, NULL); +} + +DebugMacroEntry * +DebugMacroEntry::NewIndirectEntry(const DebugMacrosSP &debug_macros_sp) +{ + return new DebugMacroEntry(DebugMacroEntry::INDIRECT, debug_macros_sp); +} Index: source/Symbol/ObjectFile.cpp =================================================================== --- source/Symbol/ObjectFile.cpp +++ source/Symbol/ObjectFile.cpp @@ -362,6 +362,7 @@ case eSectionTypeDWARFDebugLine: case eSectionTypeDWARFDebugLoc: case eSectionTypeDWARFDebugMacInfo: + case eSectionTypeDWARFDebugMacro: case eSectionTypeDWARFDebugPubNames: case eSectionTypeDWARFDebugPubTypes: case eSectionTypeDWARFDebugRanges: Index: source/Symbol/SymbolVendor.cpp =================================================================== --- source/Symbol/SymbolVendor.cpp +++ source/Symbol/SymbolVendor.cpp @@ -186,6 +186,18 @@ } bool +SymbolVendor::ParseCompileUnitDebugMacros (const SymbolContext &sc) +{ + ModuleSP module_sp(GetModule()); + if (module_sp) + { + lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitDebugMacros(sc); + } + return false; +} +bool SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) { ModuleSP module_sp(GetModule()); Index: source/Utility/ConvertEnum.cpp =================================================================== --- source/Utility/ConvertEnum.cpp +++ source/Utility/ConvertEnum.cpp @@ -77,6 +77,8 @@ return "dwarf-loc"; case eSectionTypeDWARFDebugMacInfo: return "dwarf-macinfo"; + case eSectionTypeDWARFDebugMacro: + return "dwarf-macro"; case eSectionTypeDWARFDebugPubNames: return "dwarf-pubnames"; case eSectionTypeDWARFDebugPubTypes: