1 //===-- Section.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/Core/Section.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Symbol/ObjectFile.h"
13 #include "lldb/Target/Target.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 Section::Section (const ModuleSP &module_sp,
19                   user_id_t sect_id,
20                   const ConstString &name,
21                   SectionType sect_type,
22                   addr_t file_addr,
23                   addr_t byte_size,
24                   uint64_t file_offset,
25                   uint64_t file_size,
26                   uint32_t flags) :
27     ModuleChild     (module_sp),
28     UserID          (sect_id),
29     Flags           (flags),
30     m_parent_wp     (),
31     m_name          (name),
32     m_type          (sect_type),
33     m_file_addr     (file_addr),
34     m_byte_size     (byte_size),
35     m_file_offset   (file_offset),
36     m_file_size     (file_size),
37     m_children      (),
38     m_fake          (false),
39     m_encrypted     (false),
40     m_thread_specific (false),
41     m_linked_section_wp(),
42     m_linked_offset (0)
43 {
44 //    printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16llx, addr=[0x%16.16llx - 0x%16.16llx), file [0x%16.16llx - 0x%16.16llx), flags = 0x%8.8x, name = %s\n",
45 //            this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString());
46 }
47 
48 Section::Section (const lldb::SectionSP &parent_section_sp,
49                   const ModuleSP &module_sp,
50                   user_id_t sect_id,
51                   const ConstString &name,
52                   SectionType sect_type,
53                   addr_t file_addr,
54                   addr_t byte_size,
55                   uint64_t file_offset,
56                   uint64_t file_size,
57                   uint32_t flags) :
58     ModuleChild     (module_sp),
59     UserID          (sect_id),
60     Flags           (flags),
61     m_parent_wp     (),
62     m_name          (name),
63     m_type          (sect_type),
64     m_file_addr     (file_addr),
65     m_byte_size     (byte_size),
66     m_file_offset   (file_offset),
67     m_file_size     (file_size),
68     m_children      (),
69     m_fake          (false),
70     m_encrypted     (false),
71     m_thread_specific (false),
72     m_linked_section_wp(),
73     m_linked_offset (0)
74 {
75 //    printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16llx, addr=[0x%16.16llx - 0x%16.16llx), file [0x%16.16llx - 0x%16.16llx), flags = 0x%8.8x, name = %s.%s\n",
76 //            this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString());
77     if (parent_section_sp)
78         m_parent_wp = parent_section_sp;
79 }
80 
81 Section::~Section()
82 {
83 //    printf ("Section::~Section(%p)\n", this);
84 }
85 
86 const ConstString&
87 Section::GetName() const
88 {
89     SectionSP linked_section_sp (m_linked_section_wp.lock());
90     if (linked_section_sp)
91         return linked_section_sp->GetName();
92     return m_name;
93 }
94 
95 addr_t
96 Section::GetFileAddress () const
97 {
98     SectionSP parent_sp (GetParent ());
99     if (parent_sp)
100     {
101         // This section has a parent which means m_file_addr is an offset into
102         // the parent section, so the file address for this section is the file
103         // address of the parent plus the offset
104         return parent_sp->GetFileAddress() + m_file_addr;
105     }
106     // This section has no parent, so m_file_addr is the file base address
107     return m_file_addr;
108 }
109 
110 lldb::addr_t
111 Section::GetOffset () const
112 {
113     // This section has a parent which means m_file_addr is an offset.
114     SectionSP parent_sp (GetParent ());
115     if (parent_sp)
116         return m_file_addr;
117 
118     // This section has no parent, so there is no offset to be had
119     return 0;
120 }
121 
122 
123 addr_t
124 Section::GetLinkedFileAddress () const
125 {
126     SectionSP linked_section_sp (m_linked_section_wp.lock());
127     if (linked_section_sp)
128         return linked_section_sp->GetFileAddress() + m_linked_offset;
129     return LLDB_INVALID_ADDRESS;
130 }
131 
132 
133 addr_t
134 Section::GetLoadBaseAddress (Target *target) const
135 {
136     addr_t load_base_addr = LLDB_INVALID_ADDRESS;
137     SectionSP linked_section_sp (m_linked_section_wp.lock());
138     if (linked_section_sp)
139     {
140         load_base_addr = linked_section_sp->GetLoadBaseAddress(target);
141         if (load_base_addr != LLDB_INVALID_ADDRESS)
142             load_base_addr += m_linked_offset;
143     }
144     else
145     {
146         SectionSP parent_sp (GetParent ());
147         if (parent_sp)
148         {
149             load_base_addr = parent_sp->GetLoadBaseAddress (target);
150             if (load_base_addr != LLDB_INVALID_ADDRESS)
151                 load_base_addr += GetOffset();
152         }
153         else
154         {
155             load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this());
156         }
157     }
158 
159     return load_base_addr;
160 }
161 
162 bool
163 Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
164 {
165     const uint32_t num_children = m_children.GetSize();
166     if (num_children > 0)
167     {
168         for (uint32_t i=0; i<num_children; i++)
169         {
170             Section* child_section = m_children.GetSectionAtIndex (i).get();
171 
172             addr_t child_offset = child_section->GetOffset();
173             if (child_offset <= offset && offset - child_offset < child_section->GetByteSize())
174                 return child_section->ResolveContainedAddress (offset - child_offset, so_addr);
175         }
176     }
177     SectionSP linked_section_sp (m_linked_section_wp.lock());
178     if (linked_section_sp)
179     {
180         so_addr.SetOffset(m_linked_offset + offset);
181         so_addr.SetSection(linked_section_sp);
182     }
183     else
184     {
185         so_addr.SetOffset(offset);
186         so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
187 
188 #ifdef LLDB_CONFIGURATION_DEBUG
189         // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections.
190         assert(GetModule().get());
191 #endif
192     }
193     return true;
194 }
195 
196 bool
197 Section::ContainsFileAddress (addr_t vm_addr) const
198 {
199     const addr_t file_addr = GetFileAddress();
200     if (file_addr != LLDB_INVALID_ADDRESS)
201     {
202         if (file_addr <= vm_addr)
203         {
204             const addr_t offset = vm_addr - file_addr;
205             return offset < GetByteSize();
206         }
207     }
208     return false;
209 }
210 
211 bool
212 Section::ContainsLinkedFileAddress (addr_t vm_addr) const
213 {
214     const addr_t linked_file_addr = GetLinkedFileAddress();
215     if (linked_file_addr != LLDB_INVALID_ADDRESS)
216     {
217         if (linked_file_addr <= vm_addr)
218         {
219             const addr_t offset = vm_addr - linked_file_addr;
220             return offset < GetByteSize();
221         }
222     }
223     return false;
224 }
225 
226 int
227 Section::Compare (const Section& a, const Section& b)
228 {
229     if (&a == &b)
230         return 0;
231 
232     const ModuleSP a_module_sp = a.GetModule();
233     const ModuleSP b_module_sp = b.GetModule();
234     if (a_module_sp == b_module_sp)
235     {
236         user_id_t a_sect_uid = a.GetID();
237         user_id_t b_sect_uid = b.GetID();
238         if (a_sect_uid < b_sect_uid)
239             return -1;
240         if (a_sect_uid > b_sect_uid)
241             return 1;
242         return 0;
243     }
244     else
245     {
246         // The modules are different, just compare the module pointers
247         if (a_module_sp.get() < b_module_sp.get())
248             return -1;
249         else
250             return 1;   // We already know the modules aren't equal
251     }
252 }
253 
254 
255 void
256 Section::Dump (Stream *s, Target *target, uint32_t depth) const
257 {
258 //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
259     s->Indent();
260     s->Printf("0x%8.8llx %-16s ", GetID(), GetSectionTypeAsCString (m_type));
261     bool resolved = true;
262     addr_t addr = LLDB_INVALID_ADDRESS;
263 
264     SectionSP linked_section_sp (m_linked_section_wp.lock());
265     if (GetByteSize() == 0)
266         s->Printf("%39s", "");
267     else
268     {
269         if (target && linked_section_sp.get() == NULL)
270             addr = GetLoadBaseAddress (target);
271 
272         if (addr == LLDB_INVALID_ADDRESS)
273         {
274             if (target)
275                 resolved = false;
276             addr = GetFileAddress();
277         }
278 
279         VMRange range(addr, addr + m_byte_size);
280         range.Dump (s, 0);
281     }
282 
283     s->Printf("%c 0x%8.8llx 0x%8.8llx 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get());
284 
285     DumpName (s);
286 
287     s->EOL();
288 
289     if (linked_section_sp)
290     {
291         addr = LLDB_INVALID_ADDRESS;
292         resolved = true;
293         if (target)
294         {
295             addr = linked_section_sp->GetLoadBaseAddress(target);
296             if (addr != LLDB_INVALID_ADDRESS)
297                 addr += m_linked_offset;
298         }
299 
300         if (addr == LLDB_INVALID_ADDRESS)
301         {
302             if (target)
303                 resolved = false;
304             addr = linked_section_sp->GetFileAddress() + m_linked_offset;
305         }
306 
307         int indent = 26 + s->GetIndentLevel();
308         s->Printf("%*.*s", indent, indent, "");
309         VMRange linked_range(addr, addr + m_byte_size);
310         linked_range.Dump (s, 0);
311         indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
312         s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
313 
314         linked_section_sp->DumpName(s);
315         s->Printf(" + 0x%llx\n", m_linked_offset);
316     }
317 
318     if (depth > 0)
319         m_children.Dump(s, target, false, depth - 1);
320 }
321 
322 void
323 Section::DumpName (Stream *s) const
324 {
325     SectionSP parent_sp (GetParent ());
326     if (parent_sp)
327     {
328         parent_sp->DumpName (s);
329         s->PutChar('.');
330     }
331     else
332     {
333         // The top most section prints the module basename
334         ModuleSP module_sp (GetModule());
335         if (module_sp)
336         {
337             const char *module_basename = module_sp->GetFileSpec().GetFilename().AsCString();
338             if (module_basename && module_basename[0])
339                 s->Printf("%s.", module_basename);
340         }
341     }
342     m_name.Dump(s);
343 }
344 
345 bool
346 Section::IsDescendant (const Section *section)
347 {
348     if (this == section)
349         return true;
350     SectionSP parent_sp (GetParent ());
351     if (parent_sp)
352         return parent_sp->IsDescendant (section);
353     return false;
354 }
355 
356 bool
357 Section::Slide (addr_t slide_amount, bool slide_children)
358 {
359     if (m_file_addr != LLDB_INVALID_ADDRESS)
360     {
361         if (slide_amount == 0)
362             return true;
363 
364         m_file_addr += slide_amount;
365 
366         if (slide_children)
367             m_children.Slide (slide_amount, slide_children);
368 
369         return true;
370     }
371     return false;
372 }
373 
374 void
375 Section::SetLinkedLocation (const lldb::SectionSP &linked_section_sp, uint64_t linked_offset)
376 {
377     if (linked_section_sp)
378         m_module_wp = linked_section_sp->GetModule();
379     m_linked_section_wp = linked_section_sp;
380     m_linked_offset  = linked_offset;
381 }
382 
383 #pragma mark SectionList
384 
385 SectionList::SectionList () :
386     m_sections()
387 #ifdef LLDB_CONFIGURATION_DEBUG
388     , m_finalized(false)
389 #endif
390 {
391 }
392 
393 
394 SectionList::~SectionList ()
395 {
396 }
397 
398 uint32_t
399 SectionList::AddSection (const lldb::SectionSP& section_sp)
400 {
401     assert (section_sp.get());
402     uint32_t section_index = m_sections.size();
403     m_sections.push_back(section_sp);
404     InvalidateRangeCache();
405     return section_index;
406 }
407 
408 uint32_t
409 SectionList::FindSectionIndex (const Section* sect)
410 {
411     iterator sect_iter;
412     iterator begin = m_sections.begin();
413     iterator end = m_sections.end();
414     for (sect_iter = begin; sect_iter != end; ++sect_iter)
415     {
416         if (sect_iter->get() == sect)
417         {
418             // The secton was already in this section list
419             return std::distance (begin, sect_iter);
420         }
421     }
422     return UINT32_MAX;
423 }
424 
425 uint32_t
426 SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp)
427 {
428     uint32_t sect_idx = FindSectionIndex (sect_sp.get());
429     if (sect_idx == UINT32_MAX)
430         sect_idx = AddSection (sect_sp);
431     return sect_idx;
432 }
433 
434 
435 bool
436 SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth)
437 {
438     iterator sect_iter, end = m_sections.end();
439     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
440     {
441         if ((*sect_iter)->GetID() == sect_id)
442         {
443             *sect_iter = sect_sp;
444             InvalidateRangeCache();
445             return true;
446         }
447         else if (depth > 0)
448         {
449             if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
450                 return true;
451         }
452     }
453     return false;
454 }
455 
456 
457 size_t
458 SectionList::GetNumSections (uint32_t depth) const
459 {
460     size_t count = m_sections.size();
461     if (depth > 0)
462     {
463         const_iterator sect_iter, end = m_sections.end();
464         for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
465         {
466             count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
467         }
468     }
469     return count;
470 }
471 
472 SectionSP
473 SectionList::GetSectionAtIndex (uint32_t idx) const
474 {
475     SectionSP sect_sp;
476     if (idx < m_sections.size())
477         sect_sp = m_sections[idx];
478     return sect_sp;
479 }
480 
481 SectionSP
482 SectionList::FindSectionByName (const ConstString &section_dstr) const
483 {
484     SectionSP sect_sp;
485     // Check if we have a valid section string
486     if (section_dstr && !m_sections.empty())
487     {
488         const_iterator sect_iter;
489         const_iterator end = m_sections.end();
490         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
491         {
492             Section *child_section = sect_iter->get();
493             assert (child_section);
494             if (child_section->GetName() == section_dstr)
495             {
496                 sect_sp = *sect_iter;
497             }
498             else
499             {
500                 sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
501             }
502         }
503     }
504     return sect_sp;
505 }
506 
507 SectionSP
508 SectionList::FindSectionByID (user_id_t sect_id) const
509 {
510     SectionSP sect_sp;
511     if (sect_id)
512     {
513         const_iterator sect_iter;
514         const_iterator end = m_sections.end();
515         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
516         {
517             if ((*sect_iter)->GetID() == sect_id)
518             {
519                 sect_sp = *sect_iter;
520                 break;
521             }
522             else
523             {
524                 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
525             }
526         }
527     }
528     return sect_sp;
529 }
530 
531 
532 SectionSP
533 SectionList::FindSectionByType (SectionType sect_type, bool check_children, uint32_t start_idx) const
534 {
535     SectionSP sect_sp;
536     uint32_t num_sections = m_sections.size();
537     for (uint32_t idx = start_idx; idx < num_sections; ++idx)
538     {
539         if (m_sections[idx]->GetType() == sect_type)
540         {
541             sect_sp = m_sections[idx];
542             break;
543         }
544         else if (check_children)
545         {
546             sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0);
547             if (sect_sp)
548                 break;
549         }
550     }
551     return sect_sp;
552 }
553 
554 SectionSP
555 SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
556 {
557     SectionSP sect_sp;
558     const_iterator sect_iter;
559     const_iterator end = m_sections.end();
560     for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
561     {
562         Section *sect = sect_iter->get();
563         if (sect->ContainsFileAddress (vm_addr))
564         {
565             // The file address is in this section. We need to make sure one of our child
566             // sections doesn't contain this address as well as obeying the depth limit
567             // that was passed in.
568             if (depth > 0)
569                 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
570 
571             if (sect_sp.get() == NULL && !sect->IsFake())
572                 sect_sp = *sect_iter;
573         }
574     }
575     return sect_sp;
576 }
577 
578 void
579 SectionList::BuildRangeCache() const
580 {
581     m_range_cache.Clear();
582 
583     for (collection::size_type idx = 0, last_idx = m_sections.size();
584          idx < last_idx;
585          ++idx)
586     {
587         Section *sect = m_sections[idx].get();
588 
589         addr_t linked_file_address = sect->GetLinkedFileAddress();
590 
591         if (linked_file_address != LLDB_INVALID_ADDRESS)
592             m_range_cache.Append(SectionRangeCache::Entry(linked_file_address, sect->GetByteSize(), idx));
593     }
594 
595     m_range_cache.Sort();
596 
597 #ifdef LLDB_CONFIGURATION_DEBUG
598     m_finalized = true;
599 #endif
600 }
601 
602 void
603 SectionList::InvalidateRangeCache() const
604 {
605 #ifdef LLDB_CONFIGURATION_DEBUG
606     assert(!m_finalized);
607 #endif
608     m_range_cache.Clear();
609 }
610 
611 SectionSP
612 SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const
613 {
614     //if (m_range_cache.IsEmpty())
615     //    BuildRangeCache();
616 #ifdef LLDB_CONFIGURATION_DEBUG
617     assert(m_finalized);
618 #endif
619 
620     SectionRangeCache::Entry *entry = m_range_cache.FindEntryThatContains(vm_addr);
621 
622     if (entry)
623         return m_sections[entry->data];
624 
625     if (depth == 0)
626         return SectionSP();
627 
628     for (const_iterator si = m_sections.begin(), se = m_sections.end();
629          si != se;
630          ++si)
631     {
632         Section *sect = si->get();
633 
634         SectionSP sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress(vm_addr, depth - 1);
635 
636         if (sect_sp)
637             return sect_sp;
638     }
639 
640     return SectionSP();
641 }
642 
643 bool
644 SectionList::ContainsSection(user_id_t sect_id) const
645 {
646     return FindSectionByID (sect_id).get() != NULL;
647 }
648 
649 void
650 SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const
651 {
652     bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
653     if (show_header && !m_sections.empty())
654     {
655         s->Indent();
656         s->Printf(    "SectID     Type             %s Address                             File Off.  File Size  Flags      Section Name\n", target_has_loaded_sections ? "Load" : "File");
657         s->Indent();
658         s->PutCString("---------- ---------------- ---------------------------------------  ---------- ---------- ---------- ----------------------------\n");
659     }
660 
661 
662     const_iterator sect_iter;
663     const_iterator end = m_sections.end();
664     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
665     {
666         (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth);
667     }
668 
669     if (show_header && !m_sections.empty())
670         s->IndentLess();
671 
672 }
673 
674 size_t
675 SectionList::Slide (addr_t slide_amount, bool slide_children)
676 {
677     size_t count = 0;
678     const_iterator pos, end = m_sections.end();
679     for (pos = m_sections.begin(); pos != end; ++pos)
680     {
681         if ((*pos)->Slide(slide_amount, slide_children))
682             ++count;
683     }
684     InvalidateRangeCache();
685     return count;
686 }
687 
688 void
689 SectionList::Finalize ()
690 {
691     BuildRangeCache();
692 
693     for (const_iterator si = m_sections.begin(), se = m_sections.end();
694          si != se;
695          ++si)
696     {
697         Section *sect = si->get();
698 
699         sect->GetChildren().Finalize();
700     }
701 }
702 
703