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