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 (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 {
383 }
384 
385 
386 SectionList::~SectionList ()
387 {
388 }
389 
390 uint32_t
391 SectionList::AddSection (const lldb::SectionSP& section_sp)
392 {
393     assert (section_sp.get());
394     uint32_t section_index = m_sections.size();
395     m_sections.push_back(section_sp);
396     return section_index;
397 }
398 
399 uint32_t
400 SectionList::FindSectionIndex (const Section* sect)
401 {
402     iterator sect_iter;
403     iterator begin = m_sections.begin();
404     iterator end = m_sections.end();
405     for (sect_iter = begin; sect_iter != end; ++sect_iter)
406     {
407         if (sect_iter->get() == sect)
408         {
409             // The secton was already in this section list
410             return std::distance (begin, sect_iter);
411         }
412     }
413     return UINT32_MAX;
414 }
415 
416 uint32_t
417 SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp)
418 {
419     uint32_t sect_idx = FindSectionIndex (sect_sp.get());
420     if (sect_idx == UINT32_MAX)
421         sect_idx = AddSection (sect_sp);
422     return sect_idx;
423 }
424 
425 
426 bool
427 SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth)
428 {
429     iterator sect_iter, end = m_sections.end();
430     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
431     {
432         if ((*sect_iter)->GetID() == sect_id)
433         {
434             *sect_iter = sect_sp;
435             return true;
436         }
437         else if (depth > 0)
438         {
439             if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
440                 return true;
441         }
442     }
443     return false;
444 }
445 
446 
447 size_t
448 SectionList::GetNumSections (uint32_t depth) const
449 {
450     size_t count = m_sections.size();
451     if (depth > 0)
452     {
453         const_iterator sect_iter, end = m_sections.end();
454         for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
455         {
456             count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
457         }
458     }
459     return count;
460 }
461 
462 SectionSP
463 SectionList::GetSectionAtIndex (uint32_t idx) const
464 {
465     SectionSP sect_sp;
466     if (idx < m_sections.size())
467         sect_sp = m_sections[idx];
468     return sect_sp;
469 }
470 
471 SectionSP
472 SectionList::FindSectionByName (const ConstString &section_dstr) const
473 {
474     SectionSP sect_sp;
475     // Check if we have a valid section string
476     if (section_dstr && !m_sections.empty())
477     {
478         const_iterator sect_iter;
479         const_iterator end = m_sections.end();
480         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
481         {
482             Section *child_section = sect_iter->get();
483             assert (child_section);
484             if (child_section->GetName() == section_dstr)
485             {
486                 sect_sp = *sect_iter;
487             }
488             else
489             {
490                 sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
491             }
492         }
493     }
494     return sect_sp;
495 }
496 
497 SectionSP
498 SectionList::FindSectionByID (user_id_t sect_id) const
499 {
500     SectionSP sect_sp;
501     if (sect_id)
502     {
503         const_iterator sect_iter;
504         const_iterator end = m_sections.end();
505         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
506         {
507             if ((*sect_iter)->GetID() == sect_id)
508             {
509                 sect_sp = *sect_iter;
510                 break;
511             }
512             else
513             {
514                 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
515             }
516         }
517     }
518     return sect_sp;
519 }
520 
521 
522 SectionSP
523 SectionList::FindSectionByType (SectionType sect_type, bool check_children, uint32_t start_idx) const
524 {
525     SectionSP sect_sp;
526     uint32_t num_sections = m_sections.size();
527     for (uint32_t idx = start_idx; idx < num_sections; ++idx)
528     {
529         if (m_sections[idx]->GetType() == sect_type)
530         {
531             sect_sp = m_sections[idx];
532             break;
533         }
534         else if (check_children)
535         {
536             sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0);
537             if (sect_sp)
538                 break;
539         }
540     }
541     return sect_sp;
542 }
543 
544 SectionSP
545 SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
546 {
547     SectionSP sect_sp;
548     const_iterator sect_iter;
549     const_iterator end = m_sections.end();
550     for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
551     {
552         Section *sect = sect_iter->get();
553         if (sect->ContainsFileAddress (vm_addr))
554         {
555             // The file address is in this section. We need to make sure one of our child
556             // sections doesn't contain this address as well as obeying the depth limit
557             // that was passed in.
558             if (depth > 0)
559                 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
560 
561             if (sect_sp.get() == NULL && !sect->IsFake())
562                 sect_sp = *sect_iter;
563         }
564     }
565     return sect_sp;
566 }
567 
568 
569 SectionSP
570 SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const
571 {
572     SectionSP sect_sp;
573     const_iterator sect_iter;
574     const_iterator end = m_sections.end();
575     for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
576     {
577         Section *sect = sect_iter->get();
578         if (sect->ContainsLinkedFileAddress (vm_addr))
579         {
580             sect_sp = *sect_iter;
581         }
582         else if (depth > 0)
583         {
584             sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress (vm_addr, depth - 1);
585         }
586     }
587     return sect_sp;
588 }
589 
590 bool
591 SectionList::ContainsSection(user_id_t sect_id) const
592 {
593     return FindSectionByID (sect_id).get() != NULL;
594 }
595 
596 void
597 SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const
598 {
599     bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
600     if (show_header && !m_sections.empty())
601     {
602         s->Indent();
603         s->Printf(    "SectID     Type             %s Address                             File Off.  File Size  Flags      Section Name\n", target_has_loaded_sections ? "Load" : "File");
604         s->Indent();
605         s->PutCString("---------- ---------------- ---------------------------------------  ---------- ---------- ---------- ----------------------------\n");
606     }
607 
608 
609     const_iterator sect_iter;
610     const_iterator end = m_sections.end();
611     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
612     {
613         (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth);
614     }
615 
616     if (show_header && !m_sections.empty())
617         s->IndentLess();
618 
619 }
620 
621 size_t
622 SectionList::Slide (addr_t slide_amount, bool slide_children)
623 {
624     size_t count = 0;
625     const_iterator pos, end = m_sections.end();
626     for (pos = m_sections.begin(); pos != end; ++pos)
627     {
628         if ((*pos)->Slide(slide_amount, slide_children))
629             ++count;
630     }
631     return count;
632 }
633 
634