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