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     return true;
189 }
190 
191 bool
192 Section::ContainsFileAddress (addr_t vm_addr) const
193 {
194     const addr_t file_addr = GetFileAddress();
195     if (file_addr != LLDB_INVALID_ADDRESS)
196     {
197         if (file_addr <= vm_addr)
198         {
199             const addr_t offset = vm_addr - file_addr;
200             return offset < GetByteSize();
201         }
202     }
203     return false;
204 }
205 
206 bool
207 Section::ContainsLinkedFileAddress (addr_t vm_addr) const
208 {
209     const addr_t linked_file_addr = GetLinkedFileAddress();
210     if (linked_file_addr != LLDB_INVALID_ADDRESS)
211     {
212         if (linked_file_addr <= vm_addr)
213         {
214             const addr_t offset = vm_addr - linked_file_addr;
215             return offset < GetByteSize();
216         }
217     }
218     return false;
219 }
220 
221 int
222 Section::Compare (const Section& a, const Section& b)
223 {
224     if (&a == &b)
225         return 0;
226 
227     const ModuleSP a_module_sp = a.GetModule();
228     const ModuleSP b_module_sp = b.GetModule();
229     if (a_module_sp == b_module_sp)
230     {
231         user_id_t a_sect_uid = a.GetID();
232         user_id_t b_sect_uid = b.GetID();
233         if (a_sect_uid < b_sect_uid)
234             return -1;
235         if (a_sect_uid > b_sect_uid)
236             return 1;
237         return 0;
238     }
239     else
240     {
241         // The modules are different, just compare the module pointers
242         if (a_module_sp.get() < b_module_sp.get())
243             return -1;
244         else
245             return 1;   // We already know the modules aren't equal
246     }
247 }
248 
249 
250 void
251 Section::Dump (Stream *s, Target *target, uint32_t depth) const
252 {
253 //    s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
254     s->Indent();
255     s->Printf("0x%8.8llx %-16s ", GetID(), GetSectionTypeAsCString (m_type));
256     bool resolved = true;
257     addr_t addr = LLDB_INVALID_ADDRESS;
258 
259     SectionSP linked_section_sp (m_linked_section_wp.lock());
260     if (GetByteSize() == 0)
261         s->Printf("%39s", "");
262     else
263     {
264         if (target && linked_section_sp.get() == NULL)
265             addr = GetLoadBaseAddress (target);
266 
267         if (addr == LLDB_INVALID_ADDRESS)
268         {
269             if (target)
270                 resolved = false;
271             addr = GetFileAddress();
272         }
273 
274         VMRange range(addr, addr + m_byte_size);
275         range.Dump (s, 0);
276     }
277 
278     s->Printf("%c 0x%8.8llx 0x%8.8llx 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get());
279 
280     DumpName (s);
281 
282     s->EOL();
283 
284     if (linked_section_sp)
285     {
286         addr = LLDB_INVALID_ADDRESS;
287         resolved = true;
288         if (target)
289         {
290             addr = linked_section_sp->GetLoadBaseAddress(target);
291             if (addr != LLDB_INVALID_ADDRESS)
292                 addr += m_linked_offset;
293         }
294 
295         if (addr == LLDB_INVALID_ADDRESS)
296         {
297             if (target)
298                 resolved = false;
299             addr = linked_section_sp->GetFileAddress() + m_linked_offset;
300         }
301 
302         int indent = 26 + s->GetIndentLevel();
303         s->Printf("%*.*s", indent, indent, "");
304         VMRange linked_range(addr, addr + m_byte_size);
305         linked_range.Dump (s, 0);
306         indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
307         s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
308 
309         linked_section_sp->DumpName(s);
310         s->Printf(" + 0x%llx\n", m_linked_offset);
311     }
312 
313     if (depth > 0)
314         m_children.Dump(s, target, false, depth - 1);
315 }
316 
317 void
318 Section::DumpName (Stream *s) const
319 {
320     SectionSP parent_sp (GetParent ());
321     if (parent_sp)
322     {
323         parent_sp->DumpName (s);
324         s->PutChar('.');
325     }
326     else
327     {
328         // The top most section prints the module basename
329         ModuleSP module_sp (GetModule());
330         if (module_sp)
331         {
332             const char *module_basename = module_sp->GetFileSpec().GetFilename().AsCString();
333             if (module_basename && module_basename[0])
334                 s->Printf("%s.", module_basename);
335         }
336     }
337     m_name.Dump(s);
338 }
339 
340 bool
341 Section::IsDescendant (const Section *section)
342 {
343     if (this == section)
344         return true;
345     SectionSP parent_sp (GetParent ());
346     if (parent_sp)
347         return parent_sp->IsDescendant (section);
348     return false;
349 }
350 
351 bool
352 Section::Slide (addr_t slide_amount, bool slide_children)
353 {
354     if (m_file_addr != LLDB_INVALID_ADDRESS)
355     {
356         if (slide_amount == 0)
357             return true;
358 
359         m_file_addr += slide_amount;
360 
361         if (slide_children)
362             m_children.Slide (slide_amount, slide_children);
363 
364         return true;
365     }
366     return false;
367 }
368 
369 void
370 Section::SetLinkedLocation (const lldb::SectionSP &linked_section_sp, uint64_t linked_offset)
371 {
372     if (linked_section_sp)
373         m_module_wp = linked_section_sp->GetModule();
374     m_linked_section_wp = linked_section_sp;
375     m_linked_offset  = linked_offset;
376 }
377 
378 #pragma mark SectionList
379 
380 SectionList::SectionList () :
381     m_sections()
382 #ifdef LLDB_CONFIGURATION_DEBUG
383     , m_finalized(false)
384 #endif
385 {
386 }
387 
388 
389 SectionList::~SectionList ()
390 {
391 }
392 
393 uint32_t
394 SectionList::AddSection (const lldb::SectionSP& section_sp)
395 {
396     assert (section_sp.get());
397     uint32_t section_index = m_sections.size();
398     m_sections.push_back(section_sp);
399     InvalidateRangeCache();
400     return section_index;
401 }
402 
403 uint32_t
404 SectionList::FindSectionIndex (const Section* sect)
405 {
406     iterator sect_iter;
407     iterator begin = m_sections.begin();
408     iterator end = m_sections.end();
409     for (sect_iter = begin; sect_iter != end; ++sect_iter)
410     {
411         if (sect_iter->get() == sect)
412         {
413             // The secton was already in this section list
414             return std::distance (begin, sect_iter);
415         }
416     }
417     return UINT32_MAX;
418 }
419 
420 uint32_t
421 SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp)
422 {
423     uint32_t sect_idx = FindSectionIndex (sect_sp.get());
424     if (sect_idx == UINT32_MAX)
425         sect_idx = AddSection (sect_sp);
426     return sect_idx;
427 }
428 
429 
430 bool
431 SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth)
432 {
433     iterator sect_iter, end = m_sections.end();
434     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
435     {
436         if ((*sect_iter)->GetID() == sect_id)
437         {
438             *sect_iter = sect_sp;
439             InvalidateRangeCache();
440             return true;
441         }
442         else if (depth > 0)
443         {
444             if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
445                 return true;
446         }
447     }
448     return false;
449 }
450 
451 
452 size_t
453 SectionList::GetNumSections (uint32_t depth) const
454 {
455     size_t count = m_sections.size();
456     if (depth > 0)
457     {
458         const_iterator sect_iter, end = m_sections.end();
459         for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
460         {
461             count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
462         }
463     }
464     return count;
465 }
466 
467 SectionSP
468 SectionList::GetSectionAtIndex (uint32_t idx) const
469 {
470     SectionSP sect_sp;
471     if (idx < m_sections.size())
472         sect_sp = m_sections[idx];
473     return sect_sp;
474 }
475 
476 SectionSP
477 SectionList::FindSectionByName (const ConstString &section_dstr) const
478 {
479     SectionSP sect_sp;
480     // Check if we have a valid section string
481     if (section_dstr && !m_sections.empty())
482     {
483         const_iterator sect_iter;
484         const_iterator end = m_sections.end();
485         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
486         {
487             Section *child_section = sect_iter->get();
488             assert (child_section);
489             if (child_section->GetName() == section_dstr)
490             {
491                 sect_sp = *sect_iter;
492             }
493             else
494             {
495                 sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
496             }
497         }
498     }
499     return sect_sp;
500 }
501 
502 SectionSP
503 SectionList::FindSectionByID (user_id_t sect_id) const
504 {
505     SectionSP sect_sp;
506     if (sect_id)
507     {
508         const_iterator sect_iter;
509         const_iterator end = m_sections.end();
510         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
511         {
512             if ((*sect_iter)->GetID() == sect_id)
513             {
514                 sect_sp = *sect_iter;
515                 break;
516             }
517             else
518             {
519                 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
520             }
521         }
522     }
523     return sect_sp;
524 }
525 
526 
527 SectionSP
528 SectionList::FindSectionByType (SectionType sect_type, bool check_children, uint32_t start_idx) const
529 {
530     SectionSP sect_sp;
531     uint32_t num_sections = m_sections.size();
532     for (uint32_t idx = start_idx; idx < num_sections; ++idx)
533     {
534         if (m_sections[idx]->GetType() == sect_type)
535         {
536             sect_sp = m_sections[idx];
537             break;
538         }
539         else if (check_children)
540         {
541             sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0);
542             if (sect_sp)
543                 break;
544         }
545     }
546     return sect_sp;
547 }
548 
549 SectionSP
550 SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
551 {
552     SectionSP sect_sp;
553     const_iterator sect_iter;
554     const_iterator end = m_sections.end();
555     for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
556     {
557         Section *sect = sect_iter->get();
558         if (sect->ContainsFileAddress (vm_addr))
559         {
560             // The file address is in this section. We need to make sure one of our child
561             // sections doesn't contain this address as well as obeying the depth limit
562             // that was passed in.
563             if (depth > 0)
564                 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
565 
566             if (sect_sp.get() == NULL && !sect->IsFake())
567                 sect_sp = *sect_iter;
568         }
569     }
570     return sect_sp;
571 }
572 
573 void
574 SectionList::BuildRangeCache() const
575 {
576     m_range_cache.Clear();
577 
578     for (collection::size_type idx = 0, last_idx = m_sections.size();
579          idx < last_idx;
580          ++idx)
581     {
582         Section *sect = m_sections[idx].get();
583 
584         addr_t linked_file_address = sect->GetLinkedFileAddress();
585 
586         if (linked_file_address != LLDB_INVALID_ADDRESS)
587             m_range_cache.Append(SectionRangeCache::Entry(linked_file_address, sect->GetByteSize(), idx));
588     }
589 
590     m_range_cache.Sort();
591 
592 #ifdef LLDB_CONFIGURATION_DEBUG
593     m_finalized = true;
594 #endif
595 }
596 
597 void
598 SectionList::InvalidateRangeCache() const
599 {
600 #ifdef LLDB_CONFIGURATION_DEBUG
601     assert(!m_finalized);
602 #endif
603     m_range_cache.Clear();
604 }
605 
606 SectionSP
607 SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const
608 {
609     //if (m_range_cache.IsEmpty())
610     //    BuildRangeCache();
611 #ifdef LLDB_CONFIGURATION_DEBUG
612     assert(m_finalized);
613 #endif
614 
615     SectionRangeCache::Entry *entry = m_range_cache.FindEntryThatContains(vm_addr);
616 
617     if (entry)
618         return m_sections[entry->data];
619 
620     if (depth == 0)
621         return SectionSP();
622 
623     for (const_iterator si = m_sections.begin(), se = m_sections.end();
624          si != se;
625          ++si)
626     {
627         Section *sect = si->get();
628 
629         SectionSP sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress(vm_addr, depth - 1);
630 
631         if (sect_sp)
632             return sect_sp;
633     }
634 
635     return SectionSP();
636 }
637 
638 bool
639 SectionList::ContainsSection(user_id_t sect_id) const
640 {
641     return FindSectionByID (sect_id).get() != NULL;
642 }
643 
644 void
645 SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const
646 {
647     bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
648     if (show_header && !m_sections.empty())
649     {
650         s->Indent();
651         s->Printf(    "SectID     Type             %s Address                             File Off.  File Size  Flags      Section Name\n", target_has_loaded_sections ? "Load" : "File");
652         s->Indent();
653         s->PutCString("---------- ---------------- ---------------------------------------  ---------- ---------- ---------- ----------------------------\n");
654     }
655 
656 
657     const_iterator sect_iter;
658     const_iterator end = m_sections.end();
659     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
660     {
661         (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth);
662     }
663 
664     if (show_header && !m_sections.empty())
665         s->IndentLess();
666 
667 }
668 
669 size_t
670 SectionList::Slide (addr_t slide_amount, bool slide_children)
671 {
672     size_t count = 0;
673     const_iterator pos, end = m_sections.end();
674     for (pos = m_sections.begin(); pos != end; ++pos)
675     {
676         if ((*pos)->Slide(slide_amount, slide_children))
677             ++count;
678     }
679     InvalidateRangeCache();
680     return count;
681 }
682 
683 void
684 SectionList::Finalize ()
685 {
686     BuildRangeCache();
687 
688     for (const_iterator si = m_sections.begin(), se = m_sections.end();
689          si != se;
690          ++si)
691     {
692         Section *sect = si->get();
693 
694         sect->GetChildren().Finalize();
695     }
696 }
697 
698