説明を見る。00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef V8_V8_DEBUG_H_
00029 #define V8_V8_DEBUG_H_
00030
00031 #include "../include/v8-debug.h"
00032 #include "assembler.h"
00033 #include "code-stubs.h"
00034 #include "execution.h"
00035 #include "factory.h"
00036 #include "platform.h"
00037 #include "string-stream.h"
00038
00039
00040 namespace v8 { namespace internal {
00041
00042
00043 enum StepAction {
00044 StepNone = -1,
00045 StepOut = 0,
00046 StepNext = 1,
00047 StepIn = 2,
00048
00049 StepMin = 3,
00050 StepInMin = 4
00051
00052 };
00053
00054
00055
00056 enum ExceptionBreakType {
00057 BreakException = 0,
00058 BreakUncaughtException = 1
00059 };
00060
00061
00062
00063 enum BreakLocatorType {
00064 ALL_BREAK_LOCATIONS = 0,
00065 SOURCE_BREAK_LOCATIONS = 1
00066 };
00067
00068
00069
00070
00071 class BreakLocationIterator {
00072 public:
00073 explicit BreakLocationIterator(Handle<DebugInfo> debug_info,
00074 BreakLocatorType type);
00075 virtual ~BreakLocationIterator();
00076
00077 void Next();
00078 void Next(int count);
00079 void FindBreakLocationFromAddress(Address pc);
00080 void FindBreakLocationFromPosition(int position);
00081 void Reset();
00082 bool Done() const;
00083 void SetBreakPoint(Handle<Object> break_point_object);
00084 void ClearBreakPoint(Handle<Object> break_point_object);
00085 void SetOneShot();
00086 void ClearOneShot();
00087 void PrepareStepIn();
00088 bool IsExit() const;
00089 bool HasBreakPoint();
00090 bool IsDebugBreak();
00091 Object* BreakPointObjects();
00092
00093
00094 inline int code_position() { return pc() - debug_info_->code()->entry(); }
00095 inline int break_point() { return break_point_; }
00096 inline int position() { return position_; }
00097 inline int statement_position() { return statement_position_; }
00098 inline Address pc() { return reloc_iterator_->rinfo()->pc(); }
00099 inline Code* code() { return debug_info_->code(); }
00100 inline RelocInfo* rinfo() { return reloc_iterator_->rinfo(); }
00101 inline RelocInfo::Mode rmode() const {
00102 return reloc_iterator_->rinfo()->rmode();
00103 }
00104 inline RelocInfo* original_rinfo() {
00105 return reloc_iterator_original_->rinfo();
00106 }
00107 inline RelocInfo::Mode original_rmode() const {
00108 return reloc_iterator_original_->rinfo()->rmode();
00109 }
00110
00111 protected:
00112 bool RinfoDone() const;
00113 void RinfoNext();
00114
00115 BreakLocatorType type_;
00116 int break_point_;
00117 int position_;
00118 int statement_position_;
00119 Handle<DebugInfo> debug_info_;
00120 RelocIterator* reloc_iterator_;
00121 RelocIterator* reloc_iterator_original_;
00122
00123 private:
00124 void SetDebugBreak();
00125 void ClearDebugBreak();
00126
00127 DISALLOW_COPY_AND_ASSIGN(BreakLocationIterator);
00128 };
00129
00130
00131
00132
00133 class DebugInfoListNode {
00134 public:
00135 explicit DebugInfoListNode(DebugInfo* debug_info);
00136 virtual ~DebugInfoListNode();
00137
00138 DebugInfoListNode* next() { return next_; }
00139 void set_next(DebugInfoListNode* next) { next_ = next; }
00140 Handle<DebugInfo> debug_info() { return debug_info_; }
00141
00142 private:
00143
00144 Handle<DebugInfo> debug_info_;
00145
00146
00147 DebugInfoListNode* next_;
00148 };
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 class Debug {
00159 public:
00160 static void Setup(bool create_heap_objects);
00161 static bool Load();
00162 static void Unload();
00163 static bool IsLoaded() { return !debug_context_.is_null(); }
00164 static bool InDebugger() { return Top::is_break(); }
00165 static void Iterate(ObjectVisitor* v);
00166
00167 static Object* Break(Arguments args);
00168 static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
00169 int source_position,
00170 Handle<Object> break_point_object);
00171 static void ClearBreakPoint(Handle<Object> break_point_object);
00172 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
00173 static void FloodHandlerWithOneShot();
00174 static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
00175 static void PrepareStep(StepAction step_action, int step_count);
00176 static void ClearStepping();
00177 static bool StepNextContinue(BreakLocationIterator* break_location_iterator,
00178 JavaScriptFrame* frame);
00179 static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
00180 static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
00181
00182
00183 static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
00184
00185 static bool IsDebugBreak(Address addr);
00186
00187
00188
00189 static bool IsSourceBreakStub(Code* code);
00190 static bool IsBreakStub(Code* code);
00191
00192
00193 static Handle<Code> FindDebugBreak(RelocInfo* rinfo);
00194
00195 static Handle<Object> GetSourceBreakLocations(
00196 Handle<SharedFunctionInfo> shared);
00197 static Code* GetCodeTarget(Address target);
00198
00199
00200 inline static Handle<Context> debug_context() { return debug_context_; }
00201
00202
00203 static bool IsDebugGlobal(GlobalObject* global);
00204
00205
00206 inline static bool has_break_points() { return has_break_points_; }
00207
00208 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
00209 static Address step_in_fp() { return thread_local_.step_into_fp_; }
00210 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
00211
00212
00213 static bool disable_break() { return disable_break_; }
00214 static void set_disable_break(bool disable_break) {
00215 disable_break_ = disable_break;
00216 }
00217
00218
00219 static bool break_on_exception() { return break_on_exception_; }
00220 static bool break_on_uncaught_exception() {
00221 return break_on_uncaught_exception_;
00222 }
00223
00224 enum AddressId {
00225 k_after_break_target_address,
00226 k_debug_break_return_address,
00227 k_register_address
00228 };
00229
00230
00231 static Address* after_break_target_address() {
00232 return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
00233 }
00234
00235
00236 static Object** register_address(int r) {
00237 return ®isters_[r];
00238 }
00239
00240
00241 static Code* debug_break_return_entry() { return debug_break_return_entry_; }
00242
00243
00244 static Code** debug_break_return_address() {
00245 return &debug_break_return_;
00246 }
00247
00248 static const int kEstimatedNofDebugInfoEntries = 16;
00249 static const int kEstimatedNofBreakPointsInFunction = 16;
00250
00251 static void HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data);
00252
00253 friend class Debugger;
00254 friend Handle<FixedArray> GetDebuggedFunctions();
00255
00256
00257 static char* ArchiveDebug(char* to);
00258 static char* RestoreDebug(char* from);
00259 static int ArchiveSpacePerThread();
00260
00261
00262 static const int kIa32CallInstructionLength = 5;
00263 static const int kIa32JSReturnSequenceLength = 6;
00264
00265 private:
00266 static bool CompileDebuggerScript(int index);
00267 static void ClearOneShot();
00268 static void ActivateStepIn(StackFrame* frame);
00269 static void ClearStepIn();
00270 static void ClearStepNext();
00271
00272 static bool EnsureCompiled(Handle<SharedFunctionInfo> shared);
00273 static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
00274 static void SetAfterBreakTarget(JavaScriptFrame* frame);
00275 static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
00276 static bool CheckBreakPoint(Handle<Object> break_point_object);
00277
00278
00279
00280 static Handle<Context> debug_context_;
00281
00282
00283 static bool has_break_points_;
00284 static DebugInfoListNode* debug_info_list_;
00285
00286 static bool disable_break_;
00287 static bool break_on_exception_;
00288 static bool break_on_uncaught_exception_;
00289
00290
00291 class ThreadLocal {
00292 public:
00293
00294 StepAction last_step_action_;
00295
00296
00297 int last_statement_position_;
00298
00299
00300 int step_count_;
00301
00302
00303 Address last_fp_;
00304
00305
00306 Address step_into_fp_;
00307
00308
00309 Address after_break_target_;
00310 };
00311
00312
00313 static JSCallerSavedBuffer registers_;
00314 static ThreadLocal thread_local_;
00315 static void ThreadInit();
00316
00317
00318 static Code* debug_break_return_entry_;
00319
00320
00321 static Code* debug_break_return_;
00322
00323 DISALLOW_COPY_AND_ASSIGN(Debug);
00324 };
00325
00326
00327 class DebugMessageThread;
00328
00329 class Debugger {
00330 public:
00331 static void DebugRequest(const uint16_t* json_request, int length);
00332
00333 static Handle<Object> MakeJSObject(Vector<const char> constructor_name,
00334 int argc, Object*** argv,
00335 bool* caught_exception);
00336 static Handle<Object> MakeExecutionState(bool* caught_exception);
00337 static Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
00338 Handle<Object> break_points_hit,
00339 bool* caught_exception);
00340 static Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
00341 Handle<Object> exception,
00342 bool uncaught,
00343 bool* caught_exception);
00344 static Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
00345 bool* caught_exception);
00346 static Handle<Object> MakeCompileEvent(Handle<Script> script,
00347 Handle<Object> script_function,
00348 bool* caught_exception);
00349 static Handle<String> ProcessRequest(Handle<Object> exec_state,
00350 Handle<Object> request,
00351 bool stopped);
00352 static void OnDebugBreak(Handle<Object> break_points_hit);
00353 static void OnException(Handle<Object> exception, bool uncaught);
00354 static void OnBeforeCompile(Handle<Script> script);
00355 static void OnAfterCompile(Handle<Script> script,
00356 Handle<JSFunction> fun);
00357 static void OnNewFunction(Handle<JSFunction> fun);
00358 static void ProcessDebugEvent(v8::DebugEvent event,
00359 Handle<Object> event_data);
00360 static void SetMessageHandler(v8::DebugMessageHandler handler, void* data);
00361 static void SendMessage(Vector<uint16_t> message);
00362 static void ProcessCommand(Vector<const uint16_t> command);
00363 static void UpdateActiveDebugger();
00364 inline static bool EventActive(v8::DebugEvent event) {
00365
00366 return !Debugger::compiling_natives_ && Debugger::debugger_active_;
00367 }
00368
00369 static void set_debugger_active(bool debugger_active) {
00370 Debugger::debugger_active_ = debugger_active;
00371 }
00372 static bool debugger_active() { return Debugger::debugger_active_; }
00373 static void set_compiling_natives(bool compiling_natives) {
00374 Debugger::compiling_natives_ = compiling_natives;
00375 }
00376 static bool compiling_natives() { return Debugger::compiling_natives_; }
00377 static void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
00378 static bool is_loading_debugger() { return Debugger::is_loading_debugger_; }
00379
00380 private:
00381 static bool debugger_active_;
00382 static bool compiling_natives_;
00383 static bool is_loading_debugger_;
00384 static DebugMessageThread* message_thread_;
00385 static v8::DebugMessageHandler debug_message_handler_;
00386 static void* debug_message_handler_data_;
00387 };
00388
00389
00390
00391
00392 class MessageQueue BASE_EMBEDDED {
00393 public:
00394 explicit MessageQueue(int size);
00395 ~MessageQueue();
00396 bool IsEmpty() const { return start_ == end_; }
00397 Vector<uint16_t> Get();
00398 void Put(const Vector<uint16_t>& message);
00399 void Clear() { start_ = end_ = 0; }
00400 private:
00401
00402 void Expand();
00403
00404 Vector<uint16_t>* messages_;
00405 int start_;
00406 int end_;
00407 int size_;
00408 };
00409
00410
00411
00412
00413
00414
00415 class LockingMessageQueue BASE_EMBEDDED {
00416 public:
00417 explicit LockingMessageQueue(int size);
00418 ~LockingMessageQueue();
00419 bool IsEmpty() const;
00420 Vector<uint16_t> Get();
00421 void Put(const Vector<uint16_t>& message);
00422 void Clear();
00423 private:
00424 MessageQueue queue_;
00425 Mutex* lock_;
00426 DISALLOW_COPY_AND_ASSIGN(LockingMessageQueue);
00427 };
00428
00429
00430
00431
00432
00433
00434 class DebugMessageThread: public Thread {
00435 public:
00436 DebugMessageThread();
00437 virtual ~DebugMessageThread();
00438
00439
00440
00441 void DebugEvent(v8::DebugEvent,
00442 Handle<Object> exec_state,
00443 Handle<Object> event_data);
00444
00445
00446
00447
00448 void SendMessage(Vector<uint16_t> event_json);
00449
00450 void SetEventJSONFromEvent(Handle<Object> event_data);
00451
00452
00453
00454 void ProcessCommand(Vector<uint16_t> command);
00455 void OnDebuggerInactive();
00456
00457
00458 void Run();
00459
00460 bool host_running_;
00461 Semaphore* command_received_;
00462 Semaphore* message_received_;
00463 private:
00464 bool TwoByteEqualsAscii(Vector<uint16_t> two_byte, const char* ascii);
00465
00466 static const int kQueueInitialSize = 4;
00467 LockingMessageQueue command_queue_;
00468 LockingMessageQueue message_queue_;
00469 DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
00470 };
00471
00472
00473
00474
00475
00476
00477 class EnterDebugger BASE_EMBEDDED {
00478 public:
00479 EnterDebugger() : set_(!it_.done()) {
00480
00481
00482 if (set_) {
00483
00484 break_id_ = Top::break_id();
00485 break_frame_id_ = Top::break_frame_id();
00486
00487
00488 Top::new_break(it_.frame()->id());
00489 }
00490
00491
00492 load_failed_ = !Debug::Load();
00493 if (!load_failed_) {
00494
00495
00496 Top::set_context(*Debug::debug_context());
00497 }
00498 }
00499
00500 ~EnterDebugger() {
00501 if (set_) {
00502
00503 Top::set_break(break_frame_id_, break_id_);
00504 }
00505 }
00506
00507
00508 inline bool FailedToEnter() { return load_failed_; }
00509
00510 private:
00511 JavaScriptFrameIterator it_;
00512 const bool set_;
00513 StackFrame::Id break_frame_id_;
00514 int break_id_;
00515 bool load_failed_;
00516 SaveContext save_;
00517 };
00518
00519
00520
00521 class DisableBreak BASE_EMBEDDED {
00522 public:
00523
00524
00525 explicit DisableBreak(bool disable_break) {
00526 prev_disable_break_ = Debug::disable_break();
00527 Debug::set_disable_break(disable_break);
00528 }
00529 ~DisableBreak() {
00530 Debug::set_disable_break(prev_disable_break_);
00531 }
00532
00533 private:
00534
00535
00536 bool prev_disable_break_;
00537 };
00538
00539
00540
00541
00542 class Debug_Address {
00543 public:
00544 Debug_Address(Debug::AddressId id, int reg = 0)
00545 : id_(id), reg_(reg) {
00546 ASSERT(reg == 0 || id == Debug::k_register_address);
00547 }
00548
00549 static Debug_Address AfterBreakTarget() {
00550 return Debug_Address(Debug::k_after_break_target_address);
00551 }
00552
00553 static Debug_Address DebugBreakReturn() {
00554 return Debug_Address(Debug::k_debug_break_return_address);
00555 }
00556
00557 static Debug_Address Register(int reg) {
00558 return Debug_Address(Debug::k_register_address, reg);
00559 }
00560
00561 Address address() const {
00562 switch (id_) {
00563 case Debug::k_after_break_target_address:
00564 return reinterpret_cast<Address>(Debug::after_break_target_address());
00565 case Debug::k_debug_break_return_address:
00566 return reinterpret_cast<Address>(Debug::debug_break_return_address());
00567 case Debug::k_register_address:
00568 return reinterpret_cast<Address>(Debug::register_address(reg_));
00569 default:
00570 UNREACHABLE();
00571 return NULL;
00572 }
00573 }
00574 private:
00575 Debug::AddressId id_;
00576 int reg_;
00577 };
00578
00579
00580 } }
00581
00582 #endif // V8_V8_DEBUG_H_