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