]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Symbol/UnwindPlan.cpp
Merge ^/head r306906 through r307382.
[FreeBSD/FreeBSD.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                 s.Printf ("CFA%+d", m_location.offset);
98                 if (m_type == atCFAPlusOffset)
99                     s.PutChar(']');
100             }
101             break;
102
103         case inOtherRegister: 
104             {
105                 const RegisterInfo *other_reg_info = nullptr;
106                 if (unwind_plan)
107                     other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num);
108                 if (other_reg_info)
109                     s.Printf ("=%s", other_reg_info->name); 
110                 else
111                     s.Printf ("=reg(%u)", m_location.reg_num); 
112             }
113             break;
114
115         case atDWARFExpression: 
116         case isDWARFExpression: 
117             {
118                 s.PutChar('=');
119                 if (m_type == atDWARFExpression)
120                     s.PutCString("[dwarf-expr]");
121                 else
122                     s.PutCString("dwarf-expr");
123             }
124             break;
125         
126     }
127 }
128
129 static void
130 DumpRegisterName (Stream &s, const UnwindPlan* unwind_plan, Thread *thread, uint32_t reg_num) {
131     const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, reg_num);
132     if (reg_info)
133         s.PutCString (reg_info->name);
134     else
135         s.Printf ("reg(%u)", reg_num);
136 }
137
138 bool
139 UnwindPlan::Row::CFAValue::operator == (const UnwindPlan::Row::CFAValue& rhs) const
140 {
141     if (m_type == rhs.m_type)
142     {
143         switch (m_type)
144         {
145             case unspecified:
146                 return true;
147
148             case isRegisterPlusOffset:
149                 return m_value.reg.offset == rhs.m_value.reg.offset;
150
151             case isRegisterDereferenced:
152                 return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
153
154             case isDWARFExpression:
155                 if (m_value.expr.length == rhs.m_value.expr.length)
156                     return !memcmp (m_value.expr.opcodes, rhs.m_value.expr.opcodes, m_value.expr.length);
157                 break;
158         }
159     }
160     return false;
161 }
162
163 void
164 UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan* unwind_plan, Thread* thread) const
165 {
166     switch(m_type) {
167     case isRegisterPlusOffset:
168         DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
169         s.Printf ("%+3d", m_value.reg.offset);
170         break;
171     case isRegisterDereferenced:
172         s.PutChar ('[');
173         DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
174         s.PutChar (']');
175         break;
176     case isDWARFExpression:
177         s.PutCString ("dwarf-expr");
178         break;
179     default:
180         s.PutCString ("unspecified");
181         break;
182     }
183 }
184
185 void
186 UnwindPlan::Row::Clear ()
187 {
188     m_cfa_value.SetUnspecified();
189     m_offset = 0;
190     m_register_locations.clear();
191 }
192
193 void
194 UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const
195 {
196     if (base_addr != LLDB_INVALID_ADDRESS)
197         s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
198     else
199         s.Printf ("%4" PRId64 ": CFA=", GetOffset());
200             
201     m_cfa_value.Dump(s, unwind_plan, thread);
202     s.Printf(" => ");
203     for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
204     {
205         DumpRegisterName(s, unwind_plan, thread, idx->first);
206         const bool verbose = false;
207         idx->second.Dump(s, unwind_plan, this, thread, verbose);
208         s.PutChar (' ');
209     }
210     s.EOL();
211 }
212
213 UnwindPlan::Row::Row() :
214     m_offset (0),
215     m_cfa_value (),
216     m_register_locations ()
217 {
218 }
219
220 bool
221 UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
222 {
223     collection::const_iterator pos = m_register_locations.find(reg_num);
224     if (pos != m_register_locations.end())
225     {
226         register_location = pos->second;
227         return true;
228     }
229     return false;
230 }
231
232 void
233 UnwindPlan::Row::RemoveRegisterInfo (uint32_t reg_num)
234 {
235     collection::const_iterator pos = m_register_locations.find(reg_num);
236     if (pos != m_register_locations.end())
237     {
238         m_register_locations.erase(pos);
239     }
240 }
241
242 void
243 UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
244 {
245     m_register_locations[reg_num] = register_location;
246 }
247
248 bool
249 UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
250 {
251     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
252         return false;
253     RegisterLocation reg_loc;
254     reg_loc.SetAtCFAPlusOffset(offset);
255     m_register_locations[reg_num] = reg_loc;
256     return true;
257 }
258
259 bool
260 UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace)
261 {
262     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
263         return false;
264     RegisterLocation reg_loc;
265     reg_loc.SetIsCFAPlusOffset(offset);
266     m_register_locations[reg_num] = reg_loc;
267     return true;
268 }
269
270 bool
271 UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified)
272 {
273     collection::iterator pos = m_register_locations.find(reg_num);
274     collection::iterator end = m_register_locations.end();
275     
276     if (pos != end)
277     {
278         if (!can_replace)
279             return false;
280         if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
281             return false;
282     }
283     RegisterLocation reg_loc;
284     reg_loc.SetUndefined();
285     m_register_locations[reg_num] = reg_loc;
286     return true;
287 }
288
289 bool
290 UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace)
291 {
292     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
293         return false;
294     RegisterLocation reg_loc;
295     reg_loc.SetUnspecified();
296     m_register_locations[reg_num] = reg_loc;
297     return true;
298 }
299
300 bool
301 UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, 
302                                                 uint32_t other_reg_num,
303                                                 bool can_replace)
304 {
305     if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end())
306         return false;
307     RegisterLocation reg_loc;
308     reg_loc.SetInRegister(other_reg_num);
309     m_register_locations[reg_num] = reg_loc;
310     return true;
311 }
312
313 bool
314 UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace)
315 {
316     if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end())
317         return false;
318     RegisterLocation reg_loc;
319     reg_loc.SetSame();
320     m_register_locations[reg_num] = reg_loc;
321     return true;
322 }
323
324 bool
325 UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const
326 {
327     return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
328         m_register_locations == rhs.m_register_locations;
329 }
330
331 void
332 UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp)
333 {
334     if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset())
335         m_row_list.push_back(row_sp);
336     else
337         m_row_list.back() = row_sp;
338 }
339
340 void
341 UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp, bool replace_existing)
342 {
343     collection::iterator it = m_row_list.begin();
344     while (it != m_row_list.end()) {
345         RowSP row = *it;
346         if (row->GetOffset() >= row_sp->GetOffset())
347             break;
348         it++;
349     }
350     if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
351         m_row_list.insert(it, row_sp);
352     else if (replace_existing)
353         *it = row_sp;
354 }
355
356 UnwindPlan::RowSP
357 UnwindPlan::GetRowForFunctionOffset (int offset) const
358 {
359     RowSP row;
360     if (!m_row_list.empty())
361     {
362         if (offset == -1)
363             row = m_row_list.back();
364         else
365         {
366             collection::const_iterator pos, end = m_row_list.end();
367             for (pos = m_row_list.begin(); pos != end; ++pos)
368             {
369                 if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
370                     row = *pos;
371                 else
372                     break;
373             }
374         }
375     }
376     return row;
377 }
378
379 bool
380 UnwindPlan::IsValidRowIndex (uint32_t idx) const
381 {
382     return idx < m_row_list.size();
383 }
384
385 const UnwindPlan::RowSP
386 UnwindPlan::GetRowAtIndex (uint32_t idx) const
387 {
388     if (idx < m_row_list.size())
389         return m_row_list[idx];
390     else
391     {
392         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
393         if (log)
394             log->Printf ("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index (number rows is %u)", idx, (uint32_t)m_row_list.size());
395         return UnwindPlan::RowSP();
396     }
397 }
398
399 const UnwindPlan::RowSP
400 UnwindPlan::GetLastRow () const
401 {
402     if (m_row_list.empty())
403     {
404         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
405         if (log)
406             log->Printf ("UnwindPlan::GetLastRow() when rows are empty");
407         return UnwindPlan::RowSP();
408     }
409     return m_row_list.back();
410 }
411
412 int
413 UnwindPlan::GetRowCount () const
414 {
415     return m_row_list.size ();
416 }
417
418 void
419 UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
420 {
421    if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
422        m_plan_valid_address_range = range;
423 }
424
425 bool
426 UnwindPlan::PlanValidAtAddress (Address addr)
427 {
428     // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
429     if (GetRowCount() == 0)
430     {
431         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
432         if (log)
433         {
434             StreamString s;
435             if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
436             {
437                 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s",
438                              m_source_name.GetCString(), s.GetData());
439             }
440             else
441             {
442                 log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
443                              m_source_name.GetCString());
444             }
445         }
446         return false;
447     }
448
449     // If the 0th Row of unwind instructions is missing, or if it doesn't provide
450     // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
451     if (GetRowAtIndex(0).get() == nullptr ||
452             GetRowAtIndex(0)->GetCFAValue().GetValueType() == Row::CFAValue::unspecified)
453     {
454         Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
455         if (log)
456         {
457             StreamString s;
458             if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset))
459             {
460                 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s",
461                              m_source_name.GetCString(), s.GetData());
462             }
463             else
464             {
465                 log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'",
466                              m_source_name.GetCString());
467             }
468         }
469         return false;
470     }
471
472     if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
473         return true;
474
475     if (!addr.IsValid())
476         return true;
477
478     if (m_plan_valid_address_range.ContainsFileAddress (addr))
479         return true;
480
481     return false;
482 }
483
484 void
485 UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const
486 {
487     if (!m_source_name.IsEmpty())
488     {
489         s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString());
490     }
491     if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid())
492     {
493         TargetSP target_sp(thread->CalculateTarget());
494         addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get());
495         addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get());
496         
497         if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS)
498         {
499             s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n",
500                      lsda_load_addr, personality_func_load_addr);
501         }
502     }
503     s.Printf ("This UnwindPlan is sourced from the compiler: ");
504     switch (m_plan_is_sourced_from_compiler)
505     {
506         case eLazyBoolYes:
507             s.Printf ("yes.\n");
508             break;
509         case eLazyBoolNo:
510             s.Printf ("no.\n");
511             break;
512         case eLazyBoolCalculate:
513             s.Printf ("not specified.\n");
514             break;
515     }
516     s.Printf ("This UnwindPlan is valid at all instruction locations: ");
517     switch (m_plan_is_valid_at_all_instruction_locations)
518     {
519         case eLazyBoolYes:
520             s.Printf ("yes.\n");
521             break;
522         case eLazyBoolNo:
523             s.Printf ("no.\n");
524             break;
525         case eLazyBoolCalculate:
526             s.Printf ("not specified.\n");
527             break;
528     }
529     if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0)
530     {
531         s.PutCString ("Address range of this UnwindPlan: ");
532         TargetSP target_sp(thread->CalculateTarget());
533         m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
534         s.EOL();
535     }
536     collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end();
537     for (pos = begin; pos != end; ++pos)
538     {
539         s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos));
540         (*pos)->Dump(s, this, thread, base_addr);
541     }
542 }
543
544 void
545 UnwindPlan::SetSourceName (const char *source)
546 {
547     m_source_name = ConstString (source);
548 }
549
550 ConstString
551 UnwindPlan::GetSourceName () const
552 {
553     return m_source_name;
554 }
555
556 const RegisterInfo *
557 UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const
558 {
559     if (thread)
560     {
561         RegisterContext *reg_ctx = thread->GetRegisterContext().get();
562         if (reg_ctx)
563         {
564             uint32_t reg;
565             if (m_register_kind == eRegisterKindLLDB)
566                 reg = unwind_reg;
567             else
568                 reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg);
569             if (reg != LLDB_INVALID_REGNUM)
570                 return reg_ctx->GetRegisterInfoAtIndex (reg);
571         }
572     }
573     return nullptr;
574 }
575