977 lines
27 KiB
C
977 lines
27 KiB
C
|
/* ide-debugger-breakpoint.c
|
||
|
*
|
||
|
* Copyright 2017-2019 Christian Hergert <chergert@redhat.com>
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
*/
|
||
|
|
||
|
#define G_LOG_DOMAIN "ide-debugger-breakpoint"
|
||
|
|
||
|
#include "config.h"
|
||
|
|
||
|
#include "ide-debugger-breakpoint.h"
|
||
|
#include "ide-debugger-private.h"
|
||
|
#include "ide-debugger-types.h"
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
gchar *function;
|
||
|
gchar *id;
|
||
|
gchar *file;
|
||
|
gchar *spec;
|
||
|
gchar *thread;
|
||
|
|
||
|
guint line;
|
||
|
|
||
|
IdeDebuggerDisposition disposition : 8;
|
||
|
IdeDebuggerBreakMode mode : 8;
|
||
|
guint enabled : 1;
|
||
|
|
||
|
IdeDebuggerAddress address;
|
||
|
gint64 count;
|
||
|
} IdeDebuggerBreakpointPrivate;
|
||
|
|
||
|
enum {
|
||
|
PROP_0,
|
||
|
PROP_ADDRESS,
|
||
|
PROP_COUNT,
|
||
|
PROP_DISPOSITION,
|
||
|
PROP_ENABLED,
|
||
|
PROP_FILE,
|
||
|
PROP_FUNCTION,
|
||
|
PROP_ID,
|
||
|
PROP_LINE,
|
||
|
PROP_MODE,
|
||
|
PROP_SPEC,
|
||
|
PROP_THREAD,
|
||
|
N_PROPS
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
RESET,
|
||
|
N_SIGNALS
|
||
|
};
|
||
|
|
||
|
G_DEFINE_TYPE_WITH_PRIVATE (IdeDebuggerBreakpoint, ide_debugger_breakpoint, G_TYPE_OBJECT)
|
||
|
|
||
|
static GParamSpec *properties [N_PROPS];
|
||
|
static guint signals [N_SIGNALS];
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_real_reset (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_assert (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
g_clear_pointer (&priv->id, g_free);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ID]);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_finalize (GObject *object)
|
||
|
{
|
||
|
IdeDebuggerBreakpoint *self = (IdeDebuggerBreakpoint *)object;
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_clear_pointer (&priv->function, g_free);
|
||
|
g_clear_pointer (&priv->id, g_free);
|
||
|
g_clear_pointer (&priv->file, g_free);
|
||
|
g_clear_pointer (&priv->spec, g_free);
|
||
|
g_clear_pointer (&priv->thread, g_free);
|
||
|
|
||
|
G_OBJECT_CLASS (ide_debugger_breakpoint_parent_class)->finalize (object);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_get_property (GObject *object,
|
||
|
guint prop_id,
|
||
|
GValue *value,
|
||
|
GParamSpec *pspec)
|
||
|
{
|
||
|
IdeDebuggerBreakpoint *self = IDE_DEBUGGER_BREAKPOINT (object);
|
||
|
|
||
|
switch (prop_id)
|
||
|
{
|
||
|
case PROP_ADDRESS:
|
||
|
g_value_set_uint64 (value, ide_debugger_breakpoint_get_address (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_ID:
|
||
|
g_value_set_string (value, ide_debugger_breakpoint_get_id (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_COUNT:
|
||
|
g_value_set_int64 (value, ide_debugger_breakpoint_get_count (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_DISPOSITION:
|
||
|
g_value_set_enum (value, ide_debugger_breakpoint_get_disposition (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_ENABLED:
|
||
|
g_value_set_boolean (value, ide_debugger_breakpoint_get_enabled (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_FILE:
|
||
|
g_value_set_string (value, ide_debugger_breakpoint_get_file (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_FUNCTION:
|
||
|
g_value_set_string (value, ide_debugger_breakpoint_get_function (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_LINE:
|
||
|
g_value_set_uint (value, ide_debugger_breakpoint_get_line (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_MODE:
|
||
|
g_value_set_enum (value, ide_debugger_breakpoint_get_mode (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_SPEC:
|
||
|
g_value_set_string (value, ide_debugger_breakpoint_get_spec (self));
|
||
|
break;
|
||
|
|
||
|
case PROP_THREAD:
|
||
|
g_value_set_string (value, ide_debugger_breakpoint_get_thread (self));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_set_property (GObject *object,
|
||
|
guint prop_id,
|
||
|
const GValue *value,
|
||
|
GParamSpec *pspec)
|
||
|
{
|
||
|
IdeDebuggerBreakpoint *self = IDE_DEBUGGER_BREAKPOINT (object);
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
switch (prop_id)
|
||
|
{
|
||
|
case PROP_ADDRESS:
|
||
|
ide_debugger_breakpoint_set_address (self, g_value_get_uint64 (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_ID:
|
||
|
priv->id = g_value_dup_string (value);
|
||
|
break;
|
||
|
|
||
|
case PROP_COUNT:
|
||
|
ide_debugger_breakpoint_set_count (self, g_value_get_int64 (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_DISPOSITION:
|
||
|
ide_debugger_breakpoint_set_disposition (self, g_value_get_enum (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_ENABLED:
|
||
|
ide_debugger_breakpoint_set_enabled (self, g_value_get_boolean (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_FILE:
|
||
|
ide_debugger_breakpoint_set_file (self, g_value_get_string (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_FUNCTION:
|
||
|
ide_debugger_breakpoint_set_function (self, g_value_get_string (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_LINE:
|
||
|
ide_debugger_breakpoint_set_line (self, g_value_get_uint (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_MODE:
|
||
|
ide_debugger_breakpoint_set_mode (self, g_value_get_enum (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_SPEC:
|
||
|
ide_debugger_breakpoint_set_spec (self, g_value_get_string (value));
|
||
|
break;
|
||
|
|
||
|
case PROP_THREAD:
|
||
|
ide_debugger_breakpoint_set_thread (self, g_value_get_string (value));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_class_init (IdeDebuggerBreakpointClass *klass)
|
||
|
{
|
||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
|
|
||
|
object_class->finalize = ide_debugger_breakpoint_finalize;
|
||
|
object_class->get_property = ide_debugger_breakpoint_get_property;
|
||
|
object_class->set_property = ide_debugger_breakpoint_set_property;
|
||
|
|
||
|
klass->reset = ide_debugger_breakpoint_real_reset;
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:address:
|
||
|
*
|
||
|
* The address of the breakpoint, if available.
|
||
|
*
|
||
|
* Builder only supports up to 64-bit addresses at this time.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_ADDRESS] =
|
||
|
g_param_spec_uint64 ("address",
|
||
|
"Address",
|
||
|
"The address of the breakpoint",
|
||
|
0, G_MAXUINT64, IDE_DEBUGGER_ADDRESS_INVALID,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:count:
|
||
|
*
|
||
|
* The number of times the breakpoint has been reached.
|
||
|
*
|
||
|
* This is backend specific, and may not be supported by all backends.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_COUNT] =
|
||
|
g_param_spec_int64 ("count",
|
||
|
"Count",
|
||
|
"The number of times the breakpoint has hit",
|
||
|
0, G_MAXINT64, 0,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:disposition:
|
||
|
*
|
||
|
* This property describes what should happen to the breakpoint upon the
|
||
|
* next stop of the debugger.
|
||
|
*
|
||
|
* Generally, breakpoints are kept. But some backends allow you to remove
|
||
|
* a breakpoint upon the next stop of the debugger or when the breakpoint
|
||
|
* is next reached.
|
||
|
*
|
||
|
* This is backend specific, and not all values may be supported by all
|
||
|
* backends.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_DISPOSITION] =
|
||
|
g_param_spec_enum ("disposition",
|
||
|
"Disposition",
|
||
|
"The disposition of the breakpoint",
|
||
|
IDE_TYPE_DEBUGGER_DISPOSITION,
|
||
|
IDE_DEBUGGER_DISPOSITION_KEEP,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:enabled:
|
||
|
*
|
||
|
* This property is %TRUE when the breakpoint is enabled.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_ENABLED] =
|
||
|
g_param_spec_boolean ("enabled",
|
||
|
"Enabled",
|
||
|
"Enabled",
|
||
|
TRUE,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:function:
|
||
|
*
|
||
|
* The name of the function containing the breakpoint.
|
||
|
*
|
||
|
* The value of this is backend specific and may look vastly different
|
||
|
* based on the language being debugged.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_FUNCTION] =
|
||
|
g_param_spec_string ("function",
|
||
|
"Function",
|
||
|
"Function",
|
||
|
NULL,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:id:
|
||
|
*
|
||
|
* The identifier of the breakpoint.
|
||
|
*
|
||
|
* This is backend specific.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_ID] =
|
||
|
g_param_spec_string ("id",
|
||
|
"Identifier",
|
||
|
"The identifier for the breakpoint",
|
||
|
NULL,
|
||
|
(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:file:
|
||
|
*
|
||
|
* The file containing the breakpoint, if any.
|
||
|
*
|
||
|
* If the breakpoint exists at an assembly instruction that cannot be
|
||
|
* represented by a file, this will be %NULL.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_FILE] =
|
||
|
g_param_spec_string ("file",
|
||
|
"File",
|
||
|
"The file containing the breakpoint",
|
||
|
NULL,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:line:
|
||
|
*
|
||
|
* The line number within #IdeDebuggerBreakpoint:file where the
|
||
|
* breakpoint exists.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_LINE] =
|
||
|
g_param_spec_uint ("line",
|
||
|
"Line",
|
||
|
"Line",
|
||
|
0, G_MAXUINT, 0,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:mode:
|
||
|
*
|
||
|
* The mode of the breakpoint, such as a breakpoint, countpoint, or watchpoint.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_MODE] =
|
||
|
g_param_spec_enum ("mode",
|
||
|
"Mode",
|
||
|
"The breakpoint mode",
|
||
|
IDE_TYPE_DEBUGGER_BREAK_MODE,
|
||
|
IDE_DEBUGGER_BREAK_BREAKPOINT,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:spec:
|
||
|
*
|
||
|
* The specification for the breakpoint, which may be used by watchpoints
|
||
|
* to determine of the breakpoint should be applied while executing.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_SPEC] =
|
||
|
g_param_spec_string ("spec",
|
||
|
"Spec",
|
||
|
"The specification for a data breakpoint",
|
||
|
NULL,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint:thread:
|
||
|
*
|
||
|
* The thread the breakpoint is currently stopped in, or %NULL.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
properties [PROP_THREAD] =
|
||
|
g_param_spec_string ("thread",
|
||
|
"Thread",
|
||
|
"Thread",
|
||
|
NULL,
|
||
|
(G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
|
||
|
|
||
|
g_object_class_install_properties (object_class, N_PROPS, properties);
|
||
|
|
||
|
/**
|
||
|
* IdeDebuggerBreakpoint::reset:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* The "reset" signal is emitted after the debugger has exited so that the
|
||
|
* breakpoint can reset any internal state. This allows the breakpoint to be
|
||
|
* propagated to the next debugger instance, allowing the user to move
|
||
|
* between debugger sessions without loosing state.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
signals [RESET] =
|
||
|
g_signal_new ("reset",
|
||
|
G_TYPE_FROM_CLASS (klass),
|
||
|
G_SIGNAL_RUN_LAST,
|
||
|
G_STRUCT_OFFSET (IdeDebuggerBreakpointClass, reset),
|
||
|
NULL, NULL,
|
||
|
g_cclosure_marshal_VOID__VOID,
|
||
|
G_TYPE_NONE, 0);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
ide_debugger_breakpoint_init (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
priv->disposition = IDE_DEBUGGER_DISPOSITION_KEEP;
|
||
|
priv->enabled = TRUE;
|
||
|
priv->mode = IDE_DEBUGGER_BREAK_BREAKPOINT;
|
||
|
}
|
||
|
|
||
|
IdeDebuggerBreakpoint *
|
||
|
ide_debugger_breakpoint_new (const gchar *id)
|
||
|
{
|
||
|
return g_object_new (IDE_TYPE_DEBUGGER_BREAKPOINT,
|
||
|
"id", id,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_id:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the identifier for the breakpoint that is backend specific.
|
||
|
*
|
||
|
* Returns: the id of the breakpoint
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
const gchar *
|
||
|
ide_debugger_breakpoint_get_id (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
|
||
|
|
||
|
return priv->id;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_address:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "address" property, which defines where the breakpoint is
|
||
|
* located in memory.
|
||
|
*
|
||
|
* Builder only supports up to 64-bit addresses at this time.
|
||
|
*
|
||
|
* Returns: The address of the breakpoint, if any.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
IdeDebuggerAddress
|
||
|
ide_debugger_breakpoint_get_address (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), IDE_DEBUGGER_ADDRESS_INVALID);
|
||
|
|
||
|
return priv->address;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_address:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
* @address: The address of the breakpoint
|
||
|
*
|
||
|
* Sets the address of the breakpoint, if any.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_address (IdeDebuggerBreakpoint *self,
|
||
|
IdeDebuggerAddress address)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (priv->address != address)
|
||
|
{
|
||
|
priv->address = address;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ADDRESS]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_file:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the file that contains the breakpoint. This may be %NULL, particularly
|
||
|
* if the breakpoint does not exist with in a known file, such as at a memory
|
||
|
* address.
|
||
|
*
|
||
|
* Returns: (nullable): The file containing the breakpoint, or %NULL
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
const gchar *
|
||
|
ide_debugger_breakpoint_get_file (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
|
||
|
|
||
|
return priv->file;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_file:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
* @file: (nullable): the file containing the breakpoint, or %NULL
|
||
|
*
|
||
|
* Sets the file that contains the breakpoint, if any.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_file (IdeDebuggerBreakpoint *self,
|
||
|
const gchar *file)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (g_strcmp0 (file, priv->file) != 0)
|
||
|
{
|
||
|
g_free (priv->file);
|
||
|
priv->file = g_strdup (file);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_spec:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "spec" property of the breakpoint.
|
||
|
*
|
||
|
* The spec is used when the #IdeDebuggerBreakMode is
|
||
|
* %IDE_DEBUGGER_BREAK_WATCHPOINT.
|
||
|
*
|
||
|
* Returns: (nullable): A string containing the spec, or %NULL
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
const gchar *
|
||
|
ide_debugger_breakpoint_get_spec (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
|
||
|
|
||
|
return priv->spec;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_spec:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
* @spec: (nullable): the specification or %NULL
|
||
|
*
|
||
|
* Sets the specification for the debugger breakpoint. This describes
|
||
|
* a statement which the debugger can use to determine of the breakpoint
|
||
|
* should be applied when stopping the debugger.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_spec (IdeDebuggerBreakpoint *self,
|
||
|
const gchar *spec)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (g_strcmp0 (spec, priv->spec) != 0)
|
||
|
{
|
||
|
g_free (priv->spec);
|
||
|
priv->spec = g_strdup (spec);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPEC]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_count:
|
||
|
*
|
||
|
* Gets the number of times the breakpoint has been reached, if supported
|
||
|
* by the debugger backend.
|
||
|
*
|
||
|
* Returns: An integer greater than or equal to zero representing the
|
||
|
* number of times the breakpoint has been reached.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
gint64
|
||
|
ide_debugger_breakpoint_get_count (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
|
||
|
|
||
|
return priv->count;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_count:
|
||
|
*
|
||
|
* Sets the number of times the breakpoint has been reached if the
|
||
|
* breakpoint is a countpoint (or if the backend supports counting of
|
||
|
* regular breakpoints).
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_count (IdeDebuggerBreakpoint *self,
|
||
|
gint64 count)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (priv->count != count)
|
||
|
{
|
||
|
priv->count = count;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_COUNT]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_mode:
|
||
|
*
|
||
|
* Gets teh mode for the breakpoint. This describes if the breakpoint
|
||
|
* is a normal breakpoint type, countpoint, or watchpoint.
|
||
|
*
|
||
|
* See also: #IdeDebuggerBreakMode
|
||
|
*
|
||
|
* Returns: The mode of the breakpoint
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
IdeDebuggerBreakMode
|
||
|
ide_debugger_breakpoint_get_mode (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
|
||
|
|
||
|
return priv->mode;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_mode:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
* @mode: An #IdeDebuggerBreakMode
|
||
|
*
|
||
|
* Sets the "mode" property for the breakpoint.
|
||
|
*
|
||
|
* This should represent the mode for which the breakpoint is used.
|
||
|
*
|
||
|
* For example, if it is a countpoint (a breakpoint which increments a
|
||
|
* counter), you would use %IDE_DEBUGGER_BREAK_COUNTPOINT.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_mode (IdeDebuggerBreakpoint *self,
|
||
|
IdeDebuggerBreakMode mode)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAK_MODE (mode));
|
||
|
|
||
|
if (priv->mode != mode)
|
||
|
{
|
||
|
priv->mode = mode;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MODE]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_disposition:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "disposition" property of the breakpoint.
|
||
|
*
|
||
|
* Returns: An #IdeDebugerDisposition
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
IdeDebuggerDisposition
|
||
|
ide_debugger_breakpoint_get_disposition (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
|
||
|
|
||
|
return priv->disposition;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_disposition:
|
||
|
* @self: an #IdeDebuggerBreakpoint
|
||
|
* @disposition: an #IdeDebuggerDisposition
|
||
|
*
|
||
|
* Sets the "disposition" property.
|
||
|
*
|
||
|
* The disposition property is used to to track what should happen to a
|
||
|
* breakpoint when movements are made in the debugger.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_disposition (IdeDebuggerBreakpoint *self,
|
||
|
IdeDebuggerDisposition disposition)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_DISPOSITION (disposition));
|
||
|
|
||
|
if (disposition != priv->disposition)
|
||
|
{
|
||
|
priv->disposition = disposition;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DISPOSITION]);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ENABLED]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_enabled:
|
||
|
*
|
||
|
* Checks if the breakpoint is enabled.
|
||
|
*
|
||
|
* Returns: %TRUE if the breakpoint is enabled
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
gboolean
|
||
|
ide_debugger_breakpoint_get_enabled (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), FALSE);
|
||
|
|
||
|
return priv->enabled;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_enabled:
|
||
|
* @self: a #IdeDebuggerBreakpoint
|
||
|
* @enabled: if the breakpoint is enabled
|
||
|
*
|
||
|
* Sets the enabled state of the breakpoint instance.
|
||
|
*
|
||
|
* You must call ide_debugger_breakpoint_modify_breakpoint_async() to actually
|
||
|
* modify the breakpoint in the backend.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_enabled (IdeDebuggerBreakpoint *self,
|
||
|
gboolean enabled)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
enabled = !!enabled;
|
||
|
|
||
|
if (priv->enabled != enabled)
|
||
|
{
|
||
|
priv->enabled = enabled;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ENABLED]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_function:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "function" property of the breakpoint.
|
||
|
*
|
||
|
* This is a user-readable value representing the name of the function.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
const gchar *
|
||
|
ide_debugger_breakpoint_get_function (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
|
||
|
|
||
|
return priv->function;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_function:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
* @function: (nullable): the name of the function, or %NULL
|
||
|
*
|
||
|
* Sets the "function" property, which is a user-readable value representing
|
||
|
* the name of the function.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_function (IdeDebuggerBreakpoint *self,
|
||
|
const gchar *function)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (g_strcmp0 (function, priv->function) != 0)
|
||
|
{
|
||
|
g_free (priv->function);
|
||
|
priv->function = g_strdup (function);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FUNCTION]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_line:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "line" property, which is the line number within the file
|
||
|
* that contains the breakpoint.
|
||
|
*
|
||
|
* This value is indexed from 1, and 0 indicates that the value is unset.
|
||
|
*
|
||
|
* Returns: An integer greater than 0 if set, otherwise 0.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
guint
|
||
|
ide_debugger_breakpoint_get_line (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), 0);
|
||
|
|
||
|
return priv->line;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_line:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Sets the line for the breakpoint. A value of 0 means the line is unset.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_line (IdeDebuggerBreakpoint *self,
|
||
|
guint line)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (priv->line != line)
|
||
|
{
|
||
|
priv->line = line;
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LINE]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_get_thread:
|
||
|
* @self: An #IdeDebuggerBreakpoint
|
||
|
*
|
||
|
* Gets the "thread" property, which is the thread the breakpoint is
|
||
|
* currently stopped in (if any).
|
||
|
*
|
||
|
* Returns: (nullable): the thread identifier or %NULL
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
const gchar *
|
||
|
ide_debugger_breakpoint_get_thread (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_val_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self), NULL);
|
||
|
|
||
|
return priv->thread;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ide_debugger_breakpoint_set_thread:
|
||
|
*
|
||
|
* Sets the thread that the breakpoint is currently stopped in.
|
||
|
*
|
||
|
* This should generally only be used by debugger implementations.
|
||
|
*
|
||
|
* Since: 3.32
|
||
|
*/
|
||
|
void
|
||
|
ide_debugger_breakpoint_set_thread (IdeDebuggerBreakpoint *self,
|
||
|
const gchar *thread)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv = ide_debugger_breakpoint_get_instance_private (self);
|
||
|
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
if (g_strcmp0 (priv->thread, thread) != 0)
|
||
|
{
|
||
|
g_free (priv->thread);
|
||
|
priv->thread = g_strdup (thread);
|
||
|
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_THREAD]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gint
|
||
|
ide_debugger_breakpoint_compare (IdeDebuggerBreakpoint *a,
|
||
|
IdeDebuggerBreakpoint *b)
|
||
|
{
|
||
|
IdeDebuggerBreakpointPrivate *priv_a = ide_debugger_breakpoint_get_instance_private (a);
|
||
|
IdeDebuggerBreakpointPrivate *priv_b = ide_debugger_breakpoint_get_instance_private (b);
|
||
|
|
||
|
if (a == b)
|
||
|
return 0;
|
||
|
|
||
|
/* Rely on pointer comparison for breakpoints that
|
||
|
* don't yet have an identifier.
|
||
|
*/
|
||
|
if (priv_a->id == NULL && priv_b->id == NULL)
|
||
|
return a - b;
|
||
|
|
||
|
if (priv_a->id && priv_b->id)
|
||
|
{
|
||
|
if (g_ascii_isdigit (*priv_a->id) && g_ascii_isdigit (*priv_b->id))
|
||
|
return g_ascii_strtoll (priv_a->id, NULL, 10) -
|
||
|
g_ascii_strtoll (priv_b->id, NULL, 10);
|
||
|
}
|
||
|
|
||
|
return g_strcmp0 (priv_a->id, priv_b->id);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
_ide_debugger_breakpoint_reset (IdeDebuggerBreakpoint *self)
|
||
|
{
|
||
|
g_return_if_fail (IDE_IS_DEBUGGER_BREAKPOINT (self));
|
||
|
|
||
|
g_signal_emit (self, signals [RESET], 0);
|
||
|
}
|