Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "vm/debugger.h" | |
| 6 | |
| 7 #include "vm/code_patcher.h" | |
| 8 #include "vm/compiler.h" | |
| 9 #include "vm/flags.h" | |
| 10 #include "vm/globals.h" | |
| 11 #include "vm/object.h" | |
| 12 #include "vm/object_store.h" | |
| 13 #include "vm/os.h" | |
| 14 #include "vm/stub_code.h" | |
| 15 #include "vm/visitor.h" | |
| 16 | |
| 17 | |
| 18 namespace dart { | |
| 19 | |
| 20 DEFINE_FLAG(bool, debugger, false, "Debug breakpoint at main"); | |
| 21 DEFINE_FLAG(charp, bpt, NULL, "Debug breakpoint at <func>"); | |
|
siva
2011/11/30 00:00:47
I hope all these flags are just temporary stuff be
hausner
2011/11/30 01:17:05
Yes, only temporary.
| |
| 22 | |
| 23 | |
| 24 class Breakpoint { | |
| 25 public: | |
| 26 Breakpoint(const Function& func, int pc_desc_index, uword pc) | |
|
srdjan
2011/11/29 22:26:00
intptr_t pc_dec_index
hausner
2011/11/30 01:17:05
Done.
| |
| 27 : function_(func.raw()), | |
| 28 pc_desc_index_(pc_desc_index), | |
| 29 pc_(pc), | |
| 30 next_(NULL) { | |
| 31 } | |
| 32 | |
| 33 RawFunction* function() const { return function_; } | |
| 34 uword pc() const { return pc_; } | |
| 35 | |
| 36 void set_next(Breakpoint* value) { next_ = value; } | |
| 37 Breakpoint* next() const { return this->next_; } | |
| 38 | |
| 39 void VisitObjectPointers(ObjectPointerVisitor* visitor) { | |
| 40 visitor->VisitPointer(reinterpret_cast<RawObject**>(&function_)); | |
| 41 } | |
| 42 | |
| 43 private: | |
|
srdjan
2011/11/29 22:26:00
DISALLOW_....
hausner
2011/11/30 01:17:05
Done.
| |
| 44 RawFunction* function_; | |
| 45 int pc_desc_index_; | |
|
srdjan
2011/11/29 22:26:00
intptr_t
hausner
2011/11/30 01:17:05
Done, but over the long run I would change this to
| |
| 46 uword pc_; | |
|
siva
2011/11/30 00:00:47
Don't you also need to store the original contents
hausner
2011/11/30 01:17:05
At this point I don't need to. To remove a BP I ju
| |
| 47 Breakpoint* next_; | |
| 48 }; | |
| 49 | |
| 50 | |
| 51 Debugger::Debugger() | |
| 52 : initialized_(false), | |
| 53 breakpoints_(NULL) { | |
| 54 } | |
| 55 | |
| 56 | |
| 57 static RawFunction* ResolveLibraryFunction(const String& fname) { | |
| 58 Isolate* isolate = Isolate::Current(); | |
| 59 const Library& root_lib = | |
| 60 Library::Handle(isolate->object_store()->root_library()); | |
|
srdjan
2011/11/29 22:26:00
4 spaces indent.
hausner
2011/11/30 01:17:05
Done.
| |
| 61 ASSERT(!root_lib.IsNull()); | |
| 62 Function& function = Function::Handle(); | |
| 63 const Object& object = Object::Handle(root_lib.LookupObject(fname)); | |
| 64 if (!object.IsNull() && object.IsFunction()) { | |
| 65 function ^= object.raw(); | |
| 66 } | |
| 67 return function.raw(); | |
| 68 } | |
| 69 | |
| 70 | |
| 71 static RawFunction* ResolveFunction(const String& class_name, | |
| 72 const String& function_name) { | |
| 73 Isolate* isolate = Isolate::Current(); | |
| 74 const Library& root_lib = | |
| 75 Library::Handle(isolate->object_store()->root_library()); | |
| 76 const Class& cls = Class::Handle(root_lib.LookupClass(class_name)); | |
| 77 | |
| 78 Function& function = Function::Handle(); | |
| 79 if (!cls.IsNull()) { | |
| 80 function = cls.LookupStaticFunction(function_name); | |
| 81 if (function.IsNull()) { | |
| 82 function = cls.LookupDynamicFunction(function_name); | |
| 83 } | |
| 84 } | |
| 85 return function.raw(); | |
| 86 } | |
| 87 | |
| 88 | |
| 89 | |
| 90 void Debugger::SetBreakpoint(const String& class_name, | |
| 91 const String& function_name) { | |
| 92 Function& func = Function::Handle(); | |
| 93 if (class_name.IsNull() || (class_name.Length() == 0)) { | |
| 94 func = ResolveLibraryFunction(function_name); | |
| 95 } else { | |
| 96 func = ResolveFunction(class_name, function_name); | |
| 97 } | |
| 98 if (func.IsNull()) { | |
| 99 printf("could not find function '%s' in class '%s'\n", | |
| 100 function_name.ToCString(), class_name.ToCString()); | |
|
srdjan
2011/11/29 22:26:00
OS::Print
hausner
2011/11/30 01:17:05
Done.
| |
| 101 return; | |
| 102 } | |
| 103 if (!func.HasCode()) { | |
| 104 Compiler::CompileFunction(func); | |
| 105 } | |
|
siva
2011/11/30 00:00:47
If the function already has code and it is running
hausner
2011/11/30 01:17:05
Yes. For now I just assume the optimizing compiler
| |
| 106 Code& code = Code::Handle(func.code()); | |
| 107 ASSERT(!code.IsNull()); | |
| 108 PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors()); | |
| 109 for (int i = 0; i < desc.Length(); i++) { | |
| 110 PcDescriptors::Kind kind = desc.DescriptorKind(i); | |
| 111 if (kind == PcDescriptors::kIcCall) { | |
| 112 printf("patching dynamic call at %p\n", desc.PC(i)); | |
|
srdjan
2011/11/29 22:26:00
ditto
Maybe add a tracing flag and hide the print
hausner
2011/11/30 01:17:05
As mentioned above, all these prints will go away
| |
| 113 CodePatcher::PatchInstanceCallAt( | |
| 114 desc.PC(i), StubCode::BreakpointDynamicEntryPoint()); | |
| 115 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); | |
|
siva
2011/11/30 00:00:47
you probably need a return here too, otherwise the
hausner
2011/11/30 01:17:05
Good catch.
| |
| 116 } else if (kind == PcDescriptors::kOther) { | |
| 117 if (CodePatcher::IsDartCall(desc.PC(i))) { | |
| 118 printf("patching static call at %p\n", desc.PC(i)); | |
| 119 CodePatcher::PatchStaticCallAt( | |
| 120 desc.PC(i), StubCode::BreakpointStaticEntryPoint()); | |
| 121 AddBreakpoint(new Breakpoint(func, i, desc.PC(i))); | |
|
srdjan
2011/11/29 22:26:00
Who deletes breakpoints? Do we need a ~Debugger()
hausner
2011/11/30 01:17:05
Nobody yet. I think it's ok to leave this for futu
| |
| 122 return; | |
| 123 } | |
|
siva
2011/11/30 00:00:47
Why don't we want to set breakpoints on locations
hausner
2011/11/30 01:17:05
I had to leave some functionality for version 2 :)
| |
| 124 } | |
| 125 } | |
| 126 printf("no breakpoint location found in function '%s'\n", | |
| 127 function_name.ToCString()); | |
| 128 } | |
| 129 | |
| 130 | |
| 131 void Debugger::VisitObjectPointers(ObjectPointerVisitor* visitor) { | |
| 132 ASSERT(visitor != NULL); | |
| 133 Breakpoint* bpt = this->breakpoints_; | |
| 134 while (bpt != NULL) { | |
| 135 bpt->VisitObjectPointers(visitor); | |
| 136 bpt = bpt->next(); | |
| 137 } | |
| 138 } | |
| 139 | |
| 140 | |
| 141 void Debugger::Initialize(Isolate* isolate) { | |
| 142 if (initialized_) { | |
| 143 return; | |
| 144 } | |
| 145 initialized_ = true; | |
| 146 if (!FLAG_debugger) { | |
| 147 return; | |
| 148 } | |
| 149 if (FLAG_bpt == NULL) { | |
| 150 FLAG_bpt = "main"; | |
| 151 } | |
| 152 String& cname = String::Handle(); | |
| 153 String& fname = String::Handle(); | |
|
siva
2011/11/30 00:00:47
We would need a library name too over here, may no
hausner
2011/11/30 01:17:05
Very true. To keep things simple for the beginning
| |
| 154 char* dot = strchr(FLAG_bpt, '.'); | |
| 155 if (dot == NULL) { | |
| 156 fname = String::New(FLAG_bpt); | |
| 157 } else { | |
| 158 fname = String::New(dot + 1); | |
| 159 cname = String::New(reinterpret_cast<const uint8_t*>(FLAG_bpt), | |
| 160 dot - FLAG_bpt); | |
| 161 } | |
| 162 | |
| 163 SetBreakpoint(cname, fname); | |
| 164 } | |
| 165 | |
| 166 | |
| 167 Breakpoint* Debugger::GetBreakpoint(uword breakpoint_address) { | |
| 168 Breakpoint* bpt = this->breakpoints_; | |
| 169 while (bpt != NULL) { | |
| 170 if (bpt->pc() == breakpoint_address) { | |
| 171 return bpt; | |
| 172 } | |
| 173 bpt = bpt->next(); | |
| 174 } | |
| 175 return NULL; | |
| 176 } | |
| 177 | |
| 178 | |
| 179 void Debugger::AddBreakpoint(Breakpoint* bpt) { | |
| 180 ASSERT(bpt->next() == NULL); | |
| 181 bpt->set_next(this->breakpoints_); | |
| 182 this->breakpoints_ = bpt; | |
| 183 } | |
| 184 | |
| 185 | |
| 186 } // namespace dart | |
| OLD | NEW |