@@ -3,8 +3,9 @@ libtracefs(3)
NAME
----
-tracefs_kprobe_alloc, tracefs_kretprobe_alloc, tracefs_kprobe_raw, tracefs_kretprobe_raw -
-Allocate, get, and create kprobes
+tracefs_kprobe_alloc, tracefs_kretprobe_alloc, tracefs_kprobe_raw, tracefs_kretprobe_raw,
+tracefs_kprobe_destroy -
+Allocate, get, create, and remove kprobes
SYNOPSIS
--------
@@ -22,6 +23,8 @@ int *tracefs_kprobe_raw*(const char pass:[*]_system_, const char pass:[*]_event_
const char pass:[*]_addr_, const char pass:[*]_format_);
int *tracefs_kretprobe_raw*(const char pass:[*]_system_, const char pass:[*]_event_,
const char pass:[*]_addr_, const char pass:[*]_format_);
+int *tracefs_kprobe_destroy*(const char pass:[*]_system_, const char pass:[*]_event_,
+ const char pass:[*]_addr_, const char pass:[*]_format_, bool _force_);
--
DESCRIPTION
@@ -49,6 +52,9 @@ document.
creates a kretprobe instead of a kprobe. The difference is also described
in the Linux kernel source in the Documentation/trace/kprobetrace.rst file.
+*tracefs_kprobe_destroy*() will destroy a specific kprobe or kretprobe created by
+*tracefs_kprobe_raw*() or *tracefs_kretprobe_raw*() with the same parameters.
+
RETURN VALUE
------------
@@ -61,6 +67,10 @@ tracefs_dynevent structure, describing the probe. This pointer must be freed by
*tracefs_dynevent_free*(3). Note, this only allocates a descriptor representing the kprobe. It does
not modify the running system.
+The *tracefs_kprobe_destroy*() returns 0 on success or -1 on error if it was not able to
+successful destory (or find) the kprobe or kretprobe.
+
+
ERRORS
------
The following errors are for all the above calls:
@@ -325,6 +325,8 @@ int tracefs_kprobe_raw(const char *system, const char *event,
const char *addr, const char *format);
int tracefs_kretprobe_raw(const char *system, const char *event,
const char *addr, const char *format);
+int tracefs_kprobe_destroy(const char *system, const char *event,
+ const char *addr, const char *format, bool force);
enum tracefs_hist_key_type {
TRACEFS_HIST_KEY_NORMAL = 0,
@@ -63,6 +63,8 @@ $(EXAMPLES): $(patsubst %,$(sdir)/%,$(TARGETS))
#
# $(bdir)/XX.o: $(bdir)/XX.c
# $(CC) -g -Wall $(CFLAGS) -c -o $@ $^ -I../include/ $(LIBTRACEEVENT_INCLUDES)
+$(bdir)/kprobes.o: $(bdir)/kprobes.c
+ $(CC) -g -Wall $(CFLAGS) -c -o $@ $^ -I../include/ $(LIBTRACEEVENT_INCLUDES)
$(bdir)/%.o: $(bdir)/%.c
$(call do_sample_obj,$@,$^)
@@ -196,3 +196,33 @@ int tracefs_kretprobe_raw(const char *system, const char *event,
{
return kprobe_raw(TRACEFS_DYNEVENT_KRETPROBE, system, event, addr, format);
}
+
+/**
+ * tracefs_kprobe_destroy - Remove an individual kprobe or kretprobe
+ * @system: The system of the kprobe to remove (could be NULL)
+ * @event: The event of the kprobe or kretprobe to remove
+ * @addr: The address used to create the kprobe
+ * @format: The format used to create the kprobe
+ * @force: If true, try to disable the kprobe/kretprobe first
+ *
+ * This removes the kprobe or kretprobe that was created by
+ * tracefs_kprobe_raw() or tracefs_kretprobe_raw().
+ *
+ * Returns 0 on success and -1 otherwise.
+ */
+int tracefs_kprobe_destroy(const char *system, const char *event,
+ const char *addr, const char *format, bool force)
+{
+ struct tracefs_dynevent *kp;
+ int ret;
+
+ kp = tracefs_kprobe_alloc(system, event, addr, format);
+ if (!kp)
+ return -1;
+
+ ret = tracefs_dynevent_destroy(kp, force);
+
+ tracefs_dynevent_free(kp);
+
+ return ret;
+}
@@ -1368,7 +1368,23 @@ static void test_kprobes_instance(struct tracefs_instance *instance)
tracefs_dynevent_list_free(devents);
devents = NULL;
- destroy_dynevents(TRACEFS_DYNEVENT_KPROBE | TRACEFS_DYNEVENT_KRETPROBE);
+ /* Try destroying all the events using tracefs_kprobe_destroy */
+ for (i = 0; i < kprobe_count; i++) {
+ ret = tracefs_kprobe_destroy(ktests[i].system, ktests[i].event,
+ ktests[i].address, ktests[i].format, true);
+ CU_TEST(ret == 0);
+ get_dynevents_check(TRACEFS_DYNEVENT_KPROBE, kprobe_count - (i + 1));
+ }
+ get_dynevents_check(TRACEFS_DYNEVENT_KPROBE, 0);
+
+ for (i = 0; i < kretprobe_count; i++) {
+ ret = tracefs_kprobe_destroy(kretests[i].system, kretests[i].event,
+ kretests[i].address, kretests[i].format, true);
+ CU_TEST(ret == 0);
+ get_dynevents_check(TRACEFS_DYNEVENT_KRETPROBE, kretprobe_count - (i + 1));
+ }
+ get_dynevents_check(TRACEFS_DYNEVENT_KRETPROBE, 0);
+
free(dkretprobe);
free(dkprobe);
tep_free(tep);