Author: [email protected]
Date: Thu Jul  9 06:30:27 2009
New Revision: 2421

Modified:
    branches/bleeding_edge/src/debug.h
    branches/bleeding_edge/src/x64/assembler-x64.cc
    branches/bleeding_edge/src/x64/codegen-x64.cc
    branches/bleeding_edge/src/x64/debug-x64.cc

Log:
X64: Let debugger patch JSReturn with a debug break.
Review URL: http://codereview.chromium.org/155286

Modified: branches/bleeding_edge/src/debug.h
==============================================================================
--- branches/bleeding_edge/src/debug.h  (original)
+++ branches/bleeding_edge/src/debug.h  Thu Jul  9 06:30:27 2009
@@ -363,6 +363,10 @@
    static const int kIa32CallInstructionLength = 5;
    static const int kIa32JSReturnSequenceLength = 6;

+  // The x64 JS return sequence is padded with int3 to make it large
+  // enough to hold a call instruction when the debugger patches it.
+  static const int kX64JSReturnSequenceLength = 13;
+
    // Code generator routines.
    static void GenerateLoadICDebugBreak(MacroAssembler* masm);
    static void GenerateStoreICDebugBreak(MacroAssembler* masm);

Modified: branches/bleeding_edge/src/x64/assembler-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/assembler-x64.cc     (original)
+++ branches/bleeding_edge/src/x64/assembler-x64.cc     Thu Jul  9 06:30:27 2009
@@ -73,45 +73,8 @@
  XMMRegister xmm15 = { 15 };


-Operand::Operand(Register base, int32_t disp): rex_(0) {
-  len_ = 1;
-  if (base.is(rsp) || base.is(r12)) {
-    // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
-    set_sib(times_1, rsp, base);
-  }
-
-  if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
-    set_modrm(0, base);
-  } else if (is_int8(disp)) {
-    set_modrm(1, base);
-    set_disp8(disp);
-  } else {
-    set_modrm(2, base);
-    set_disp32(disp);
-  }
-}
-
-
-Operand::Operand(Register base,
-                 Register index,
-                 ScaleFactor scale,
-                 int32_t disp): rex_(0) {
-  ASSERT(!index.is(rsp));
-  len_ = 1;
-  set_sib(scale, index, base);
-  if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
-    // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
-    // possibly set by set_sib.
-    set_modrm(0, rsp);
-  } else if (is_int8(disp)) {
-    set_modrm(1, rsp);
-    set_disp8(disp);
-  } else {
-    set_modrm(2, rsp);
-    set_disp32(disp);
-  }
-}
-
+//  
-----------------------------------------------------------------------------
+// Implementation of CpuFeatures

  // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
  //   fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
@@ -192,6 +155,71 @@
    ASSERT(IsSupported(SSE2));
    ASSERT(IsSupported(CMOV));
  }
+
+
+//  
-----------------------------------------------------------------------------
+// Implementation of RelocInfo
+
+// Patch the code at the current PC with a call to the target address.
+// Additional guard int3 instructions can be added if required.
+void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
+  // Call instruction takes up 13 bytes and int3 takes up one byte.
+  Address patch_site = pc_;
+  Memory::uint16_at(patch_site) = 0xBA49u;  // movq r10, imm64
+  // Write "0x00, call r10" starting at last byte of address.  We overwrite
+  // the 0x00 later, and this lets us write a uint32.
+  Memory::uint32_at(patch_site + 9) = 0xD2FF4900u;  // 0x00, call r10
+  Memory::Address_at(patch_site + 2) = target;
+
+  // Add the requested number of int3 instructions after the call.
+  for (int i = 0; i < guard_bytes; i++) {
+    *(patch_site + 13 + i) = 0xCC;  // int3
+  }
+}
+
+
+//  
-----------------------------------------------------------------------------
+// Implementation of Operand
+
+Operand::Operand(Register base, int32_t disp): rex_(0) {
+  len_ = 1;
+  if (base.is(rsp) || base.is(r12)) {
+    // SIB byte is needed to encode (rsp + offset) or (r12 + offset).
+    set_sib(times_1, rsp, base);
+  }
+
+  if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
+    set_modrm(0, base);
+  } else if (is_int8(disp)) {
+    set_modrm(1, base);
+    set_disp8(disp);
+  } else {
+    set_modrm(2, base);
+    set_disp32(disp);
+  }
+}
+
+
+Operand::Operand(Register base,
+                 Register index,
+                 ScaleFactor scale,
+                 int32_t disp): rex_(0) {
+  ASSERT(!index.is(rsp));
+  len_ = 1;
+  set_sib(scale, index, base);
+  if (disp == 0 && !base.is(rbp) && !base.is(r13)) {
+    // This call to set_modrm doesn't overwrite the REX.B (or REX.X) bits
+    // possibly set by set_sib.
+    set_modrm(0, rsp);
+  } else if (is_int8(disp)) {
+    set_modrm(1, rsp);
+    set_disp8(disp);
+  } else {
+    set_modrm(2, rsp);
+    set_disp32(disp);
+  }
+}
+

  //  
-----------------------------------------------------------------------------
  // Implementation of Assembler

Modified: branches/bleeding_edge/src/x64/codegen-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/codegen-x64.cc       (original)
+++ branches/bleeding_edge/src/x64/codegen-x64.cc       Thu Jul  9 06:30:27 2009
@@ -355,14 +355,19 @@
    // receiver.
    frame_->Exit();
    masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
+  // Add padding that will be overwritten by a debugger breakpoint.
+  // frame_->Exit() generates "movq rsp, rbp; pop rbp" length 5.
+  // "ret k" has length 2.
+  const int kPadding = Debug::kX64JSReturnSequenceLength - 5 - 2;
+  for (int i = 0; i < kPadding; ++i) {
+    masm_->int3();
+  }
    DeleteFrame();

-  // TODO(x64): introduce kX64JSReturnSequenceLength and enable assert.
-
    // Check that the size of the code used for returning matches what is
    // expected by the debugger.
-  // ASSERT_EQ(Debug::kIa32JSReturnSequenceLength,
-  //          masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
+  ASSERT_EQ(Debug::kX64JSReturnSequenceLength,
+            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
  }



Modified: branches/bleeding_edge/src/x64/debug-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/debug-x64.cc (original)
+++ branches/bleeding_edge/src/x64/debug-x64.cc Thu Jul  9 06:30:27 2009
@@ -38,8 +38,10 @@
  #ifdef ENABLE_DEBUGGER_SUPPORT

  bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) {
-  UNIMPLEMENTED();
-  return false;
+  ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
+  // 11th byte of patch is 0x49, 11th byte of JS return is 0xCC (int3).
+  ASSERT(*(rinfo->pc() + 10) == 0x49 || *(rinfo->pc() + 10) == 0xCC);
+  return (*(rinfo->pc() + 10) == 0x49);
  }

  void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to