blob: 57c519918f23cc581a7aa83b6ed0cad51081da25 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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/Process.h"
14
15using namespace lldb;
16using namespace lldb_private;
17
18Section::Section
19(
20 Section *parent,
21 Module* module,
22 user_id_t sect_id,
23 const ConstString &name,
24 SectionType sect_type,
25 addr_t file_addr,
26 addr_t byte_size,
27 uint64_t file_offset,
28 uint64_t file_size,
29 uint32_t flags
30) :
31 ModuleChild (module),
32 UserID (sect_id),
33 Flags (flags),
34 m_parent (parent),
35 m_name (name),
36 m_type (sect_type),
37 m_file_addr (file_addr),
38 m_byte_size (byte_size),
39 m_file_offset (file_offset),
40 m_file_size (file_size),
41 m_children (),
42 m_fake (false),
43 m_linked_section(NULL),
44 m_linked_offset (0)
45{
46}
47
48//Section::Section
49//(
50// Section *parent,
51// Module* module,
52// user_id_t sect_id,
53// const ConstString &name,
54// const AddressRange *file_vm_range,
55// uint64_t file_offset,
56// uint64_t file_size,
57// uint32_t flags
58//) :
59// ModuleChild (module),
60// UserID (sect_id),
61// Flags (flags),
62// m_parent (parent),
63// m_name (name),
64// m_range (),
65// m_file_offset (file_offset),
66// m_file_size (file_size),
67// m_children (),
68// m_fake (false)
69//{
70// if (file_vm_range)
71// m_range = *file_vm_range;
72//}
73
74Section::~Section()
75{
76}
77
78
79// Get a valid shared pointer to this section object
80SectionSP
81Section::GetSharedPointer() const
82{
83 SectionSP this_sp;
84 if (m_parent)
85 this_sp = m_parent->GetChildren().GetSharedPointer (this, false);
86 else
87 {
88 ObjectFile *objfile = m_module->GetObjectFile();
89 if (objfile)
90 {
91 SectionList *section_list = objfile->GetSectionList();
92 if (section_list)
93 this_sp = section_list->GetSharedPointer (this, false);
94 }
95 }
96 return this_sp;
97}
98
99
100
101ConstString&
102Section::GetName()
103{
104 if (m_linked_section)
105 return const_cast<Section *>(m_linked_section)->GetName();
106 return m_name;
107}
108
109const ConstString&
110Section::GetName() const
111{
112 if (m_linked_section)
113 return m_linked_section->GetName();
114 return m_name;
115}
116
117SectionList&
118Section::GetChildren()
119{
120 return m_children;
121}
122
123const SectionList&
124Section::GetChildren() const
125{
126 return m_children;
127}
128
129addr_t
130Section::GetFileAddress () const
131{
132 if (m_parent)
133 {
134 // This section has a parent which means m_file_addr is an offset into
135 // the parent section, so the file address for this section is the file
136 // address of the parent plus the offset
137 return m_parent->GetFileAddress() + m_file_addr;
138 }
139 // This section has no parent, so m_file_addr is the file base address
140 return m_file_addr;
141}
142
143addr_t
144Section::GetLinkedFileAddress () const
145{
146 if (m_linked_section)
147 return m_linked_section->GetFileAddress() + m_linked_offset;
148 return LLDB_INVALID_ADDRESS;
149}
150
151addr_t
152Section::GetOffset () const
153{
154 if (m_parent)
155 {
156 // This section has a parent which means m_file_addr is an offset.
157 return m_file_addr;
158 }
159
160 // This section has no parent, so there is no offset to be had
161 return 0;
162}
163
164addr_t
165Section::GetByteSize () const
166{
167 return m_byte_size;
168}
169
170void
171Section::SetByteSize (addr_t byte_size)
172{
173 m_byte_size = byte_size;
174}
175
176
177addr_t
178Section::GetLoadBaseAddress (Process *process) const
179{
180 addr_t load_base_addr = LLDB_INVALID_ADDRESS;
181 if (m_linked_section)
182 {
183 load_base_addr = m_linked_section->GetLoadBaseAddress(process) + m_linked_offset;
184 }
185 else
186 if (m_parent)
187 {
188 load_base_addr = m_parent->GetLoadBaseAddress (process);
189 if (load_base_addr != LLDB_INVALID_ADDRESS)
190 load_base_addr += GetOffset();
191 }
192 else
193 {
194 load_base_addr = process->GetSectionLoadAddress(this);
195 }
196
197 return load_base_addr;
198}
199
200bool
201Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
202{
203 const uint32_t num_children = m_children.GetSize();
204 if (num_children > 0)
205 {
206 for (uint32_t i=0; i<num_children; i++)
207 {
208 Section* child_section = m_children.GetSectionAtIndex (i).get();
209
210 addr_t child_offset = child_section->GetOffset();
211 if (child_offset <= offset && offset - child_offset < child_section->GetByteSize())
212 return child_section->ResolveContainedAddress (offset - child_offset, so_addr);
213 }
214 }
215 if (m_linked_section)
216 {
217 so_addr.SetOffset(m_linked_offset + offset);
218 so_addr.SetSection(m_linked_section);
219 }
220 else
221 {
222 so_addr.SetOffset(offset);
223 so_addr.SetSection(this);
224 }
225 return true;
226}
227
228uint64_t
229Section::GetFileOffset() const
230{
231 return m_file_offset;
232}
233
234uint64_t
235Section::GetFileSize() const
236{
237 return m_file_size;
238}
239
240bool
241Section::ContainsFileAddress (addr_t vm_addr) const
242{
243 const addr_t file_addr = GetFileAddress();
244 if (file_addr != LLDB_INVALID_ADDRESS)
245 {
246 if (file_addr <= vm_addr)
247 {
248 const addr_t offset = vm_addr - file_addr;
249 return offset < GetByteSize();
250 }
251 }
252 return false;
253}
254
255bool
256Section::ContainsLinkedFileAddress (addr_t vm_addr) const
257{
258 const addr_t linked_file_addr = GetLinkedFileAddress();
259 if (linked_file_addr != LLDB_INVALID_ADDRESS)
260 {
261 if (linked_file_addr <= vm_addr)
262 {
263 const addr_t offset = vm_addr - linked_file_addr;
264 return offset < GetByteSize();
265 }
266 }
267 return false;
268}
269
270int
271Section::Compare (const Section& a, const Section& b)
272{
273 if (&a == &b)
274 return 0;
275
276 const Module* a_module = a.GetModule();
277 const Module* b_module = b.GetModule();
278 if (a_module == b_module)
279 {
280 user_id_t a_sect_uid = a.GetID();
281 user_id_t b_sect_uid = b.GetID();
282 if (a_sect_uid < b_sect_uid)
283 return -1;
284 if (a_sect_uid > b_sect_uid)
285 return 1;
286 return 0;
287 }
288 else
289 {
290 // The modules are different, just compare the module pointers
291 if (a_module < b_module)
292 return -1;
293 else
294 return 1; // We already know the modules aren't equal
295 }
296}
297
298
299void
300Section::Dump(Stream *s, Process *process) const
301{
302 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
303 s->Indent();
304 s->Printf("0x%8.8x ", GetID());
305 bool resolved = true;
306 addr_t addr = LLDB_INVALID_ADDRESS;
307
308 if (GetByteSize() == 0)
309 s->Printf("%39s", "");
310 else
311 {
312 if (process)
313 addr = GetLoadBaseAddress (process);
314
315 if (addr == LLDB_INVALID_ADDRESS)
316 {
317 if (process)
318 resolved = false;
319 addr = GetFileAddress();
320 }
321
322 VMRange range(addr, addr + m_byte_size);
323 range.Dump (s, 0);
324 }
325
326 s->Printf("%c 0x%8.8llx 0x%8.8llx 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, GetAllFlagBits());
327
328 DumpName (s);
329
330 s->EOL();
331
332 if (m_linked_section)
333 {
334 addr = LLDB_INVALID_ADDRESS;
335
336 if (process)
337 {
338 addr = m_linked_section->GetLoadBaseAddress(process);
339 if (addr != LLDB_INVALID_ADDRESS)
340 addr += m_linked_offset;
341 }
342
343 if (addr == LLDB_INVALID_ADDRESS)
344 {
345 if (process)
346 resolved = false;
347 addr = m_linked_section->GetFileAddress() + m_linked_offset;
348 }
349
350 int indent = (sizeof(void*) + 1 + sizeof(user_id_t) + 1) * 2 + 3 + s->GetIndentLevel();
351 s->Printf("%*.*s", indent, indent, "");
352 VMRange linked_range(addr, addr + m_byte_size);
353 linked_range.Dump (s, 0);
354 indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
355 s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
356
357 m_linked_section->DumpName(s);
358 s->Printf(" + 0x%llx\n", m_linked_offset);
359 }
360
361 m_children.Dump(s, process, false);
362}
363
364void
365Section::DumpName (Stream *s) const
366{
367 if (m_linked_section)
368 return m_linked_section->DumpName(s);
369 else if (m_parent == NULL)
370 {
371 // The top most section prints the module basename
372 const char *module_basename = m_module->GetFileSpec().GetFilename().AsCString();
373 if (module_basename && module_basename[0])
374 s->Printf("%s.", module_basename);
375 }
376 else
377 {
378 m_parent->DumpName (s);
379 s->PutChar('.');
380 }
381 m_name.Dump(s);
382}
383
384//----------------------------------------------------------------------
385// Get the section data from a complete contiguous copy of the
386// entire executable image.
387//----------------------------------------------------------------------
388size_t
389Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const
390{
391 size_t file_size = GetByteSize();
392 if (file_size > 0)
393 {
394 off_t file_offset = GetFileOffset();
395 if (section_data.SetData (image_data, file_offset, file_size) == file_size)
396 return true;
397 }
398 return false;
399}
400
401//----------------------------------------------------------------------
402// Get the section data the file on disk
403//----------------------------------------------------------------------
404size_t
405Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
406{
407 if (objfile == NULL)
408 return 0;
409
410 const FileSpec& file = objfile->GetFileSpec();
411
412 if (file)
413 {
414 size_t section_file_size = GetByteSize();
415 if (section_file_size > 0)
416 {
417 off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
418 DataBufferSP sectionDataSP(file.ReadFileContents(section_file_offset, section_file_size));
419
420 section_data.SetByteOrder(objfile->GetByteOrder());
421 section_data.SetAddressByteSize(objfile->GetAddressByteSize());
422 return section_data.SetData (sectionDataSP);
423 }
424 }
425 return 0;
426}
427
428size_t
429Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
430{
431 if (objfile == NULL)
432 return 0;
433
434 const FileSpec& file = objfile->GetFileSpec();
435
436 if (file)
437 {
438 size_t section_file_size = GetFileSize();
439 if (section_file_size > 0)
440 {
441 off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
442 DataBufferSP sectionDataSP(file.MemoryMapFileContents(section_file_offset, section_file_size));
443 section_data.SetByteOrder(objfile->GetByteOrder());
444 section_data.SetAddressByteSize(objfile->GetAddressByteSize());
445 return section_data.SetData (sectionDataSP);
446 }
447 }
448 return 0;
449}
450
451bool
452Section::IsFake() const
453{
454 return m_fake;
455}
456
457void
458Section::SetIsFake(bool fake)
459{
460 m_fake = fake;
461}
462
463
464bool
465Section::IsDescendant (const Section *section)
466{
467 if (this == section)
468 return true;
469 if (m_parent)
470 return m_parent->IsDescendant (section);
471 return false;
472}
473
474bool
475Section::Slide (addr_t slide_amount, bool slide_children)
476{
477 if (m_file_addr != LLDB_INVALID_ADDRESS)
478 {
479 if (slide_amount == 0)
480 return true;
481
482 m_file_addr += slide_amount;
483
484 if (slide_children)
485 m_children.Slide (slide_amount, slide_children);
486
487 return true;
488 }
489 return false;
490}
491
492void
493Section::SetLinkedLocation (const Section *linked_section, uint64_t linked_offset)
494{
495 if (linked_section)
496 m_module = linked_section->GetModule();
497 m_linked_section = linked_section;
498 m_linked_offset = linked_offset;
499}
500
501const Section *
502Section::GetLinkedSection () const
503{
504 return m_linked_section;
505}
506
507uint64_t
508Section::GetLinkedOffset () const
509{
510 return m_linked_offset;
511}
512
513#pragma mark SectionList
514
515SectionList::SectionList () :
516 m_sections()
517{
518}
519
520
521SectionList::~SectionList ()
522{
523}
524
525uint32_t
526SectionList::AddSection (SectionSP& sect_sp)
527{
528 uint32_t section_index = m_sections.size();
529 m_sections.push_back(sect_sp);
530 return section_index;
531}
532
533uint32_t
534SectionList::FindSectionIndex (const Section* sect)
535{
536 iterator sect_iter;
537 iterator begin = m_sections.begin();
538 iterator end = m_sections.end();
539 for (sect_iter = begin; sect_iter != end; ++sect_iter)
540 {
541 if (sect_iter->get() == sect)
542 {
543 // The secton was already in this section list
544 return std::distance (begin, sect_iter);
545 }
546 }
547 return UINT32_MAX;
548}
549
550uint32_t
551SectionList::AddUniqueSection (SectionSP& sect_sp)
552{
553 uint32_t sect_idx = FindSectionIndex (sect_sp.get());
554 if (sect_idx == UINT32_MAX)
555 sect_idx = AddSection (sect_sp);
556 return sect_idx;
557}
558
559
560bool
561SectionList::ReplaceSection (user_id_t sect_id, SectionSP& sect_sp, uint32_t depth)
562{
563 iterator sect_iter, end = m_sections.end();
564 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
565 {
566 if ((*sect_iter)->GetID() == sect_id)
567 {
568 *sect_iter = sect_sp;
569 return true;
570 }
571 else if (depth > 0)
572 {
573 if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
574 return true;
575 }
576 }
577 return false;
578}
579
580
581size_t
582SectionList::GetSize () const
583{
584 return m_sections.size();
585}
586
587size_t
588SectionList::GetNumSections (uint32_t depth) const
589{
590 size_t count = m_sections.size();
591 if (depth > 0)
592 {
593 const_iterator sect_iter, end = m_sections.end();
594 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
595 {
596 count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
597 }
598 }
599 return count;
600}
601
602SectionSP
603SectionList::GetSectionAtIndex (uint32_t idx) const
604{
605 SectionSP sect_sp;
606 if (idx < m_sections.size())
607 sect_sp = m_sections[idx];
608 return sect_sp;
609}
610
611SectionSP
612SectionList::FindSectionByName (const ConstString &section_dstr) const
613{
614 SectionSP sect_sp;
615 // Check if we have a valid section string
616 if (section_dstr)
617 {
618 const_iterator sect_iter;
619 const_iterator end = m_sections.end();
620 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
621 {
622 if ((*sect_iter)->GetName() == section_dstr)
623 {
624 sect_sp = *sect_iter;
625 }
626 else
627 {
628 sect_sp = (*sect_iter)->GetChildren().FindSectionByName(section_dstr);
629 }
630 }
631 }
632 return sect_sp;
633}
634//
635//SectionSP
636//SectionList::FindSectionByNames (const char *s, ...) const
637//{
638// SectionSP sect_sp;
639// va_list ap;
640// va_start(ap, s);
641// uint32_t idx = 0;
642// for (const char *sect_name = s; sect_name != NULL; sect_name = va_arg(ap, const char *))
643// {
644// printf("[%u] %s\n", idx++, sect_name);
645// }
646// va_end(ap);
647// return sect_sp;
648//}
649
650SectionSP
651SectionList::FindSectionByID (user_id_t sect_id) const
652{
653 SectionSP sect_sp;
654 if (sect_id)
655 {
656 const_iterator sect_iter;
657 const_iterator end = m_sections.end();
658 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
659 {
660 if ((*sect_iter)->GetID() == sect_id)
661 {
662 sect_sp = *sect_iter;
663 break;
664 }
665 else
666 {
667 sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
668 }
669 }
670 }
671 return sect_sp;
672}
673
674SectionSP
675SectionList::GetSharedPointer (const Section *section, bool check_children) const
676{
677 SectionSP sect_sp;
678 if (section)
679 {
680 const_iterator sect_iter;
681 const_iterator end = m_sections.end();
682 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
683 {
684 if (sect_iter->get() == section)
685 {
686 sect_sp = *sect_iter;
687 break;
688 }
689 else if (check_children)
690 {
691 sect_sp = (*sect_iter)->GetChildren().GetSharedPointer (section, true);
692 }
693 }
694 }
695 return sect_sp;
696}
697
698
699
700SectionSP
701SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
702{
703 SectionSP sect_sp;
704 const_iterator sect_iter;
705 const_iterator end = m_sections.end();
706 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
707 {
708 Section *sect = sect_iter->get();
709 if (sect->ContainsFileAddress (vm_addr))
710 {
711 // The file address is in this section. We need to make sure one of our child
712 // sections doesn't contain this address as well as obeying the depth limit
713 // that was passed in.
714 if (depth > 0)
715 sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
716
717 if (sect_sp.get() == NULL && !sect->IsFake())
718 sect_sp = *sect_iter;
719 }
720 }
721 return sect_sp;
722}
723
724
725SectionSP
726SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr) const
727{
728 SectionSP sect_sp;
729 const_iterator sect_iter;
730 const_iterator end = m_sections.end();
731 for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
732 {
733 Section *sect = sect_iter->get();
734 if (sect->ContainsLinkedFileAddress (vm_addr))
735 {
736 sect_sp = *sect_iter;
737 break;
738 }
739 }
740 return sect_sp;
741}
742
743bool
744SectionList::ContainsSection(user_id_t sect_id) const
745{
746 return FindSectionByID (sect_id).get() != NULL;
747}
748
749void
750SectionList::Dump (Stream *s, Process *process, bool show_header) const
751{
752 if (show_header && !m_sections.empty())
753 {
754 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
755 s->Indent();
756 s->PutCString( "SectionList\n");
757 s->IndentMore();
758 s->Printf("%*s", 2*(sizeof(void *) + 2), "");
759 s->Indent();
760 s->Printf("SectID %s Address File Off. File Size Flags Section Name\n", process ? "Load" : "File");
761 s->Printf("%*s", 2*(sizeof(void *) + 2), "");
762 s->Indent();
763 s->PutCString("---------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n");
764 }
765
766
767 const_iterator sect_iter;
768 const_iterator end = m_sections.end();
769 for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
770 {
771 (*sect_iter)->Dump(s, process);
772 }
773
774 if (show_header && !m_sections.empty())
775 s->IndentLess();
776
777}
778
779size_t
780SectionList::Slide (addr_t slide_amount, bool slide_children)
781{
782 size_t count = 0;
783 const_iterator pos, end = m_sections.end();
784 for (pos = m_sections.begin(); pos != end; ++pos)
785 {
786 if ((*pos)->Slide(slide_amount, slide_children))
787 ++count;
788 }
789 return count;
790}
791