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                   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 
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 
81 Section::~Section()
82 {
83 //    printf ("Section::~Section(%p)\n", this);
84 }
85 
86 addr_t
87 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
102 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
114 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
132 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
157 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
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
201 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
238 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
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
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 
294 SectionList::SectionList () :
295     m_changed(false),
296     m_revision_id(0),
297     m_sections()
298 {
299 }
300 
301 
302 SectionList::~SectionList ()
303 {
304 }
305 
306 bool
307 SectionList::Copy (SectionList *dest_section_list)
308 {
309     if (dest_section_list)
310     {
311         dest_section_list->m_sections = m_sections;
312         dest_section_list->m_changed = true;
313         return true;
314     }
315     return false;
316 }
317 
318 size_t
319 SectionList::AddSection (const lldb::SectionSP& section_sp)
320 {
321     m_changed = true;
322     assert (section_sp.get());
323     size_t section_index = m_sections.size();
324     m_sections.push_back(section_sp);
325     return section_index;
326 }
327 
328 // Warning, this can be slow as it's removing items from a std::vector.
329 bool
330 SectionList::DeleteSection (size_t idx)
331 {
332     if (idx < m_sections.size())
333     {
334         m_changed = true;
335         m_sections.erase (m_sections.begin() + idx);
336         return true;
337     }
338     return false;
339 }
340 
341 size_t
342 SectionList::FindSectionIndex (const Section* sect)
343 {
344     iterator sect_iter;
345     iterator begin = m_sections.begin();
346     iterator end = m_sections.end();
347     for (sect_iter = begin; sect_iter != end; ++sect_iter)
348     {
349         if (sect_iter->get() == sect)
350         {
351             // The secton was already in this section list
352             return std::distance (begin, sect_iter);
353         }
354     }
355     return UINT32_MAX;
356 }
357 
358 size_t
359 SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp)
360 {
361     size_t sect_idx = FindSectionIndex (sect_sp.get());
362     if (sect_idx == UINT32_MAX)
363     {
364         m_changed = true;
365         sect_idx = AddSection (sect_sp);
366     }
367     return sect_idx;
368 }
369 
370 bool
371 SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth)
372 {
373     iterator sect_iter, end = m_sections.end();
374     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
375     {
376         if ((*sect_iter)->GetID() == sect_id)
377         {
378             m_changed = true;
379             *sect_iter = sect_sp;
380             return true;
381         }
382         else if (depth > 0)
383         {
384             if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
385                 return true;
386         }
387     }
388     return false;
389 }
390 
391 size_t
392 SectionList::GetNumSections (uint32_t depth) const
393 {
394     size_t count = m_sections.size();
395     if (depth > 0)
396     {
397         const_iterator sect_iter, end = m_sections.end();
398         for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
399         {
400             count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
401         }
402     }
403     return count;
404 }
405 
406 SectionSP
407 SectionList::GetSectionAtIndex (size_t idx) const
408 {
409     SectionSP sect_sp;
410     if (idx < m_sections.size())
411         sect_sp = m_sections[idx];
412     return sect_sp;
413 }
414 
415 SectionSP
416 SectionList::FindSectionByName (const ConstString &section_dstr) const
417 {
418     SectionSP sect_sp;
419     // Check if we have a valid section string
420     if (section_dstr && !m_sections.empty())
421     {
422         const_iterator sect_iter;
423         const_iterator end = m_sections.end();
424         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
425         {
426             Section *child_section = sect_iter->get();
427             assert (child_section);
428             if (child_section->GetName() == section_dstr)
429             {
430                 sect_sp = *sect_iter;
431             }
432             else
433             {
434                 sect_sp = child_section->GetChildren().FindSectionByName(section_dstr);
435             }
436         }
437     }
438     return sect_sp;
439 }
440 
441 SectionSP
442 SectionList::FindSectionByID (user_id_t sect_id) const
443 {
444     SectionSP sect_sp;
445     if (sect_id)
446     {
447         const_iterator sect_iter;
448         const_iterator end = m_sections.end();
449         for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
450         {
451             if ((*sect_iter)->GetID() == sect_id)
452             {
453                 sect_sp = *sect_iter;
454                 break;
455             }
456             else
457             {
458                 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
459             }
460         }
461     }
462     return sect_sp;
463 }
464 
465 
466 SectionSP
467 SectionList::FindSectionByType (SectionType sect_type, bool check_children, size_t start_idx) const
468 {
469     SectionSP sect_sp;
470     size_t num_sections = m_sections.size();
471     for (size_t idx = start_idx; idx < num_sections; ++idx)
472     {
473         if (m_sections[idx]->GetType() == sect_type)
474         {
475             sect_sp = m_sections[idx];
476             break;
477         }
478         else if (check_children)
479         {
480             sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0);
481             if (sect_sp)
482                 break;
483         }
484     }
485     return sect_sp;
486 }
487 
488 SectionSP
489 SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
490 {
491     SectionSP sect_sp;
492     const_iterator sect_iter;
493     const_iterator end = m_sections.end();
494     for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
495     {
496         Section *sect = sect_iter->get();
497         if (sect->ContainsFileAddress (vm_addr))
498         {
499             // The file address is in this section. We need to make sure one of our child
500             // sections doesn't contain this address as well as obeying the depth limit
501             // that was passed in.
502             if (depth > 0)
503                 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
504 
505             if (sect_sp.get() == NULL && !sect->IsFake())
506                 sect_sp = *sect_iter;
507         }
508     }
509     return sect_sp;
510 }
511 
512 bool
513 SectionList::ContainsSection(user_id_t sect_id) const
514 {
515     return FindSectionByID (sect_id).get() != NULL;
516 }
517 
518 void
519 SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const
520 {
521     bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
522     if (show_header && !m_sections.empty())
523     {
524         s->Indent();
525         s->Printf(    "SectID     Type             %s Address                             File Off.  File Size  Flags      Section Name\n", target_has_loaded_sections ? "Load" : "File");
526         s->Indent();
527         s->PutCString("---------- ---------------- ---------------------------------------  ---------- ---------- ---------- ----------------------------\n");
528     }
529 
530 
531     const_iterator sect_iter;
532     const_iterator end = m_sections.end();
533     for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
534     {
535         (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth);
536     }
537 
538     if (show_header && !m_sections.empty())
539         s->IndentLess();
540 
541 }
542 
543 size_t
544 SectionList::Slide (addr_t slide_amount, bool slide_children)
545 {
546     size_t count = 0;
547     const_iterator pos, end = m_sections.end();
548     for (pos = m_sections.begin(); pos != end; ++pos)
549     {
550         if ((*pos)->Slide(slide_amount, slide_children))
551             ++count;
552     }
553     return count;
554 }
555 
556 void
557 SectionList::Finalize ()
558 {
559     for (const_iterator si = m_sections.begin(), se = m_sections.end();
560          si != se;
561          ++si)
562     {
563         Section *sect = si->get();
564 
565         sect->GetChildren().Finalize();
566     }
567 
568     if (m_changed)
569     {
570         m_revision_id++;
571         m_changed = false;
572     }
573 }
574