2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include "lttng/lttng-error.h"
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/hashtable/hashtable.h>
15 #include <common/hashtable/utils.h>
17 #include <lttng/constant.h>
18 #include <lttng/kernel-probe.h>
19 #include <lttng/kernel-probe-internal.h>
21 #include <sys/types.h>
22 #include <sys/unistd.h>
25 int lttng_kernel_probe_location_address_serialize(
26 const struct lttng_kernel_probe_location
*location
,
27 struct lttng_payload
*payload
);
30 int lttng_kernel_probe_location_symbol_serialize(
31 const struct lttng_kernel_probe_location
*location
,
32 struct lttng_payload
*payload
);
35 bool lttng_kernel_probe_location_address_is_equal(
36 const struct lttng_kernel_probe_location
*a
,
37 const struct lttng_kernel_probe_location
*b
);
40 bool lttng_kernel_probe_location_symbol_is_equal(
41 const struct lttng_kernel_probe_location
*a
,
42 const struct lttng_kernel_probe_location
*b
);
45 unsigned long lttng_kernel_probe_location_address_hash(
46 const struct lttng_kernel_probe_location
*location
);
49 unsigned long lttng_kernel_probe_location_symbol_hash(
50 const struct lttng_kernel_probe_location
*location
);
52 enum lttng_kernel_probe_location_type
lttng_kernel_probe_location_get_type(
53 const struct lttng_kernel_probe_location
*location
)
55 return location
? location
->type
:
56 LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN
;
60 void lttng_kernel_probe_location_address_destroy(
61 struct lttng_kernel_probe_location
*location
)
68 void lttng_kernel_probe_location_symbol_destroy(
69 struct lttng_kernel_probe_location
*location
)
71 struct lttng_kernel_probe_location_symbol
*location_symbol
= NULL
;
75 location_symbol
= container_of(location
,
76 struct lttng_kernel_probe_location_symbol
,
79 assert(location_symbol
);
81 free(location_symbol
->symbol_name
);
85 void lttng_kernel_probe_location_destroy(
86 struct lttng_kernel_probe_location
*location
)
92 switch (location
->type
) {
93 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
94 lttng_kernel_probe_location_address_destroy(location
);
96 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
97 lttng_kernel_probe_location_symbol_destroy(location
);
104 struct lttng_kernel_probe_location
*
105 lttng_kernel_probe_location_address_create(uint64_t address
)
107 struct lttng_kernel_probe_location
*ret
= NULL
;
108 struct lttng_kernel_probe_location_address
*location
;
110 location
= zmalloc(sizeof(*location
));
112 PERROR("Error allocating userspace probe location.");
116 location
->address
= address
;
118 ret
= &location
->parent
;
119 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
120 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
121 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
122 ret
->hash
= lttng_kernel_probe_location_address_hash
;
128 struct lttng_kernel_probe_location
*
129 lttng_kernel_probe_location_symbol_create(const char *symbol_name
,
132 char *symbol_name_copy
= NULL
;
133 struct lttng_kernel_probe_location
*ret
= NULL
;
134 struct lttng_kernel_probe_location_symbol
*location
;
136 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
140 symbol_name_copy
= strdup(symbol_name
);
141 if (!symbol_name_copy
) {
142 PERROR("Failed to copy symbol name '%s'", symbol_name
);
146 location
= zmalloc(sizeof(*location
));
148 PERROR("Failed to allocate kernel symbol probe location");
152 location
->symbol_name
= symbol_name_copy
;
153 location
->offset
= offset
;
155 ret
= &location
->parent
;
156 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
157 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
158 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
159 ret
->hash
= lttng_kernel_probe_location_symbol_hash
;
163 free(symbol_name_copy
);
168 enum lttng_kernel_probe_location_status
169 lttng_kernel_probe_location_address_get_address(
170 const struct lttng_kernel_probe_location
*location
,
173 enum lttng_kernel_probe_location_status ret
=
174 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
175 struct lttng_kernel_probe_location_address
*address_location
;
179 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
180 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
181 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
182 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
186 address_location
= container_of(location
,
187 struct lttng_kernel_probe_location_address
, parent
);
188 *offset
= address_location
->address
;
193 const char *lttng_kernel_probe_location_symbol_get_name(
194 const struct lttng_kernel_probe_location
*location
)
196 const char *ret
= NULL
;
197 struct lttng_kernel_probe_location_symbol
*symbol_location
;
199 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
200 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
201 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
205 symbol_location
= container_of(location
,
206 struct lttng_kernel_probe_location_symbol
, parent
);
207 ret
= symbol_location
->symbol_name
;
212 enum lttng_kernel_probe_location_status
213 lttng_kernel_probe_location_symbol_get_offset(
214 const struct lttng_kernel_probe_location
*location
,
217 enum lttng_kernel_probe_location_status ret
=
218 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
219 struct lttng_kernel_probe_location_symbol
*symbol_location
;
223 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
224 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
225 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
226 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
230 symbol_location
= container_of(location
,
231 struct lttng_kernel_probe_location_symbol
, parent
);
232 *offset
= symbol_location
->offset
;
238 int lttng_kernel_probe_location_symbol_serialize(
239 const struct lttng_kernel_probe_location
*location
,
240 struct lttng_payload
*payload
)
243 size_t symbol_name_len
;
244 size_t original_payload_size
;
245 struct lttng_kernel_probe_location_symbol
*location_symbol
;
246 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
248 if (!location
|| !payload
) {
249 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
250 ret
= -LTTNG_ERR_INVALID
;
254 assert(lttng_kernel_probe_location_get_type(location
) ==
255 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
257 original_payload_size
= payload
->buffer
.size
;
258 location_symbol
= container_of(location
,
259 struct lttng_kernel_probe_location_symbol
, parent
);
261 if (!location_symbol
->symbol_name
) {
262 ret
= -LTTNG_ERR_INVALID
;
266 symbol_name_len
= strlen(location_symbol
->symbol_name
);
267 if (symbol_name_len
== 0) {
268 ret
= -LTTNG_ERR_INVALID
;
272 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
273 location_symbol_comm
.offset
= location_symbol
->offset
;
275 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
276 &location_symbol_comm
, sizeof(location_symbol_comm
));
278 ret
= -LTTNG_ERR_INVALID
;
282 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
283 location_symbol
->symbol_name
,
284 location_symbol_comm
.symbol_len
);
286 ret
= -LTTNG_ERR_INVALID
;
290 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
296 int lttng_kernel_probe_location_address_serialize(
297 const struct lttng_kernel_probe_location
*location
,
298 struct lttng_payload
*payload
)
301 size_t original_payload_size
;
302 struct lttng_kernel_probe_location_address
*location_address
;
303 struct lttng_kernel_probe_location_address_comm location_address_comm
;
306 assert(lttng_kernel_probe_location_get_type(location
) ==
307 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
309 original_payload_size
= payload
->buffer
.size
;
310 location_address
= container_of(location
,
311 struct lttng_kernel_probe_location_address
,
314 location_address_comm
.address
= location_address
->address
;
316 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
317 &location_address_comm
,
318 sizeof(location_address_comm
));
320 ret
= -LTTNG_ERR_INVALID
;
324 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
330 int lttng_kernel_probe_location_serialize(
331 const struct lttng_kernel_probe_location
*location
,
332 struct lttng_payload
*payload
)
335 size_t original_payload_size
;
336 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
338 if (!location
|| !payload
) {
339 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
340 ret
= -LTTNG_ERR_INVALID
;
344 original_payload_size
= payload
->buffer
.size
;
345 location_generic_comm
.type
= (int8_t) location
->type
;
346 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
347 &location_generic_comm
,
348 sizeof(location_generic_comm
));
353 ret
= location
->serialize(location
, payload
);
358 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
364 int lttng_kernel_probe_location_symbol_create_from_payload(
365 struct lttng_payload_view
*view
,
366 struct lttng_kernel_probe_location
**location
)
368 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
369 const char *symbol_name_src
;
371 size_t expected_size
;
375 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
376 ret
= -LTTNG_ERR_INVALID
;
380 location_symbol_comm
=
381 (typeof(location_symbol_comm
)) view
->buffer
.data
;
383 expected_size
= sizeof(*location_symbol_comm
) +
384 location_symbol_comm
->symbol_len
;
386 if (view
->buffer
.size
< expected_size
) {
387 ret
= -LTTNG_ERR_INVALID
;
391 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
393 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
394 location_symbol_comm
->symbol_len
)) {
395 ret
= -LTTNG_ERR_INVALID
;
399 *location
= lttng_kernel_probe_location_symbol_create(
400 symbol_name_src
, location_symbol_comm
->offset
);
402 ret
= -LTTNG_ERR_INVALID
;
406 ret
= (ssize_t
) expected_size
;
412 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
413 struct lttng_payload_view
*view
,
414 struct lttng_kernel_probe_location
**location
)
416 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
418 size_t expected_size
;
422 expected_size
= sizeof(*location_address_comm
);
424 if (view
->buffer
.size
< expected_size
) {
425 ret
= -LTTNG_ERR_INVALID
;
429 location_address_comm
=
430 (typeof(location_address_comm
)) view
->buffer
.data
;
432 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
434 ret
= -LTTNG_ERR_INVALID
;
438 ret
= (size_t) expected_size
;
444 ssize_t
lttng_kernel_probe_location_create_from_payload(
445 struct lttng_payload_view
*view
,
446 struct lttng_kernel_probe_location
**location
)
448 enum lttng_kernel_probe_location_type type
;
449 ssize_t consumed
= 0;
451 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
452 const struct lttng_payload_view probe_location_comm_view
=
453 lttng_payload_view_from_view(
454 view
, 0, sizeof(*probe_location_comm
));
459 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
460 ret
= -LTTNG_ERR_INVALID
;
464 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
465 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
466 consumed
+= sizeof(*probe_location_comm
);
469 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
471 struct lttng_payload_view location_view
=
472 lttng_payload_view_from_view(
475 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
476 &location_view
, location
);
479 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
481 struct lttng_payload_view location_view
=
482 lttng_payload_view_from_view(view
, consumed
, -1);
484 ret
= lttng_kernel_probe_location_address_create_from_payload(
485 &location_view
, location
);
489 ret
= -LTTNG_ERR_INVALID
;
494 ret
= -LTTNG_ERR_INVALID
;
505 unsigned long lttng_kernel_probe_location_address_hash(
506 const struct lttng_kernel_probe_location
*location
)
508 unsigned long hash
= hash_key_ulong(
509 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
,
511 struct lttng_kernel_probe_location_address
*address_location
=
512 container_of(location
, typeof(*address_location
),
515 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
521 bool lttng_kernel_probe_location_address_is_equal(
522 const struct lttng_kernel_probe_location
*_a
,
523 const struct lttng_kernel_probe_location
*_b
)
525 bool is_equal
= false;
526 struct lttng_kernel_probe_location_address
*a
, *b
;
528 a
= container_of(_a
, struct lttng_kernel_probe_location_address
,
530 b
= container_of(_b
, struct lttng_kernel_probe_location_address
,
533 if (a
->address
!= b
->address
) {
544 unsigned long lttng_kernel_probe_location_symbol_hash(
545 const struct lttng_kernel_probe_location
*location
)
547 unsigned long hash
= hash_key_ulong(
548 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
,
550 struct lttng_kernel_probe_location_symbol
*symbol_location
=
551 container_of(location
, typeof(*symbol_location
),
554 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
555 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
561 bool lttng_kernel_probe_location_symbol_is_equal(
562 const struct lttng_kernel_probe_location
*_a
,
563 const struct lttng_kernel_probe_location
*_b
)
565 bool is_equal
= false;
566 struct lttng_kernel_probe_location_symbol
*a
, *b
;
568 a
= container_of(_a
, struct lttng_kernel_probe_location_symbol
,
570 b
= container_of(_b
, struct lttng_kernel_probe_location_symbol
,
573 assert(a
->symbol_name
);
574 assert(b
->symbol_name
);
575 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
579 if (a
->offset
!= b
->offset
) {
590 bool lttng_kernel_probe_location_is_equal(
591 const struct lttng_kernel_probe_location
*a
,
592 const struct lttng_kernel_probe_location
*b
)
594 bool is_equal
= false;
605 if (a
->type
!= b
->type
) {
609 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
614 static struct lttng_kernel_probe_location
*
615 lttng_kernel_probe_location_symbol_copy(
616 const struct lttng_kernel_probe_location
*location
)
618 struct lttng_kernel_probe_location
*new_location
= NULL
;
619 struct lttng_kernel_probe_location_symbol
*symbol_location
;
620 enum lttng_kernel_probe_location_status status
;
621 const char *symbol_name
= NULL
;
625 assert(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
626 symbol_location
= container_of(
627 location
, typeof(*symbol_location
), parent
);
629 /* Get probe location offset */
630 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
631 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
632 ERR("Get kernel probe location offset failed.");
636 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
638 ERR("Kernel probe symbol name is NULL.");
642 /* Create the probe_location */
643 new_location
= lttng_kernel_probe_location_symbol_create(
644 symbol_name
, offset
);
653 static struct lttng_kernel_probe_location
*
654 lttng_kernel_probe_location_address_copy(
655 const struct lttng_kernel_probe_location
*location
)
657 struct lttng_kernel_probe_location
*new_location
= NULL
;
658 struct lttng_kernel_probe_location_address
*address_location
;
659 enum lttng_kernel_probe_location_status status
;
663 assert(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
664 address_location
= container_of(
665 location
, typeof(*address_location
), parent
);
668 /* Get probe location fields */
669 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
670 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
671 ERR("Get kernel probe address failed.");
675 /* Create the probe_location */
676 new_location
= lttng_kernel_probe_location_address_create(address
);
687 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_copy(
688 const struct lttng_kernel_probe_location
*location
)
690 struct lttng_kernel_probe_location
*new_location
= NULL
;
691 enum lttng_kernel_probe_location_type type
;
697 type
= lttng_kernel_probe_location_get_type(location
);
699 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
701 lttng_kernel_probe_location_address_copy(location
);
706 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
708 lttng_kernel_probe_location_symbol_copy(location
);
722 unsigned long lttng_kernel_probe_location_hash(
723 const struct lttng_kernel_probe_location
*location
)
725 return location
->hash(location
);