15ffd83dbSDimitry Andric //===-- CommandObjectWatchpoint.cpp ---------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "CommandObjectWatchpoint.h" 100b57cec5SDimitry Andric #include "CommandObjectWatchpointCommand.h" 110b57cec5SDimitry Andric 1206c3fb27SDimitry Andric #include <memory> 130b57cec5SDimitry Andric #include <vector> 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "lldb/Breakpoint/Watchpoint.h" 180b57cec5SDimitry Andric #include "lldb/Breakpoint/WatchpointList.h" 190b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 200b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h" 210b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 22fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h" 230b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h" 2406c3fb27SDimitry Andric #include "lldb/Symbol/Function.h" 250b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 260b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h" 270b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 280b57cec5SDimitry Andric #include "lldb/Target/Target.h" 290b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace lldb; 320b57cec5SDimitry Andric using namespace lldb_private; 330b57cec5SDimitry Andric 3406c3fb27SDimitry Andric static void AddWatchpointDescription(Stream &s, Watchpoint &wp, 350b57cec5SDimitry Andric lldb::DescriptionLevel level) { 3606c3fb27SDimitry Andric s.IndentMore(); 3706c3fb27SDimitry Andric wp.GetDescription(&s, level); 3806c3fb27SDimitry Andric s.IndentLess(); 3906c3fb27SDimitry Andric s.EOL(); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static bool CheckTargetForWatchpointOperations(Target *target, 430b57cec5SDimitry Andric CommandReturnObject &result) { 440b57cec5SDimitry Andric bool process_is_valid = 450b57cec5SDimitry Andric target->GetProcessSP() && target->GetProcessSP()->IsAlive(); 460b57cec5SDimitry Andric if (!process_is_valid) { 475ffd83dbSDimitry Andric result.AppendError("There's no process or it is not alive."); 480b57cec5SDimitry Andric return false; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric // Target passes our checks, return true. 510b57cec5SDimitry Andric return true; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // Equivalent class: {"-", "to", "To", "TO"} of range specifier array. 550b57cec5SDimitry Andric static const char *RSA[4] = {"-", "to", "To", "TO"}; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // Return the index to RSA if found; otherwise -1 is returned. 580b57cec5SDimitry Andric static int32_t WithRSAIndex(llvm::StringRef Arg) { 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric uint32_t i; 610b57cec5SDimitry Andric for (i = 0; i < 4; ++i) 62349cc55cSDimitry Andric if (Arg.contains(RSA[i])) 630b57cec5SDimitry Andric return i; 640b57cec5SDimitry Andric return -1; 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Return true if wp_ids is successfully populated with the watch ids. False 680b57cec5SDimitry Andric // otherwise. 690b57cec5SDimitry Andric bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 700b57cec5SDimitry Andric Target *target, Args &args, std::vector<uint32_t> &wp_ids) { 710b57cec5SDimitry Andric // Pre-condition: args.GetArgumentCount() > 0. 720b57cec5SDimitry Andric if (args.GetArgumentCount() == 0) { 730b57cec5SDimitry Andric if (target == nullptr) 740b57cec5SDimitry Andric return false; 750b57cec5SDimitry Andric WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); 760b57cec5SDimitry Andric if (watch_sp) { 770b57cec5SDimitry Andric wp_ids.push_back(watch_sp->GetID()); 780b57cec5SDimitry Andric return true; 790b57cec5SDimitry Andric } else 800b57cec5SDimitry Andric return false; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric llvm::StringRef Minus("-"); 840b57cec5SDimitry Andric std::vector<llvm::StringRef> StrRefArgs; 850b57cec5SDimitry Andric llvm::StringRef first; 860b57cec5SDimitry Andric llvm::StringRef second; 870b57cec5SDimitry Andric size_t i; 880b57cec5SDimitry Andric int32_t idx; 890b57cec5SDimitry Andric // Go through the arguments and make a canonical form of arg list containing 900b57cec5SDimitry Andric // only numbers with possible "-" in between. 910b57cec5SDimitry Andric for (auto &entry : args.entries()) { 929dba64beSDimitry Andric if ((idx = WithRSAIndex(entry.ref())) == -1) { 939dba64beSDimitry Andric StrRefArgs.push_back(entry.ref()); 940b57cec5SDimitry Andric continue; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric // The Arg contains the range specifier, split it, then. 979dba64beSDimitry Andric std::tie(first, second) = entry.ref().split(RSA[idx]); 980b57cec5SDimitry Andric if (!first.empty()) 990b57cec5SDimitry Andric StrRefArgs.push_back(first); 1000b57cec5SDimitry Andric StrRefArgs.push_back(Minus); 1010b57cec5SDimitry Andric if (!second.empty()) 1020b57cec5SDimitry Andric StrRefArgs.push_back(second); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric // Now process the canonical list and fill in the vector of uint32_t's. If 1050b57cec5SDimitry Andric // there is any error, return false and the client should ignore wp_ids. 1060b57cec5SDimitry Andric uint32_t beg, end, id; 1070b57cec5SDimitry Andric size_t size = StrRefArgs.size(); 1080b57cec5SDimitry Andric bool in_range = false; 1090b57cec5SDimitry Andric for (i = 0; i < size; ++i) { 1100b57cec5SDimitry Andric llvm::StringRef Arg = StrRefArgs[i]; 1110b57cec5SDimitry Andric if (in_range) { 1120b57cec5SDimitry Andric // Look for the 'end' of the range. Note StringRef::getAsInteger() 1130b57cec5SDimitry Andric // returns true to signify error while parsing. 1140b57cec5SDimitry Andric if (Arg.getAsInteger(0, end)) 1150b57cec5SDimitry Andric return false; 1160b57cec5SDimitry Andric // Found a range! Now append the elements. 1170b57cec5SDimitry Andric for (id = beg; id <= end; ++id) 1180b57cec5SDimitry Andric wp_ids.push_back(id); 1190b57cec5SDimitry Andric in_range = false; 1200b57cec5SDimitry Andric continue; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric if (i < (size - 1) && StrRefArgs[i + 1] == Minus) { 1230b57cec5SDimitry Andric if (Arg.getAsInteger(0, beg)) 1240b57cec5SDimitry Andric return false; 1250b57cec5SDimitry Andric // Turn on the in_range flag, we are looking for end of range next. 1260b57cec5SDimitry Andric ++i; 1270b57cec5SDimitry Andric in_range = true; 1280b57cec5SDimitry Andric continue; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric // Otherwise, we have a simple ID. Just append it. 1310b57cec5SDimitry Andric if (Arg.getAsInteger(0, beg)) 1320b57cec5SDimitry Andric return false; 1330b57cec5SDimitry Andric wp_ids.push_back(beg); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric // It is an error if after the loop, we're still in_range. 1370b57cec5SDimitry Andric return !in_range; 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // CommandObjectWatchpointList 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // CommandObjectWatchpointList::Options 1430b57cec5SDimitry Andric #pragma mark List::CommandOptions 1440b57cec5SDimitry Andric #define LLDB_OPTIONS_watchpoint_list 1450b57cec5SDimitry Andric #include "CommandOptions.inc" 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric #pragma mark List 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric class CommandObjectWatchpointList : public CommandObjectParsed { 1500b57cec5SDimitry Andric public: 1510b57cec5SDimitry Andric CommandObjectWatchpointList(CommandInterpreter &interpreter) 1520b57cec5SDimitry Andric : CommandObjectParsed( 1530b57cec5SDimitry Andric interpreter, "watchpoint list", 1549dba64beSDimitry Andric "List all watchpoints at configurable levels of detail.", nullptr, 15504eeddc0SDimitry Andric eCommandRequiresTarget) { 156*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric ~CommandObjectWatchpointList() override = default; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric class CommandOptions : public Options { 1640b57cec5SDimitry Andric public: 16581ad6265SDimitry Andric CommandOptions() = default; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric ~CommandOptions() override = default; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1700b57cec5SDimitry Andric ExecutionContext *execution_context) override { 1710b57cec5SDimitry Andric Status error; 1720b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric switch (short_option) { 1750b57cec5SDimitry Andric case 'b': 1760b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelBrief; 1770b57cec5SDimitry Andric break; 1780b57cec5SDimitry Andric case 'f': 1790b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelFull; 1800b57cec5SDimitry Andric break; 1810b57cec5SDimitry Andric case 'v': 1820b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelVerbose; 1830b57cec5SDimitry Andric break; 1840b57cec5SDimitry Andric default: 1859dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric return error; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 1920b57cec5SDimitry Andric m_level = lldb::eDescriptionLevelFull; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 196bdd1243dSDimitry Andric return llvm::ArrayRef(g_watchpoint_list_options); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Instance variables to hold the values for command options. 2000b57cec5SDimitry Andric 201fe6060f1SDimitry Andric lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief; 2020b57cec5SDimitry Andric }; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric protected: 2055f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 2069dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { 20906c3fb27SDimitry Andric std::optional<uint32_t> num_supported_hardware_watchpoints = 21006c3fb27SDimitry Andric target->GetProcessSP()->GetWatchpointSlotCount(); 21106c3fb27SDimitry Andric 21206c3fb27SDimitry Andric if (num_supported_hardware_watchpoints) 2130b57cec5SDimitry Andric result.AppendMessageWithFormat( 2140b57cec5SDimitry Andric "Number of supported hardware watchpoints: %u\n", 21506c3fb27SDimitry Andric *num_supported_hardware_watchpoints); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 2210b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric if (num_watchpoints == 0) { 2260b57cec5SDimitry Andric result.AppendMessage("No watchpoints currently set."); 2270b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 2285f757f3fSDimitry Andric return; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream(); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 2340b57cec5SDimitry Andric // No watchpoint selected; show info about all currently set watchpoints. 2350b57cec5SDimitry Andric result.AppendMessage("Current watchpoints:"); 2360b57cec5SDimitry Andric for (size_t i = 0; i < num_watchpoints; ++i) { 23706c3fb27SDimitry Andric WatchpointSP watch_sp = watchpoints.GetByIndex(i); 23806c3fb27SDimitry Andric AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 2410b57cec5SDimitry Andric } else { 2420b57cec5SDimitry Andric // Particular watchpoints selected; enable them. 2430b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 2440b57cec5SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 2450b57cec5SDimitry Andric target, command, wp_ids)) { 2460b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 2475f757f3fSDimitry Andric return; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric const size_t size = wp_ids.size(); 2510b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) { 25206c3fb27SDimitry Andric WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]); 25306c3fb27SDimitry Andric if (watch_sp) 25406c3fb27SDimitry Andric AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level); 2550b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric private: 2610b57cec5SDimitry Andric CommandOptions m_options; 2620b57cec5SDimitry Andric }; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric // CommandObjectWatchpointEnable 2650b57cec5SDimitry Andric #pragma mark Enable 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric class CommandObjectWatchpointEnable : public CommandObjectParsed { 2680b57cec5SDimitry Andric public: 2690b57cec5SDimitry Andric CommandObjectWatchpointEnable(CommandInterpreter &interpreter) 2700b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "enable", 2710b57cec5SDimitry Andric "Enable the specified disabled watchpoint(s). If " 2720b57cec5SDimitry Andric "no watchpoints are specified, enable all of them.", 2739dba64beSDimitry Andric nullptr, eCommandRequiresTarget) { 274*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric ~CommandObjectWatchpointEnable() override = default; 2780b57cec5SDimitry Andric 279e8d8bef9SDimitry Andric void 280e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 281e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 28206c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 28306c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 28406c3fb27SDimitry Andric nullptr); 285e8d8bef9SDimitry Andric } 286e8d8bef9SDimitry Andric 2870b57cec5SDimitry Andric protected: 2885f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 2899dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 2900b57cec5SDimitry Andric if (!CheckTargetForWatchpointOperations(target, result)) 2915f757f3fSDimitry Andric return; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 2940b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric if (num_watchpoints == 0) { 3010b57cec5SDimitry Andric result.AppendError("No watchpoints exist to be enabled."); 3025f757f3fSDimitry Andric return; 3030b57cec5SDimitry Andric } 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 3060b57cec5SDimitry Andric // No watchpoint selected; enable all currently set watchpoints. 3070b57cec5SDimitry Andric target->EnableAllWatchpoints(); 3080b57cec5SDimitry Andric result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 3090b57cec5SDimitry Andric " watchpoints)\n", 3100b57cec5SDimitry Andric (uint64_t)num_watchpoints); 3110b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 3120b57cec5SDimitry Andric } else { 3130b57cec5SDimitry Andric // Particular watchpoints selected; enable them. 3140b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 3150b57cec5SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 3160b57cec5SDimitry Andric target, command, wp_ids)) { 3170b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 3185f757f3fSDimitry Andric return; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric int count = 0; 3220b57cec5SDimitry Andric const size_t size = wp_ids.size(); 3230b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 3240b57cec5SDimitry Andric if (target->EnableWatchpointByID(wp_ids[i])) 3250b57cec5SDimitry Andric ++count; 3260b57cec5SDimitry Andric result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 3270b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric }; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric // CommandObjectWatchpointDisable 3330b57cec5SDimitry Andric #pragma mark Disable 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric class CommandObjectWatchpointDisable : public CommandObjectParsed { 3360b57cec5SDimitry Andric public: 3370b57cec5SDimitry Andric CommandObjectWatchpointDisable(CommandInterpreter &interpreter) 3380b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint disable", 3390b57cec5SDimitry Andric "Disable the specified watchpoint(s) without " 3400b57cec5SDimitry Andric "removing it/them. If no watchpoints are " 3410b57cec5SDimitry Andric "specified, disable them all.", 3429dba64beSDimitry Andric nullptr, eCommandRequiresTarget) { 343*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric ~CommandObjectWatchpointDisable() override = default; 3470b57cec5SDimitry Andric 348e8d8bef9SDimitry Andric void 349e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 350e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 35106c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 35206c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 35306c3fb27SDimitry Andric nullptr); 354e8d8bef9SDimitry Andric } 355e8d8bef9SDimitry Andric 3560b57cec5SDimitry Andric protected: 3575f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 3589dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 3590b57cec5SDimitry Andric if (!CheckTargetForWatchpointOperations(target, result)) 3605f757f3fSDimitry Andric return; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 3630b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 3660b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric if (num_watchpoints == 0) { 3690b57cec5SDimitry Andric result.AppendError("No watchpoints exist to be disabled."); 3705f757f3fSDimitry Andric return; 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 3740b57cec5SDimitry Andric // No watchpoint selected; disable all currently set watchpoints. 3750b57cec5SDimitry Andric if (target->DisableAllWatchpoints()) { 3760b57cec5SDimitry Andric result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 3770b57cec5SDimitry Andric " watchpoints)\n", 3780b57cec5SDimitry Andric (uint64_t)num_watchpoints); 3790b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 3800b57cec5SDimitry Andric } else { 3810b57cec5SDimitry Andric result.AppendError("Disable all watchpoints failed\n"); 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric } else { 3840b57cec5SDimitry Andric // Particular watchpoints selected; disable them. 3850b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 3860b57cec5SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 3870b57cec5SDimitry Andric target, command, wp_ids)) { 3880b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 3895f757f3fSDimitry Andric return; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric int count = 0; 3930b57cec5SDimitry Andric const size_t size = wp_ids.size(); 3940b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 3950b57cec5SDimitry Andric if (target->DisableWatchpointByID(wp_ids[i])) 3960b57cec5SDimitry Andric ++count; 3970b57cec5SDimitry Andric result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 3980b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric }; 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric // CommandObjectWatchpointDelete 404480093f4SDimitry Andric #define LLDB_OPTIONS_watchpoint_delete 405480093f4SDimitry Andric #include "CommandOptions.inc" 406480093f4SDimitry Andric 407480093f4SDimitry Andric // CommandObjectWatchpointDelete 4080b57cec5SDimitry Andric #pragma mark Delete 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric class CommandObjectWatchpointDelete : public CommandObjectParsed { 4110b57cec5SDimitry Andric public: 4120b57cec5SDimitry Andric CommandObjectWatchpointDelete(CommandInterpreter &interpreter) 4130b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint delete", 4140b57cec5SDimitry Andric "Delete the specified watchpoint(s). If no " 4150b57cec5SDimitry Andric "watchpoints are specified, delete them all.", 41604eeddc0SDimitry Andric nullptr, eCommandRequiresTarget) { 417*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric ~CommandObjectWatchpointDelete() override = default; 4210b57cec5SDimitry Andric 422e8d8bef9SDimitry Andric void 423e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 424e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 42506c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 42606c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 42706c3fb27SDimitry Andric nullptr); 428e8d8bef9SDimitry Andric } 429e8d8bef9SDimitry Andric 430480093f4SDimitry Andric Options *GetOptions() override { return &m_options; } 431480093f4SDimitry Andric 432480093f4SDimitry Andric class CommandOptions : public Options { 433480093f4SDimitry Andric public: 43481ad6265SDimitry Andric CommandOptions() = default; 435480093f4SDimitry Andric 436480093f4SDimitry Andric ~CommandOptions() override = default; 437480093f4SDimitry Andric 438480093f4SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 439480093f4SDimitry Andric ExecutionContext *execution_context) override { 440480093f4SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 441480093f4SDimitry Andric 442480093f4SDimitry Andric switch (short_option) { 443480093f4SDimitry Andric case 'f': 444480093f4SDimitry Andric m_force = true; 445480093f4SDimitry Andric break; 446480093f4SDimitry Andric default: 447480093f4SDimitry Andric llvm_unreachable("Unimplemented option"); 448480093f4SDimitry Andric } 449480093f4SDimitry Andric 450480093f4SDimitry Andric return {}; 451480093f4SDimitry Andric } 452480093f4SDimitry Andric 453480093f4SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 454480093f4SDimitry Andric m_force = false; 455480093f4SDimitry Andric } 456480093f4SDimitry Andric 457480093f4SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 458bdd1243dSDimitry Andric return llvm::ArrayRef(g_watchpoint_delete_options); 459480093f4SDimitry Andric } 460480093f4SDimitry Andric 461480093f4SDimitry Andric // Instance variables to hold the values for command options. 462fe6060f1SDimitry Andric bool m_force = false; 463480093f4SDimitry Andric }; 464480093f4SDimitry Andric 4650b57cec5SDimitry Andric protected: 4665f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 4679dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 4680b57cec5SDimitry Andric if (!CheckTargetForWatchpointOperations(target, result)) 4695f757f3fSDimitry Andric return; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 4720b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric if (num_watchpoints == 0) { 4790b57cec5SDimitry Andric result.AppendError("No watchpoints exist to be deleted."); 4805f757f3fSDimitry Andric return; 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 483480093f4SDimitry Andric if (command.empty()) { 484480093f4SDimitry Andric if (!m_options.m_force && 485480093f4SDimitry Andric !m_interpreter.Confirm( 4860b57cec5SDimitry Andric "About to delete all watchpoints, do you want to do that?", 4870b57cec5SDimitry Andric true)) { 4880b57cec5SDimitry Andric result.AppendMessage("Operation cancelled..."); 4890b57cec5SDimitry Andric } else { 4900b57cec5SDimitry Andric target->RemoveAllWatchpoints(); 4910b57cec5SDimitry Andric result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 4920b57cec5SDimitry Andric " watchpoints)\n", 4930b57cec5SDimitry Andric (uint64_t)num_watchpoints); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 4965f757f3fSDimitry Andric return; 497480093f4SDimitry Andric } 498480093f4SDimitry Andric 4990b57cec5SDimitry Andric // Particular watchpoints selected; delete them. 5000b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 501480093f4SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, 502480093f4SDimitry Andric wp_ids)) { 5030b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 5045f757f3fSDimitry Andric return; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric int count = 0; 5080b57cec5SDimitry Andric const size_t size = wp_ids.size(); 5090b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 5100b57cec5SDimitry Andric if (target->RemoveWatchpointByID(wp_ids[i])) 5110b57cec5SDimitry Andric ++count; 5120b57cec5SDimitry Andric result.AppendMessageWithFormat("%d watchpoints deleted.\n", count); 5130b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 5140b57cec5SDimitry Andric } 515480093f4SDimitry Andric 516480093f4SDimitry Andric private: 517480093f4SDimitry Andric CommandOptions m_options; 5180b57cec5SDimitry Andric }; 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric // CommandObjectWatchpointIgnore 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric #pragma mark Ignore::CommandOptions 5230b57cec5SDimitry Andric #define LLDB_OPTIONS_watchpoint_ignore 5240b57cec5SDimitry Andric #include "CommandOptions.inc" 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric class CommandObjectWatchpointIgnore : public CommandObjectParsed { 5270b57cec5SDimitry Andric public: 5280b57cec5SDimitry Andric CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) 5290b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "watchpoint ignore", 5300b57cec5SDimitry Andric "Set ignore count on the specified watchpoint(s). " 5310b57cec5SDimitry Andric "If no watchpoints are specified, set them all.", 53204eeddc0SDimitry Andric nullptr, eCommandRequiresTarget) { 533*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric ~CommandObjectWatchpointIgnore() override = default; 5370b57cec5SDimitry Andric 538e8d8bef9SDimitry Andric void 539e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 540e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 54106c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 54206c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 54306c3fb27SDimitry Andric nullptr); 544e8d8bef9SDimitry Andric } 545e8d8bef9SDimitry Andric 5460b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric class CommandOptions : public Options { 5490b57cec5SDimitry Andric public: 55081ad6265SDimitry Andric CommandOptions() = default; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric ~CommandOptions() override = default; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 5550b57cec5SDimitry Andric ExecutionContext *execution_context) override { 5560b57cec5SDimitry Andric Status error; 5570b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric switch (short_option) { 5600b57cec5SDimitry Andric case 'i': 5610b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore_count)) 5620b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid ignore count '%s'", 5630b57cec5SDimitry Andric option_arg.str().c_str()); 5640b57cec5SDimitry Andric break; 5650b57cec5SDimitry Andric default: 5669dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric return error; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 5730b57cec5SDimitry Andric m_ignore_count = 0; 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 577bdd1243dSDimitry Andric return llvm::ArrayRef(g_watchpoint_ignore_options); 5780b57cec5SDimitry Andric } 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric // Instance variables to hold the values for command options. 5810b57cec5SDimitry Andric 582fe6060f1SDimitry Andric uint32_t m_ignore_count = 0; 5830b57cec5SDimitry Andric }; 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric protected: 5865f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 5879dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 5880b57cec5SDimitry Andric if (!CheckTargetForWatchpointOperations(target, result)) 5895f757f3fSDimitry Andric return; 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 5920b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric if (num_watchpoints == 0) { 5990b57cec5SDimitry Andric result.AppendError("No watchpoints exist to be ignored."); 6005f757f3fSDimitry Andric return; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 6040b57cec5SDimitry Andric target->IgnoreAllWatchpoints(m_options.m_ignore_count); 6050b57cec5SDimitry Andric result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 6060b57cec5SDimitry Andric " watchpoints)\n", 6070b57cec5SDimitry Andric (uint64_t)num_watchpoints); 6080b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 6090b57cec5SDimitry Andric } else { 6100b57cec5SDimitry Andric // Particular watchpoints selected; ignore them. 6110b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 6120b57cec5SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 6130b57cec5SDimitry Andric target, command, wp_ids)) { 6140b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 6155f757f3fSDimitry Andric return; 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric int count = 0; 6190b57cec5SDimitry Andric const size_t size = wp_ids.size(); 6200b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) 6210b57cec5SDimitry Andric if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 6220b57cec5SDimitry Andric ++count; 6230b57cec5SDimitry Andric result.AppendMessageWithFormat("%d watchpoints ignored.\n", count); 6240b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric private: 6290b57cec5SDimitry Andric CommandOptions m_options; 6300b57cec5SDimitry Andric }; 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric // CommandObjectWatchpointModify 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric #pragma mark Modify::CommandOptions 6350b57cec5SDimitry Andric #define LLDB_OPTIONS_watchpoint_modify 6360b57cec5SDimitry Andric #include "CommandOptions.inc" 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric #pragma mark Modify 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric class CommandObjectWatchpointModify : public CommandObjectParsed { 6410b57cec5SDimitry Andric public: 6420b57cec5SDimitry Andric CommandObjectWatchpointModify(CommandInterpreter &interpreter) 6430b57cec5SDimitry Andric : CommandObjectParsed( 6440b57cec5SDimitry Andric interpreter, "watchpoint modify", 6450b57cec5SDimitry Andric "Modify the options on a watchpoint or set of watchpoints in the " 6460b57cec5SDimitry Andric "executable. " 6470b57cec5SDimitry Andric "If no watchpoint is specified, act on the last created " 6480b57cec5SDimitry Andric "watchpoint. " 6490b57cec5SDimitry Andric "Passing an empty argument clears the modification.", 65004eeddc0SDimitry Andric nullptr, eCommandRequiresTarget) { 651*0fca6ea1SDimitry Andric CommandObject::AddIDsArgumentData(eWatchpointArgs); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric ~CommandObjectWatchpointModify() override = default; 6550b57cec5SDimitry Andric 656e8d8bef9SDimitry Andric void 657e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request, 658e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override { 65906c3fb27SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 66006c3fb27SDimitry Andric GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 66106c3fb27SDimitry Andric nullptr); 662e8d8bef9SDimitry Andric } 663e8d8bef9SDimitry Andric 6640b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric class CommandOptions : public Options { 6670b57cec5SDimitry Andric public: 66881ad6265SDimitry Andric CommandOptions() = default; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric ~CommandOptions() override = default; 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 6730b57cec5SDimitry Andric ExecutionContext *execution_context) override { 6740b57cec5SDimitry Andric Status error; 6750b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val; 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric switch (short_option) { 6780b57cec5SDimitry Andric case 'c': 6795ffd83dbSDimitry Andric m_condition = std::string(option_arg); 6800b57cec5SDimitry Andric m_condition_passed = true; 6810b57cec5SDimitry Andric break; 6820b57cec5SDimitry Andric default: 6839dba64beSDimitry Andric llvm_unreachable("Unimplemented option"); 6840b57cec5SDimitry Andric } 6850b57cec5SDimitry Andric 6860b57cec5SDimitry Andric return error; 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override { 6900b57cec5SDimitry Andric m_condition.clear(); 6910b57cec5SDimitry Andric m_condition_passed = false; 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 695bdd1243dSDimitry Andric return llvm::ArrayRef(g_watchpoint_modify_options); 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric // Instance variables to hold the values for command options. 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric std::string m_condition; 701fe6060f1SDimitry Andric bool m_condition_passed = false; 7020b57cec5SDimitry Andric }; 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric protected: 7055f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 7069dba64beSDimitry Andric Target *target = &GetSelectedTarget(); 7070b57cec5SDimitry Andric if (!CheckTargetForWatchpointOperations(target, result)) 7085f757f3fSDimitry Andric return; 7090b57cec5SDimitry Andric 7100b57cec5SDimitry Andric std::unique_lock<std::recursive_mutex> lock; 7110b57cec5SDimitry Andric target->GetWatchpointList().GetListMutex(lock); 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric const WatchpointList &watchpoints = target->GetWatchpointList(); 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric size_t num_watchpoints = watchpoints.GetSize(); 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric if (num_watchpoints == 0) { 7180b57cec5SDimitry Andric result.AppendError("No watchpoints exist to be modified."); 7195f757f3fSDimitry Andric return; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric if (command.GetArgumentCount() == 0) { 72306c3fb27SDimitry Andric WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); 72406c3fb27SDimitry Andric watch_sp->SetCondition(m_options.m_condition.c_str()); 7250b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 7260b57cec5SDimitry Andric } else { 7270b57cec5SDimitry Andric // Particular watchpoints selected; set condition on them. 7280b57cec5SDimitry Andric std::vector<uint32_t> wp_ids; 7290b57cec5SDimitry Andric if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 7300b57cec5SDimitry Andric target, command, wp_ids)) { 7310b57cec5SDimitry Andric result.AppendError("Invalid watchpoints specification."); 7325f757f3fSDimitry Andric return; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric int count = 0; 7360b57cec5SDimitry Andric const size_t size = wp_ids.size(); 7370b57cec5SDimitry Andric for (size_t i = 0; i < size; ++i) { 73806c3fb27SDimitry Andric WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]); 73906c3fb27SDimitry Andric if (watch_sp) { 74006c3fb27SDimitry Andric watch_sp->SetCondition(m_options.m_condition.c_str()); 7410b57cec5SDimitry Andric ++count; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric result.AppendMessageWithFormat("%d watchpoints modified.\n", count); 7450b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult); 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric 7490b57cec5SDimitry Andric private: 7500b57cec5SDimitry Andric CommandOptions m_options; 7510b57cec5SDimitry Andric }; 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric // CommandObjectWatchpointSetVariable 7540b57cec5SDimitry Andric #pragma mark SetVariable 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric class CommandObjectWatchpointSetVariable : public CommandObjectParsed { 7570b57cec5SDimitry Andric public: 7580b57cec5SDimitry Andric CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter) 7590b57cec5SDimitry Andric : CommandObjectParsed( 7600b57cec5SDimitry Andric interpreter, "watchpoint set variable", 7610b57cec5SDimitry Andric "Set a watchpoint on a variable. " 7620b57cec5SDimitry Andric "Use the '-w' option to specify the type of watchpoint and " 7630b57cec5SDimitry Andric "the '-s' option to specify the byte size to watch for. " 7645f757f3fSDimitry Andric "If no '-w' option is specified, it defaults to modify. " 7650b57cec5SDimitry Andric "If no '-s' option is specified, it defaults to the variable's " 7660b57cec5SDimitry Andric "byte size. " 7670b57cec5SDimitry Andric "Note that there are limited hardware resources for watchpoints. " 7680b57cec5SDimitry Andric "If watchpoint setting fails, consider disable/delete existing " 7690b57cec5SDimitry Andric "ones " 7700b57cec5SDimitry Andric "to free up resources.", 7710b57cec5SDimitry Andric nullptr, 7720b57cec5SDimitry Andric eCommandRequiresFrame | eCommandTryTargetAPILock | 77304eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 7740b57cec5SDimitry Andric SetHelpLong( 7750b57cec5SDimitry Andric R"( 7760b57cec5SDimitry Andric Examples: 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric (lldb) watchpoint set variable -w read_write my_global_var 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric )" 7810b57cec5SDimitry Andric " Watches my_global_var for read/write access, with the region to watch \ 7820b57cec5SDimitry Andric corresponding to the byte size of the data type."); 7830b57cec5SDimitry Andric 784*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeVarName); 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric // Absorb the '-w' and '-s' options into our option group. 78706c3fb27SDimitry Andric m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1); 7880b57cec5SDimitry Andric m_option_group.Finalize(); 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric ~CommandObjectWatchpointSetVariable() override = default; 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric protected: 7960b57cec5SDimitry Andric static size_t GetVariableCallback(void *baton, const char *name, 7970b57cec5SDimitry Andric VariableList &variable_list) { 7989dba64beSDimitry Andric size_t old_size = variable_list.GetSize(); 7990b57cec5SDimitry Andric Target *target = static_cast<Target *>(baton); 8009dba64beSDimitry Andric if (target) 8019dba64beSDimitry Andric target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, 8029dba64beSDimitry Andric variable_list); 8039dba64beSDimitry Andric return variable_list.GetSize() - old_size; 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric 8065f757f3fSDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override { 8070b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 8080b57cec5SDimitry Andric StackFrame *frame = m_exe_ctx.GetFramePtr(); 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric // If no argument is present, issue an error message. There's no way to 8110b57cec5SDimitry Andric // set a watchpoint. 8120b57cec5SDimitry Andric if (command.GetArgumentCount() <= 0) { 813fe6060f1SDimitry Andric result.AppendError("required argument missing; " 814fe6060f1SDimitry Andric "specify your program variable to watch for"); 8155f757f3fSDimitry Andric return; 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 8185f757f3fSDimitry Andric // If no '-w' is specified, default to '-w modify'. 8190b57cec5SDimitry Andric if (!m_option_watchpoint.watch_type_specified) { 8205f757f3fSDimitry Andric m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric // We passed the sanity check for the command. Proceed to set the 8240b57cec5SDimitry Andric // watchpoint now. 8250b57cec5SDimitry Andric lldb::addr_t addr = 0; 8260b57cec5SDimitry Andric size_t size = 0; 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric VariableSP var_sp; 8290b57cec5SDimitry Andric ValueObjectSP valobj_sp; 8300b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream(); 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // A simple watch variable gesture allows only one argument. 8330b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) { 834fe6060f1SDimitry Andric result.AppendError("specify exactly one variable to watch for"); 8355f757f3fSDimitry Andric return; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric // Things have checked out ok... 8390b57cec5SDimitry Andric Status error; 8400b57cec5SDimitry Andric uint32_t expr_path_options = 8410b57cec5SDimitry Andric StackFrame::eExpressionPathOptionCheckPtrVsMember | 8420b57cec5SDimitry Andric StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; 8430b57cec5SDimitry Andric valobj_sp = frame->GetValueForVariableExpressionPath( 8440b57cec5SDimitry Andric command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options, 8450b57cec5SDimitry Andric var_sp, error); 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric if (!valobj_sp) { 8480b57cec5SDimitry Andric // Not in the frame; let's check the globals. 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric VariableList variable_list; 8510b57cec5SDimitry Andric ValueObjectList valobj_list; 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric Status error(Variable::GetValuesForVariableExpressionPath( 8540b57cec5SDimitry Andric command.GetArgumentAtIndex(0), 8550b57cec5SDimitry Andric m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target, 8560b57cec5SDimitry Andric variable_list, valobj_list)); 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric if (valobj_list.GetSize()) 8590b57cec5SDimitry Andric valobj_sp = valobj_list.GetValueObjectAtIndex(0); 8600b57cec5SDimitry Andric } 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric CompilerType compiler_type; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric if (valobj_sp) { 8650b57cec5SDimitry Andric AddressType addr_type; 8660b57cec5SDimitry Andric addr = valobj_sp->GetAddressOf(false, &addr_type); 8670b57cec5SDimitry Andric if (addr_type == eAddressTypeLoad) { 8680b57cec5SDimitry Andric // We're in business. 8690b57cec5SDimitry Andric // Find out the size of this variable. 8705f757f3fSDimitry Andric size = m_option_watchpoint.watch_size.GetCurrentValue() == 0 87181ad6265SDimitry Andric ? valobj_sp->GetByteSize().value_or(0) 8725f757f3fSDimitry Andric : m_option_watchpoint.watch_size.GetCurrentValue(); 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric compiler_type = valobj_sp->GetCompilerType(); 8750b57cec5SDimitry Andric } else { 8760b57cec5SDimitry Andric const char *error_cstr = error.AsCString(nullptr); 8770b57cec5SDimitry Andric if (error_cstr) 878fe6060f1SDimitry Andric result.AppendError(error_cstr); 8790b57cec5SDimitry Andric else 880fe6060f1SDimitry Andric result.AppendErrorWithFormat("unable to find any variable " 881fe6060f1SDimitry Andric "expression path that matches '%s'", 8820b57cec5SDimitry Andric command.GetArgumentAtIndex(0)); 8835f757f3fSDimitry Andric return; 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric // Now it's time to create the watchpoint. 8875f757f3fSDimitry Andric uint32_t watch_type = 0; 8885f757f3fSDimitry Andric switch (m_option_watchpoint.watch_type) { 8895f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchModify: 8905f757f3fSDimitry Andric watch_type |= LLDB_WATCH_TYPE_MODIFY; 8915f757f3fSDimitry Andric break; 8925f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchRead: 8935f757f3fSDimitry Andric watch_type |= LLDB_WATCH_TYPE_READ; 8945f757f3fSDimitry Andric break; 8955f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchReadWrite: 8965f757f3fSDimitry Andric watch_type |= LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; 8975f757f3fSDimitry Andric break; 8985f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchWrite: 8995f757f3fSDimitry Andric watch_type |= LLDB_WATCH_TYPE_WRITE; 9005f757f3fSDimitry Andric break; 9015f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchInvalid: 9025f757f3fSDimitry Andric break; 9035f757f3fSDimitry Andric }; 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric error.Clear(); 90606c3fb27SDimitry Andric WatchpointSP watch_sp = 90706c3fb27SDimitry Andric target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); 90806c3fb27SDimitry Andric if (!watch_sp) { 9090b57cec5SDimitry Andric result.AppendErrorWithFormat( 9100b57cec5SDimitry Andric "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 9110b57cec5SDimitry Andric ", variable expression='%s').\n", 91206c3fb27SDimitry Andric addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0)); 91306c3fb27SDimitry Andric if (const char *error_message = error.AsCString(nullptr)) 91406c3fb27SDimitry Andric result.AppendError(error_message); 9155f757f3fSDimitry Andric return; 9160b57cec5SDimitry Andric } 9170b57cec5SDimitry Andric 91806c3fb27SDimitry Andric watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0)); 91906c3fb27SDimitry Andric watch_sp->SetWatchVariable(true); 92006c3fb27SDimitry Andric if (var_sp) { 92106c3fb27SDimitry Andric if (var_sp->GetDeclaration().GetFile()) { 92206c3fb27SDimitry Andric StreamString ss; 92306c3fb27SDimitry Andric // True to show fullpath for declaration file. 92406c3fb27SDimitry Andric var_sp->GetDeclaration().DumpStopContext(&ss, true); 92506c3fb27SDimitry Andric watch_sp->SetDeclInfo(std::string(ss.GetString())); 92606c3fb27SDimitry Andric } 92706c3fb27SDimitry Andric if (var_sp->GetScope() == eValueTypeVariableLocal) 92806c3fb27SDimitry Andric watch_sp->SetupVariableWatchpointDisabler(m_exe_ctx.GetFrameSP()); 92906c3fb27SDimitry Andric } 93006c3fb27SDimitry Andric output_stream.Printf("Watchpoint created: "); 93106c3fb27SDimitry Andric watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 93206c3fb27SDimitry Andric output_stream.EOL(); 93306c3fb27SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric private: 9370b57cec5SDimitry Andric OptionGroupOptions m_option_group; 9380b57cec5SDimitry Andric OptionGroupWatchpoint m_option_watchpoint; 9390b57cec5SDimitry Andric }; 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric // CommandObjectWatchpointSetExpression 9420b57cec5SDimitry Andric #pragma mark Set 9430b57cec5SDimitry Andric 9440b57cec5SDimitry Andric class CommandObjectWatchpointSetExpression : public CommandObjectRaw { 9450b57cec5SDimitry Andric public: 9460b57cec5SDimitry Andric CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter) 9470b57cec5SDimitry Andric : CommandObjectRaw( 9480b57cec5SDimitry Andric interpreter, "watchpoint set expression", 9490b57cec5SDimitry Andric "Set a watchpoint on an address by supplying an expression. " 95006c3fb27SDimitry Andric "Use the '-l' option to specify the language of the expression. " 9510b57cec5SDimitry Andric "Use the '-w' option to specify the type of watchpoint and " 9520b57cec5SDimitry Andric "the '-s' option to specify the byte size to watch for. " 9535f757f3fSDimitry Andric "If no '-w' option is specified, it defaults to modify. " 9540b57cec5SDimitry Andric "If no '-s' option is specified, it defaults to the target's " 9550b57cec5SDimitry Andric "pointer byte size. " 9560b57cec5SDimitry Andric "Note that there are limited hardware resources for watchpoints. " 9570b57cec5SDimitry Andric "If watchpoint setting fails, consider disable/delete existing " 9580b57cec5SDimitry Andric "ones " 9590b57cec5SDimitry Andric "to free up resources.", 9600b57cec5SDimitry Andric "", 9610b57cec5SDimitry Andric eCommandRequiresFrame | eCommandTryTargetAPILock | 96204eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 9630b57cec5SDimitry Andric SetHelpLong( 9640b57cec5SDimitry Andric R"( 9650b57cec5SDimitry Andric Examples: 9660b57cec5SDimitry Andric 9675f757f3fSDimitry Andric (lldb) watchpoint set expression -w modify -s 1 -- foo + 32 9680b57cec5SDimitry Andric 9690b57cec5SDimitry Andric Watches write access for the 1-byte region pointed to by the address 'foo + 32')"); 9700b57cec5SDimitry Andric 971*0fca6ea1SDimitry Andric AddSimpleArgumentList(eArgTypeExpression); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric // Absorb the '-w' and '-s' options into our option group. 9740b57cec5SDimitry Andric m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL, 9750b57cec5SDimitry Andric LLDB_OPT_SET_1); 9760b57cec5SDimitry Andric m_option_group.Finalize(); 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric ~CommandObjectWatchpointSetExpression() override = default; 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric // Overrides base class's behavior where WantsCompletion = 9820b57cec5SDimitry Andric // !WantsRawCommandString. 9830b57cec5SDimitry Andric bool WantsCompletion() override { return true; } 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; } 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric protected: 9885f757f3fSDimitry Andric void DoExecute(llvm::StringRef raw_command, 9890b57cec5SDimitry Andric CommandReturnObject &result) override { 9900b57cec5SDimitry Andric auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 9910b57cec5SDimitry Andric m_option_group.NotifyOptionParsingStarting( 9920b57cec5SDimitry Andric &exe_ctx); // This is a raw command, so notify the option group 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get(); 9950b57cec5SDimitry Andric StackFrame *frame = m_exe_ctx.GetFramePtr(); 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric OptionsWithRaw args(raw_command); 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric llvm::StringRef expr = args.GetRawPart(); 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric if (args.HasArgs()) 10020b57cec5SDimitry Andric if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 10030b57cec5SDimitry Andric exe_ctx)) 10045f757f3fSDimitry Andric return; 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric // If no argument is present, issue an error message. There's no way to 10070b57cec5SDimitry Andric // set a watchpoint. 10080b57cec5SDimitry Andric if (raw_command.trim().empty()) { 1009fe6060f1SDimitry Andric result.AppendError("required argument missing; specify an expression " 1010fe6060f1SDimitry Andric "to evaluate into the address to watch for"); 10115f757f3fSDimitry Andric return; 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric // If no '-w' is specified, default to '-w write'. 10150b57cec5SDimitry Andric if (!m_option_watchpoint.watch_type_specified) { 10165f757f3fSDimitry Andric m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric // We passed the sanity check for the command. Proceed to set the 10200b57cec5SDimitry Andric // watchpoint now. 10210b57cec5SDimitry Andric lldb::addr_t addr = 0; 10220b57cec5SDimitry Andric size_t size = 0; 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric ValueObjectSP valobj_sp; 10250b57cec5SDimitry Andric 10260b57cec5SDimitry Andric // Use expression evaluation to arrive at the address to watch. 10270b57cec5SDimitry Andric EvaluateExpressionOptions options; 10280b57cec5SDimitry Andric options.SetCoerceToId(false); 10290b57cec5SDimitry Andric options.SetUnwindOnError(true); 10300b57cec5SDimitry Andric options.SetKeepInMemory(false); 10310b57cec5SDimitry Andric options.SetTryAllThreads(true); 1032bdd1243dSDimitry Andric options.SetTimeout(std::nullopt); 103306c3fb27SDimitry Andric if (m_option_watchpoint.language_type != eLanguageTypeUnknown) 103406c3fb27SDimitry Andric options.SetLanguage(m_option_watchpoint.language_type); 10350b57cec5SDimitry Andric 10360b57cec5SDimitry Andric ExpressionResults expr_result = 10370b57cec5SDimitry Andric target->EvaluateExpression(expr, frame, valobj_sp, options); 10380b57cec5SDimitry Andric if (expr_result != eExpressionCompleted) { 1039fe6060f1SDimitry Andric result.AppendError("expression evaluation of address to watch failed"); 1040fe6060f1SDimitry Andric result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data()); 10415ffd83dbSDimitry Andric if (valobj_sp && !valobj_sp->GetError().Success()) 1042fe6060f1SDimitry Andric result.AppendError(valobj_sp->GetError().AsCString()); 10435f757f3fSDimitry Andric return; 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric // Get the address to watch. 10470b57cec5SDimitry Andric bool success = false; 10480b57cec5SDimitry Andric addr = valobj_sp->GetValueAsUnsigned(0, &success); 10490b57cec5SDimitry Andric if (!success) { 1050fe6060f1SDimitry Andric result.AppendError("expression did not evaluate to an address"); 10515f757f3fSDimitry Andric return; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10545f757f3fSDimitry Andric if (m_option_watchpoint.watch_size.GetCurrentValue() != 0) 10555f757f3fSDimitry Andric size = m_option_watchpoint.watch_size.GetCurrentValue(); 10560b57cec5SDimitry Andric else 10570b57cec5SDimitry Andric size = target->GetArchitecture().GetAddressByteSize(); 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric // Now it's time to create the watchpoint. 10605f757f3fSDimitry Andric uint32_t watch_type; 10615f757f3fSDimitry Andric switch (m_option_watchpoint.watch_type) { 10625f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchRead: 10635f757f3fSDimitry Andric watch_type = LLDB_WATCH_TYPE_READ; 10645f757f3fSDimitry Andric break; 10655f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchWrite: 10665f757f3fSDimitry Andric watch_type = LLDB_WATCH_TYPE_WRITE; 10675f757f3fSDimitry Andric break; 10685f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchModify: 10695f757f3fSDimitry Andric watch_type = LLDB_WATCH_TYPE_MODIFY; 10705f757f3fSDimitry Andric break; 10715f757f3fSDimitry Andric case OptionGroupWatchpoint::eWatchReadWrite: 10725f757f3fSDimitry Andric watch_type = LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; 10735f757f3fSDimitry Andric break; 10745f757f3fSDimitry Andric default: 10755f757f3fSDimitry Andric watch_type = LLDB_WATCH_TYPE_MODIFY; 10765f757f3fSDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric // Fetch the type from the value object, the type of the watched object is 10790b57cec5SDimitry Andric // the pointee type 10800b57cec5SDimitry Andric /// of the expression, so convert to that if we found a valid type. 10810b57cec5SDimitry Andric CompilerType compiler_type(valobj_sp->GetCompilerType()); 10820b57cec5SDimitry Andric 1083*0fca6ea1SDimitry Andric std::optional<uint64_t> valobj_size = valobj_sp->GetByteSize(); 1084*0fca6ea1SDimitry Andric // Set the type as a uint8_t array if the size being watched is 1085*0fca6ea1SDimitry Andric // larger than the ValueObject's size (which is probably the size 1086*0fca6ea1SDimitry Andric // of a pointer). 1087*0fca6ea1SDimitry Andric if (valobj_size && size > *valobj_size) { 1088*0fca6ea1SDimitry Andric auto type_system = compiler_type.GetTypeSystem(); 1089*0fca6ea1SDimitry Andric if (type_system) { 1090*0fca6ea1SDimitry Andric CompilerType clang_uint8_type = 1091*0fca6ea1SDimitry Andric type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8); 1092*0fca6ea1SDimitry Andric compiler_type = clang_uint8_type.GetArrayType(size); 1093*0fca6ea1SDimitry Andric } 1094*0fca6ea1SDimitry Andric } 1095*0fca6ea1SDimitry Andric 10960b57cec5SDimitry Andric Status error; 109706c3fb27SDimitry Andric WatchpointSP watch_sp = 109806c3fb27SDimitry Andric target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); 109906c3fb27SDimitry Andric if (watch_sp) { 110006c3fb27SDimitry Andric watch_sp->SetWatchSpec(std::string(expr)); 11010b57cec5SDimitry Andric Stream &output_stream = result.GetOutputStream(); 11020b57cec5SDimitry Andric output_stream.Printf("Watchpoint created: "); 110306c3fb27SDimitry Andric watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 11040b57cec5SDimitry Andric output_stream.EOL(); 11050b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult); 11060b57cec5SDimitry Andric } else { 11070b57cec5SDimitry Andric result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 11080b57cec5SDimitry Andric ", size=%" PRIu64 ").\n", 11090b57cec5SDimitry Andric addr, (uint64_t)size); 11100b57cec5SDimitry Andric if (error.AsCString(nullptr)) 11110b57cec5SDimitry Andric result.AppendError(error.AsCString()); 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric private: 11160b57cec5SDimitry Andric OptionGroupOptions m_option_group; 11170b57cec5SDimitry Andric OptionGroupWatchpoint m_option_watchpoint; 11180b57cec5SDimitry Andric }; 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric // CommandObjectWatchpointSet 11210b57cec5SDimitry Andric #pragma mark Set 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric class CommandObjectWatchpointSet : public CommandObjectMultiword { 11240b57cec5SDimitry Andric public: 11250b57cec5SDimitry Andric CommandObjectWatchpointSet(CommandInterpreter &interpreter) 11260b57cec5SDimitry Andric : CommandObjectMultiword( 11270b57cec5SDimitry Andric interpreter, "watchpoint set", "Commands for setting a watchpoint.", 11280b57cec5SDimitry Andric "watchpoint set <subcommand> [<subcommand-options>]") { 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric LoadSubCommand( 11310b57cec5SDimitry Andric "variable", 11320b57cec5SDimitry Andric CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter))); 11330b57cec5SDimitry Andric LoadSubCommand( 11340b57cec5SDimitry Andric "expression", 11350b57cec5SDimitry Andric CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter))); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric ~CommandObjectWatchpointSet() override = default; 11390b57cec5SDimitry Andric }; 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric // CommandObjectMultiwordWatchpoint 11420b57cec5SDimitry Andric #pragma mark MultiwordWatchpoint 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint( 11450b57cec5SDimitry Andric CommandInterpreter &interpreter) 11460b57cec5SDimitry Andric : CommandObjectMultiword(interpreter, "watchpoint", 11470b57cec5SDimitry Andric "Commands for operating on watchpoints.", 11480b57cec5SDimitry Andric "watchpoint <subcommand> [<command-options>]") { 11490b57cec5SDimitry Andric CommandObjectSP list_command_object( 11500b57cec5SDimitry Andric new CommandObjectWatchpointList(interpreter)); 11510b57cec5SDimitry Andric CommandObjectSP enable_command_object( 11520b57cec5SDimitry Andric new CommandObjectWatchpointEnable(interpreter)); 11530b57cec5SDimitry Andric CommandObjectSP disable_command_object( 11540b57cec5SDimitry Andric new CommandObjectWatchpointDisable(interpreter)); 11550b57cec5SDimitry Andric CommandObjectSP delete_command_object( 11560b57cec5SDimitry Andric new CommandObjectWatchpointDelete(interpreter)); 11570b57cec5SDimitry Andric CommandObjectSP ignore_command_object( 11580b57cec5SDimitry Andric new CommandObjectWatchpointIgnore(interpreter)); 11590b57cec5SDimitry Andric CommandObjectSP command_command_object( 11600b57cec5SDimitry Andric new CommandObjectWatchpointCommand(interpreter)); 11610b57cec5SDimitry Andric CommandObjectSP modify_command_object( 11620b57cec5SDimitry Andric new CommandObjectWatchpointModify(interpreter)); 11630b57cec5SDimitry Andric CommandObjectSP set_command_object( 11640b57cec5SDimitry Andric new CommandObjectWatchpointSet(interpreter)); 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric list_command_object->SetCommandName("watchpoint list"); 11670b57cec5SDimitry Andric enable_command_object->SetCommandName("watchpoint enable"); 11680b57cec5SDimitry Andric disable_command_object->SetCommandName("watchpoint disable"); 11690b57cec5SDimitry Andric delete_command_object->SetCommandName("watchpoint delete"); 11700b57cec5SDimitry Andric ignore_command_object->SetCommandName("watchpoint ignore"); 11710b57cec5SDimitry Andric command_command_object->SetCommandName("watchpoint command"); 11720b57cec5SDimitry Andric modify_command_object->SetCommandName("watchpoint modify"); 11730b57cec5SDimitry Andric set_command_object->SetCommandName("watchpoint set"); 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric LoadSubCommand("list", list_command_object); 11760b57cec5SDimitry Andric LoadSubCommand("enable", enable_command_object); 11770b57cec5SDimitry Andric LoadSubCommand("disable", disable_command_object); 11780b57cec5SDimitry Andric LoadSubCommand("delete", delete_command_object); 11790b57cec5SDimitry Andric LoadSubCommand("ignore", ignore_command_object); 11800b57cec5SDimitry Andric LoadSubCommand("command", command_command_object); 11810b57cec5SDimitry Andric LoadSubCommand("modify", modify_command_object); 11820b57cec5SDimitry Andric LoadSubCommand("set", set_command_object); 11830b57cec5SDimitry Andric } 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default; 1186