[Lldb-commits] [lldb] r182067 - <rdar://problem/13217784>

Greg Clayton gclayton at apple.com
Thu May 16 17:56:10 PDT 2013


Author: gclayton
Date: Thu May 16 19:56:10 2013
New Revision: 182067

URL: http://llvm.org/viewvc/llvm-project?rev=182067&view=rev
Log:
<rdar://problem/13217784>

"source list -n <func>" can now show more than one location that matches a function name. It will unique multiple of the same source locations so they don't get displayed. It also handles inline functions correctly.


Modified:
    lldb/trunk/include/lldb/Symbol/SymbolContext.h
    lldb/trunk/source/Commands/CommandObjectSource.cpp
    lldb/trunk/source/Symbol/SymbolContext.cpp

Modified: lldb/trunk/include/lldb/Symbol/SymbolContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolContext.h?rev=182067&r1=182066&r2=182067&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolContext.h Thu May 16 19:56:10 2013
@@ -285,7 +285,31 @@ public:
     ///     The name of the function represented by this symbol context.
     //------------------------------------------------------------------
     ConstString
-    GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled);
+    GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const;
+
+    
+    //------------------------------------------------------------------
+    /// Get the line entry that corresponds to the function.
+    ///
+    /// If the symbol context contains an inlined block, the line entry
+    /// for the start address of the inlined function will be returned,
+    /// otherwise the line entry for the start address of the function
+    /// will be returned. This can be used after doing a
+    /// Module::FindFunctions(...) or ModuleList::FindFunctions(...)
+    /// call in order to get the correct line table information for
+    /// the symbol context.
+    /// it will return the inlined function name.
+    ///
+    /// @param[in] prefer_mangled
+    ///    if \btrue, then the mangled name will be returned if there
+    ///    is one.  Otherwise the unmangled name will be returned if it
+    ///    is available.
+    ///
+    /// @return
+    ///     The name of the function represented by this symbol context.
+    //------------------------------------------------------------------
+    LineEntry
+    GetFunctionStartLineEntry () const;
 
     //------------------------------------------------------------------
     /// Find the block containing the inlined block that contains this block.

Modified: lldb/trunk/source/Commands/CommandObjectSource.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectSource.cpp?rev=182067&r1=182066&r2=182067&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectSource.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectSource.cpp Thu May 16 19:56:10 2013
@@ -296,6 +296,149 @@ public:
     }
 
 protected:
+
+    struct SourceInfo
+    {
+        ConstString function;
+        LineEntry line_entry;
+        
+        SourceInfo (const ConstString &name, const LineEntry &line_entry) :
+            function(name),
+            line_entry(line_entry)
+        {
+        }
+        
+        SourceInfo () :
+            function(),
+            line_entry()
+        {
+        }
+        
+        bool
+        IsValid () const
+        {
+            return (bool)function && line_entry.IsValid();
+        }
+        
+        bool
+        operator == (const SourceInfo &rhs) const
+        {
+            return function == rhs.function &&
+            line_entry.file == rhs.line_entry.file &&
+            line_entry.line == rhs.line_entry.line;
+        }
+        
+        bool
+        operator != (const SourceInfo &rhs) const
+        {
+            return function != rhs.function ||
+            line_entry.file != rhs.line_entry.file ||
+            line_entry.line != rhs.line_entry.line;
+        }
+        
+        bool
+        operator < (const SourceInfo &rhs) const
+        {
+            if (function.GetCString() < rhs.function.GetCString())
+                return true;
+            if (line_entry.file.GetDirectory().GetCString() < rhs.line_entry.file.GetDirectory().GetCString())
+                return true;
+            if (line_entry.file.GetFilename().GetCString() < rhs.line_entry.file.GetFilename().GetCString())
+                return true;
+            if (line_entry.line < rhs.line_entry.line)
+                return true;
+            return false;
+        }
+    };
+
+    size_t
+    DisplayFunctionSource (const SymbolContext &sc,
+                           SourceInfo &source_info,
+                           CommandReturnObject &result)
+    {
+        if (!source_info.IsValid())
+        {
+            source_info.function = sc.GetFunctionName();
+            source_info.line_entry = sc.GetFunctionStartLineEntry();
+        }
+    
+        if (sc.function)
+        {
+            Target *target = m_exe_ctx.GetTargetPtr();
+
+            FileSpec start_file;
+            uint32_t start_line;
+            uint32_t end_line;
+            FileSpec end_file;
+            
+            if (sc.block == NULL)
+            {
+                // Not an inlined function
+                sc.function->GetStartLineSourceInfo (start_file, start_line);
+                if (start_line == 0)
+                {
+                    result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", source_info.function.GetCString());
+                    result.SetStatus (eReturnStatusFailed);
+                    return 0;
+                }
+                sc.function->GetEndLineSourceInfo (end_file, end_line);
+            }
+            else
+            {
+                // We have an inlined function
+                start_file = source_info.line_entry.file;
+                start_line = source_info.line_entry.line;
+                end_line = start_line + m_options.num_lines;
+            }
+
+            // This is a little hacky, but the first line table entry for a function points to the "{" that
+            // starts the function block.  It would be nice to actually get the function
+            // declaration in there too.  So back up a bit, but not further than what you're going to display.
+            uint32_t extra_lines;
+            if (m_options.num_lines >= 10)
+                extra_lines = 5;
+            else
+                extra_lines = m_options.num_lines/2;
+            uint32_t line_no;
+            if (start_line <= extra_lines)
+                line_no = 1;
+            else
+                line_no = start_line - extra_lines;
+            
+            // For fun, if the function is shorter than the number of lines we're supposed to display,
+            // only display the function...
+            if (end_line != 0)
+            {
+                if (m_options.num_lines > end_line - line_no)
+                    m_options.num_lines = end_line - line_no + extra_lines;
+            }
+            
+            m_breakpoint_locations.Clear();
+
+            if (m_options.show_bp_locs)
+            {
+                const bool show_inlines = true;
+                m_breakpoint_locations.Reset (start_file, 0, show_inlines);
+                SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
+                target_search_filter.Search (m_breakpoint_locations);
+            }
+            
+            result.AppendMessageWithFormat("File: %s\n", start_file.GetPath().c_str());
+            return target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
+                                                                                 line_no,
+                                                                                 0,
+                                                                                 m_options.num_lines,
+                                                                                 "",
+                                                                                 &result.GetOutputStream(),
+                                                                                 GetBreakpointLocations ());
+        }
+        else
+        {
+            result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
+        }
+        return 0;
+    }
+
     bool
     DoExecute (Args& command, CommandReturnObject &result)
     {
@@ -353,123 +496,48 @@ protected:
                 return false;
             }
             
-            sc_list.GetContextAtIndex (0, sc);
-            FileSpec start_file;
-            uint32_t start_line;
-            uint32_t end_line;
-            FileSpec end_file;
-            if (sc.function != NULL)
-            {
-                sc.function->GetStartLineSourceInfo (start_file, start_line);
-                if (start_line == 0)
-                {
-                    result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", m_options.symbol_name.c_str());
-                    result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
-                sc.function->GetEndLineSourceInfo (end_file, end_line);
-            }
-            else
-            {
-                result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
-                result.SetStatus (eReturnStatusFailed);
-                return false;
-            }
-
             if (num_matches > 1)
             {
-                // This could either be because there are multiple functions of this name, in which case
-                // we'll have to specify this further...  Or it could be because there are multiple inlined instances
-                // of one function.  So run through the matches and if they all have the same file & line then we can just
-                // list one.
-                
-                bool found_multiple = false;
+                std::set<SourceInfo> source_match_set;
                 
-                for (size_t i = 1; i < num_matches; i++)
+                bool displayed_something = false;
+                for (size_t i = 0; i < num_matches; i++)
                 {
-                    SymbolContext scratch_sc;
-                    sc_list.GetContextAtIndex (i, scratch_sc);
-                    if (scratch_sc.function != NULL)
+                    sc_list.GetContextAtIndex (i, sc);
+                    SourceInfo source_info (sc.GetFunctionName(),
+                                            sc.GetFunctionStartLineEntry());
+                    
+                    if (source_info.IsValid())
                     {
-                        FileSpec scratch_file;
-                        uint32_t scratch_line;
-                        scratch_sc.function->GetStartLineSourceInfo (scratch_file, scratch_line);
-                        if (scratch_file != start_file 
-                            || scratch_line != start_line)
+                        if (source_match_set.find(source_info) == source_match_set.end())
                         {
-                            found_multiple = true;
-                            break;
+                            source_match_set.insert(source_info);
+                            if (DisplayFunctionSource (sc, source_info, result))
+                                displayed_something = true;
                         }
                     }
                 }
-                if (found_multiple)
-                {
-                    StreamString s;
-                    for (size_t i = 0; i < num_matches; i++)
-                    {
-                        SymbolContext scratch_sc;
-                        sc_list.GetContextAtIndex (i, scratch_sc);
-                        if (scratch_sc.function != NULL)
-                        {
-                            s.Printf("\n%lu: ", i); 
-                            scratch_sc.function->Dump (&s, true);
-                        }
-                    }
-                    result.AppendErrorWithFormat("Multiple functions found matching: %s: \n%s\n", 
-                                                 m_options.symbol_name.c_str(),
-                                                 s.GetData());
+                
+                if (displayed_something)
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                else
                     result.SetStatus (eReturnStatusFailed);
-                    return false;
-                }
             }
-            
-            // This is a little hacky, but the first line table entry for a function points to the "{" that 
-            // starts the function block.  It would be nice to actually get the function
-            // declaration in there too.  So back up a bit, but not further than what you're going to display.
-            uint32_t extra_lines;
-            if (m_options.num_lines >= 10)
-                extra_lines = 5;
             else
-                extra_lines = m_options.num_lines/2;
-            uint32_t line_no;
-            if (start_line <= extra_lines)
-                line_no = 1;
-            else
-                line_no = start_line - extra_lines;
-                
-            // For fun, if the function is shorter than the number of lines we're supposed to display, 
-            // only display the function...
-            if (end_line != 0)
             {
-                if (m_options.num_lines > end_line - line_no)
-                    m_options.num_lines = end_line - line_no + extra_lines;
-            }
-            
-            char path_buf[PATH_MAX];
-            start_file.GetPath(path_buf, sizeof(path_buf));
-            
-            if (m_options.show_bp_locs)
-            {
-                const bool show_inlines = true;
-                m_breakpoint_locations.Reset (start_file, 0, show_inlines);
-                SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
-                target_search_filter.Search (m_breakpoint_locations);
+                sc_list.GetContextAtIndex (0, sc);
+                SourceInfo source_info;
+                
+                if (DisplayFunctionSource (sc, source_info, result))
+                {
+                    result.SetStatus (eReturnStatusSuccessFinishResult);
+                }
+                else
+                {
+                    result.SetStatus (eReturnStatusFailed);
+                }
             }
-            else
-                m_breakpoint_locations.Clear();
-
-            result.AppendMessageWithFormat("File: %s\n", path_buf);
-            target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
-                                                                          line_no,
-                                                                          0,
-                                                                          m_options.num_lines,
-                                                                          "",
-                                                                          &result.GetOutputStream(),
-                                                                          GetBreakpointLocations ());
-            
-            result.SetStatus (eReturnStatusSuccessFinishResult);
-            return true;
-
+            return result.Succeeded();
         }
         else if (m_options.address != LLDB_INVALID_ADDRESS)
         {

Modified: lldb/trunk/source/Symbol/SymbolContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=182067&r1=182066&r2=182067&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolContext.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolContext.cpp Thu May 16 19:56:10 2013
@@ -319,7 +319,6 @@ SymbolContext::GetResolvedMask () const
     return resolved_mask;
 }
 
-
 void
 SymbolContext::Dump(Stream *s, Target *target) const
 {
@@ -593,7 +592,7 @@ SymbolContext::GetFunctionMethodInfo (ll
 }
 
 ConstString
-SymbolContext::GetFunctionName (Mangled::NamePreference preference)
+SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
 {
     if (function)
     {
@@ -621,6 +620,33 @@ SymbolContext::GetFunctionName (Mangled:
     }
 }
 
+LineEntry
+SymbolContext::GetFunctionStartLineEntry () const
+{
+    LineEntry line_entry;
+    Address start_addr;
+    if (block)
+    {
+        Block *inlined_block = block->GetContainingInlinedBlock();
+        if (inlined_block)
+        {
+            if (inlined_block->GetStartAddress (start_addr))
+            {
+                if (start_addr.CalculateSymbolContextLineEntry (line_entry))
+                    return line_entry;
+            }
+            return LineEntry();
+        }
+    }
+    
+    if (function)
+    {
+        if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
+            return line_entry;
+    }
+    return LineEntry();
+}
+
 //----------------------------------------------------------------------
 //
 //  SymbolContextSpecifier





More information about the lldb-commits mailing list