1 //===-- BreakpointOptions.h -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_BREAKPOINT_BREAKPOINTOPTIONS_H 10 #define LLDB_BREAKPOINT_BREAKPOINTOPTIONS_H 11 12 #include <memory> 13 #include <string> 14 15 #include "lldb/Breakpoint/StopCondition.h" 16 #include "lldb/Utility/Baton.h" 17 #include "lldb/Utility/Flags.h" 18 #include "lldb/Utility/StringList.h" 19 #include "lldb/Utility/StructuredData.h" 20 #include "lldb/lldb-private.h" 21 22 namespace lldb_private { 23 24 /// \class BreakpointOptions BreakpointOptions.h 25 /// "lldb/Breakpoint/BreakpointOptions.h" Class that manages the options on a 26 /// breakpoint or breakpoint location. 27 28 class BreakpointOptions { 29 friend class BreakpointLocation; 30 friend class BreakpointName; 31 friend class lldb_private::BreakpointOptionGroup; 32 friend class Breakpoint; 33 34 public: 35 enum OptionKind { 36 eCallback = 1 << 0, 37 eEnabled = 1 << 1, 38 eOneShot = 1 << 2, 39 eIgnoreCount = 1 << 3, 40 eThreadSpec = 1 << 4, 41 eCondition = 1 << 5, 42 eAutoContinue = 1 << 6, 43 eAllOptions = (eCallback | eEnabled | eOneShot | eIgnoreCount | eThreadSpec 44 | eCondition | eAutoContinue) 45 }; 46 struct CommandData { 47 CommandData() = default; 48 CommandDataCommandData49 CommandData(const StringList &user_source, lldb::ScriptLanguage interp) 50 : user_source(user_source), interpreter(interp), stop_on_error(true) {} 51 52 virtual ~CommandData() = default; 53 GetSerializationKeyCommandData54 static const char *GetSerializationKey() { return "BKPTCMDData"; } 55 56 StructuredData::ObjectSP SerializeToStructuredData(); 57 58 static std::unique_ptr<CommandData> 59 CreateFromStructuredData(const StructuredData::Dictionary &options_dict, 60 Status &error); 61 62 StringList user_source; 63 std::string script_source; 64 enum lldb::ScriptLanguage interpreter = 65 lldb::eScriptLanguageNone; // eScriptLanguageNone means command 66 // interpreter. 67 bool stop_on_error = true; 68 69 private: 70 enum class OptionNames : uint32_t { 71 UserSource = 0, 72 Interpreter, 73 StopOnError, 74 LastOptionName 75 }; 76 77 static const char 78 *g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)]; 79 GetKeyCommandData80 static const char *GetKey(OptionNames enum_value) { 81 return g_option_names[static_cast<uint32_t>(enum_value)]; 82 } 83 }; 84 85 class CommandBaton : public TypedBaton<CommandData> { 86 public: CommandBaton(std::unique_ptr<CommandData> Data)87 explicit CommandBaton(std::unique_ptr<CommandData> Data) 88 : TypedBaton(std::move(Data)) {} 89 90 void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level, 91 unsigned indentation) const override; 92 }; 93 94 typedef std::shared_ptr<CommandBaton> CommandBatonSP; 95 96 // Constructors and Destructors 97 98 /// This constructor allows you to specify all the breakpoint options except 99 /// the callback. That one is more complicated, and better to do by hand. 100 /// 101 /// \param[in] condition 102 /// The expression which if it evaluates to \b true if we are to stop 103 /// 104 /// \param[in] enabled 105 /// Is this breakpoint enabled. 106 /// 107 /// \param[in] ignore 108 /// How many breakpoint hits we should ignore before stopping. 109 /// 110 /// \param[in] one_shot 111 /// Should this breakpoint delete itself after being hit once. 112 /// 113 /// \param[in] auto_continue 114 /// Should this breakpoint auto-continue after running its commands. 115 /// 116 BreakpointOptions(const char *condition, bool enabled = true, 117 int32_t ignore = 0, bool one_shot = false, 118 bool auto_continue = false); 119 120 /// Breakpoints make options with all flags set. Locations and Names make 121 /// options with no flags set. 122 BreakpointOptions(bool all_flags_set); 123 BreakpointOptions(const BreakpointOptions &rhs); 124 125 virtual ~BreakpointOptions(); 126 127 static std::unique_ptr<BreakpointOptions> 128 CreateFromStructuredData(Target &target, 129 const StructuredData::Dictionary &data_dict, 130 Status &error); 131 132 virtual StructuredData::ObjectSP SerializeToStructuredData(); 133 GetSerializationKey()134 static const char *GetSerializationKey() { return "BKPTOptions"; } 135 136 // Operators 137 const BreakpointOptions &operator=(const BreakpointOptions &rhs); 138 139 /// Copy over only the options set in the incoming BreakpointOptions. 140 void CopyOverSetOptions(const BreakpointOptions &rhs); 141 142 // Callbacks 143 // 144 // Breakpoint callbacks come in two forms, synchronous and asynchronous. 145 // Synchronous callbacks will get run before any of the thread plans are 146 // consulted, and if they return false the target will continue "under the 147 // radar" of the thread plans. There are a couple of restrictions to 148 // synchronous callbacks: 149 // 1) They should NOT resume the target themselves. 150 // Just return false if you want the target to restart. 151 // 2) Breakpoints with synchronous callbacks can't have conditions 152 // (or rather, they can have them, but they won't do anything. 153 // Ditto with ignore counts, etc... You are supposed to control that all 154 // through the callback. 155 // Asynchronous callbacks get run as part of the "ShouldStop" logic in the 156 // thread plan. The logic there is: 157 // a) If the breakpoint is thread specific and not for this thread, continue 158 // w/o running the callback. 159 // NB. This is actually enforced underneath the breakpoint system, the 160 // Process plugin is expected to 161 // call BreakpointSite::IsValidForThread, and set the thread's StopInfo 162 // to "no reason". That way, 163 // thread displays won't show stops for breakpoints not for that 164 // thread... 165 // b) If the ignore count says we shouldn't stop, then ditto. 166 // c) If the condition says we shouldn't stop, then ditto. 167 // d) Otherwise, the callback will get run, and if it returns true we will 168 // stop, and if false we won't. 169 // The asynchronous callback can run the target itself, but at present that 170 // should be the last action the callback does. We will relax this condition 171 // at some point, but it will take a bit of plumbing to get that to work. 172 // 173 174 /// Adds a callback to the breakpoint option set. 175 /// 176 /// \param[in] callback 177 /// The function to be called when the breakpoint gets hit. 178 /// 179 /// \param[in] baton_sp 180 /// A baton which will get passed back to the callback when it is invoked. 181 /// 182 /// \param[in] synchronous 183 /// Whether this is a synchronous or asynchronous callback. See discussion 184 /// above. 185 void SetCallback(BreakpointHitCallback callback, 186 const lldb::BatonSP &baton_sp, bool synchronous = false); 187 188 void SetCallback(BreakpointHitCallback callback, 189 const BreakpointOptions::CommandBatonSP &command_baton_sp, 190 bool synchronous = false); 191 192 /// Returns the command line commands for the callback on this breakpoint. 193 /// 194 /// \param[out] command_list 195 /// The commands will be appended to this list. 196 /// 197 /// \return 198 /// \b true if the command callback is a command-line callback, 199 /// \b false otherwise. 200 bool GetCommandLineCallbacks(StringList &command_list); 201 202 /// Remove the callback from this option set. 203 void ClearCallback(); 204 205 // The rest of these functions are meant to be used only within the 206 // breakpoint handling mechanism. 207 208 /// Use this function to invoke the callback for a specific stop. 209 /// 210 /// \param[in] context 211 /// The context in which the callback is to be invoked. This includes the 212 /// stop event, the 213 /// execution context of the stop (since you might hit the same breakpoint 214 /// on multiple threads) and 215 /// whether we are currently executing synchronous or asynchronous 216 /// callbacks. 217 /// 218 /// \param[in] break_id 219 /// The breakpoint ID that owns this option set. 220 /// 221 /// \param[in] break_loc_id 222 /// The breakpoint location ID that owns this option set. 223 /// 224 /// \return 225 /// The callback return value. 226 bool InvokeCallback(StoppointCallbackContext *context, 227 lldb::user_id_t break_id, lldb::user_id_t break_loc_id); 228 229 /// Used in InvokeCallback to tell whether it is the right time to run this 230 /// kind of callback. 231 /// 232 /// \return 233 /// The synchronicity of our callback. IsCallbackSynchronous()234 bool IsCallbackSynchronous() const { return m_callback_is_synchronous; } 235 236 /// Fetch the baton from the callback. 237 /// 238 /// \return 239 /// The baton. 240 Baton *GetBaton(); 241 242 /// Fetch a const version of the baton from the callback. 243 /// 244 /// \return 245 /// The baton. 246 const Baton *GetBaton() const; 247 248 // Condition 249 /// Set the breakpoint stop condition. 250 /// 251 /// \param[in] condition 252 /// The condition to evaluate when the breakpoint is hit. 253 void SetCondition(StopCondition condition); 254 255 /// Return the breakpoint condition. 256 const StopCondition &GetCondition() const; 257 StopCondition &GetCondition(); 258 259 // Enabled/Ignore Count 260 261 /// Check the Enable/Disable state. 262 /// \return 263 /// \b true if the breakpoint is enabled, \b false if disabled. IsEnabled()264 bool IsEnabled() const { return m_enabled; } 265 266 /// If \a enable is \b true, enable the breakpoint, if \b false disable it. SetEnabled(bool enabled)267 void SetEnabled(bool enabled) { 268 m_enabled = enabled; 269 m_set_flags.Set(eEnabled); 270 } 271 272 /// Check the auto-continue state. 273 /// \return 274 /// \b true if the breakpoint is set to auto-continue, \b false otherwise. IsAutoContinue()275 bool IsAutoContinue() const { return m_auto_continue; } 276 277 /// Set the auto-continue state. SetAutoContinue(bool auto_continue)278 void SetAutoContinue(bool auto_continue) { 279 m_auto_continue = auto_continue; 280 m_set_flags.Set(eAutoContinue); 281 } 282 283 /// Check the One-shot state. 284 /// \return 285 /// \b true if the breakpoint is one-shot, \b false otherwise. IsOneShot()286 bool IsOneShot() const { return m_one_shot; } 287 288 /// If \a enable is \b true, enable the breakpoint, if \b false disable it. SetOneShot(bool one_shot)289 void SetOneShot(bool one_shot) { 290 m_one_shot = one_shot; 291 m_set_flags.Set(eOneShot); 292 } 293 294 /// Set the breakpoint to ignore the next \a count breakpoint hits. 295 /// \param[in] n 296 /// The number of breakpoint hits to ignore. SetIgnoreCount(uint32_t n)297 void SetIgnoreCount(uint32_t n) { 298 m_ignore_count = n; 299 m_set_flags.Set(eIgnoreCount); 300 } 301 302 /// Return the current Ignore Count. 303 /// \return 304 /// The number of breakpoint hits to be ignored. GetIgnoreCount()305 uint32_t GetIgnoreCount() const { return m_ignore_count; } 306 307 /// Return the current thread spec for this option. This will return nullptr 308 /// if the no thread specifications have been set for this Option yet. 309 /// \return 310 /// The thread specification pointer for this option, or nullptr if none 311 /// has 312 /// been set yet. 313 const ThreadSpec *GetThreadSpecNoCreate() const; 314 315 /// Returns a pointer to the ThreadSpec for this option, creating it. if it 316 /// hasn't been created already. This API is used for setting the 317 /// ThreadSpec items for this option. 318 ThreadSpec *GetThreadSpec(); 319 320 void SetThreadID(lldb::tid_t thread_id); 321 322 void GetDescription(Stream *s, lldb::DescriptionLevel level) const; 323 324 /// Check if the breakpoint option has a callback set. 325 /// 326 /// \return 327 /// If the breakpoint option has a callback, \b true otherwise \b false. 328 bool HasCallback() const; 329 330 /// This is the default empty callback. 331 static bool NullCallback(void *baton, StoppointCallbackContext *context, 332 lldb::user_id_t break_id, 333 lldb::user_id_t break_loc_id); 334 335 /// Set a callback based on BreakpointOptions::CommandData. \param[in] 336 /// cmd_data 337 /// A UP holding the new'ed CommandData object. 338 /// The breakpoint will take ownership of pointer held by this object. 339 void SetCommandDataCallback(std::unique_ptr<CommandData> &cmd_data); 340 341 void Clear(); 342 AnySet()343 bool AnySet() const { 344 return m_set_flags.AnySet(eAllOptions); 345 } 346 347 protected: 348 // Classes that inherit from BreakpointOptions can see and modify these IsOptionSet(OptionKind kind)349 bool IsOptionSet(OptionKind kind) 350 { 351 return m_set_flags.Test(kind); 352 } 353 354 enum class OptionNames { 355 ConditionText = 0, 356 IgnoreCount, 357 EnabledState, 358 OneShotState, 359 AutoContinue, 360 LastOptionName 361 }; 362 static const char *g_option_names[(size_t)OptionNames::LastOptionName]; 363 GetKey(OptionNames enum_value)364 static const char *GetKey(OptionNames enum_value) { 365 return g_option_names[(size_t)enum_value]; 366 } 367 368 static bool BreakpointOptionsCallbackFunction( 369 void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, 370 lldb::user_id_t break_loc_id); 371 372 void SetThreadSpec(std::unique_ptr<ThreadSpec> &thread_spec_up); 373 374 private: 375 /// For BreakpointOptions only 376 377 /// This is the callback function pointer 378 BreakpointHitCallback m_callback; 379 /// This is the client data for the callback 380 lldb::BatonSP m_callback_baton_sp; 381 bool m_baton_is_command_baton; 382 bool m_callback_is_synchronous; 383 bool m_enabled; 384 /// If set, the breakpoint delete itself after being hit once. 385 bool m_one_shot; 386 /// Number of times to ignore this breakpoint. 387 uint32_t m_ignore_count; 388 /// Thread for which this breakpoint will stop. 389 std::unique_ptr<ThreadSpec> m_thread_spec_up; 390 /// The condition to test. 391 StopCondition m_condition; 392 /// If set, inject breakpoint condition into process. 393 bool m_inject_condition; 394 /// If set, auto-continue from breakpoint. 395 bool m_auto_continue; 396 /// Which options are set at this level. 397 /// Drawn from BreakpointOptions::SetOptionsFlags. 398 Flags m_set_flags; 399 }; 400 401 } // namespace lldb_private 402 403 #endif // LLDB_BREAKPOINT_BREAKPOINTOPTIONS_H 404