]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Symbol / UnwindPlan.cpp
1 //===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Symbol/UnwindPlan.h"
11
12 #include "lldb/Core/ConstString.h"
13 #include "lldb/Core/Log.h"
14 #include "lldb/Target/Process.h"
15 #include "lldb/Target/RegisterContext.h"
16 #include "lldb/Target/Thread.h"
17
18 using namespace lldb;
19 using namespace lldb_private;
20
21 bool
22 UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
23 {
24     if (m_type == rhs.m_type)
25     {
26         switch (m_type)
27         {
28             case unspecified:
29             case undefined:
30             case same:
31                 return true;
32                 
33             case atCFAPlusOffset:
34             case isCFAPlusOffset:
35                 return m_location.offset == rhs.m_location.offset;
36
37             case inOtherRegister:
38                 return m_location.reg_num == rhs.m_location.reg_num;
39             
40             case atDWARFExpression:
41             case isDWARFExpression:
42                 if (m_location.expr.length == rhs.m_location.expr.length)
43                     return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
44                 break;
45         }
46     }
47     return false;
48 }
49
50 // This function doesn't copy the dwarf expression bytes; they must remain in allocated
51 // memory for the lifespan of this UnwindPlan object.
52 void
53 UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
54 {
55     m_type = atDWARFExpression;
56     m_location.expr.opcodes = opcodes;
57     m_location.expr.length = len;
58 }
59
60 // This function doesn't copy the dwarf expression bytes; they must remain in allocated
61 // memory for the lifespan of this UnwindPlan object.
62 void
63 UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
64 {
65     m_type = isDWARFExpression;
66     m_location.expr.opcodes = opcodes;
67     m_location.expr.length = len;
68 }
69
70 void
71 UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const
72 {
73     switch (m_type)
74     {
75         case unspecified: 
76             if (verbose)
77                 s.PutCString ("=<unspec>"); 
78             else
79                 s.PutCString ("=!"); 
80             break;
81         case undefined: 
82             if (verbose)
83                 s.PutCString ("=<undef>"); 
84             else
85                 s.PutCString ("=?"); 
86             break;
87         case same: 
88             s.PutCString ("= <same>"); 
89             break;
90
91         case atCFAPlusOffset: 
92         case isCFAPlusOffset: 
93             {
94                 s.PutChar('=');
95                 if (m_type == atCFAPlusOffset)
96                     s.PutChar('[');
97                 if (verbose)
98                     s.Printf ("CFA%+d", m_location.offset);
99
100                 if (unwind_plan && row)
101                 {
102                     const uint32_t cfa_reg = row->GetCFARegister();
103                     const RegisterInfo *cfa_reg_info = unwind_plan->GetRegisterInfo (thread, cfa_reg);
104                     const int32_t offset = row->GetCFAOffset() + m_location.offset;
105                     if (verbose)
106                     {                        
107                         if (cfa_reg_info)
108                             s.Printf (" (%s%+d)",  cfa_reg_info->name, offset); 
109                         else
110                             s.Printf (" (reg(%u)%+d)",  cfa_reg, offset); 
111                     }
112                     else
113                     {
114                         if (cfa_reg_info)
115                             s.Printf ("%s",  cfa_reg_info->name); 
116                         else
117                             s.Printf ("reg(%u)",  cfa_reg); 
118                         if (offset != 0)
119                             s.Printf ("%+d", offset);
120                     }
121                 }
122                 if (m_type == atCFAPlusOffset)
123                     s.PutChar(']');
124             }
125             break;
126
127         case inOtherRegister: 
128             {
129                 const RegisterInfo *other_reg_info = NULL;
130                 if (unwind_plan)
131                     other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num);
132                 if (other_reg_info)
133                     s.Printf ("=%s", other_reg_info->name); 
134                 else
135                     s.Printf ("=reg(%u)", m_location.reg_num); 
136             }
137             break;
138
139         case atDWARFExpression: 
140         case isDWARFExpression: 
141             {
142                 s.PutChar('=');
143                 if (m_type == atDWARFExpression)
144                     s.PutCString("[dwarf-expr]");
145                 else
146                     s.PutCString("dwarf-expr");
147             }
148             break;
149         
150     }
151 }
152
153 void
154 UnwindPlan::Row::Clear ()
155 {
156     m_offset = 0;
157     m_cfa_reg_num = LLDB_INVALID_REGNUM;
158     m_cfa_offset = 0;
159     m_register_locations.clear();
160 }
161
162 void
163 UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const
164 {
165     const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, GetCFARegister());
166
167     if (base_addr != LLDB_INVALID_ADDRESS)
168         s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
169     else
170         s.Printf ("0x%8.8" PRIx64 ": CFA=", GetOffset());
171             
172     if (reg_info)
173         s.Printf ("%s", reg_info->name);
174     else
175         s.Printf ("reg(%u)", GetCFARegister());
176     s.Printf ("%+3d => ", GetCFAOffset ());
177     for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
178     {
179         reg_info = unwind_plan->GetRegisterInfo (thread, idx->first);
180         if (reg_info)
181             s.Printf ("%s", reg_info->name);
182         else
183             s.Printf ("reg(%u)", idx->first);
184         const bool verbose = false;
185         idx->second.Dump(s, unwind_plan, this, thread, verbose);
186         s.PutChar (' ');
187     }
188     s.EOL();
189 }
190
191 UnwindPlan::Row::Row() :
192     m_offset(0),
193     m_cfa_reg_num(LLDB_INVALID_REGNUM),
194     m_cfa_offset(0),
195     m_register_locations()
196 {
197 }
198
199 bool
200 UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
201 {
202     collection::const_iterator pos = m_register_locations.find(reg_num);
203     if (pos != m_register_locations.end())
204     {
205         register_location = pos->second;
206         return true;
207     }
208     return false;
209 }
210
211 void
212 UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
213 {
214     m_register_locations[reg_num] = register_location;
215 }
216
217 bool
218 UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
219 {
220     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
221         return false;
222     RegisterLocation reg_loc;
223     reg_loc.SetAtCFAPlusOffset(offset);
224     m_register_locations[reg_num] = reg_loc;
225     return true;
226 }
227
228 bool
229 UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
230 {
231     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
232         return false;
233     RegisterLocation reg_loc;
234     reg_loc.SetIsCFAPlusOffset(offset);
235     m_register_locations[reg_num] = reg_loc;
236     return true;
237 }
238
239 bool
240 UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
241 {
242     collection::iterator pos = m_register_locations.find(reg_num);
243     collection::iterator end = m_register_locations.end();
244     
245     if (pos != end)
246     {
247         if (!can_replace)
248             return false;
249         if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
250             return false;
251     }
252     RegisterLocation reg_loc;
253     reg_loc.SetUndefined();
254     m_register_locations[reg_num] = reg_loc;
255     return true;
256 }
257
258 bool
259 UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace)
260 {
261     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
262         return false;
263     RegisterLocation reg_loc;
264     reg_loc.SetUnspecified();
265     m_register_locations[reg_num] = reg_loc;
266     return true;
267 }
268
269 bool
270 UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, 
271                                                 uint32_t other_reg_num,
272                                                 bool can_replace)
273 {
274     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
275         return false;
276     RegisterLocation reg_loc;
277     reg_loc.SetInRegister(other_reg_num);
278     m_register_locations[reg_num] = reg_loc;
279     return true;
280 }
281
282 bool
283 UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace)
284 {
285     if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end())
286         return false;
287     RegisterLocation reg_loc;
288     reg_loc.SetSame();
289     m_register_locations[reg_num] = reg_loc;
290     return true;
291 }
292
293 void
294 UnwindPlan::Row::SetCFARegister (uint32_t reg_num)
295 {
296     m_cfa_reg_num = reg_num;
297 }
298
299 bool
300 UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const
301 {
302     if (m_offset != rhs.m_offset || m_cfa_reg_num != rhs.m_cfa_reg_num || m_cfa_offset != rhs.m_cfa_offset)
303         return false;
304     return m_register_locations == rhs.m_register_locations;
305 }
306
307 void
308 UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp)
309 {
310     if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset())
311         m_row_list.push_back(row_sp);
312     else
313         m_row_list.back() = row_sp;
314 }
315
316 UnwindPlan::RowSP
317 UnwindPlan::GetRowForFunctionOffset (int offset) const
318 {
319     RowSP row;
320     if (!m_row_list.empty())
321     {
322         if (offset == -1)
323             row = m_row_list.back();
324         else
325         {
326             collection::const_iterator pos, end = m_row_list.end();
327             for (pos = m_row_list.begin(); pos != end; ++pos)
328             {
329                 if ((*pos)->GetOffset() <= offset)
330                     row = *pos;
331                 else
332                     break;
333             }
334         }
335     }
336     return row;
337 }
338
339 bool
340 UnwindPlan::IsValidRowIndex (uint32_t idx) const
341 {
342     return idx < m_row_list.size();
343 }
344
345 const UnwindPlan::RowSP
346 UnwindPlan::GetRowAtIndex (uint32_t idx) const
347 {
348     // You must call IsValidRowIndex(idx) first before calling this!!!
349     assert (idx < m_row_list.size());
350     return m_row_list[idx];
351 }
352
353 const UnwindPlan::RowSP
354 UnwindPlan::GetLastRow () const
355 {
356     // You must call GetRowCount() first to make sure there is at least one row
357     assert (!m_row_list.empty());
358     return m_row_list.back();
359 }
360
361 int
362 UnwindPlan::GetRowCount () const
363 {
364     return m_row_list.size ();
365 }
366
367 void
368 UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
369 {
370    if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
371        m_plan_valid_address_range = range;
372 }
373
374 bool
375 UnwindPlan::PlanValidAtAddress (Address addr)
376 {
377     // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
378     if (GetRowCount() == 0)
379     {
380         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
381         if (log)
382         {
383             StreamString s;
384             if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
385             {
386                 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s",
387                              m_source_name.GetCString(), s.GetData());
388             }
389             else
390             {
391                 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
392                              m_source_name.GetCString());
393             }
394         }
395         return false;
396     }
397
398     // If the 0th Row of unwind instructions is missing, or if it doesn't provide
399     // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
400     if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
401     {
402         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
403         if (log)
404         {
405             StreamString s;
406             if (addr.Dump (&s, NULL, Address::DumpStyleSectionNameOffset))
407             {
408                 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s",
409                              m_source_name.GetCString(), s.GetData());
410             }
411             else
412             {
413                 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'",
414                              m_source_name.GetCString());
415             }
416         }
417         return false;
418     }
419
420     if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
421         return true;
422
423     if (!addr.IsValid())
424         return true;
425
426     if (m_plan_valid_address_range.ContainsFileAddress (addr))
427         return true;
428
429     return false;
430 }
431
432 void
433 UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const
434 {
435     if (!m_source_name.IsEmpty())
436     {
437         s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
438     }
439     if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
440     {
441         s.PutCString ("Address range of this UnwindPlan: ");
442         TargetSP target_sp(thread->CalculateTarget());
443         m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
444         s.EOL();
445     }
446     collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end();
447     for (pos = begin; pos != end; ++pos)
448     {
449         s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos));
450         (*pos)->Dump(s, this, thread, base_addr);
451     }
452 }
453
454 void
455 UnwindPlan::SetSourceName (const char *source)
456 {
457     m_source_name = ConstString (source);
458 }
459
460 ConstString
461 UnwindPlan::GetSourceName () const
462 {
463     return m_source_name;
464 }
465
466 const RegisterInfo *
467 UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const
468 {
469     if (thread)
470     {
471         RegisterContext *reg_ctx = thread->GetRegisterContext().get();
472         if (reg_ctx)
473         {
474             uint32_t reg;
475             if (m_register_kind == eRegisterKindLLDB)
476                 reg = unwind_reg;
477             else
478                 reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg);
479             if (reg != LLDB_INVALID_REGNUM)
480                 return reg_ctx->GetRegisterInfoAtIndex (reg);
481         }
482     }
483     return NULL;
484 }
485