blob: 697098d5e3ce7c8f107596c7208293f546bbcb1a [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;
61 ConstString str;
62 m_object_file.GetTargetTriple (str);
63 arch.SetArchFromTargetTriple (str.GetCString());
64 m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch);
65
66 m_initialized = true;
67}
68
69UnwindTable::~UnwindTable ()
70{
71 if (m_eh_frame)
72 delete m_eh_frame;
73}
74
75FuncUnwindersSP
76UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
77{
78 FuncUnwindersSP no_unwind_found;
79
Greg Claytone2f90642011-01-08 00:05:12 +000080 Initialize();
Jason Molenda3a4ea242010-09-10 07:49:16 +000081
Greg Claytone2f90642011-01-08 00:05:12 +000082 // There is an UnwindTable per object file, so we can safely use file handles
83 addr_t file_addr = addr.GetFileAddress();
84 iterator end = m_unwinds.end ();
85 iterator insert_pos = end;
86 if (!m_unwinds.empty())
87 {
88 insert_pos = m_unwinds.lower_bound (file_addr);
89 iterator pos = insert_pos;
90 if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
91 --pos;
Jason Molenda3a4ea242010-09-10 07:49:16 +000092
Greg Claytone2f90642011-01-08 00:05:12 +000093 if (pos->second->ContainsAddress (addr))
94 return pos->second;
Jason Molenda3a4ea242010-09-10 07:49:16 +000095 }
96
97 AddressRange range;
Jason Molenda800d11d2010-11-04 00:53:20 +000098 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range) || !range.GetBaseAddress().IsValid())
Jason Molenda3a4ea242010-09-10 07:49:16 +000099 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000100 // Does the eh_frame unwind info has a function bounds for this addr?
Jason Molendad6ef16a2010-11-09 01:21:22 +0000101 if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
Jason Molenda3a4ea242010-09-10 07:49:16 +0000102 {
Jason Molenda800d11d2010-11-04 00:53:20 +0000103 return no_unwind_found;
Jason Molenda3a4ea242010-09-10 07:49:16 +0000104 }
105 }
Jason Molenda800d11d2010-11-04 00:53:20 +0000106
Greg Claytone2f90642011-01-08 00:05:12 +0000107 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
108 m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
109// StreamFile s(stdout);
110// Dump (s);
111 return func_unwinder_sp;
112}
113
114void
115UnwindTable::Dump (Stream &s)
116{
117 s.Printf("UnwindTable for %s/%s:\n", m_object_file.GetFileSpec().GetDirectory().GetCString(), m_object_file.GetFileSpec().GetFilename().GetCString());
118 const_iterator begin = m_unwinds.begin();
119 const_iterator end = m_unwinds.end();
120 for (const_iterator pos = begin; pos != end; ++pos)
121 {
122 s.Printf ("[%zu] 0x%16.16llx\n", std::distance (begin, pos), pos->first);
123 }
124 s.EOL();
Jason Molenda3a4ea242010-09-10 07:49:16 +0000125}
126
127DWARFCallFrameInfo *
128UnwindTable::GetEHFrameInfo ()
129{
Greg Claytone2f90642011-01-08 00:05:12 +0000130 Initialize();
Jason Molenda3a4ea242010-09-10 07:49:16 +0000131 return m_eh_frame;
132}