+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_tracepoint_location_probe_name,
+ probe_name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Close the userspace probe tracepoint attribute. */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * Save the userspace probe function event associated with the event to the
+ * config writer.
+ */
+static
+int save_kernel_userspace_probe_function_event(struct config_writer *writer,
+ struct ltt_kernel_event *event)
+{
+ int ret = 0;
+ const char *function_name, *binary_path;
+ const struct lttng_userspace_probe_location *userspace_probe_location;
+ const struct lttng_userspace_probe_location_lookup_method *lookup_method;
+ enum lttng_userspace_probe_location_lookup_method_type lookup_type;
+
+ /* Get userspace probe location from the event. */
+ userspace_probe_location = event->userspace_probe_location;
+ if (!userspace_probe_location) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Get lookup method and lookup method type. */
+ lookup_method = lttng_userspace_probe_location_get_lookup_method(
+ userspace_probe_location);
+ if (!lookup_method) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Get the binary path and the function name. */
+ binary_path =
+ lttng_userspace_probe_location_function_get_binary_path(
+ userspace_probe_location);
+ if (!binary_path) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ function_name =
+ lttng_userspace_probe_location_function_get_function_name(
+ userspace_probe_location);
+ if (!function_name) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Open a userspace probe function attribute. */
+ ret = config_writer_open_element(writer,
+ config_element_userspace_probe_function_attributes);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ lookup_type = lttng_userspace_probe_location_lookup_method_get_type(lookup_method);
+ switch (lookup_type) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_lookup,
+ config_element_userspace_probe_lookup_function_elf);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_lookup,
+ config_element_userspace_probe_lookup_function_default);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ default:
+ ERR("Unsupported kernel userspace probe function lookup method.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* Write the binary path and the function name. */
+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_location_binary_path,
+ binary_path);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_function_location_function_name,
+ function_name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Close the userspace probe function attribute. */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int save_kernel_userspace_probe_event(struct config_writer *writer,
+ struct ltt_kernel_event *event)
+{
+ int ret;
+ struct lttng_userspace_probe_location *userspace_probe_location;
+
+ /* Get userspace probe location from the event. */
+ userspace_probe_location = event->userspace_probe_location;
+ if (!userspace_probe_location) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ switch(lttng_userspace_probe_location_get_type(userspace_probe_location)) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
+ {
+ ret = save_kernel_userspace_probe_function_event(writer, event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+ {
+ ret = save_kernel_userspace_probe_tracepoint_event(writer, event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
+ default:
+ ERR("Unsupported kernel userspace probe location type.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int save_kernel_event(struct config_writer *writer,
+ struct ltt_kernel_event *event)
+{
+ int ret;
+ const char *instrumentation_type;
+
+ ret = config_writer_open_element(writer, config_element_event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->event->name[0]) {
+ ret = config_writer_write_element_string(writer,
+ config_element_name, event->event->name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ ret = config_writer_write_element_bool(writer, config_element_enabled,
+ event->enabled);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ instrumentation_type = get_kernel_instrumentation_string(
+ event->event->instrumentation);
+ if (!instrumentation_type) {
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = config_writer_write_element_string(writer, config_element_type,
+ instrumentation_type);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->filter_expression) {
+ ret = config_writer_write_element_string(writer,
+ config_element_filter,
+ event->filter_expression);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
+ event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
+ event->event->instrumentation == LTTNG_KERNEL_UPROBE ||
+ event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
+
+ ret = config_writer_open_element(writer,
+ config_element_attributes);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ switch (event->event->instrumentation) {
+ case LTTNG_KERNEL_SYSCALL:
+ case LTTNG_KERNEL_FUNCTION:
+ ret = save_kernel_function_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ case LTTNG_KERNEL_KRETPROBE:
+ ret = save_kernel_kprobe_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_KERNEL_UPROBE:
+ ret = save_kernel_userspace_probe_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ default:
+ ERR("Unsupported kernel instrumentation type.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* /attributes */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ /* /event */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = LTTNG_OK;
+end:
+ return ret;
+}
+
+/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
+static
+int save_kernel_events(struct config_writer *writer,
+ struct ltt_kernel_channel *kchan)
+{
+ int ret;
+ struct ltt_kernel_event *event;
+
+ ret = config_writer_open_element(writer, config_element_events);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ cds_list_for_each_entry(event, &kchan->events_list.head, list) {
+ ret = save_kernel_event(writer, event);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+ }
+
+ /* /events */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = LTTNG_OK;
+end:
+ return ret;
+}
+
+/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
+static
+int save_ust_event(struct config_writer *writer,
+ struct ltt_ust_event *event)
+{