BreakpointResolverFileLine.cpp revision c705730b96ede40118fc7b06d2807e9a4e503139
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- BreakpointResolverFileLine.cpp --------------------------*- C++ -*-===//
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//                     The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===//
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Breakpoint/BreakpointLocation.h"
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Log.h"
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/StreamString.h"
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/lldb-private-log.h"
2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// BreakpointResolverFileLine:
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//----------------------------------------------------------------------
2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::BreakpointResolverFileLine
2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Breakpoint *bkpt,
3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t line_no,
3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool check_inlines
3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner) :
34a62ad7c886252a08d614a2b391d0774a151b7196Johnny Chen    BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_file_spec (file_spec),
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_line_number (line_no),
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_inlines (check_inlines)
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::~BreakpointResolverFileLine ()
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerSearcher::CallbackReturn
4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::SearchCallback
4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SearchFilter &filter,
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SymbolContext &context,
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Address *addr,
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    bool containing
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    SymbolContextList sc_list;
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    assert (m_breakpoint != NULL);
57e005f2ce03c489ebde9110678a29cbfe8488d5b4Greg Clayton    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
58a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
59a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // There is a tricky bit here.  You can have two compilation units that #include the same file, and
60a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // in one of them the function at m_line_number is used (and so code and a line entry for it is generated) but in the
61a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // other it isn't.  If we considered the CU's independently, then in the second inclusion, we'd move the breakpoint
62a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // to the next function that actually generated code in the header file.  That would end up being confusing.
63a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // So instead, we do the CU iterations by hand here, then scan through the complete list of matches, and figure out
64a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // the closest line number match, and only set breakpoints on that match.
65a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
66a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // Note also that if file_spec only had a file name and not a directory, there may be many different file spec's in
67a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // the resultant list.  The closest line match for one will not be right for some totally different file.
68a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // So we go through the match list and pull out the sets that have the same file spec in their line_entry
69a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    // and treat each set separately.
70a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
71a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    uint32_t num_comp_units = context.module_sp->GetNumCompileUnits();
72a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    for (uint32_t i = 0; i < num_comp_units; i++)
73a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    {
74a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        CompUnitSP cu_sp (context.module_sp->GetCompileUnitAtIndex (i));
75c705730b96ede40118fc7b06d2807e9a4e503139Greg Clayton        if (cu_sp)
76c705730b96ede40118fc7b06d2807e9a4e503139Greg Clayton        {
77c705730b96ede40118fc7b06d2807e9a4e503139Greg Clayton            if (filter.CompUnitPasses(*cu_sp))
78c705730b96ede40118fc7b06d2807e9a4e503139Greg Clayton                cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list);
79c705730b96ede40118fc7b06d2807e9a4e503139Greg Clayton        }
80a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    }
81a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
82a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    while (sc_list.GetSize() > 0)
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
84a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        SymbolContextList tmp_sc_list;
85a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        int current_idx = 0;
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        SymbolContext sc;
87a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        bool first_entry = true;
88a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
89a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        FileSpec match_file_spec;
90a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        uint32_t closest_line_number = UINT32_MAX;
91a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
92a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list.
93a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        while (current_idx < sc_list.GetSize())
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
95a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            bool matches;
96a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
97a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            sc_list.GetContextAtIndex (current_idx, sc);
98a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            if (first_entry)
99a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            {
100a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                match_file_spec = sc.line_entry.file;
101a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                matches = true;
102a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                first_entry = false;
103a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            }
104a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            else
105a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                matches = (sc.line_entry.file == match_file_spec);
106a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
107a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            if (matches)
10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
109a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                tmp_sc_list.Append (sc);
110a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                sc_list.RemoveContextAtIndex(current_idx);
111a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
112a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                // ResolveSymbolContext will always return a number that is >= the line number you pass in.
113a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                // So the smaller line number is always better.
114a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                if (sc.line_entry.line < closest_line_number)
115a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    closest_line_number = sc.line_entry.line;
116a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            }
117a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            else
118a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                current_idx++;
119a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        }
120a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
121a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        // Okay, we've found the closest line number match, now throw away all the others,
122a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        // and make breakpoints out of the closest line number match.
123a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
124a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        uint32_t tmp_sc_list_size = tmp_sc_list.GetSize();
125a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
126a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        for (uint32_t i = 0; i < tmp_sc_list_size; i++)
127a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        {
128a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            SymbolContext sc;
129a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            if (tmp_sc_list.GetContextAtIndex(i, sc))
130a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham            {
131a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                if (sc.line_entry.line == closest_line_number)
13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
133a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    Address line_start = sc.line_entry.range.GetBaseAddress();
134a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    if (line_start.IsValid())
13503c8ee5aeafcd6c43f10002a4f8096af01780f86Jim Ingham                    {
136a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        if (filter.AddressPasses(line_start))
137a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        {
138a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
139a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            if (log && bp_loc_sp && !m_breakpoint->IsInternal())
140a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            {
141a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                StreamString s;
142a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
143a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                log->Printf ("Added location: %s\n", s.GetData());
144a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            }
145a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        }
146a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        else if (log)
147a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        {
148a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass the filter.\n",
149a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         line_start.GetFileAddress(),
150a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         m_file_spec.GetFilename().AsCString("<Unknown>"),
151a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         m_line_number);
152a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        }
153a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    }
154a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    else
155a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    {
156a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        if (log)
157a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                            log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
158a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         line_start.GetFileAddress(),
159a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         m_file_spec.GetFilename().AsCString("<Unknown>"),
160a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                                         m_line_number);
16103c8ee5aeafcd6c43f10002a4f8096af01780f86Jim Ingham                    }
16203c8ee5aeafcd6c43f10002a4f8096af01780f86Jim Ingham                }
163a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                else
16403c8ee5aeafcd6c43f10002a4f8096af01780f86Jim Ingham                {
165a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        #if 0
166a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    s << "error: Breakpoint at '" << pos->c_str() << "' isn't resolved yet: \n";
167a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionNameOffset))
168a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        s.EOL();
169a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    if (sc.line_entry.address.Dump(&s, Address::DumpStyleSectionPointerOffset))
170a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        s.EOL();
171a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    if (sc.line_entry.address.Dump(&s, Address::DumpStyleFileAddress))
172a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        s.EOL();
173a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                    if (sc.line_entry.address.Dump(&s, Address::DumpStyleLoadAddress))
174a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham                        s.EOL();
175a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham        #endif
17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
180a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return Searcher::eCallbackReturnContinue;
18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerSearcher::Depth
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::GetDepth()
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
187a44297a3a58c46fe88a37e3de18ce97c4c85edc5Jim Ingham    return Searcher::eDepthModule;
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::GetDescription (Stream *s)
19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
19312bec71b323dc520f0e985a86e09c4712559e115Greg Clayton    s->Printf ("file ='%s', line = %u", m_file_spec.GetFilename().AsCString(), m_line_number);
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerBreakpointResolverFileLine::Dump (Stream *s) const
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
202