1254721Semaste//===-- UnwindPlan.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/Symbol/UnwindPlan.h"
11254721Semaste
12254721Semaste#include "lldb/Core/ConstString.h"
13263367Semaste#include "lldb/Core/Log.h"
14254721Semaste#include "lldb/Target/Process.h"
15254721Semaste#include "lldb/Target/RegisterContext.h"
16254721Semaste#include "lldb/Target/Thread.h"
17254721Semaste
18254721Semasteusing namespace lldb;
19254721Semasteusing namespace lldb_private;
20254721Semaste
21254721Semastebool
22254721SemasteUnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
23254721Semaste{
24254721Semaste    if (m_type == rhs.m_type)
25254721Semaste    {
26254721Semaste        switch (m_type)
27254721Semaste        {
28254721Semaste            case unspecified:
29254721Semaste            case undefined:
30254721Semaste            case same:
31254721Semaste                return true;
32254721Semaste
33254721Semaste            case atCFAPlusOffset:
34254721Semaste            case isCFAPlusOffset:
35254721Semaste                return m_location.offset == rhs.m_location.offset;
36254721Semaste
37254721Semaste            case inOtherRegister:
38254721Semaste                return m_location.reg_num == rhs.m_location.reg_num;
39254721Semaste
40254721Semaste            case atDWARFExpression:
41254721Semaste            case isDWARFExpression:
42254721Semaste                if (m_location.expr.length == rhs.m_location.expr.length)
43254721Semaste                    return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
44254721Semaste                break;
45254721Semaste        }
46254721Semaste    }
47254721Semaste    return false;
48254721Semaste}
49254721Semaste
50254721Semaste// This function doesn't copy the dwarf expression bytes; they must remain in allocated
51254721Semaste// memory for the lifespan of this UnwindPlan object.
52254721Semastevoid
53254721SemasteUnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
54254721Semaste{
55254721Semaste    m_type = atDWARFExpression;
56254721Semaste    m_location.expr.opcodes = opcodes;
57254721Semaste    m_location.expr.length = len;
58254721Semaste}
59254721Semaste
60254721Semaste// This function doesn't copy the dwarf expression bytes; they must remain in allocated
61254721Semaste// memory for the lifespan of this UnwindPlan object.
62254721Semastevoid
63254721SemasteUnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
64254721Semaste{
65254721Semaste    m_type = isDWARFExpression;
66254721Semaste    m_location.expr.opcodes = opcodes;
67254721Semaste    m_location.expr.length = len;
68254721Semaste}
69254721Semaste
70254721Semastevoid
71254721SemasteUnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const
72254721Semaste{
73254721Semaste    switch (m_type)
74254721Semaste    {
75254721Semaste        case unspecified:
76254721Semaste            if (verbose)
77254721Semaste                s.PutCString ("=<unspec>");
78254721Semaste            else
79254721Semaste                s.PutCString ("=!");
80254721Semaste            break;
81254721Semaste        case undefined:
82254721Semaste            if (verbose)
83254721Semaste                s.PutCString ("=<undef>");
84254721Semaste            else
85254721Semaste                s.PutCString ("=?");
86254721Semaste            break;
87254721Semaste        case same:
88254721Semaste            s.PutCString ("= <same>");
89254721Semaste            break;
90254721Semaste
91254721Semaste        case atCFAPlusOffset:
92254721Semaste        case isCFAPlusOffset:
93254721Semaste            {
94254721Semaste                s.PutChar('=');
95254721Semaste                if (m_type == atCFAPlusOffset)
96254721Semaste                    s.PutChar('[');
97254721Semaste                if (verbose)
98254721Semaste                    s.Printf ("CFA%+d", m_location.offset);
99254721Semaste
100254721Semaste                if (unwind_plan && row)
101254721Semaste                {
102254721Semaste                    const uint32_t cfa_reg = row->GetCFARegister();
103254721Semaste                    const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg);
104254721Semaste                    const int32_t offset = row->GetCFAOffset() + m_location.offset;
105254721Semaste                    if (verbose)
106254721Semaste                    {
107254721Semaste                        if (cfa_reg_info)
108254721Semaste                            s.Printf (" (%s%+d)",  cfa_reg_info->name, offset);
109254721Semaste                        else
110254721Semaste                            s.Printf (" (reg(%u)%+d)",  cfa_reg, offset);
111254721Semaste                    }
112254721Semaste                    else
113254721Semaste                    {
114254721Semaste                        if (cfa_reg_info)
115254721Semaste                            s.Printf ("%s",  cfa_reg_info->name);
116254721Semaste                        else
117254721Semaste                            s.Printf ("reg(%u)",  cfa_reg);
118254721Semaste                        if (offset != 0)
119254721Semaste                            s.Printf ("%+d", offset);
120254721Semaste                    }
121254721Semaste                }
122254721Semaste                if (m_type == atCFAPlusOffset)
123254721Semaste                    s.PutChar(']');
124254721Semaste            }
125254721Semaste            break;
126254721Semaste
127254721Semaste        case inOtherRegister:
128254721Semaste            {
129254721Semaste                const RegisterInfo *other_reg_info = NULL;
130254721Semaste                if (unwind_plan)
131254721Semaste                    other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num);
132254721Semaste                if (other_reg_info)
133254721Semaste                    s.Printf ("=%s", other_reg_info->name);
134254721Semaste                else
135254721Semaste                    s.Printf ("=reg(%u)", m_location.reg_num);
136254721Semaste            }
137254721Semaste            break;
138254721Semaste
139254721Semaste        case atDWARFExpression:
140254721Semaste        case isDWARFExpression:
141254721Semaste            {
142254721Semaste                s.PutChar('=');
143254721Semaste                if (m_type == atDWARFExpression)
144254721Semaste                    s.PutCString("[dwarf-expr]");
145254721Semaste                else
146254721Semaste                    s.PutCString("dwarf-expr");
147254721Semaste            }
148254721Semaste            break;
149254721Semaste
150254721Semaste    }
151254721Semaste}
152254721Semaste
153254721Semastevoid
154254721SemasteUnwindPlan::Row::Clear ()
155254721Semaste{
156254721Semaste    m_offset = 0;
157254721Semaste    m_cfa_reg_num = LLDB_INVALID_REGNUM;
158254721Semaste    m_cfa_offset = 0;
159254721Semaste    m_register_locations.clear();
160254721Semaste}
161254721Semaste
162254721Semastevoid
163254721SemasteUnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const
164254721Semaste{
165254721Semaste    const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister());
166254721Semaste
167254721Semaste    if (base_addr != LLDB_INVALID_ADDRESS)
168254721Semaste        s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
169254721Semaste    else
170254721Semaste        s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset());
171254721Semaste
172254721Semaste    if (reg_info)
173254721Semaste        s.Printf ("%s", reg_info->name);
174254721Semaste    else
175254721Semaste        s.Printf ("reg(%u)", GetCFARegister());
176254721Semaste    s.Printf ("%+3d => ", GetCFAOffset ());
177254721Semaste    for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
178254721Semaste    {
179254721Semaste        reg_info = unwind_plan->GetRegisterInfo (thread, idx->first);
180254721Semaste        if (reg_info)
181254721Semaste            s.Printf ("%s", reg_info->name);
182254721Semaste        else
183254721Semaste            s.Printf ("reg(%u)", idx->first);
184254721Semaste        const bool verbose = false;
185254721Semaste        idx->second.Dump(s, unwind_plan, this, thread, verbose);
186254721Semaste        s.PutChar (' ');
187254721Semaste    }
188254721Semaste    s.EOL();
189254721Semaste}
190254721Semaste
191254721SemasteUnwindPlan::Row::Row() :
192254721Semaste    m_offset(0),
193254721Semaste    m_cfa_reg_num(LLDB_INVALID_REGNUM),
194254721Semaste    m_cfa_offset(0),
195254721Semaste    m_register_locations()
196254721Semaste{
197254721Semaste}
198254721Semaste
199254721Semastebool
200254721SemasteUnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
201254721Semaste{
202254721Semaste    collection::const_iterator pos = m_register_locations.find(reg_num);
203254721Semaste    if (pos != m_register_locations.end())
204254721Semaste    {
205254721Semaste        register_location = pos->second;
206254721Semaste        return true;
207254721Semaste    }
208254721Semaste    return false;
209254721Semaste}
210254721Semaste
211254721Semastevoid
212254721SemasteUnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
213254721Semaste{
214254721Semaste    m_register_locations[reg_num] = register_location;
215254721Semaste}
216254721Semaste
217254721Semastebool
218254721SemasteUnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
219254721Semaste{
220254721Semaste    if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
221254721Semaste        return false;
222254721Semaste    RegisterLocation reg_loc;
223254721Semaste    reg_loc.SetAtCFAPlusOffset(offset);
224254721Semaste    m_register_locations[reg_num] = reg_loc;
225254721Semaste    return true;
226254721Semaste}
227254721Semaste
228254721Semastebool
229254721SemasteUnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
230254721Semaste{
231254721Semaste    if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
232254721Semaste        return false;
233254721Semaste    RegisterLocation reg_loc;
234254721Semaste    reg_loc.SetIsCFAPlusOffset(offset);
235254721Semaste    m_register_locations[reg_num] = reg_loc;
236254721Semaste    return true;
237254721Semaste}
238254721Semaste
239254721Semastebool
240254721SemasteUnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
241254721Semaste{
242254721Semaste    collection::iterator pos = m_register_locations.find(reg_num);
243254721Semaste    collection::iterator end = m_register_locations.end();
244254721Semaste
245254721Semaste    if (pos != end)
246254721Semaste    {
247254721Semaste        if (!can_replace)
248254721Semaste            return false;
249254721Semaste        if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
250254721Semaste            return false;
251254721Semaste    }
252254721Semaste    RegisterLocation reg_loc;
253254721Semaste    reg_loc.SetUndefined();
254254721Semaste    m_register_locations[reg_num] = reg_loc;
255254721Semaste    return true;
256254721Semaste}
257254721Semaste
258254721Semastebool
259254721SemasteUnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace)
260254721Semaste{
261254721Semaste    if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
262254721Semaste        return false;
263254721Semaste    RegisterLocation reg_loc;
264254721Semaste    reg_loc.SetUnspecified();
265254721Semaste    m_register_locations[reg_num] = reg_loc;
266254721Semaste    return true;
267254721Semaste}
268254721Semaste
269254721Semastebool
270254721SemasteUnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num,
271254721Semaste                                                uint32_t other_reg_num,
272254721Semaste                                                bool can_replace)
273254721Semaste{
274254721Semaste    if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
275254721Semaste        return false;
276254721Semaste    RegisterLocation reg_loc;
277254721Semaste    reg_loc.SetInRegister(other_reg_num);
278254721Semaste    m_register_locations[reg_num] = reg_loc;
279254721Semaste    return true;
280254721Semaste}
281254721Semaste
282254721Semastebool
283254721SemasteUnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace)
284254721Semaste{
285254721Semaste    if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end())
286254721Semaste        return false;
287254721Semaste    RegisterLocation reg_loc;
288254721Semaste    reg_loc.SetSame();
289254721Semaste    m_register_locations[reg_num] = reg_loc;
290254721Semaste    return true;
291254721Semaste}
292254721Semaste
293254721Semastevoid
294254721SemasteUnwindPlan::Row::SetCFARegister (uint32_t reg_num)
295254721Semaste{
296254721Semaste    m_cfa_reg_num = reg_num;
297254721Semaste}
298254721Semaste
299254721Semastebool
300254721SemasteUnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const
301254721Semaste{
302254721Semaste    if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)
303254721Semaste        return false;
304254721Semaste    return m_register_locations == rhs.m_register_locations;
305254721Semaste}
306254721Semaste
307254721Semastevoid
308254721SemasteUnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp)
309254721Semaste{
310254721Semaste    if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset())
311254721Semaste        m_row_list.push_back(row_sp);
312254721Semaste    else
313254721Semaste        m_row_list.back() = row_sp;
314254721Semaste}
315254721Semaste
316254721SemasteUnwindPlan::RowSP
317254721SemasteUnwindPlan::GetRowForFunctionOffset (int offset) const
318254721Semaste{
319254721Semaste    RowSP row;
320254721Semaste    if (!m_row_list.empty())
321254721Semaste    {
322254721Semaste        if (offset == -1)
323254721Semaste            row = m_row_list.back();
324254721Semaste        else
325254721Semaste        {
326254721Semaste            collection::const_iterator pos, end = m_row_list.end();
327254721Semaste            for (pos = m_row_list.begin(); pos != end; ++pos)
328254721Semaste            {
329254721Semaste                if ((*pos)->GetOffset() <= offset)
330254721Semaste                    row = *pos;
331254721Semaste                else
332254721Semaste                    break;
333254721Semaste            }
334254721Semaste        }
335254721Semaste    }
336254721Semaste    return row;
337254721Semaste}
338254721Semaste
339254721Semastebool
340254721SemasteUnwindPlan::IsValidRowIndex (uint32_t idx) const
341254721Semaste{
342254721Semaste    return idx < m_row_list.size();
343254721Semaste}
344254721Semaste
345254721Semasteconst UnwindPlan::RowSP
346254721SemasteUnwindPlan::GetRowAtIndex (uint32_t idx) const
347254721Semaste{
348254721Semaste    // You must call IsValidRowIndex(idx) first before calling this!!!
349254721Semaste    assert (idx < m_row_list.size());
350254721Semaste    return m_row_list[idx];
351254721Semaste}
352254721Semaste
353254721Semasteconst UnwindPlan::RowSP
354254721SemasteUnwindPlan::GetLastRow () const
355254721Semaste{
356254721Semaste    // You must call GetRowCount() first to make sure there is at least one row
357254721Semaste    assert (!m_row_list.empty());
358254721Semaste    return m_row_list.back();
359254721Semaste}
360254721Semaste
361254721Semasteint
362254721SemasteUnwindPlan::GetRowCount () const
363254721Semaste{
364254721Semaste    return m_row_list.size ();
365254721Semaste}
366254721Semaste
367254721Semastevoid
368254721SemasteUnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
369254721Semaste{
370254721Semaste   if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
371254721Semaste       m_plan_valid_address_range = range;
372254721Semaste}
373254721Semaste
374254721Semastebool
375254721SemasteUnwindPlan::PlanValidAtAddress (Address addr)
376254721Semaste{
377263367Semaste    // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
378263367Semaste    if (GetRowCount() == 0)
379263367Semaste    {
380263367Semaste        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
381263367Semaste        if (log)
382263369Semaste        {
383263369Semaste            StreamString s;
384263369Semaste            if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
385263369Semaste            {
386263369Semaste                log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s",
387263369Semaste                             m_source_name.GetCString(), s.GetData());
388263369Semaste            }
389263369Semaste            else
390263369Semaste            {
391263369Semaste                log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
392263369Semaste                             m_source_name.GetCString());
393263369Semaste            }
394263369Semaste        }
395263367Semaste        return false;
396263367Semaste    }
397263367Semaste
398263367Semaste    // If the 0th Row of unwind instructions is missing, or if it doesn't provide
399263367Semaste    // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
400263367Semaste    if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
401263367Semaste    {
402263367Semaste        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
403263367Semaste        if (log)
404263369Semaste        {
405263369Semaste            StreamString s;
406263369Semaste            if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
407263369Semaste            {
408263369Semaste                log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s",
409263369Semaste                             m_source_name.GetCString(), s.GetData());
410263369Semaste            }
411263369Semaste            else
412263369Semaste            {
413263369Semaste                log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'",
414263369Semaste                             m_source_name.GetCString());
415263369Semaste            }
416263369Semaste        }
417263367Semaste        return false;
418263367Semaste    }
419263367Semaste
420254721Semaste    if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
421254721Semaste        return true;
422254721Semaste
423254721Semaste    if (!addr.IsValid())
424254721Semaste        return true;
425254721Semaste
426254721Semaste    if (m_plan_valid_address_range.ContainsFileAddress (addr))
427254721Semaste        return true;
428254721Semaste
429254721Semaste    return false;
430254721Semaste}
431254721Semaste
432254721Semastevoid
433254721SemasteUnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const
434254721Semaste{
435254721Semaste    if (!m_source_name.IsEmpty())
436254721Semaste    {
437254721Semaste        s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
438254721Semaste    }
439254721Semaste    if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
440254721Semaste    {
441254721Semaste        s.PutCString ("Address range of this UnwindPlan: ");
442254721Semaste        TargetSP target_sp(thread->CalculateTarget());
443254721Semaste        m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
444254721Semaste        s.EOL();
445254721Semaste    }
446254721Semaste    collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end();
447254721Semaste    for (pos = begin; pos != end; ++pos)
448254721Semaste    {
449254721Semaste        s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos));
450254721Semaste        (*pos)->Dump(s, this, thread, base_addr);
451254721Semaste    }
452254721Semaste}
453254721Semaste
454254721Semastevoid
455254721SemasteUnwindPlan::SetSourceName (const char *source)
456254721Semaste{
457254721Semaste    m_source_name = ConstString (source);
458254721Semaste}
459254721Semaste
460254721SemasteConstString
461254721SemasteUnwindPlan::GetSourceName () const
462254721Semaste{
463254721Semaste    return m_source_name;
464254721Semaste}
465254721Semaste
466254721Semasteconst RegisterInfo *
467254721SemasteUnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const
468254721Semaste{
469254721Semaste    if (thread)
470254721Semaste    {
471254721Semaste        RegisterContext *reg_ctx = thread->GetRegisterContext().get();
472254721Semaste        if (reg_ctx)
473254721Semaste        {
474254721Semaste            uint32_t reg;
475254721Semaste            if (m_register_kind == eRegisterKindLLDB)
476254721Semaste                reg = unwind_reg;
477254721Semaste            else
478254721Semaste                reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg);
479254721Semaste            if (reg != LLDB_INVALID_REGNUM)
480254721Semaste                return reg_ctx->GetRegisterInfoAtIndex (reg);
481254721Semaste        }
482254721Semaste    }
483254721Semaste    return NULL;
484254721Semaste}
485254721Semaste
486