blob: d7d0a1005b5179fc4ce8635060c2c3e81abcf8d7 [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 {
Jason Molendaa2c269c2010-10-26 00:47:17 +000074 log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000075 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +000076 }
77 break;
78 }
79 if (!register_ctx->GetCFA (cursor.cfa))
80 {
81 delete register_ctx;
82 if (log)
83 {
Jason Molendaa2c269c2010-10-26 00:47:17 +000084 log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000085 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molendaa2c269c2010-10-26 00:47:17 +000086 }
87 break;
88 }
89 if (cursor.cfa == (addr_t) -1 || cursor.cfa == 1 || cursor.cfa == 0)
90 {
91 delete register_ctx;
92 if (log)
93 {
94 log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +000095 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +000096 }
97 break;
98 }
99 if (!register_ctx->GetPC (cursor.start_pc))
100 {
101 delete register_ctx;
102 if (log)
103 {
Jason Molendaa2c269c2010-10-26 00:47:17 +0000104 log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
Jason Molenda2e2ba542010-10-26 04:14:12 +0000105 cur_idx < 100 ? cur_idx : 100, "", cur_idx);
Jason Molenda8280cbe2010-10-25 11:12:07 +0000106 }
107 break;
108 }
109 RegisterContextSP temp_rcs(register_ctx);
110 StackFrame *frame = new StackFrame(cur_idx, cur_idx, m_thread, temp_rcs, cursor.cfa, cursor.start_pc, &cursor.sctx);
111 register_ctx->SetStackFrame (frame);
112 cursor.reg_ctx = temp_rcs;
113 m_frames.push_back (cursor);
114 }
115 }
116 return m_frames.size ();
117}
118
119bool
120UnwindLLDB::GetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
121{
122 // FIXME don't get the entire stack if it isn't needed.
123 if (m_frames.size() == 0)
124 GetFrameCount();
125
126 if (idx < m_frames.size ())
127 {
128 cfa = m_frames[idx].cfa;
129 pc = m_frames[idx].start_pc;
130 return true;
131 }
132 return false;
133}
134
135RegisterContext *
136UnwindLLDB::CreateRegisterContextForFrame (StackFrame *frame)
137{
138 uint32_t idx = frame->GetFrameIndex ();
139
140 // FIXME don't get the entire stack if it isn't needed.
141 if (m_frames.size() == 0)
142 GetFrameCount();
143
144 if (idx == 0)
145 {
146 return m_thread.GetRegisterContext();
147 }
148 if (idx < m_frames.size ())
149 return m_frames[idx].reg_ctx.get();
150 return NULL;
151}