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