--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#ifndef LTTNG_KERNEL_PROBE_INTERNAL_H
+#define LTTNG_KERNEL_PROBE_INTERNAL_H
+
+#include <common/fd-handle.h>
+#include <common/macros.h>
+#include <lttng/kernel-probe.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct lttng_dynamic_buffer;
+
+typedef bool (*kernel_probe_location_equal_cb)(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b);
+typedef int (*kernel_probe_location_serialize_cb)(
+ const struct lttng_kernel_probe_location *kernel_probe_location,
+ struct lttng_payload *payload);
+typedef bool (*kernel_probe_location_equal_cb)(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b);
+typedef ssize_t (*kernel_probe_location_create_from_payload_cb)(
+ struct lttng_payload_view *view,
+ struct lttng_kernel_probe_location **kernel_probe_location);
+
+struct lttng_kernel_probe_location_comm {
+ /* enum lttng_kernel_probe_location_type */
+ int8_t type;
+ /*
+ * Payload is composed of, in that order,
+ * - type-specific payload
+ */
+ char payload[];
+} LTTNG_PACKED;
+
+struct lttng_kernel_probe_location_symbol_comm {
+ /* Includes the trailing \0. */
+ uint32_t symbol_len;
+ /* The offset from the symbol. */
+ uint64_t offset;
+ /*
+ * Payload is composed of, in that order,
+ * - symbol name (with trailing \0).
+ */
+ char payload[];
+} LTTNG_PACKED;
+
+struct lttng_kernel_probe_location_address_comm {
+ uint64_t address;
+} LTTNG_PACKED;
+
+/* Common ancestor of all kernel probe locations. */
+struct lttng_kernel_probe_location {
+ enum lttng_kernel_probe_location_type type;
+ kernel_probe_location_equal_cb equal;
+ kernel_probe_location_serialize_cb serialize;
+};
+
+struct lttng_kernel_probe_location_symbol {
+ struct lttng_kernel_probe_location parent;
+ char *symbol_name;
+ uint64_t offset;
+};
+
+struct lttng_kernel_probe_location_address {
+ struct lttng_kernel_probe_location parent;
+ uint64_t address;
+};
+
+LTTNG_HIDDEN
+int lttng_kernel_probe_location_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload);
+
+LTTNG_HIDDEN
+ssize_t lttng_kernel_probe_location_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_kernel_probe_location **probe_location);
+
+LTTNG_HIDDEN
+bool lttng_kernel_probe_location_is_equal(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b);
+
+#endif /* LTTNG_KERNEL_PROBE_INTERNAL_H */
--- /dev/null
+/*
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include "lttng/lttng-error.h"
+#include <assert.h>
+#include <common/error.h>
+#include <common/macros.h>
+#include <common/payload.h>
+#include <common/payload-view.h>
+#include <fcntl.h>
+#include <lttng/constant.h>
+#include <lttng/kernel-probe.h>
+#include <lttng/kernel-probe-internal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/unistd.h>
+
+static
+int lttng_kernel_probe_location_address_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload);
+
+static
+int lttng_kernel_probe_location_symbol_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload);
+
+static
+bool lttng_kernel_probe_location_address_is_equal(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b);
+
+static
+bool lttng_kernel_probe_location_symbol_is_equal(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b);
+
+enum lttng_kernel_probe_location_type lttng_kernel_probe_location_get_type(
+ const struct lttng_kernel_probe_location *location)
+{
+ return location ? location->type :
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN;
+}
+
+static
+void lttng_kernel_probe_location_address_destroy(
+ struct lttng_kernel_probe_location *location)
+{
+ assert(location);
+ free(location);
+}
+
+static
+void lttng_kernel_probe_location_symbol_destroy(
+ struct lttng_kernel_probe_location *location)
+{
+ struct lttng_kernel_probe_location_symbol *location_symbol = NULL;
+
+ assert(location);
+
+ location_symbol = container_of(location,
+ struct lttng_kernel_probe_location_symbol,
+ parent);
+
+ assert(location_symbol);
+
+ free(location_symbol->symbol_name);
+ free(location);
+}
+
+void lttng_kernel_probe_location_destroy(
+ struct lttng_kernel_probe_location *location)
+{
+ if (!location) {
+ return;
+ }
+
+ switch (location->type) {
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
+ lttng_kernel_probe_location_address_destroy(location);
+ break;
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
+ lttng_kernel_probe_location_symbol_destroy(location);
+ break;
+ default:
+ abort();
+ }
+}
+
+struct lttng_kernel_probe_location *
+lttng_kernel_probe_location_address_create(uint64_t address)
+{
+ struct lttng_kernel_probe_location *ret = NULL;
+ struct lttng_kernel_probe_location_address *location;
+
+ location = zmalloc(sizeof(*location));
+ if (!location) {
+ PERROR("Error allocating userspace probe location");
+ goto end;
+ }
+
+ location->address = address;
+
+ ret = &location->parent;
+ ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS;
+ ret->equal = lttng_kernel_probe_location_address_is_equal;
+ ret->serialize = lttng_kernel_probe_location_address_serialize;
+
+end:
+ return ret;
+}
+
+struct lttng_kernel_probe_location *
+lttng_kernel_probe_location_symbol_create(const char *symbol_name,
+ uint64_t offset)
+{
+ char *symbol_name_copy = NULL;
+ struct lttng_kernel_probe_location *ret = NULL;
+ struct lttng_kernel_probe_location_symbol *location;
+
+ if (!symbol_name || strlen(symbol_name) >= LTTNG_SYMBOL_NAME_LEN) {
+ goto error;
+ }
+
+ symbol_name_copy = strdup(symbol_name);
+ if (!symbol_name_copy) {
+ PERROR("Failed to copy symbol name '%s'", symbol_name);
+ goto error;
+ }
+
+ location = zmalloc(sizeof(*location));
+ if (!location) {
+ PERROR("Failed to allocate kernel symbol probe location");
+ goto error;
+ }
+
+ location->symbol_name = symbol_name_copy;
+ location->offset = offset;
+
+ ret = &location->parent;
+ ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET;
+ ret->equal = lttng_kernel_probe_location_symbol_is_equal;
+ ret->serialize = lttng_kernel_probe_location_symbol_serialize;
+ goto end;
+
+error:
+ free(symbol_name_copy);
+end:
+ return ret;
+}
+
+enum lttng_kernel_probe_location_status
+lttng_kernel_probe_location_address_get_address(
+ const struct lttng_kernel_probe_location *location,
+ uint64_t *offset)
+{
+ enum lttng_kernel_probe_location_status ret =
+ LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK;
+ struct lttng_kernel_probe_location_address *address_location;
+
+ assert(offset);
+
+ if (!location || lttng_kernel_probe_location_get_type(location) !=
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS) {
+ ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
+ ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID;
+ goto end;
+ }
+
+ address_location = container_of(location,
+ struct lttng_kernel_probe_location_address, parent);
+ *offset = address_location->address;
+end:
+ return ret;
+}
+
+const char *lttng_kernel_probe_location_symbol_get_name(
+ const struct lttng_kernel_probe_location *location)
+{
+ const char *ret = NULL;
+ struct lttng_kernel_probe_location_symbol *symbol_location;
+
+ if (!location || lttng_kernel_probe_location_get_type(location) !=
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) {
+ ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
+ goto end;
+ }
+
+ symbol_location = container_of(location,
+ struct lttng_kernel_probe_location_symbol, parent);
+ ret = symbol_location->symbol_name;
+end:
+ return ret;
+}
+
+enum lttng_kernel_probe_location_status
+lttng_kernel_probe_location_symbol_get_offset(
+ const struct lttng_kernel_probe_location *location,
+ uint64_t *offset)
+{
+ enum lttng_kernel_probe_location_status ret =
+ LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK;
+ struct lttng_kernel_probe_location_symbol *symbol_location;
+
+ assert(offset);
+
+ if (!location || lttng_kernel_probe_location_get_type(location) !=
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) {
+ ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
+ ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID;
+ goto end;
+ }
+
+ symbol_location = container_of(location,
+ struct lttng_kernel_probe_location_symbol, parent);
+ *offset = symbol_location->offset;
+end:
+ return ret;
+}
+
+static
+int lttng_kernel_probe_location_symbol_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload)
+{
+ int ret;
+ size_t symbol_name_len;
+ size_t original_payload_size;
+ struct lttng_kernel_probe_location_symbol *location_symbol;
+ struct lttng_kernel_probe_location_symbol_comm location_symbol_comm;
+
+ if (!location || !payload) {
+ ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ assert(lttng_kernel_probe_location_get_type(location) ==
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
+
+ original_payload_size = payload->buffer.size;
+ location_symbol = container_of(location,
+ struct lttng_kernel_probe_location_symbol, parent);
+
+ if (!location_symbol->symbol_name) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ symbol_name_len = strlen(location_symbol->symbol_name);
+ if (symbol_name_len == 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ location_symbol_comm.symbol_len = symbol_name_len + 1;
+ location_symbol_comm.offset = location_symbol->offset;
+
+ ret = lttng_dynamic_buffer_append(&payload->buffer,
+ &location_symbol_comm, sizeof(location_symbol_comm));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = lttng_dynamic_buffer_append(&payload->buffer,
+ location_symbol->symbol_name,
+ location_symbol_comm.symbol_len);
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = (int) (payload->buffer.size - original_payload_size);
+end:
+ return ret;
+}
+
+static
+int lttng_kernel_probe_location_address_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload)
+{
+ int ret;
+ size_t original_payload_size;
+ struct lttng_kernel_probe_location_address *location_address;
+ struct lttng_kernel_probe_location_address_comm location_address_comm;
+
+ assert(location);
+ assert(lttng_kernel_probe_location_get_type(location) ==
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
+
+ original_payload_size = payload->buffer.size;
+ location_address = container_of(location,
+ struct lttng_kernel_probe_location_address,
+ parent);
+
+ location_address_comm.address = location_address->address;
+
+ ret = lttng_dynamic_buffer_append(&payload->buffer,
+ &location_address_comm,
+ sizeof(location_address_comm));
+ if (ret) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = (int) (payload->buffer.size - original_payload_size);
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+int lttng_kernel_probe_location_serialize(
+ const struct lttng_kernel_probe_location *location,
+ struct lttng_payload *payload)
+{
+ int ret;
+ size_t original_payload_size;
+ struct lttng_kernel_probe_location_comm location_generic_comm = {};
+
+ if (!location || !payload) {
+ ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ original_payload_size = payload->buffer.size;
+ location_generic_comm.type = (int8_t) location->type;
+ ret = lttng_dynamic_buffer_append(&payload->buffer,
+ &location_generic_comm,
+ sizeof(location_generic_comm));
+ if (ret) {
+ goto end;
+ }
+
+ ret = location->serialize(location, payload);
+ if (ret < 0) {
+ goto end;
+ }
+
+ ret = (int) (payload->buffer.size - original_payload_size);
+end:
+ return ret;
+}
+
+static
+int lttng_kernel_probe_location_symbol_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_kernel_probe_location **location)
+{
+ struct lttng_kernel_probe_location_symbol_comm *location_symbol_comm;
+ const char *symbol_name_src;
+ ssize_t ret = 0;
+ size_t expected_size;
+
+ assert(location);
+
+ if (view->buffer.size < sizeof(*location_symbol_comm)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ location_symbol_comm =
+ (typeof(location_symbol_comm)) view->buffer.data;
+
+ expected_size = sizeof(*location_symbol_comm) +
+ location_symbol_comm->symbol_len;
+
+ if (view->buffer.size < expected_size) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ symbol_name_src = view->buffer.data + sizeof(*location_symbol_comm);
+
+ if (!lttng_buffer_view_contains_string(&view->buffer, symbol_name_src,
+ location_symbol_comm->symbol_len)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ *location = lttng_kernel_probe_location_symbol_create(
+ symbol_name_src, location_symbol_comm->offset);
+ if (!(*location)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = (ssize_t) expected_size;
+end:
+ return ret;
+}
+
+static
+ssize_t lttng_kernel_probe_location_address_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_kernel_probe_location **location)
+{
+ struct lttng_kernel_probe_location_address_comm *location_address_comm;
+ ssize_t ret = 0;
+ size_t expected_size;
+
+ assert(location);
+
+ expected_size = sizeof(*location_address_comm);
+
+ if (view->buffer.size < expected_size) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ location_address_comm =
+ (typeof(location_address_comm)) view->buffer.data;
+
+ *location = lttng_kernel_probe_location_address_create(location_address_comm->address);
+ if (!(*location)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = (size_t) expected_size;
+end:
+ return ret;
+}
+
+LTTNG_HIDDEN
+ssize_t lttng_kernel_probe_location_create_from_payload(
+ struct lttng_payload_view *view,
+ struct lttng_kernel_probe_location **location)
+{
+ struct lttng_kernel_probe_location_comm *probe_location_comm;
+ enum lttng_kernel_probe_location_type type;
+ ssize_t consumed = 0;
+ ssize_t ret;
+
+ assert(view);
+ assert(location);
+
+ if (view->buffer.size <= sizeof(*probe_location_comm)) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ probe_location_comm = (typeof(probe_location_comm)) view->buffer.data;
+ type = (enum lttng_kernel_probe_location_type) probe_location_comm->type;
+ consumed += sizeof(*probe_location_comm);
+
+ switch (type) {
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
+ {
+ struct lttng_payload_view location_view =
+ lttng_payload_view_from_view(
+ view, consumed, -1);
+
+ ret = lttng_kernel_probe_location_symbol_create_from_payload(
+ &location_view, location);
+ break;
+ }
+ case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
+ {
+ struct lttng_payload_view location_view =
+ lttng_payload_view_from_view(view, consumed, -1);
+
+ ret = lttng_kernel_probe_location_address_create_from_payload(
+ &location_view, location);
+ break;
+ }
+ default:
+ ret = -LTTNG_ERR_INVALID;
+ break;
+ }
+
+ if (ret < 0) {
+ ret = -LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret += consumed;
+
+end:
+ return ret;
+}
+
+static
+bool lttng_kernel_probe_location_address_is_equal(
+ const struct lttng_kernel_probe_location *_a,
+ const struct lttng_kernel_probe_location *_b)
+{
+ bool is_equal = false;
+ struct lttng_kernel_probe_location_address *a, *b;
+
+ a = container_of(_a, struct lttng_kernel_probe_location_address,
+ parent);
+ b = container_of(_b, struct lttng_kernel_probe_location_address,
+ parent);
+
+ if (a->address != b->address) {
+ goto end;
+ }
+
+ is_equal = true;
+
+end:
+ return is_equal;
+}
+
+static
+bool lttng_kernel_probe_location_symbol_is_equal(
+ const struct lttng_kernel_probe_location *_a,
+ const struct lttng_kernel_probe_location *_b)
+{
+ bool is_equal = false;
+ struct lttng_kernel_probe_location_symbol *a, *b;
+
+ a = container_of(_a, struct lttng_kernel_probe_location_symbol,
+ parent);
+ b = container_of(_b, struct lttng_kernel_probe_location_symbol,
+ parent);
+
+ assert(a->symbol_name);
+ assert(b->symbol_name);
+ if (strcmp(a->symbol_name, b->symbol_name)) {
+ goto end;
+ }
+
+ if (a->offset != b->offset) {
+ goto end;
+ }
+
+ is_equal = true;
+
+end:
+ return is_equal;
+}
+
+LTTNG_HIDDEN
+bool lttng_kernel_probe_location_is_equal(
+ const struct lttng_kernel_probe_location *a,
+ const struct lttng_kernel_probe_location *b)
+{
+ bool is_equal = false;
+
+ if (!a || !b) {
+ goto end;
+ }
+
+ if (a == b) {
+ is_equal = true;
+ goto end;
+ }
+
+ if (a->type != b->type) {
+ goto end;
+ }
+
+ is_equal = a->equal ? a->equal(a, b) : true;
+end:
+ return is_equal;
+}
--- /dev/null
+/*
+ * Unit tests for the kernel probe location API.
+ *
+ * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <tap/tap.h>
+
+#include <common/payload-view.h>
+#include <common/payload.h>
+#include <lttng/kernel-probe-internal.h>
+#include <lttng/kernel-probe.h>
+
+/* For error.h */
+int lttng_opt_quiet = 1;
+int lttng_opt_verbose;
+int lttng_opt_mi;
+
+#define NUM_TESTS 24
+
+static void test_kernel_probe_location_address(void)
+{
+ struct lttng_kernel_probe_location *location = NULL;
+ struct lttng_kernel_probe_location *location_from_buffer = NULL;
+ enum lttng_kernel_probe_location_status status;
+ enum lttng_kernel_probe_location_type type;
+ uint64_t address = 50, _address;
+ struct lttng_payload payload;
+
+ diag("Testing kernel probe location address");
+
+ lttng_payload_init(&payload);
+
+ location = lttng_kernel_probe_location_address_create(address);
+ ok(location, "Location object");
+
+ type = lttng_kernel_probe_location_get_type(location);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
+ "Location type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
+
+ status = lttng_kernel_probe_location_address_get_address(
+ location, &_address);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
+ ok(address == _address,
+ "Address is equal. Got %" PRIu64 " expected %" PRIu64,
+ _address, address);
+
+ ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
+ "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ ok(lttng_kernel_probe_location_create_from_payload(
+ &view, &location_from_buffer) > 0,
+ "Deserializing");
+ }
+
+ type = lttng_kernel_probe_location_get_type(location_from_buffer);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS == type,
+ "Location from buffer type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
+
+ status = lttng_kernel_probe_location_address_get_address(
+ location_from_buffer, &_address);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting address");
+ ok(address == _address,
+ "Address from buffer is equal. Got %" PRIu64
+ " expected %" PRIu64,
+ _address, address);
+
+ ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_payload_reset(&payload);
+ lttng_kernel_probe_location_destroy(location);
+ lttng_kernel_probe_location_destroy(location_from_buffer);
+}
+
+static void test_kernel_probe_location_symbol(void)
+{
+ struct lttng_kernel_probe_location *location = NULL;
+ struct lttng_kernel_probe_location *location_from_buffer = NULL;
+ enum lttng_kernel_probe_location_status status;
+ enum lttng_kernel_probe_location_type type;
+ uint64_t offset = 50, _offset;
+ const char *symbol = "Une_bonne", *_symbol;
+ struct lttng_payload payload;
+
+ diag("Testing kernel probe location symbol");
+
+ lttng_payload_init(&payload);
+
+ location = lttng_kernel_probe_location_symbol_create(symbol, offset);
+ ok(location, "Location object");
+
+ type = lttng_kernel_probe_location_get_type(location);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
+ "Location type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
+
+ _symbol = lttng_kernel_probe_location_symbol_get_name(location);
+ ok(_symbol, "Getting symbol name");
+ ok(!strncmp(symbol, _symbol, strlen(symbol)),
+ "Symbol name is equal. Got %s, expected %s", _symbol,
+ symbol);
+
+ status = lttng_kernel_probe_location_symbol_get_offset(
+ location, &_offset);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
+ ok(offset == _offset,
+ "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
+ _offset, offset);
+
+ ok(lttng_kernel_probe_location_serialize(location, &payload) > 0,
+ "Serializing");
+ {
+ struct lttng_payload_view view =
+ lttng_payload_view_from_payload(
+ &payload, 0, -1);
+ ok(lttng_kernel_probe_location_create_from_payload(
+ &view, &location_from_buffer) > 0,
+ "Deserializing");
+ }
+
+ type = lttng_kernel_probe_location_get_type(location_from_buffer);
+ ok(LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET == type,
+ "Location from buffer type got %d expected %d", type,
+ LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
+
+ _symbol = lttng_kernel_probe_location_symbol_get_name(
+ location_from_buffer);
+ ok(_symbol, "Getting symbol name");
+ ok(!strncmp(symbol, _symbol, strlen(symbol)),
+ "Symbol name is equal. Got %s, expected %s", _symbol,
+ symbol);
+
+ status = lttng_kernel_probe_location_symbol_get_offset(
+ location_from_buffer, &_offset);
+ ok(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK, "Getting offset");
+ ok(offset == _offset,
+ "Offset is equal. Got %" PRIu64 " expected %" PRIu64,
+ _offset, offset);
+
+ ok(lttng_kernel_probe_location_is_equal(location, location_from_buffer),
+ "serialized and from buffer are equal");
+
+ lttng_payload_reset(&payload);
+ lttng_kernel_probe_location_destroy(location);
+ lttng_kernel_probe_location_destroy(location_from_buffer);
+}
+
+int main(int argc, const char *argv[])
+{
+ plan_tests(NUM_TESTS);
+ test_kernel_probe_location_address();
+ test_kernel_probe_location_symbol();
+ return exit_status();
+}