forked from OSchip/llvm-project
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. <rdar://problem/19281172> llvm-svn: 243508
This commit is contained in:
parent
ff244c1d97
commit
6ab659a922
|
@ -65,6 +65,9 @@ public:
|
|||
lldb::LanguageType
|
||||
GetLanguage ();
|
||||
|
||||
bool
|
||||
GetIsOptimized ();
|
||||
|
||||
bool
|
||||
operator == (const lldb::SBFunction &rhs) const;
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ namespace lldb_private
|
|||
FunctionPCOffset,
|
||||
FunctionInitial,
|
||||
FunctionChanged,
|
||||
FunctionIsOptimized,
|
||||
LineEntryFile,
|
||||
LineEntryLineNumber,
|
||||
LineEntryStartAddress,
|
||||
|
|
|
@ -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<LineTable> 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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue