[Lldb-commits] [lldb] r244864 - [LLDB][MIPS] Handle false positives for MIPS hardware watchpoints

Jaydeep Patil via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 12 20:44:10 PDT 2015


Author: jaydeep
Date: Wed Aug 12 22:44:09 2015
New Revision: 244864

URL: http://llvm.org/viewvc/llvm-project?rev=244864&view=rev
Log:
[LLDB][MIPS] Handle false positives for MIPS hardware watchpoints
    SUMMARY:
    Last 3bits of the watchpoint address are masked by the kernel. For example, n is 
    at 0x120010d00 and m is 0x120010d04. When a watchpoint is set at m, then watch 
    exception is generated even when n is read/written. To handle this case, instruction 
    at PC is emulated to find the base address of the load/store instruction. This address 
    is then appended to the description of the stop-info packet. Client then reads this 
    information to check whether the user has set a watchpoint on this address.
    
    Reviewers: jingham, clayborg
    Subscribers: nitesh.jain, mohit.bhakkad, sagar, bhushan and lldb-commits
    Differential Revision: http://reviews.llvm.org/D11672

Modified:
    lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
    lldb/trunk/include/lldb/Target/StopInfo.h
    lldb/trunk/source/Host/common/NativeRegisterContext.cpp
    lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
    lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
    lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Target/StopInfo.cpp

Modified: lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeRegisterContext.h Wed Aug 12 22:44:09 2015
@@ -111,6 +111,19 @@ public:
     virtual lldb::addr_t
     GetWatchpointAddress (uint32_t wp_index);
 
+    // MIPS Linux kernel returns a masked address (last 3bits are masked)
+    // when a HW watchpoint is hit. However user may not have set a watchpoint
+    // on this address. This function emulates the instruction at PC and 
+    // finds the base address used in the load/store instruction. This gives the 
+    // exact address used to read/write the variable being watched.
+    // For example:
+    // 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', 
+    // then watch exception is generated even when 'n' is read/written. This function
+    // returns address of 'n' so that client can check whether a watchpoint is set
+    // on this address or not.
+    virtual lldb::addr_t
+    GetWatchpointHitAddress (uint32_t wp_index);
+
     virtual bool
     HardwareSingleStep (bool enable);
 

Modified: lldb/trunk/include/lldb/Target/StopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StopInfo.h?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/StopInfo.h (original)
+++ lldb/trunk/include/lldb/Target/StopInfo.h Wed Aug 12 22:44:09 2015
@@ -161,7 +161,7 @@ public:
     CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id, bool should_stop);
 
     static lldb::StopInfoSP
-    CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id);
+    CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id, lldb::addr_t watch_hit_addr = LLDB_INVALID_ADDRESS);
 
     static lldb::StopInfoSP
     CreateStopReasonWithSignal (Thread &thread, int signo, const char *description = nullptr);

Modified: lldb/trunk/source/Host/common/NativeRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeRegisterContext.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/NativeRegisterContext.cpp (original)
+++ lldb/trunk/source/Host/common/NativeRegisterContext.cpp Wed Aug 12 22:44:09 2015
@@ -334,6 +334,12 @@ NativeRegisterContext::GetWatchpointAddr
     return LLDB_INVALID_ADDRESS;
 }
 
+lldb::addr_t
+NativeRegisterContext::GetWatchpointHitAddress (uint32_t wp_index)
+{
+    return LLDB_INVALID_ADDRESS;
+}
+
 bool
 NativeRegisterContext::HardwareSingleStep (bool enable)
 {

Modified: lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp (original)
+++ lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp Wed Aug 12 22:44:09 2015
@@ -410,6 +410,9 @@ EmulateInstructionMIPS64::GetOpcodeForIn
         { "SD",         &EmulateInstructionMIPS64::Emulate_SD,          "SD rt,offset(rs)"          },
         { "LD",         &EmulateInstructionMIPS64::Emulate_LD,          "LD rt,offset(base)"        },
 
+        { "SW",         &EmulateInstructionMIPS64::Emulate_SW,          "SW rt,offset(rs)"          },
+        { "LW",         &EmulateInstructionMIPS64::Emulate_LW,          "LW rt,offset(rs)"          },
+
         //----------------------------------------------------------------------
         // Branch instructions
         //----------------------------------------------------------------------
@@ -657,35 +660,95 @@ EmulateInstructionMIPS64::Emulate_DADDiu
 }
 
 bool
+EmulateInstructionMIPS64::Emulate_SW (llvm::MCInst& insn)
+{
+    bool success = false;
+    uint32_t base;
+    int64_t imm, address;
+    Context bad_vaddr_context;
+
+    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+    imm = insn.getOperand(2).getImm();
+
+    RegisterInfo reg_info_base;
+    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
+        return false;
+
+    /* read base register */
+    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+    if (!success)
+        return false;
+
+    /* destination address */
+    address = address + imm;
+
+    /* Set the bad_vaddr register with base address used in the instruction */
+    bad_vaddr_context.type = eContextInvalid;
+    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
+
+    return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_LW (llvm::MCInst& insn)
+{
+    bool success = false;
+    uint32_t base;
+    int64_t imm, address;
+    Context bad_vaddr_context;
+
+    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+    imm = insn.getOperand(2).getImm();
+
+    RegisterInfo reg_info_base;
+    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
+        return false;
+
+    /* read base register */
+    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+    if (!success)
+        return false;
+
+    /* destination address */
+    address = address + imm;
+
+    /* Set the bad_vaddr register with base address used in the instruction */
+    bad_vaddr_context.type = eContextInvalid;
+    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
+
+    return true;
+}
+
+bool
 EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
 {
+    uint64_t address;
+    RegisterInfo reg_info_base;
+    RegisterInfo reg_info_src;
     bool success = false;
     uint32_t imm16 = insn.getOperand(2).getImm();
     uint64_t imm = SignedBits(imm16, 15, 0);
     uint32_t src, base;
+    Context bad_vaddr_context;
 
     src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
     base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
 
-    /* We look for sp based non-volatile register stores */
-    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
-    {
-        uint64_t address;
-        RegisterInfo reg_info_base;
-        RegisterInfo reg_info_src;
-
-        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
-            || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
-            return false;
+    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
+        || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+        return false;
 
-        /* read SP */
-        address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
-        if (!success)
-            return false;
+    /* read SP */
+    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+    if (!success)
+        return false;
 
-        /* destination address */
-        address = address + imm;
+    /* destination address */
+    address = address + imm;
 
+    /* We look for sp based non-volatile register stores */
+    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+    {
         Context context;
         RegisterValue data_src;
         context.type = eContextPushRegisterOnStack;
@@ -702,11 +765,13 @@ EmulateInstructionMIPS64::Emulate_SD (ll
 
         if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
             return false;
-
-        return true;
     }
 
-    return false;
+    /* Set the bad_vaddr register with base address used in the instruction */
+    bad_vaddr_context.type = eContextInvalid;
+    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
+
+    return true;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h (original)
+++ lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h Wed Aug 12 22:44:09 2015
@@ -128,6 +128,12 @@ protected:
     Emulate_SD (llvm::MCInst& insn);
 
     bool
+    Emulate_SW (llvm::MCInst& insn);
+
+    bool
+    Emulate_LW (llvm::MCInst& insn);
+
+    bool
     Emulate_LD (llvm::MCInst& insn);
 
     bool

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp Wed Aug 12 22:44:09 2015
@@ -20,7 +20,9 @@
 #include "lldb/Core/Log.h"
 #include "lldb/Core/DataBufferHeap.h"
 #include "lldb/Host/HostInfo.h"
-
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-enumerations.h"
 #include "Plugins/Process/Linux/NativeProcessLinux.h"
 #include "Plugins/Process/Linux/Procfs.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
@@ -997,6 +999,106 @@ NativeRegisterContextLinux_mips64::GetWa
     return hw_addr_map[wp_index];
 }
 
+struct EmulatorBaton
+{
+    lldb::addr_t m_watch_hit_addr;
+    NativeProcessLinux* m_process;
+    NativeRegisterContext* m_reg_context;
+
+    EmulatorBaton(NativeProcessLinux* process, NativeRegisterContext* reg_context) :
+            m_watch_hit_addr(LLDB_INVALID_ADDRESS), 
+            m_process(process),
+            m_reg_context(reg_context) 
+            {}
+};
+
+static size_t
+ReadMemoryCallback (EmulateInstruction *instruction, void *baton,
+                    const EmulateInstruction::Context &context, lldb::addr_t addr, 
+                    void *dst, size_t length)
+{
+    size_t bytes_read;
+    EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+    emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read);
+    return bytes_read;
+}
+
+static size_t
+WriteMemoryCallback (EmulateInstruction *instruction, void *baton,
+                     const EmulateInstruction::Context &context, 
+                     lldb::addr_t addr, const void *dst, size_t length)
+{
+    return length;
+}
+
+static bool
+ReadRegisterCallback (EmulateInstruction *instruction, void *baton,
+                      const RegisterInfo *reg_info, RegisterValue &reg_value)
+{
+    EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+
+    const RegisterInfo* full_reg_info = emulator_baton->m_reg_context->GetRegisterInfo(
+            lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]);
+
+    Error error = emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value);
+    if (error.Success())
+        return true;
+
+    return false;
+}
+
+static bool
+WriteRegisterCallback (EmulateInstruction *instruction, void *baton,
+                       const EmulateInstruction::Context &context,
+                       const RegisterInfo *reg_info, const RegisterValue &reg_value)
+{
+    if (reg_info->kinds[lldb::eRegisterKindDWARF] == gcc_dwarf_bad_mips64)
+    {
+        EmulatorBaton* emulator_baton = static_cast<EmulatorBaton*>(baton);
+        emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64 ();
+    }
+
+    return true;
+}
+
+/*
+ * MIPS Linux kernel returns a masked address (last 3bits are masked)
+ * when a HW watchpoint is hit. However user may not have set a watchpoint
+ * on this address. Emulate instruction at PC and find the base address of
+ * the load/store instruction. This will give the exact address used to
+ * read/write the variable. Send this exact address to client so that
+ * it can decide to stop or continue the thread.
+*/
+lldb::addr_t
+NativeRegisterContextLinux_mips64::GetWatchpointHitAddress (uint32_t wp_index)
+{
+    if (wp_index >= NumSupportedHardwareWatchpoints())
+        return LLDB_INVALID_ADDRESS;
+
+    lldb_private::ArchSpec arch;
+    arch = GetRegisterInfoInterface().GetTargetArchitecture();
+    std::unique_ptr<EmulateInstruction> emulator_ap(
+        EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny, nullptr));
+
+    if (emulator_ap == nullptr)
+        return LLDB_INVALID_ADDRESS;
+    
+    EmulatorBaton baton(static_cast<NativeProcessLinux*>(m_thread.GetProcess().get()), this);
+    emulator_ap->SetBaton (&baton);
+    emulator_ap->SetReadMemCallback (&ReadMemoryCallback);
+    emulator_ap->SetReadRegCallback (&ReadRegisterCallback);
+    emulator_ap->SetWriteMemCallback (&WriteMemoryCallback);
+    emulator_ap->SetWriteRegCallback (&WriteRegisterCallback);
+
+    if (!emulator_ap->ReadInstruction())
+        return LLDB_INVALID_ADDRESS;
+
+    if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone))
+        return baton.m_watch_hit_addr;
+
+    return LLDB_INVALID_ADDRESS;
+}
+
 uint32_t
 NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints ()
 {

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h Wed Aug 12 22:44:09 2015
@@ -36,6 +36,9 @@ namespace process_linux {
         lldb::addr_t
         GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override;
 
+        lldb::addr_t
+        GetWatchpointHitAddress (uint32_t wp_index) override;
+
         const RegisterSet *
         GetRegisterSet (uint32_t set_index) const override;
 

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeThreadLinux.cpp Wed Aug 12 22:44:09 2015
@@ -333,6 +333,16 @@ NativeThreadLinux::SetStoppedByWatchpoin
     std::ostringstream ostr;
     ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
     ostr << wp_index;
+
+    /*
+     * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example:
+     * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then
+     * watch exception is generated even when 'n' is read/written. To handle this case,
+     * find the base address of the load/store instruction and append it in the stop-info 
+     * packet.
+    */
+    ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);
+
     m_stop_description = ostr.str();
 
     m_stop_info.reason = StopReason::eStopReasonWatchpoint;

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Wed Aug 12 22:44:09 2015
@@ -2020,6 +2020,7 @@ ProcessGDBRemote::SetThreadStopInfo (lld
                             StringExtractor desc_extractor(description.c_str());
                             addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
                             uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
+                            addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
                             watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
                             if (wp_addr != LLDB_INVALID_ADDRESS)
                             {
@@ -2035,7 +2036,7 @@ ProcessGDBRemote::SetThreadStopInfo (lld
                                 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
                                 if (log) log->Printf ("failed to find watchpoint");
                             }
-                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id));
+                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
                             handled = true;
                         }
                         else if (reason.compare("exception") == 0)

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=244864&r1=244863&r2=244864&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Wed Aug 12 22:44:09 2015
@@ -614,10 +614,11 @@ public:
         Watchpoint *watchpoint;
     };
 
-    StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
+    StopInfoWatchpoint (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr) :
         StopInfo(thread, watch_id),
         m_should_stop(false),
-        m_should_stop_is_valid(false)
+        m_should_stop_is_valid(false),
+        m_watch_hit_addr(watch_hit_addr)
     {
     }
     
@@ -744,6 +745,21 @@ protected:
                     }
                 }
 
+                /*
+                 * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For example:
+                 * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at 'm', then
+                 * watch exception is generated even when 'n' is read/written. To handle this case,
+                 * server emulates the instruction at PC and finds the base address of the load/store
+                 * instruction and appends it in the description of the stop-info packet. If watchpoint
+                 * is not set on this address by user then this do not stop.
+                */
+                if (m_watch_hit_addr != LLDB_INVALID_ADDRESS)
+                {
+                    WatchpointSP wp_hit_sp = thread_sp->CalculateTarget()->GetWatchpointList().FindByAddress(m_watch_hit_addr);
+                    if (!wp_hit_sp)
+                        m_should_stop = false;
+                }
+                
                 if (m_should_stop && wp_sp->GetConditionText() != NULL)
                 {
                     // We need to make sure the user sees any parse errors in their condition, so we'll hook the
@@ -856,6 +872,7 @@ protected:
 private:
     bool m_should_stop;
     bool m_should_stop_is_valid;
+    lldb::addr_t m_watch_hit_addr;
 };
 
 
@@ -1153,9 +1170,9 @@ StopInfo::CreateStopReasonWithBreakpoint
 }
 
 StopInfoSP
-StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
+StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id, lldb::addr_t watch_hit_addr)
 {
-    return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
+    return StopInfoSP (new StopInfoWatchpoint (thread, watch_id, watch_hit_addr));
 }
 
 StopInfoSP




More information about the lldb-commits mailing list