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