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