Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1005)

Side by Side Diff: runtime/vm/debugger.cc

Issue 8775060: Debugger step 2 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "vm/code_index_table.h"
7 #include "vm/code_patcher.h" 8 #include "vm/code_patcher.h"
8 #include "vm/compiler.h" 9 #include "vm/compiler.h"
9 #include "vm/flags.h" 10 #include "vm/flags.h"
10 #include "vm/globals.h" 11 #include "vm/globals.h"
11 #include "vm/object.h" 12 #include "vm/object.h"
12 #include "vm/object_store.h" 13 #include "vm/object_store.h"
13 #include "vm/os.h" 14 #include "vm/os.h"
15 #include "vm/stack_frame.h"
14 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
15 #include "vm/visitor.h" 17 #include "vm/visitor.h"
16 18
17 19
18 namespace dart { 20 namespace dart {
19 21
20 DEFINE_FLAG(bool, debugger, false, "Debug breakpoint at main"); 22 DEFINE_FLAG(bool, debugger, false, "Debug breakpoint at main");
21 DEFINE_FLAG(charp, bpt, NULL, "Debug breakpoint at <func>"); 23 DEFINE_FLAG(charp, bpt, NULL, "Debug breakpoint at <func>");
22 24
23 25
24 class Breakpoint { 26
25 public: 27 Breakpoint::Breakpoint(const Function& func, intptr_t pc_desc_index)
26 Breakpoint(const Function& func, intptr_t pc_desc_index, uword pc) 28 : function_(func.raw()),
27 : function_(func.raw()), 29 pc_desc_index_(pc_desc_index),
28 pc_desc_index_(pc_desc_index), 30 pc_(0),
29 pc_(pc), 31 line_number_(-1),
30 next_(NULL) { 32 next_(NULL) {
33 Code& code = Code::Handle(func.code());
34 ASSERT(!code.IsNull()); // Function must be compiled.
35 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
36 ASSERT(pc_desc_index < desc.Length());
37 this->token_index_ = desc.TokenIndex(pc_desc_index);
38 ASSERT(this->token_index_ > 0);
39 this->pc_ = desc.PC(pc_desc_index);
40 ASSERT(this->pc_ != 0);
41 }
42
43
44 RawScript* Breakpoint::SourceCode() {
45 const Function& func = Function::Handle(this->function_);
46 const Class& cls = Class::Handle(func.owner());
47 return cls.script();
48 }
49
50
51 RawString* Breakpoint::SourceUrl() {
52 const Script& script = Script::Handle(this->SourceCode());
53 return script.url();
54 }
55
56
57 intptr_t Breakpoint::LineNumber() {
58 // Compute line number lazily since it causes scanning of the script.
59 if (this->line_number_ < 0) {
60 const Script& script = Script::Handle(this->SourceCode());
61 intptr_t ignore_column;
62 script.GetTokenLocation(this->token_index_,
63 &this->line_number_, &ignore_column);
31 } 64 }
65 return this->line_number_;
66 }
32 67
33 RawFunction* function() const { return function_; }
34 uword pc() const { return pc_; }
35 68
36 void set_next(Breakpoint* value) { next_ = value; } 69 void Breakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
37 Breakpoint* next() const { return this->next_; } 70 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_));
71 }
38 72
39 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 73
40 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); 74 ActivationFrame::ActivationFrame(uword pc)
75 : pc_(pc),
76 function_(Function::null()),
77 token_index_(-1),
78 line_number_(-1) {
79 }
80
81
82 RawFunction* ActivationFrame::DartFunction() {
83 if (function_ == Function::null()) {
84 ASSERT(Isolate::Current() != NULL);
85 CodeIndexTable* code_index_table = Isolate::Current()->code_index_table();
86 ASSERT(code_index_table != NULL);
87 function_ = code_index_table->LookupFunction(pc_);
41 } 88 }
89 return function_;
90 }
42 91
43 private: 92
44 RawFunction* function_; 93 RawString* ActivationFrame::SourceUrl() {
45 intptr_t pc_desc_index_; 94 const Script& script = Script::Handle(SourceScript());
46 uword pc_; 95 return script.url();
47 Breakpoint* next_; 96 }
48 DISALLOW_COPY_AND_ASSIGN(Breakpoint); 97
49 }; 98
99 RawScript* ActivationFrame::SourceScript() {
100 const Function& func = Function::Handle(DartFunction());
101 const Class& cls = Class::Handle(func.owner());
102 return cls.script();
103 }
104
105
106 intptr_t ActivationFrame::TokenIndex() {
107 if (token_index_ < 0) {
108 const Function& func = Function::Handle(DartFunction());
109 Code& code = Code::Handle(func.code());
110 ASSERT(!code.IsNull());
111 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
112 for (int i = 0; i < desc.Length(); i++) {
113 if (desc.PC(i) == pc_) {
114 token_index_ = desc.TokenIndex(i);
115 break;
116 }
117 }
118 ASSERT(token_index_ >= 0);
119 }
120 return token_index_;
121 }
122
123
124 intptr_t ActivationFrame::LineNumber() {
125 // Compute line number lazily since it causes scanning of the script.
126 if (line_number_ < 0) {
127 const Script& script = Script::Handle(SourceScript());
128 intptr_t ignore_column;
129 script.GetTokenLocation(TokenIndex(), &line_number_, &ignore_column);
130 }
131 return line_number_;
132 }
133
134
135 RawArray* ActivationFrame::Variables() {
136 UNIMPLEMENTED();
137 }
138
139
140 RawInstance* ActivationFrame::Value(const String& variable_name) {
141 UNIMPLEMENTED();
142 }
143
144
145 const char* ActivationFrame::ToCString() {
146 const char* kFormat = "Function: '%s%s%s' url: '%s' line: %d";
147
148 Function& func = Function::Handle(DartFunction());
149 String& func_name = String::Handle(func.name());
150 Class& func_class = Class::Handle(func.owner());
151 String& class_name = String::Handle(func_class.Name());
152 String& url = String::Handle(SourceUrl());
153 intptr_t line = LineNumber();
154
155 intptr_t len = OS::SNPrint(NULL, 0, kFormat,
156 class_name.ToCString(),
157 func_class.IsTopLevel() ? "" : ".",
158 func_name.ToCString(),
159 url.ToCString(),
160 line);
161 len++; // String terminator.
162 char* chars = reinterpret_cast<char*>(
163 Isolate::Current()->current_zone()->Allocate(len));
164 OS::SNPrint(chars, len, kFormat,
165 class_name.ToCString(),
166 func_class.IsTopLevel() ? "" : ".",
167 func_name.ToCString(),
168 url.ToCString(),
169 line);
170 return chars;
171 }
172
173
174 void StackTrace::AddActivation(ActivationFrame* frame) {
175 this->trace_.Add(frame);
176 }
50 177
51 178
52 Debugger::Debugger() 179 Debugger::Debugger()
53 : initialized_(false), 180 : initialized_(false),
181 bp_handler_(NULL),
54 breakpoints_(NULL) { 182 breakpoints_(NULL) {
55 } 183 }
56 184
57 185
58 static RawFunction* ResolveLibraryFunction(const String& fname) { 186 static RawFunction* ResolveLibraryFunction(const String& fname) {
59 Isolate* isolate = Isolate::Current(); 187 Isolate* isolate = Isolate::Current();
60 const Library& root_lib = 188 const Library& root_lib =
61 Library::Handle(isolate->object_store()->root_library()); 189 Library::Handle(isolate->object_store()->root_library());
62 ASSERT(!root_lib.IsNull()); 190 ASSERT(!root_lib.IsNull());
63 Function& function = Function::Handle(); 191 Function& function = Function::Handle();
(...skipping 16 matching lines...) Expand all
80 if (!cls.IsNull()) { 208 if (!cls.IsNull()) {
81 function = cls.LookupStaticFunction(function_name); 209 function = cls.LookupStaticFunction(function_name);
82 if (function.IsNull()) { 210 if (function.IsNull()) {
83 function = cls.LookupDynamicFunction(function_name); 211 function = cls.LookupDynamicFunction(function_name);
84 } 212 }
85 } 213 }
86 return function.raw(); 214 return function.raw();
87 } 215 }
88 216
89 217
90
91 void Debugger::SetBreakpointAtEntry(const String& class_name, 218 void Debugger::SetBreakpointAtEntry(const String& class_name,
92 const String& function_name) { 219 const String& function_name) {
93 Function& func = Function::Handle(); 220 Function& func = Function::Handle();
94 if (class_name.IsNull() || (class_name.Length() == 0)) { 221 if (class_name.IsNull() || (class_name.Length() == 0)) {
95 func = ResolveLibraryFunction(function_name); 222 func = ResolveLibraryFunction(function_name);
96 } else { 223 } else {
97 func = ResolveFunction(class_name, function_name); 224 func = ResolveFunction(class_name, function_name);
98 } 225 }
99 if (func.IsNull()) { 226 if (func.IsNull()) {
100 OS::Print("could not find function '%s' in class '%s'\n", 227 OS::Print("could not find function '%s'\n", function_name.ToCString());
101 function_name.ToCString(), class_name.ToCString());
102 return; 228 return;
103 } 229 }
104 if (!func.HasCode()) { 230 if (!func.HasCode()) {
105 Compiler::CompileFunction(func); 231 Compiler::CompileFunction(func);
106 } 232 }
107 Code& code = Code::Handle(func.code()); 233 Code& code = Code::Handle(func.code());
108 ASSERT(!code.IsNull()); 234 ASSERT(!code.IsNull());
109 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); 235 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
110 for (int i = 0; i < desc.Length(); i++) { 236 for (int i = 0; i < desc.Length(); i++) {
111 PcDescriptors::Kind kind = desc.DescriptorKind(i); 237 PcDescriptors::Kind kind = desc.DescriptorKind(i);
238 Breakpoint* bpt = NULL;
112 if (kind == PcDescriptors::kIcCall) { 239 if (kind == PcDescriptors::kIcCall) {
113 OS::Print("patching dynamic call at %p\n", desc.PC(i));
114 CodePatcher::PatchInstanceCallAt( 240 CodePatcher::PatchInstanceCallAt(
115 desc.PC(i), StubCode::BreakpointDynamicEntryPoint()); 241 desc.PC(i), StubCode::BreakpointDynamicEntryPoint());
116 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); 242 bpt = new Breakpoint(func, i);
117 return;
118 } else if (kind == PcDescriptors::kOther) { 243 } else if (kind == PcDescriptors::kOther) {
119 if (CodePatcher::IsDartCall(desc.PC(i))) { 244 if (CodePatcher::IsDartCall(desc.PC(i))) {
120 OS::Print("patching static call at %p\n", desc.PC(i));
121 CodePatcher::PatchStaticCallAt( 245 CodePatcher::PatchStaticCallAt(
122 desc.PC(i), StubCode::BreakpointStaticEntryPoint()); 246 desc.PC(i), StubCode::BreakpointStaticEntryPoint());
123 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); 247 bpt = new Breakpoint(func, i);
124 return;
125 } 248 }
126 } 249 }
250 if (bpt != NULL) {
251 OS::Print("Setting breakpoint at '%s' line %d (PC %p)\n",
252 String::Handle(bpt->SourceUrl()).ToCString(),
253 bpt->LineNumber(),
254 bpt->pc());
255 AddBreakpoint(bpt);
256 return;
257 }
127 } 258 }
128 OS::Print("no breakpoint location found in function '%s'\n", 259 OS::Print("no breakpoint location found in function '%s'\n",
129 function_name.ToCString()); 260 function_name.ToCString());
130 } 261 }
131 262
132 263
133 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { 264 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) {
134 ASSERT(visitor != NULL); 265 ASSERT(visitor != NULL);
135 Breakpoint* bpt = this->breakpoints_; 266 Breakpoint* bpt = this->breakpoints_;
136 while (bpt != NULL) { 267 while (bpt != NULL) {
137 bpt->VisitObjectPointers(visitor); 268 bpt->VisitObjectPointers(visitor);
138 bpt = bpt->next(); 269 bpt = bpt->next();
139 } 270 }
140 } 271 }
141 272
142 273
274 static void DefaultBreakpointHandler(Breakpoint* bpt, StackTrace* stack) {
275 for (intptr_t i = 0; i < stack->Length(); i++) {
276 OS::Print(" %d. %s\n",
277 i + 1, stack->ActivationFrameAt(i)->ToCString());
278 }
279 }
280
281
282 void Debugger::SetBreakpointHandler(BreakpointHandler* handler) {
283 bp_handler_ = handler;
284 if (bp_handler_ == NULL) {
285 bp_handler_ = &DefaultBreakpointHandler;
286 }
287 }
288
289
290 void Debugger::BreakpointCallback() {
291 ASSERT(initialized_);
292 DartFrameIterator iterator;
293 DartFrame* frame = iterator.NextFrame();
294 Function& func = Function::Handle();
295 ASSERT(frame != NULL);
296 Breakpoint* bpt = GetBreakpoint(frame->pc());
297 ASSERT(bpt != NULL);
298 OS::Print(">>> Breakpoint at %s:%d (Address %p)\n",
299 bpt ? String::Handle(bpt->SourceUrl()).ToCString() : "?",
300 bpt ? bpt->LineNumber() : 0,
301 frame->pc());
302 StackTrace* stack_trace = new StackTrace(8);
303 while (frame != NULL) {
304 ASSERT(frame->IsValid());
305 ASSERT(frame->IsDartFrame());
306 ActivationFrame* activation = new ActivationFrame(frame->pc());
307 stack_trace->AddActivation(activation);
308 frame = iterator.NextFrame();
309 }
310
311 if (bp_handler_ != NULL) {
312 (*bp_handler_)(bpt, stack_trace);
313 }
314 }
315
316
143 void Debugger::Initialize(Isolate* isolate) { 317 void Debugger::Initialize(Isolate* isolate) {
144 if (initialized_) { 318 if (initialized_) {
145 return; 319 return;
146 } 320 }
147 initialized_ = true; 321 initialized_ = true;
148 if (!FLAG_debugger) { 322 if (!FLAG_debugger) {
149 return; 323 return;
150 } 324 }
151 if (FLAG_bpt == NULL) { 325 if (FLAG_bpt == NULL) {
152 FLAG_bpt = "main"; 326 FLAG_bpt = "main";
153 } 327 }
154 String& cname = String::Handle(); 328 String& cname = String::Handle();
155 String& fname = String::Handle(); 329 String& fname = String::Handle();
156 const char* dot = strchr(FLAG_bpt, '.'); 330 const char* dot = strchr(FLAG_bpt, '.');
157 if (dot == NULL) { 331 if (dot == NULL) {
158 fname = String::New(FLAG_bpt); 332 fname = String::New(FLAG_bpt);
159 } else { 333 } else {
160 fname = String::New(dot + 1); 334 fname = String::New(dot + 1);
161 cname = String::New(reinterpret_cast<const uint8_t*>(FLAG_bpt), 335 cname = String::New(reinterpret_cast<const uint8_t*>(FLAG_bpt),
162 dot - FLAG_bpt); 336 dot - FLAG_bpt);
163 } 337 }
338 SetBreakpointHandler(DefaultBreakpointHandler);
164 SetBreakpointAtEntry(cname, fname); 339 SetBreakpointAtEntry(cname, fname);
165 } 340 }
166 341
167 342
168 Breakpoint* Debugger::GetBreakpoint(uword breakpoint_address) { 343 Breakpoint* Debugger::GetBreakpoint(uword breakpoint_address) {
169 Breakpoint* bpt = this->breakpoints_; 344 Breakpoint* bpt = this->breakpoints_;
170 while (bpt != NULL) { 345 while (bpt != NULL) {
171 if (bpt->pc() == breakpoint_address) { 346 if (bpt->pc() == breakpoint_address) {
172 return bpt; 347 return bpt;
173 } 348 }
174 bpt = bpt->next(); 349 bpt = bpt->next();
175 } 350 }
176 return NULL; 351 return NULL;
177 } 352 }
178 353
179 354
180 void Debugger::AddBreakpoint(Breakpoint* bpt) { 355 void Debugger::AddBreakpoint(Breakpoint* bpt) {
181 ASSERT(bpt->next() == NULL); 356 ASSERT(bpt->next() == NULL);
182 bpt->set_next(this->breakpoints_); 357 bpt->set_next(this->breakpoints_);
183 this->breakpoints_ = bpt; 358 this->breakpoints_ = bpt;
184 } 359 }
185 360
186 361
187 } // namespace dart 362 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698