1254721Semaste//===-- LineTable.cpp -------------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Core/Address.h"
11254721Semaste#include "lldb/Core/Module.h"
12254721Semaste#include "lldb/Core/Section.h"
13254721Semaste#include "lldb/Core/Stream.h"
14254721Semaste#include "lldb/Symbol/CompileUnit.h"
15254721Semaste#include "lldb/Symbol/LineTable.h"
16254721Semaste#include <algorithm>
17254721Semaste
18254721Semasteusing namespace lldb;
19254721Semasteusing namespace lldb_private;
20254721Semaste
21254721Semaste//----------------------------------------------------------------------
22254721Semaste// LineTable constructor
23254721Semaste//----------------------------------------------------------------------
24254721SemasteLineTable::LineTable(CompileUnit* comp_unit) :
25254721Semaste    m_comp_unit(comp_unit),
26254721Semaste    m_entries()
27254721Semaste{
28254721Semaste}
29254721Semaste
30254721Semaste//----------------------------------------------------------------------
31254721Semaste// Destructor
32254721Semaste//----------------------------------------------------------------------
33254721SemasteLineTable::~LineTable()
34254721Semaste{
35254721Semaste}
36254721Semaste
37254721Semastevoid
38254721SemasteLineTable::InsertLineEntry
39254721Semaste(
40254721Semaste    lldb::addr_t file_addr,
41254721Semaste    uint32_t line,
42254721Semaste    uint16_t column,
43254721Semaste    uint16_t file_idx,
44254721Semaste    bool is_start_of_statement,
45254721Semaste    bool is_start_of_basic_block,
46254721Semaste    bool is_prologue_end,
47254721Semaste    bool is_epilogue_begin,
48254721Semaste    bool is_terminal_entry
49254721Semaste)
50254721Semaste{
51254721Semaste    Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
52254721Semaste
53254721Semaste    entry_collection::iterator begin_pos = m_entries.begin();
54254721Semaste    entry_collection::iterator end_pos = m_entries.end();
55254721Semaste    LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
56254721Semaste    entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);
57254721Semaste
58254721Semaste//  Stream s(stdout);
59254721Semaste//  s << "\n\nBefore:\n";
60254721Semaste//  Dump (&s, Address::DumpStyleFileAddress);
61254721Semaste    m_entries.insert(pos, entry);
62254721Semaste//  s << "After:\n";
63254721Semaste//  Dump (&s, Address::DumpStyleFileAddress);
64254721Semaste}
65254721Semaste
66254721SemasteLineSequence::LineSequence()
67254721Semaste{
68254721Semaste}
69254721Semaste
70254721Semastevoid
71254721SemasteLineTable::LineSequenceImpl::Clear()
72254721Semaste{
73254721Semaste    m_entries.clear();
74254721Semaste}
75254721Semaste
76254721SemasteLineSequence* LineTable::CreateLineSequenceContainer ()
77254721Semaste{
78254721Semaste    return new LineTable::LineSequenceImpl();
79254721Semaste}
80254721Semaste
81254721Semastevoid
82254721SemasteLineTable::AppendLineEntryToSequence
83254721Semaste(
84254721Semaste    LineSequence* sequence,
85254721Semaste    lldb::addr_t file_addr,
86254721Semaste    uint32_t line,
87254721Semaste    uint16_t column,
88254721Semaste    uint16_t file_idx,
89254721Semaste    bool is_start_of_statement,
90254721Semaste    bool is_start_of_basic_block,
91254721Semaste    bool is_prologue_end,
92254721Semaste    bool is_epilogue_begin,
93254721Semaste    bool is_terminal_entry
94254721Semaste)
95254721Semaste{
96254721Semaste    assert(sequence != NULL);
97254721Semaste    LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
98254721Semaste    Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry);
99254721Semaste    seq->m_entries.push_back (entry);
100254721Semaste}
101254721Semaste
102254721Semastevoid
103254721SemasteLineTable::InsertSequence (LineSequence* sequence)
104254721Semaste{
105254721Semaste    assert(sequence != NULL);
106254721Semaste    LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence);
107254721Semaste    if (seq->m_entries.empty())
108254721Semaste        return;
109254721Semaste    Entry& entry = seq->m_entries.front();
110254721Semaste
111254721Semaste    // If the first entry address in this sequence is greater than or equal to
112254721Semaste    // the address of the last item in our entry collection, just append.
113254721Semaste    if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back()))
114254721Semaste    {
115254721Semaste        m_entries.insert(m_entries.end(),
116254721Semaste                         seq->m_entries.begin(),
117254721Semaste                         seq->m_entries.end());
118254721Semaste        return;
119254721Semaste    }
120254721Semaste
121254721Semaste    // Otherwise, find where this belongs in the collection
122254721Semaste    entry_collection::iterator begin_pos = m_entries.begin();
123254721Semaste    entry_collection::iterator end_pos = m_entries.end();
124254721Semaste    LineTable::Entry::LessThanBinaryPredicate less_than_bp(this);
125254721Semaste    entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp);
126254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
127254721Semaste    // If we aren't inserting at the beginning, the previous entry should
128254721Semaste    // terminate a sequence.
129254721Semaste    if (pos != begin_pos)
130254721Semaste    {
131254721Semaste        entry_collection::iterator prev_pos = pos - 1;
132254721Semaste        assert(prev_pos->is_terminal_entry);
133254721Semaste    }
134254721Semaste#endif
135254721Semaste    m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end());
136254721Semaste}
137254721Semaste
138254721Semaste//----------------------------------------------------------------------
139254721SemasteLineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) :
140254721Semaste    m_line_table (line_table)
141254721Semaste{
142254721Semaste}
143254721Semaste
144254721Semastebool
145254721SemasteLineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const
146254721Semaste{
147254721Semaste    #define LT_COMPARE(a,b) if (a != b) return a < b
148254721Semaste    LT_COMPARE (a.file_addr, b.file_addr);
149254721Semaste    // b and a reversed on purpose below.
150254721Semaste    LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry);
151254721Semaste    LT_COMPARE (a.line, b.line);
152254721Semaste    LT_COMPARE (a.column, b.column);
153254721Semaste    LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement);
154254721Semaste    LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block);
155254721Semaste    // b and a reversed on purpose below.
156254721Semaste    LT_COMPARE (b.is_prologue_end, a.is_prologue_end);
157254721Semaste    LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin);
158254721Semaste    LT_COMPARE (a.file_idx, b.file_idx);
159254721Semaste    return false;
160254721Semaste    #undef LT_COMPARE
161254721Semaste}
162254721Semaste
163254721Semaste
164254721Semaste
165254721Semasteuint32_t
166254721SemasteLineTable::GetSize() const
167254721Semaste{
168254721Semaste    return m_entries.size();
169254721Semaste}
170254721Semaste
171254721Semastebool
172254721SemasteLineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry)
173254721Semaste{
174254721Semaste    if (idx < m_entries.size())
175254721Semaste    {
176254721Semaste        ConvertEntryAtIndexToLineEntry (idx, line_entry);
177254721Semaste        return true;
178254721Semaste    }
179254721Semaste    line_entry.Clear();
180254721Semaste    return false;
181254721Semaste}
182254721Semaste
183254721Semastebool
184254721SemasteLineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr)
185254721Semaste{
186254721Semaste    if (index_ptr != NULL )
187254721Semaste        *index_ptr = UINT32_MAX;
188254721Semaste
189254721Semaste    bool success = false;
190254721Semaste
191254721Semaste    if (so_addr.GetModule().get() == m_comp_unit->GetModule().get())
192254721Semaste    {
193254721Semaste        Entry search_entry;
194254721Semaste        search_entry.file_addr = so_addr.GetFileAddress();
195254721Semaste        if (search_entry.file_addr != LLDB_INVALID_ADDRESS)
196254721Semaste        {
197254721Semaste            entry_collection::const_iterator begin_pos = m_entries.begin();
198254721Semaste            entry_collection::const_iterator end_pos = m_entries.end();
199254721Semaste            entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan);
200254721Semaste            if (pos != end_pos)
201254721Semaste            {
202254721Semaste                if (pos != begin_pos)
203254721Semaste                {
204254721Semaste                    if (pos->file_addr != search_entry.file_addr)
205254721Semaste                        --pos;
206254721Semaste                    else if (pos->file_addr == search_entry.file_addr)
207254721Semaste                    {
208254721Semaste                        // If this is a termination entry, it should't match since
209254721Semaste                        // entries with the "is_terminal_entry" member set to true
210254721Semaste                        // are termination entries that define the range for the
211254721Semaste                        // previous entry.
212254721Semaste                        if (pos->is_terminal_entry)
213254721Semaste                        {
214254721Semaste                            // The matching entry is a terminal entry, so we skip
215254721Semaste                            // ahead to the next entry to see if there is another
216254721Semaste                            // entry following this one whose section/offset matches.
217254721Semaste                            ++pos;
218254721Semaste                            if (pos != end_pos)
219254721Semaste                            {
220254721Semaste                                if (pos->file_addr != search_entry.file_addr)
221254721Semaste                                    pos = end_pos;
222254721Semaste                            }
223254721Semaste                        }
224254721Semaste
225254721Semaste                        if (pos != end_pos)
226254721Semaste                        {
227254721Semaste                            // While in the same section/offset backup to find the first
228254721Semaste                            // line entry that matches the address in case there are
229254721Semaste                            // multiple
230254721Semaste                            while (pos != begin_pos)
231254721Semaste                            {
232254721Semaste                                entry_collection::const_iterator prev_pos = pos - 1;
233254721Semaste                                if (prev_pos->file_addr == search_entry.file_addr &&
234254721Semaste                                    prev_pos->is_terminal_entry == false)
235254721Semaste                                    --pos;
236254721Semaste                                else
237254721Semaste                                    break;
238254721Semaste                            }
239254721Semaste                        }
240254721Semaste                    }
241254721Semaste
242254721Semaste                }
243254721Semaste
244254721Semaste                // Make sure we have a valid match and that the match isn't a terminating
245254721Semaste                // entry for a previous line...
246254721Semaste                if (pos != end_pos && pos->is_terminal_entry == false)
247254721Semaste                {
248254721Semaste                    uint32_t match_idx = std::distance (begin_pos, pos);
249254721Semaste                    success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry);
250254721Semaste                    if (index_ptr != NULL && success)
251254721Semaste                        *index_ptr = match_idx;
252254721Semaste                }
253254721Semaste            }
254254721Semaste        }
255254721Semaste    }
256254721Semaste    return success;
257254721Semaste}
258254721Semaste
259254721Semaste
260254721Semastebool
261254721SemasteLineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry)
262254721Semaste{
263254721Semaste    if (idx < m_entries.size())
264254721Semaste    {
265254721Semaste        const Entry& entry = m_entries[idx];
266254721Semaste        ModuleSP module_sp (m_comp_unit->GetModule());
267254721Semaste        if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress()))
268254721Semaste        {
269254721Semaste            if (!entry.is_terminal_entry && idx + 1 < m_entries.size())
270254721Semaste                line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr);
271254721Semaste            else
272254721Semaste                line_entry.range.SetByteSize(0);
273254721Semaste
274254721Semaste            line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx);
275254721Semaste            line_entry.line = entry.line;
276254721Semaste            line_entry.column = entry.column;
277254721Semaste            line_entry.is_start_of_statement = entry.is_start_of_statement;
278254721Semaste            line_entry.is_start_of_basic_block = entry.is_start_of_basic_block;
279254721Semaste            line_entry.is_prologue_end = entry.is_prologue_end;
280254721Semaste            line_entry.is_epilogue_begin = entry.is_epilogue_begin;
281254721Semaste            line_entry.is_terminal_entry = entry.is_terminal_entry;
282254721Semaste            return true;
283254721Semaste        }
284254721Semaste    }
285254721Semaste    return false;
286254721Semaste}
287254721Semaste
288254721Semasteuint32_t
289254721SemasteLineTable::FindLineEntryIndexByFileIndex
290254721Semaste(
291254721Semaste    uint32_t start_idx,
292254721Semaste    const std::vector<uint32_t> &file_indexes,
293254721Semaste    uint32_t line,
294254721Semaste    bool exact,
295254721Semaste    LineEntry* line_entry_ptr
296254721Semaste)
297254721Semaste{
298254721Semaste
299254721Semaste    const size_t count = m_entries.size();
300254721Semaste    std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin();
301254721Semaste    std::vector<uint32_t>::const_iterator end_pos = file_indexes.end();
302254721Semaste    size_t best_match = UINT32_MAX;
303254721Semaste
304254721Semaste    for (size_t idx = start_idx; idx < count; ++idx)
305254721Semaste    {
306254721Semaste        // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
307254721Semaste        if (m_entries[idx].is_terminal_entry)
308254721Semaste            continue;
309254721Semaste
310254721Semaste        if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos)
311254721Semaste            continue;
312254721Semaste
313254721Semaste        // Exact match always wins.  Otherwise try to find the closest line > the desired
314254721Semaste        // line.
315254721Semaste        // FIXME: Maybe want to find the line closest before and the line closest after and
316254721Semaste        // if they're not in the same function, don't return a match.
317254721Semaste
318254721Semaste        if (m_entries[idx].line < line)
319254721Semaste        {
320254721Semaste            continue;
321254721Semaste        }
322254721Semaste        else if (m_entries[idx].line == line)
323254721Semaste        {
324254721Semaste            if (line_entry_ptr)
325254721Semaste                ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
326254721Semaste            return idx;
327254721Semaste        }
328254721Semaste        else if (!exact)
329254721Semaste        {
330254721Semaste            if (best_match == UINT32_MAX)
331254721Semaste                best_match = idx;
332254721Semaste            else if (m_entries[idx].line < m_entries[best_match].line)
333254721Semaste                best_match = idx;
334254721Semaste        }
335254721Semaste    }
336254721Semaste
337254721Semaste    if (best_match != UINT32_MAX)
338254721Semaste    {
339254721Semaste        if (line_entry_ptr)
340254721Semaste            ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
341254721Semaste        return best_match;
342254721Semaste    }
343254721Semaste    return UINT32_MAX;
344254721Semaste}
345254721Semaste
346254721Semasteuint32_t
347254721SemasteLineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr)
348254721Semaste{
349254721Semaste    const size_t count = m_entries.size();
350254721Semaste    size_t best_match = UINT32_MAX;
351254721Semaste
352254721Semaste    for (size_t idx = start_idx; idx < count; ++idx)
353254721Semaste    {
354254721Semaste        // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
355254721Semaste        if (m_entries[idx].is_terminal_entry)
356254721Semaste            continue;
357254721Semaste
358254721Semaste        if (m_entries[idx].file_idx != file_idx)
359254721Semaste            continue;
360254721Semaste
361254721Semaste        // Exact match always wins.  Otherwise try to find the closest line > the desired
362254721Semaste        // line.
363254721Semaste        // FIXME: Maybe want to find the line closest before and the line closest after and
364254721Semaste        // if they're not in the same function, don't return a match.
365254721Semaste
366254721Semaste        if (m_entries[idx].line < line)
367254721Semaste        {
368254721Semaste            continue;
369254721Semaste        }
370254721Semaste        else if (m_entries[idx].line == line)
371254721Semaste        {
372254721Semaste            if (line_entry_ptr)
373254721Semaste                ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr);
374254721Semaste            return idx;
375254721Semaste        }
376254721Semaste        else if (!exact)
377254721Semaste        {
378254721Semaste            if (best_match == UINT32_MAX)
379254721Semaste                best_match = idx;
380254721Semaste            else if (m_entries[idx].line < m_entries[best_match].line)
381254721Semaste                best_match = idx;
382254721Semaste        }
383254721Semaste    }
384254721Semaste
385254721Semaste    if (best_match != UINT32_MAX)
386254721Semaste    {
387254721Semaste        if (line_entry_ptr)
388254721Semaste            ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr);
389254721Semaste        return best_match;
390254721Semaste    }
391254721Semaste    return UINT32_MAX;
392254721Semaste}
393254721Semaste
394254721Semastesize_t
395254721SemasteLineTable::FineLineEntriesForFileIndex (uint32_t file_idx,
396254721Semaste                                        bool append,
397254721Semaste                                        SymbolContextList &sc_list)
398254721Semaste{
399254721Semaste
400254721Semaste    if (!append)
401254721Semaste        sc_list.Clear();
402254721Semaste
403254721Semaste    size_t num_added = 0;
404254721Semaste    const size_t count = m_entries.size();
405254721Semaste    if (count > 0)
406254721Semaste    {
407254721Semaste        SymbolContext sc (m_comp_unit);
408254721Semaste
409254721Semaste        for (size_t idx = 0; idx < count; ++idx)
410254721Semaste        {
411254721Semaste            // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero)
412254721Semaste            if (m_entries[idx].is_terminal_entry)
413254721Semaste                continue;
414254721Semaste
415254721Semaste            if (m_entries[idx].file_idx == file_idx)
416254721Semaste            {
417254721Semaste                if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry))
418254721Semaste                {
419254721Semaste                    ++num_added;
420254721Semaste                    sc_list.Append(sc);
421254721Semaste                }
422254721Semaste            }
423254721Semaste        }
424254721Semaste    }
425254721Semaste    return num_added;
426254721Semaste}
427254721Semaste
428254721Semaste
429254721Semastevoid
430254721SemasteLineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges)
431254721Semaste{
432254721Semaste    const size_t count = m_entries.size();
433254721Semaste    LineEntry line_entry;
434254721Semaste    FileSpec prev_file;
435254721Semaste    for (size_t idx = 0; idx < count; ++idx)
436254721Semaste    {
437254721Semaste        ConvertEntryAtIndexToLineEntry (idx, line_entry);
438254721Semaste        line_entry.Dump (s, target, prev_file != line_entry.file, style, fallback_style, show_line_ranges);
439254721Semaste        s->EOL();
440254721Semaste        prev_file = line_entry.file;
441254721Semaste    }
442254721Semaste}
443254721Semaste
444254721Semaste
445254721Semastevoid
446254721SemasteLineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level)
447254721Semaste{
448254721Semaste    const size_t count = m_entries.size();
449254721Semaste    LineEntry line_entry;
450254721Semaste    for (size_t idx = 0; idx < count; ++idx)
451254721Semaste    {
452254721Semaste        ConvertEntryAtIndexToLineEntry (idx, line_entry);
453254721Semaste        line_entry.GetDescription (s, level, m_comp_unit, target, true);
454254721Semaste        s->EOL();
455254721Semaste    }
456254721Semaste}
457254721Semaste
458254721Semastesize_t
459254721SemasteLineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append)
460254721Semaste{
461254721Semaste    if (!append)
462254721Semaste        file_ranges.Clear();
463254721Semaste    const size_t initial_count = file_ranges.GetSize();
464254721Semaste
465254721Semaste    const size_t count = m_entries.size();
466254721Semaste    LineEntry line_entry;
467254721Semaste    FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0);
468254721Semaste    for (size_t idx = 0; idx < count; ++idx)
469254721Semaste    {
470254721Semaste        const Entry& entry = m_entries[idx];
471254721Semaste
472254721Semaste        if (entry.is_terminal_entry)
473254721Semaste        {
474254721Semaste            if (range.GetRangeBase() != LLDB_INVALID_ADDRESS)
475254721Semaste            {
476254721Semaste                range.SetRangeEnd(entry.file_addr);
477254721Semaste                file_ranges.Append(range);
478254721Semaste                range.Clear(LLDB_INVALID_ADDRESS);
479254721Semaste            }
480254721Semaste        }
481254721Semaste        else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS)
482254721Semaste        {
483254721Semaste            range.SetRangeBase(entry.file_addr);
484254721Semaste        }
485254721Semaste    }
486254721Semaste    return file_ranges.GetSize() - initial_count;
487254721Semaste}
488254721Semaste
489254721SemasteLineTable *
490254721SemasteLineTable::LinkLineTable (const FileRangeMap &file_range_map)
491254721Semaste{
492254721Semaste    std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit));
493254721Semaste    LineSequenceImpl sequence;
494254721Semaste    const size_t count = m_entries.size();
495254721Semaste    LineEntry line_entry;
496254721Semaste    const FileRangeMap::Entry *file_range_entry = NULL;
497254721Semaste    const FileRangeMap::Entry *prev_file_range_entry = NULL;
498254721Semaste    lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS;
499254721Semaste    bool prev_entry_was_linked = false;
500254721Semaste    bool range_changed = false;
501254721Semaste    for (size_t idx = 0; idx < count; ++idx)
502254721Semaste    {
503254721Semaste        const Entry& entry = m_entries[idx];
504254721Semaste
505254721Semaste        const bool end_sequence = entry.is_terminal_entry;
506254721Semaste        const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0);
507254721Semaste        if (file_range_entry == NULL || !file_range_entry->Contains(lookup_file_addr))
508254721Semaste        {
509254721Semaste            prev_file_range_entry = file_range_entry;
510254721Semaste            file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr);
511254721Semaste            range_changed = true;
512254721Semaste        }
513254721Semaste
514254721Semaste        lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS;
515254721Semaste        lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS;
516254721Semaste
517254721Semaste        bool terminate_previous_entry = false;
518254721Semaste        if (file_range_entry)
519254721Semaste        {
520254721Semaste            entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data;
521254721Semaste            // Determine if we need to terminate the previous entry when the previous
522254721Semaste            // entry was not contguous with this one after being linked.
523254721Semaste            if (range_changed && prev_file_range_entry)
524254721Semaste            {
525254721Semaste                prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr, prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
526254721Semaste                if (prev_end_entry_linked_file_addr != entry_linked_file_addr)
527254721Semaste                    terminate_previous_entry = prev_entry_was_linked;
528254721Semaste            }
529254721Semaste        }
530254721Semaste        else if (prev_entry_was_linked)
531254721Semaste        {
532254721Semaste            // This entry doesn't have a remapping and it needs to be removed.
533254721Semaste            // Watch out in case we need to terminate a previous entry needs to
534254721Semaste            // be terminated now that one line entry in a sequence is not longer valid.
535254721Semaste            if (!entry.is_terminal_entry &&
536254721Semaste                !sequence.m_entries.empty() &&
537254721Semaste                !sequence.m_entries.back().is_terminal_entry)
538254721Semaste            {
539254721Semaste                terminate_previous_entry = true;
540254721Semaste            }
541254721Semaste        }
542254721Semaste
543254721Semaste        if (terminate_previous_entry && !sequence.m_entries.empty())
544254721Semaste        {
545254721Semaste            assert (prev_file_addr != LLDB_INVALID_ADDRESS);
546254721Semaste            sequence.m_entries.push_back(sequence.m_entries.back());
547254721Semaste            if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS)
548254721Semaste                prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data;
549254721Semaste            sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr;
550254721Semaste            sequence.m_entries.back().is_terminal_entry = true;
551254721Semaste
552254721Semaste            // Append the sequence since we just terminated the previous one
553254721Semaste            line_table_ap->InsertSequence (&sequence);
554254721Semaste            sequence.Clear();
555254721Semaste            prev_entry_was_linked = false;
556254721Semaste        }
557254721Semaste
558254721Semaste        // Now link the current entry
559254721Semaste        if (file_range_entry)
560254721Semaste        {
561254721Semaste            // This entry has an address remapping and it needs to have its address relinked
562254721Semaste            sequence.m_entries.push_back(entry);
563254721Semaste            sequence.m_entries.back().file_addr = entry_linked_file_addr;
564254721Semaste        }
565254721Semaste
566254721Semaste        // If we have items in the sequence and the last entry is a terminal entry,
567254721Semaste        // insert this sequence into our new line table.
568254721Semaste        if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry)
569254721Semaste        {
570254721Semaste            line_table_ap->InsertSequence (&sequence);
571254721Semaste            sequence.Clear();
572254721Semaste            prev_entry_was_linked = false;
573254721Semaste        }
574254721Semaste        else
575254721Semaste        {
576254721Semaste            prev_entry_was_linked = file_range_entry != NULL;
577254721Semaste        }
578254721Semaste        prev_file_addr = entry.file_addr;
579254721Semaste        range_changed = false;
580254721Semaste    }
581254721Semaste    if (line_table_ap->m_entries.empty())
582254721Semaste        return NULL;
583254721Semaste    return line_table_ap.release();
584254721Semaste}
585254721Semaste
586254721Semaste
587254721Semaste
588254721Semaste
589