From 6ab659a922bf919764dc5dd7a6c47e61b35bbde5 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Wed, 29 Jul 2015 00:42:47 +0000 Subject: [PATCH] First part of an attempt to indicate to the user when they are debugging optimized code. Adds new methods on Function/SBFunction to query whether a given function is optimized. Adds a new function.is-optimized format entity and changes the default frame-format to append "[opt]" if the function was built with optimization. The only indication that a binary was built with optimization that we have right now is the presence of the DW_AT_APPLE_optimized attribute (DW_FORM_flag value 1) in the DW_TAG_compile_unit. The absence of this flag may mean that the compile_unit was not compiled with optimization, or it may mean that the producer does not generate this attribute. Currently this only works for dSYM debugging. When we create the CompileUnit with dwarf-in-.o-file debugging we don't have the attribute value yet so it's not set. I need to find the flag value when we do start to read the .o file DWARF and set the CompileUnit's status at that point - but haven't done it yet. I'm also going to add a mechanism for issuing warnings to users such that they're only issued once in a debug session and there is away for users to suppress these warnings altogether via .lldbinit file settings. But I want to get this changeset committed now that it's at a useful state. llvm-svn: 243508 --- lldb/include/lldb/API/SBFunction.h | 3 +++ lldb/include/lldb/Core/FormatEntity.h | 1 + lldb/include/lldb/Symbol/CompileUnit.h | 27 ++++++++++++++++++++-- lldb/include/lldb/Symbol/Function.h | 18 +++++++++++++++ lldb/scripts/interface/SBFunction.i | 10 ++++++++ lldb/source/API/SBFunction.cpp | 11 ++++++++- lldb/source/Core/Debugger.cpp | 2 ++ lldb/source/Core/FormatEntity.cpp | 14 ++++++++++- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 8 ++++++- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 3 ++- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 2 +- lldb/source/Symbol/CompileUnit.cpp | 16 +++++++++---- lldb/source/Symbol/Function.cpp | 15 ++++++++++++ 13 files changed, 119 insertions(+), 11 deletions(-) diff --git a/lldb/include/lldb/API/SBFunction.h b/lldb/include/lldb/API/SBFunction.h index 86cfeb4..8fb24c4 100644 --- a/lldb/include/lldb/API/SBFunction.h +++ b/lldb/include/lldb/API/SBFunction.h @@ -66,6 +66,9 @@ public: GetLanguage (); bool + GetIsOptimized (); + + bool operator == (const lldb::SBFunction &rhs) const; bool diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h index db4f591..d3a0b0c 100644 --- a/lldb/include/lldb/Core/FormatEntity.h +++ b/lldb/include/lldb/Core/FormatEntity.h @@ -81,6 +81,7 @@ namespace lldb_private FunctionPCOffset, FunctionInitial, FunctionChanged, + FunctionIsOptimized, LineEntryFile, LineEntryLineNumber, LineEntryStartAddress, diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index e0c0693..85f446d 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -66,9 +66,12 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// + /// @param[in] is_optimized + /// true if this compile unit was compiled with optimization. + /// /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language); + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized); //------------------------------------------------------------------ /// Construct with a module, file spec, UID and language. @@ -98,9 +101,12 @@ public: /// A language enumeration type that describes the main language /// of this compile unit. /// + /// @param[in] is_optimized + /// true if this compile unit was compiled with optimization. + /// /// @see lldb::LanguageType //------------------------------------------------------------------ - CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language); + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language, bool is_optimized); //------------------------------------------------------------------ /// Destructor @@ -406,6 +412,22 @@ public: SymbolContextList &sc_list); + //------------------------------------------------------------------ + /// Get whether compiler optimizations were enabled for this compile unit + /// + /// "optimized" means that the debug experience may be difficult + /// for the user to understand. Variables may not be available when + /// the developer would expect them, stepping through the source lines + /// in the function may appear strange, etc. + /// + /// @return + /// Returns 'true' if this compile unit was compiled with + /// optimization. 'false' indicates that either the optimization + /// is unknown, or this compile unit was built without optimization. + //------------------------------------------------------------------ + bool + GetIsOptimized (); + protected: void *m_user_data; ///< User data for the SymbolFile parser to store information into. lldb::LanguageType m_language; ///< The programming language enumeration value. @@ -417,6 +439,7 @@ protected: 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. 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. private: enum diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index 30c8f16..7b7c541 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -616,6 +616,24 @@ public: size_t MemorySize () const; + //------------------------------------------------------------------ + /// Get whether compiler optimizations were enabled for this function + /// + /// The debug information may provide information about whether this + /// function was compiled with optimization or not. In this case, + /// "optimized" means that the debug experience may be difficult + /// for the user to understand. Variables may not be available when + /// the developer would expect them, stepping through the source lines + /// in the function may appear strange, etc. + /// + /// @return + /// Returns 'true' if this function was compiled with + /// optimization. 'false' indicates that either the optimization + /// is unknown, or this function was built without optimization. + //------------------------------------------------------------------ + bool + GetIsOptimized (); + lldb::DisassemblerSP GetInstructions (const ExecutionContext &exe_ctx, const char *flavor, diff --git a/lldb/scripts/interface/SBFunction.i b/lldb/scripts/interface/SBFunction.i index 3462375..df8fb88 100644 --- a/lldb/scripts/interface/SBFunction.i +++ b/lldb/scripts/interface/SBFunction.i @@ -89,6 +89,16 @@ public: lldb::LanguageType GetLanguage (); + %feature("docstring", " + Returns true if the function was compiled with optimization. + Optimization, in this case, is meant to indicate that the debugger + experience may be confusing for the user -- variables optimized away, + stepping jumping between source lines -- and the driver may want to + provide some guidance to the user about this. + Returns false if unoptimized, or unknown.") GetIsOptimized; + bool + GetIsOptimized(); + bool GetDescription (lldb::SBStream &description); diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp index 2ec6072..795a726 100644 --- a/lldb/source/API/SBFunction.cpp +++ b/lldb/source/API/SBFunction.cpp @@ -258,4 +258,13 @@ SBFunction::GetLanguage () return lldb::eLanguageTypeUnknown; } - +bool +SBFunction::GetIsOptimized () +{ + if (m_opaque_ptr) + { + if (m_opaque_ptr->GetCompileUnit()) + return m_opaque_ptr->GetCompileUnit()->GetIsOptimized(); + } + return false; +} diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index cd41e5d..55324f1 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -105,6 +105,7 @@ g_language_enumerators[] = #define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" +#define IS_OPTIMIZED "{${function.is-optimized} [opt]}" #define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ "{, ${frame.pc}}"\ @@ -122,6 +123,7 @@ g_language_enumerators[] = #define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ MODULE_WITH_FUNC\ FILE_AND_LINE\ + IS_OPTIMIZED\ "\\n" // Three parts to this disassembly format specification: diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index b960007..19889ce 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -98,7 +98,8 @@ static FormatEntity::Entry::Definition g_function_child_entries[] = ENTRY ("line-offset" , FunctionLineOffset , UInt64), ENTRY ("pc-offset" , FunctionPCOffset , UInt64), ENTRY ("initial-function" , FunctionInitial , None), - ENTRY ("changed" , FunctionChanged , None) + ENTRY ("changed" , FunctionChanged , None), + ENTRY ("is-optimized" , FunctionIsOptimized , None) }; static FormatEntity::Entry::Definition g_line_child_entries[] = @@ -343,6 +344,7 @@ FormatEntity::Entry::TypeToCString (Type t) ENUM_TO_CSTR(FunctionPCOffset); ENUM_TO_CSTR(FunctionInitial); ENUM_TO_CSTR(FunctionChanged); + ENUM_TO_CSTR(FunctionIsOptimized); ENUM_TO_CSTR(LineEntryFile); ENUM_TO_CSTR(LineEntryLineNumber); ENUM_TO_CSTR(LineEntryStartAddress); @@ -1870,6 +1872,16 @@ FormatEntity::Format (const Entry &entry, case Entry::Type::FunctionChanged: return function_changed == true; + case Entry::Type::FunctionIsOptimized: + { + bool is_optimized = false; + if (sc->function && sc->function->GetIsOptimized()) + { + is_optimized = true; + } + return is_optimized; + } + case Entry::Type::FunctionInitial: return initial_function == true; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b18628f..564b2dd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1034,11 +1034,17 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0)); + bool is_optimized = false; + if (cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_APPLE_optimized, 0) == 1) + { + is_optimized = true; + } cu_sp.reset(new CompileUnit (module_sp, dwarf_cu, cu_file_spec, MakeUserID(dwarf_cu->GetOffset()), - cu_language)); + cu_language, + is_optimized)); if (cu_sp) { // If we just created a compile unit with an invalid file spec, try and get the diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index de972ac..1e973b0 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -660,7 +660,8 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) NULL, so_file_spec, cu_id, - eLanguageTypeUnknown)); + eLanguageTypeUnknown, + false)); if (m_compile_unit_infos[cu_idx].compile_unit_sp) { diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 09b9197..d535078 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -161,7 +161,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) { const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) - cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown)); + cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false)); } return cu_sp; } diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index d43ef44..29ee995 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -17,7 +17,7 @@ using namespace lldb; using namespace lldb_private; -CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : +CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) : ModuleChild(module_sp), FileSpec (pathname, false), UserID(cu_sym_id), @@ -27,14 +27,15 @@ CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, cons m_functions (), m_support_files (), m_line_table_ap (), - m_variables() + m_variables(), + m_is_optimized (is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); assert(module_sp); } -CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) : +CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, bool is_optimized) : ModuleChild(module_sp), FileSpec (fspec), UserID(cu_sym_id), @@ -44,7 +45,8 @@ CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, cons m_functions (), m_support_files (), m_line_table_ap (), - m_variables() + m_variables(), + m_is_optimized (is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); @@ -430,6 +432,12 @@ CompileUnit::ResolveSymbolContext return sc_list.GetSize() - prev_size; } +bool +CompileUnit::GetIsOptimized () +{ + return m_is_optimized; +} + void CompileUnit::SetVariableList(VariableListSP &variables) { diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 77448d4..be51925 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -466,6 +466,21 @@ Function::MemorySize () const return mem_size; } +bool +Function::GetIsOptimized () +{ + bool result = false; + + // Currently optimization is only indicted by the + // vendor extension DW_AT_APPLE_optimized which + // is set on a compile unit level. + if (m_comp_unit) + { + result = m_comp_unit->GetIsOptimized(); + } + return result; +} + ConstString Function::GetDisplayName () const { -- 2.7.4