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
15using namespace lldb;
16using namespace lldb_private;
17
18Section::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
48Section::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
81Section::~Section()
82{
83//    printf ("Section::~Section(%p)\n", this);
84}
85
86addr_t
87Section::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
101lldb::addr_t
102Section::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
113addr_t
114Section::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
131bool
132Section::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
156bool
157Section::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
171int
172Section::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
200void
201Section::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
237void
238Section::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
263bool
264Section::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
274bool
275Section::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
294SectionList::SectionList () :
295    m_sections()
296{
297}
298
299
300SectionList::~SectionList ()
301{
302}
303
304SectionList &
305SectionList::operator = (const SectionList& rhs)
306{
307    if (this != &rhs)
308        m_sections = rhs.m_sections;
309    return *this;
310}
311
312size_t
313SectionList::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.
322bool
323SectionList::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
333size_t
334SectionList::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
350size_t
351SectionList::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
361bool
362SectionList::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
381size_t
382SectionList::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
396SectionSP
397SectionList::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
405SectionSP
406SectionList::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
431SectionSP
432SectionList::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
456SectionSP
457SectionList::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
478SectionSP
479SectionList::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
502bool
503SectionList::ContainsSection(user_id_t sect_id) const
504{
505    return FindSectionByID (sect_id).get() != NULL;
506}
507
508void
509SectionList::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
533size_t
534SectionList::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