blob: 6d4c345e28e2f887a5d94b0951e7ef2e5ac7e355 [file] [log] [blame]
Jason Molenda8280cbe2010-10-25 11:12:07 +00001//===-- UnwindLLDB.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/Target/Thread.h"
11#include "lldb/Target/Target.h"
12#include "lldb/Target/Process.h"
13#include "lldb/Target/RegisterContext.h"
14#include "lldb/Core/Module.h"
15#include "lldb/Symbol/FuncUnwinders.h"
16#include "lldb/Symbol/Function.h"
17#include "lldb/Utility/ArchDefaultUnwindPlan.h"
18#include "UnwindLLDB.h"
19#include "lldb/Symbol/UnwindPlan.h"
20#include "lldb/Core/Log.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25UnwindLLDB::UnwindLLDB (Thread &thread) :
26 Unwind (thread),
27 m_frames()
28{
29}
30
31uint32_t
32UnwindLLDB::GetFrameCount()
33{
34 Log *log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND);
35 if (m_frames.empty())
36 {
37 // First, set up the 0th (initial) frame
38 Cursor first_cursor;
39 RegisterContextSP no_frame; // an empty shared pointer
40 RegisterContextLLDB *first_register_ctx = new RegisterContextLLDB(m_thread, no_frame, first_cursor.sctx, 0);
41 if (!first_register_ctx->IsValid())
42 {
43 delete first_register_ctx;
44 return 0;
45 }
46 if (!first_register_ctx->GetCFA (first_cursor.cfa))
47 {
48 delete first_register_ctx;
49 return 0;
50 }
51 if (!first_register_ctx->GetPC (first_cursor.start_pc))
52 {
53 delete first_register_ctx;
54 return 0;
55 }
56 // Reuse the StackFrame provided by the processor native machine context for the first frame
57 first_register_ctx->SetStackFrame (m_thread.GetStackFrameAtIndex(0).get());
58 RegisterContextSP temp_rcs(first_register_ctx);
59 first_cursor.reg_ctx = temp_rcs;
60 m_frames.push_back (first_cursor);
61
62 // Now walk up the rest of the stack
63 while (1)
64 {
65 Cursor cursor;
66 RegisterContextLLDB *register_ctx;
67 int cur_idx = m_frames.size ();
68 register_ctx = new RegisterContextLLDB (m_thread, m_frames[cur_idx - 1].reg_ctx, cursor.sctx, cur_idx);
69 if (!register_ctx->IsValid())
70 {
71 delete register_ctx;
72 if (log)
73 {
74 log->Printf("%*sThread %u Frame %d invalid RegisterContext for this frame, stopping stack walk",
75 cur_idx, "", m_thread.GetIndexID(), cur_idx);
76 }
77 break;
78 }
79 if (!register_ctx->GetCFA (cursor.cfa))
80 {
81 delete register_ctx;
82 if (log)
83 {
84 log->Printf("%*sThread %u Frame %d did not get CFA for this frame, stopping stack walk",
85 cur_idx, "", m_thread.GetIndexID(), cur_idx);
86 }
87 break;
88 }
89 if (!register_ctx->GetPC (cursor.start_pc))
90 {
91 delete register_ctx;
92 if (log)
93 {
94 log->Printf("%*sThread %u Frame %d did not get PC for this frame, stopping stack walk",
95 cur_idx, "", m_thread.GetIndexID(), cur_idx);
96 }
97 break;
98 }
99 RegisterContextSP temp_rcs(register_ctx);
100 StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, temp_rcs, cursor.cfa, cursor.start_pc, &cursor.sctx);
101 register_ctx->SetStackFrame (frame);
102 cursor.reg_ctx = temp_rcs;
103 m_frames.push_back (cursor);
104 }
105 }
106 return m_frames.size ();
107}
108
109bool
110UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
111{
112 // FIXME don't get the entire stack if it isn't needed.
113 if (m_frames.size() == 0)
114 GetFrameCount();
115
116 if (idx < m_frames.size ())
117 {
118 cfa = m_frames[idx].cfa;
119 pc = m_frames[idx].start_pc;
120 return true;
121 }
122 return false;
123}
124
125RegisterContext *
126UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
127{
128 uint32_t idx = frame->GetFrameIndex ();
129
130 // FIXME don't get the entire stack if it isn't needed.
131 if (m_frames.size() == 0)
132 GetFrameCount();
133
134 if (idx == 0)
135 {
136 return m_thread.GetRegisterContext();
137 }
138 if (idx < m_frames.size ())
139 return m_frames[idx].reg_ctx.get();
140 return NULL;
141}