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