blob: 4b3098068d2303a2a9d11e3fdbe6ae8620f978ff [file] [log] [blame]
Jason Molenda3a4ea242010-09-10 07:49:16 +00001//===-- UnwindTable.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
Greg Clayton412440a2010-09-23 01:09:21 +000010#include "lldb/Symbol/UnwindTable.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000011
Greg Clayton412440a2010-09-23 01:09:21 +000012#include <stdio.h>
13
14#include "lldb/lldb-forward.h"
15
16#include "lldb/Core/Module.h"
17#include "lldb/Core/Section.h"
Greg Claytone2f90642011-01-08 00:05:12 +000018//#include "lldb/Core/StreamFile.h"
Greg Clayton412440a2010-09-23 01:09:21 +000019#include "lldb/Symbol/ObjectFile.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000020#include "lldb/Symbol/FuncUnwinders.h"
21#include "lldb/Symbol/SymbolContext.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000022#include "lldb/Symbol/DWARFCallFrameInfo.h"
Greg Clayton412440a2010-09-23 01:09:21 +000023#include "lldb/Utility/UnwindAssemblyProfiler.h"
Jason Molenda3a4ea242010-09-10 07:49:16 +000024
25// There is one UnwindTable object per ObjectFile.
26// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
27// Each Unwind object has multiple UnwindPlans for different scenarios.
28
29using namespace lldb;
30using namespace lldb_private;
31
Greg Claytone2f90642011-01-08 00:05:12 +000032UnwindTable::UnwindTable (ObjectFile& objfile) :
33 m_object_file (objfile),
34 m_unwinds (),
35 m_initialized (false),
36 m_eh_frame (NULL),
37 m_assembly_profiler (NULL)
Jason Molenda3a4ea242010-09-10 07:49:16 +000038{
39}
40
41// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
42// until needed for something.
43
44void
Greg Claytone2f90642011-01-08 00:05:12 +000045UnwindTable::Initialize ()
Jason Molenda3a4ea242010-09-10 07:49:16 +000046{
47 if (m_initialized)
48 return;
49
50 SectionList* sl = m_object_file.GetSectionList ();
51 if (sl)
52 {
53 SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
54 if (sect.get())
55 {
56 m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
57 }
58 }
59
60 ArchSpec arch;
Greg Clayton395fc332011-02-15 21:59:32 +000061 if (m_object_file.GetArchitecture (arch))
62 {
63 m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch);
64 m_initialized = true;
65 }
Jason Molenda3a4ea242010-09-10 07:49:16 +000066}
67
68UnwindTable::~UnwindTable ()
69{
70 if (m_eh_frame)
71 delete m_eh_frame;
72}
73
74FuncUnwindersSP
75UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
76{
77 FuncUnwindersSP no_unwind_found;
78
Greg Claytone2f90642011-01-08 00:05:12 +000079 Initialize();
Jason Molenda3a4ea242010-09-10 07:49:16 +000080
Greg Claytone2f90642011-01-08 00:05:12 +000081 // There is an UnwindTable per object file, so we can safely use file handles
82 addr_t file_addr = addr.GetFileAddress();
83 iterator end = m_unwinds.end ();
84 iterator insert_pos = end;
85 if (!m_unwinds.empty())
86 {
87 insert_pos = m_unwinds.lower_bound (file_addr);
88 iterator pos = insert_pos;
89 if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
90 --pos;
Jason Molenda3a4ea242010-09-10 07:49:16 +000091
Greg Claytone2f90642011-01-08 00:05:12 +000092 if (pos->second->ContainsAddress (addr))
93 return pos->second;
Jason Molenda3a4ea242010-09-10 07:49:16 +000094 }
95
96 AddressRange range;
Jason Molenda800d11d2010-11-04 00:53:20 +000097 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range) || !range.GetBaseAddress().IsValid())
Jason Molenda3a4ea242010-09-10 07:49:16 +000098 {
Jason Molenda800d11d2010-11-04 00:53:20 +000099 // Does the eh_frame unwind info has a function bounds for this addr?
Jason Molendad6ef16a2010-11-09 01:21:22 +0000100 if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
Jason Molenda3a4ea242010-09-10 07:49:16 +0000101 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000102 return no_unwind_found;
Jason Molenda3a4ea242010-09-10 07:49:16 +0000103 }
104 }
Jason Molenda800d11d2010-11-04 00:53:20 +0000105
Greg Claytone2f90642011-01-08 00:05:12 +0000106 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
107 m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
108// StreamFile s(stdout);
109// Dump (s);
110 return func_unwinder_sp;
111}
112
113void
114UnwindTable::Dump (Stream &s)
115{
116 s.Printf("UnwindTable for %s/%s:\n", m_object_file.GetFileSpec().GetDirectory().GetCString(), m_object_file.GetFileSpec().GetFilename().GetCString());
117 const_iterator begin = m_unwinds.begin();
118 const_iterator end = m_unwinds.end();
119 for (const_iterator pos = begin; pos != end; ++pos)
120 {
121 s.Printf ("[%zu] 0x%16.16llx\n", std::distance (begin, pos), pos->first);
122 }
123 s.EOL();
Jason Molenda3a4ea242010-09-10 07:49:16 +0000124}
125
126DWARFCallFrameInfo *
127UnwindTable::GetEHFrameInfo ()
128{
Greg Claytone2f90642011-01-08 00:05:12 +0000129 Initialize();
Jason Molenda3a4ea242010-09-10 07:49:16 +0000130 return m_eh_frame;
131}