1 //===-- Block.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/Block.h"
11 #include "lldb/Symbol/Function.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/Section.h"
14 #include "lldb/Symbol/SymbolVendor.h"
15 #include "lldb/Symbol/VariableList.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) :
21     UserID(uid),
22     m_block_list(blocks),
23     m_depth(depth),
24     m_ranges(),
25     m_inlineInfoSP(),
26     m_variables()
27 {
28 }
29 
30 Block::Block(const Block& rhs) :
31     UserID(rhs),
32     m_block_list(rhs.m_block_list),
33     m_depth(rhs.m_depth),
34     m_ranges(rhs.m_ranges),
35     m_inlineInfoSP(rhs.m_inlineInfoSP),
36     m_variables(rhs.m_variables)
37 {
38 }
39 
40 const Block&
41 Block::operator= (const Block& rhs)
42 {
43     if (this != &rhs)
44     {
45         UserID::operator= (rhs);
46         m_block_list = rhs.m_block_list;
47         m_depth = rhs.m_depth;
48         m_ranges = rhs.m_ranges;
49         m_inlineInfoSP = rhs.m_inlineInfoSP;
50         m_variables = rhs.m_variables;
51     }
52     return *this;
53 }
54 
55 Block::~Block ()
56 {
57 }
58 
59 void
60 Block::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const
61 {
62     size_t num_ranges = m_ranges.size();
63     if (num_ranges)
64     {
65 
66         addr_t base_addr = LLDB_INVALID_ADDRESS;
67         if (process)
68             base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
69         if (base_addr == LLDB_INVALID_ADDRESS)
70             base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetFileAddress();
71 
72         s->Printf("range%s = ", num_ranges > 1 ? "s" : "");
73         std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
74         for (pos = m_ranges.begin(); pos != end; ++pos)
75             pos->Dump(s, base_addr, 4);
76     }
77     *s << ", id = " << ((const UserID&)*this);
78 
79     if (m_inlineInfoSP.get() != NULL)
80         m_inlineInfoSP->Dump(s);
81 }
82 
83 void
84 Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
85 {
86     if (depth < 0)
87     {
88         // We have a depth that is less than zero, print our parent blocks
89         // first
90         m_block_list->Dump(s, GetParentUID(), depth + 1, show_context);
91     }
92 
93     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
94     s->Indent();
95     *s << "Block" << ((const UserID&)*this);
96     const Block* parent_block = GetParent();
97     if (parent_block)
98     {
99         s->Printf(", parent = {0x%8.8x}", parent_block->GetID());
100     }
101     if (m_inlineInfoSP.get() != NULL)
102         m_inlineInfoSP->Dump(s);
103 
104     if (!m_ranges.empty())
105     {
106         *s << ", ranges =";
107         std::vector<VMRange>::const_iterator pos;
108         std::vector<VMRange>::const_iterator end = m_ranges.end();
109         for (pos = m_ranges.begin(); pos != end; ++pos)
110         {
111             if (parent_block != NULL && parent_block->Contains(*pos) == false)
112                 *s << '!';
113             else
114                 *s << ' ';
115             pos->Dump(s, base_addr);
116         }
117     }
118     s->EOL();
119 
120     if (depth > 0)
121     {
122         s->IndentMore();
123 
124         if (m_variables.get())
125         {
126             m_variables->Dump(s, show_context);
127         }
128 
129         uint32_t blockID = m_block_list->GetFirstChild(GetID());
130         while (blockID != Block::InvalidID)
131         {
132             m_block_list->Dump(s, blockID, depth - 1, show_context);
133 
134             blockID = m_block_list->GetSibling(blockID);
135         }
136 
137         s->IndentLess();
138     }
139 
140 }
141 
142 
143 void
144 Block::CalculateSymbolContext(SymbolContext* sc)
145 {
146     sc->block = this;
147     m_block_list->GetFunction()->CalculateSymbolContext(sc);
148 }
149 
150 void
151 Block::DumpStopContext (Stream *s, const SymbolContext *sc)
152 {
153     Block* parent_block = GetParent();
154 
155     InlineFunctionInfo* inline_info = InlinedFunctionInfo ();
156     if (inline_info)
157     {
158         const Declaration &call_site = inline_info->GetCallSite();
159         if (sc)
160         {
161             // First frame, dump the first inline call site
162 //            if (call_site.IsValid())
163 //            {
164 //                s->PutCString(" at ");
165 //                call_site.DumpStopContext (s);
166 //            }
167             s->PutCString (" [inlined]");
168         }
169         s->EOL();
170         inline_info->DumpStopContext (s);
171         if (sc == NULL)
172         {
173             if (call_site.IsValid())
174             {
175                 s->PutCString(" at ");
176                 call_site.DumpStopContext (s);
177             }
178         }
179     }
180 
181     if (sc)
182     {
183         // If we have any inlined functions, this will be the deepest most
184         // inlined location
185         if (sc->line_entry.IsValid())
186         {
187             s->PutCString(" at ");
188             sc->line_entry.DumpStopContext (s);
189         }
190     }
191     if (parent_block)
192         parent_block->Block::DumpStopContext (s, NULL);
193 }
194 
195 
196 void
197 Block::DumpSymbolContext(Stream *s)
198 {
199     m_block_list->GetFunction()->DumpSymbolContext(s);
200     s->Printf(", Block{0x%8.8x}", GetID());
201 }
202 
203 bool
204 Block::Contains (addr_t range_offset) const
205 {
206     return VMRange::ContainsValue(m_ranges, range_offset);
207 }
208 
209 bool
210 Block::Contains (const VMRange& range) const
211 {
212     return VMRange::ContainsRange(m_ranges, range);
213 }
214 
215 
216 
217 bool
218 BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const
219 {
220     if (block_id == Block::InvalidID)
221         return false;
222 
223     if (block_id == find_block_id)
224         return true;
225     else
226     {
227         user_id_t child_block_id = GetFirstChild(block_id);
228         while (child_block_id != Block::InvalidID)
229         {
230             if (BlockContainsBlockWithID (child_block_id, find_block_id))
231                 return true;
232             child_block_id = GetSibling(child_block_id);
233         }
234     }
235 
236     return false;
237 }
238 
239 bool
240 Block::ContainsBlockWithID (user_id_t block_id) const
241 {
242     return m_block_list->BlockContainsBlockWithID (GetID(), block_id);
243 }
244 
245 
246 void
247 Block::AddRange(addr_t start_offset, addr_t end_offset)
248 {
249     m_ranges.resize(m_ranges.size()+1);
250     m_ranges.back().Reset(start_offset, end_offset);
251 }
252 
253 InlineFunctionInfo*
254 Block::InlinedFunctionInfo ()
255 {
256     return m_inlineInfoSP.get();
257 }
258 
259 const InlineFunctionInfo*
260 Block::InlinedFunctionInfo () const
261 {
262     return m_inlineInfoSP.get();
263 }
264 
265 // Return the current number of bytes that this object occupies in memory
266 size_t
267 Block::MemorySize() const
268 {
269     size_t mem_size = sizeof(Block) + m_ranges.size() * sizeof(VMRange);
270     if (m_inlineInfoSP.get())
271         mem_size += m_inlineInfoSP->MemorySize();
272     if (m_variables.get())
273         mem_size += m_variables->MemorySize();
274     return mem_size;
275 
276 }
277 
278 Block *
279 Block::GetParent () const
280 {
281     return m_block_list->GetBlockByID (m_block_list->GetParent(GetID()));
282 }
283 
284 Block *
285 Block::GetSibling () const
286 {
287     return m_block_list->GetBlockByID (m_block_list->GetSibling(GetID()));
288 }
289 
290 Block *
291 Block::GetFirstChild () const
292 {
293     return m_block_list->GetBlockByID (m_block_list->GetFirstChild(GetID()));
294 }
295 
296 user_id_t
297 Block::GetParentUID() const
298 {
299     return m_block_list->GetParent(GetID());
300 }
301 
302 user_id_t
303 Block::GetSiblingUID() const
304 {
305     return m_block_list->GetSibling(GetID());
306 }
307 
308 user_id_t
309 Block::GetFirstChildUID() const
310 {
311     return m_block_list->GetFirstChild(GetID());
312 }
313 
314 user_id_t
315 Block::AddChild(user_id_t userID)
316 {
317     return m_block_list->AddChild(GetID(), userID);
318 }
319 
320 void
321 Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
322 {
323     m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr));
324 }
325 
326 BlockList::BlockList(Function *function, const AddressRange& range) :
327     m_function(function),
328     m_range(range),
329     m_blocks()
330 {
331 }
332 
333 BlockList::~BlockList()
334 {
335 }
336 
337 AddressRange &
338 BlockList::GetAddressRange()
339 {
340     return m_range;
341 }
342 
343 const AddressRange &
344 BlockList::GetAddressRange() const
345 {
346     return m_range;
347 }
348 
349 void
350 BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const
351 {
352     const Block* block = GetBlockByID(blockID);
353     if (block)
354         block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context);
355 }
356 
357 Function *
358 BlockList::GetFunction()
359 {
360     return m_function;
361 }
362 
363 
364 const Function *
365 BlockList::GetFunction() const
366 {
367     return m_function;
368 }
369 
370 user_id_t
371 BlockList::GetParent(user_id_t blockID) const
372 {
373     collection::const_iterator end = m_blocks.end();
374     collection::const_iterator begin = m_blocks.begin();
375     collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID));
376 
377     if (pos != end && pos != begin && pos->Depth() > 0)
378     {
379         const uint32_t parent_depth = pos->Depth() - 1;
380 
381         while (--pos >= begin)
382         {
383             if (pos->Depth() == parent_depth)
384                 return pos->GetID();
385         }
386     }
387     return Block::InvalidID;
388 }
389 
390 user_id_t
391 BlockList::GetSibling(user_id_t blockID) const
392 {
393     collection::const_iterator end = m_blocks.end();
394     collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
395 
396     if (pos != end)
397     {
398         const uint32_t sibling_depth = pos->Depth();
399         while (++pos != end)
400         {
401             uint32_t depth = pos->Depth();
402             if (depth == sibling_depth)
403                 return pos->GetID();
404             if (depth < sibling_depth)
405                 break;
406         }
407     }
408     return Block::InvalidID;
409 }
410 
411 user_id_t
412 BlockList::GetFirstChild(user_id_t blockID) const
413 {
414     if (!m_blocks.empty())
415     {
416         if (blockID == Block::RootID)
417         {
418             return m_blocks.front().GetID();
419         }
420         else
421         {
422             collection::const_iterator end = m_blocks.end();
423             collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
424 
425             if (pos != end)
426             {
427                 collection::const_iterator child_pos = pos + 1;
428                 if (child_pos != end)
429                 {
430                     if (child_pos->Depth() == pos->Depth() + 1)
431                         return child_pos->GetID();
432                 }
433             }
434         }
435     }
436     return Block::InvalidID;
437 }
438 
439 
440 // Return the current number of bytes that this object occupies in memory
441 size_t
442 BlockList::MemorySize() const
443 {
444     size_t mem_size = sizeof(BlockList);
445 
446     collection::const_iterator pos, end = m_blocks.end();
447     for (pos = m_blocks.begin(); pos != end; ++pos)
448         mem_size += pos->MemorySize();  // Each block can vary in size
449 
450     return mem_size;
451 
452 }
453 
454 user_id_t
455 BlockList::AddChild (user_id_t parentID, user_id_t childID)
456 {
457     bool added = false;
458     if (parentID == Block::RootID)
459     {
460         assert(m_blocks.empty());
461         Block block(childID, 0, this);
462         m_blocks.push_back(block);
463         added = true;
464     }
465     else
466     {
467         collection::iterator end = m_blocks.end();
468         collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID));
469         assert(parent_pos != end);
470         if (parent_pos != end)
471         {
472             const uint32_t parent_sibling_depth = parent_pos->Depth();
473 
474             collection::iterator insert_pos = parent_pos;
475             collection::iterator prev_sibling = end;
476             while (++insert_pos != end)
477             {
478                 if (insert_pos->Depth() <= parent_sibling_depth)
479                     break;
480             }
481 
482             Block child_block(childID, parent_pos->Depth() + 1, this);
483             collection::iterator child_pos = m_blocks.insert(insert_pos, child_block);
484             added = true;
485         }
486     }
487     if (added)
488         return childID;
489     return Block::InvalidID;
490 }
491 
492 const Block *
493 BlockList::GetBlockByID(user_id_t blockID) const
494 {
495     if (m_blocks.empty() || blockID == Block::InvalidID)
496         return NULL;
497 
498     if (blockID == Block::RootID)
499         blockID = m_blocks.front().GetID();
500 
501     collection::const_iterator end = m_blocks.end();
502     collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
503     if (pos != end)
504         return &(*pos);
505     return NULL;
506 }
507 
508 Block *
509 BlockList::GetBlockByID(user_id_t blockID)
510 {
511     if (m_blocks.empty() || blockID == Block::InvalidID)
512         return NULL;
513 
514     if (blockID == Block::RootID)
515         blockID = m_blocks.front().GetID();
516 
517     collection::iterator end = m_blocks.end();
518     collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
519     if (pos != end)
520         return &(*pos);
521     return NULL;
522 }
523 
524 bool
525 BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset)
526 {
527     Block *block = GetBlockByID(blockID);
528 
529     if (block)
530     {
531         block->AddRange(start_offset, end_offset);
532         return true;
533     }
534     return false;
535 }
536 //
537 //const Block *
538 //BlockList::FindDeepestBlockForAddress (const Address &addr)
539 //{
540 //    if (m_range.Contains(addr))
541 //    {
542 //        addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress();
543 //        collection::const_iterator pos, end = m_blocks.end();
544 //        collection::const_iterator deepest_match_pos = end;
545 //        for (pos = m_blocks.begin(); pos != end; ++pos)
546 //        {
547 //            if (pos->Contains (block_offset))
548 //            {
549 //                if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth())
550 //                    deepest_match_pos = pos;
551 //            }
552 //        }
553 //        if (deepest_match_pos != end)
554 //            return &(*deepest_match_pos);
555 //    }
556 //    return NULL;
557 //}
558 //
559 bool
560 BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
561 {
562     Block *block = GetBlockByID(blockID);
563 
564     if (block)
565     {
566         block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr);
567         return true;
568     }
569     return false;
570 }
571 
572 VariableListSP
573 BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create)
574 {
575     VariableListSP variable_list_sp;
576     Block *block = GetBlockByID(blockID);
577     if (block)
578         variable_list_sp = block->GetVariableList(get_child_variables, can_create);
579     return variable_list_sp;
580 }
581 
582 bool
583 BlockList::IsEmpty() const
584 {
585     return m_blocks.empty();
586 }
587 
588 
589 
590 bool
591 BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables)
592 {
593     Block *block = GetBlockByID(blockID);
594     if (block)
595     {
596         block->SetVariableList(variables);
597         return true;
598     }
599     return false;
600 
601 }
602 
603 
604 VariableListSP
605 Block::GetVariableList (bool get_child_variables, bool can_create)
606 {
607     VariableListSP variable_list_sp;
608     if (m_variables.get() == NULL && can_create)
609     {
610         SymbolContext sc;
611         CalculateSymbolContext(&sc);
612         assert(sc.module_sp);
613         sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
614     }
615 
616     if (m_variables.get())
617     {
618         variable_list_sp.reset(new VariableList());
619         if (variable_list_sp.get())
620             variable_list_sp->AddVariables(m_variables.get());
621 
622         if (get_child_variables)
623         {
624             Block *child_block = GetFirstChild();
625             while (child_block)
626             {
627                 VariableListSP child_block_variable_list(child_block->GetVariableList(get_child_variables, can_create));
628                 if (child_block_variable_list.get())
629                     variable_list_sp->AddVariables(child_block_variable_list.get());
630                 child_block = child_block->GetSibling();
631             }
632         }
633     }
634 
635     return variable_list_sp;
636 }
637 
638 uint32_t
639 Block::AppendVariables (bool can_create, bool get_parent_variables, VariableList *variable_list)
640 {
641     uint32_t num_variables_added = 0;
642     VariableListSP variable_list_sp(GetVariableList(false, can_create));
643 
644     if (variable_list_sp.get())
645     {
646         num_variables_added = variable_list_sp->GetSize();
647         variable_list->AddVariables(variable_list_sp.get());
648     }
649 
650     if (get_parent_variables)
651     {
652         Block* parent_block = GetParent();
653         if (parent_block)
654             num_variables_added += parent_block->AppendVariables (can_create, get_parent_variables, variable_list);
655     }
656     return num_variables_added;
657 }
658 
659 
660 void
661 Block::SetVariableList(VariableListSP& variables)
662 {
663     m_variables = variables;
664 }
665 
666 uint32_t
667 Block::Depth () const
668 {
669     return m_depth;
670 }
671 
672