Commit | Line | Data |
---|---|---|
808cb744 JR |
1 | /* |
2 | * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #include "lttng/lttng-error.h" | |
28ab034a | 9 | |
c9e313bc SM |
10 | #include <common/error.hpp> |
11 | #include <common/hashtable/hashtable.hpp> | |
12 | #include <common/hashtable/utils.hpp> | |
13 | #include <common/macros.hpp> | |
14 | #include <common/mi-lttng.hpp> | |
15 | #include <common/payload-view.hpp> | |
16 | #include <common/payload.hpp> | |
28ab034a | 17 | |
808cb744 | 18 | #include <lttng/constant.h> |
c9e313bc | 19 | #include <lttng/kernel-probe-internal.hpp> |
6a751b95 | 20 | #include <lttng/kernel-probe.h> |
28ab034a JG |
21 | |
22 | #include <fcntl.h> | |
808cb744 JR |
23 | #include <sys/stat.h> |
24 | #include <sys/types.h> | |
8f14767d | 25 | #include <unistd.h> |
808cb744 | 26 | |
28ab034a JG |
27 | static int |
28 | lttng_kernel_probe_location_address_serialize(const struct lttng_kernel_probe_location *location, | |
29 | struct lttng_payload *payload); | |
30 | ||
31 | static int | |
32 | lttng_kernel_probe_location_symbol_serialize(const struct lttng_kernel_probe_location *location, | |
33 | struct lttng_payload *payload); | |
34 | ||
35 | static bool | |
36 | lttng_kernel_probe_location_address_is_equal(const struct lttng_kernel_probe_location *a, | |
37 | const struct lttng_kernel_probe_location *b); | |
38 | ||
39 | static bool | |
40 | lttng_kernel_probe_location_symbol_is_equal(const struct lttng_kernel_probe_location *a, | |
41 | const struct lttng_kernel_probe_location *b); | |
42 | ||
43 | static unsigned long | |
44 | lttng_kernel_probe_location_address_hash(const struct lttng_kernel_probe_location *location); | |
45 | ||
46 | static unsigned long | |
47 | lttng_kernel_probe_location_symbol_hash(const struct lttng_kernel_probe_location *location); | |
48 | ||
49 | static enum lttng_error_code | |
50 | lttng_kernel_probe_location_address_mi_serialize(const struct lttng_kernel_probe_location *location, | |
51 | struct mi_writer *writer); | |
52 | ||
53 | static enum lttng_error_code | |
54 | lttng_kernel_probe_location_symbol_mi_serialize(const struct lttng_kernel_probe_location *location, | |
55 | struct mi_writer *writer); | |
56 | ||
57 | enum lttng_kernel_probe_location_type | |
58 | lttng_kernel_probe_location_get_type(const struct lttng_kernel_probe_location *location) | |
808cb744 | 59 | { |
28ab034a | 60 | return location ? location->type : LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN; |
808cb744 JR |
61 | } |
62 | ||
28ab034a JG |
63 | static void |
64 | lttng_kernel_probe_location_address_destroy(struct lttng_kernel_probe_location *location) | |
808cb744 | 65 | { |
a0377dfe | 66 | LTTNG_ASSERT(location); |
808cb744 JR |
67 | free(location); |
68 | } | |
69 | ||
28ab034a | 70 | static void lttng_kernel_probe_location_symbol_destroy(struct lttng_kernel_probe_location *location) |
808cb744 | 71 | { |
cd9adb8b | 72 | struct lttng_kernel_probe_location_symbol *location_symbol = nullptr; |
808cb744 | 73 | |
a0377dfe | 74 | LTTNG_ASSERT(location); |
808cb744 | 75 | |
28ab034a JG |
76 | location_symbol = |
77 | lttng::utils::container_of(location, <tng_kernel_probe_location_symbol::parent); | |
808cb744 | 78 | |
a0377dfe | 79 | LTTNG_ASSERT(location_symbol); |
808cb744 JR |
80 | |
81 | free(location_symbol->symbol_name); | |
82 | free(location); | |
83 | } | |
84 | ||
28ab034a | 85 | void lttng_kernel_probe_location_destroy(struct lttng_kernel_probe_location *location) |
808cb744 JR |
86 | { |
87 | if (!location) { | |
88 | return; | |
89 | } | |
90 | ||
91 | switch (location->type) { | |
92 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
93 | lttng_kernel_probe_location_address_destroy(location); | |
94 | break; | |
95 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
96 | lttng_kernel_probe_location_symbol_destroy(location); | |
97 | break; | |
98 | default: | |
99 | abort(); | |
100 | } | |
101 | } | |
102 | ||
28ab034a | 103 | struct lttng_kernel_probe_location *lttng_kernel_probe_location_address_create(uint64_t address) |
808cb744 | 104 | { |
cd9adb8b | 105 | struct lttng_kernel_probe_location *ret = nullptr; |
808cb744 JR |
106 | struct lttng_kernel_probe_location_address *location; |
107 | ||
64803277 | 108 | location = zmalloc<lttng_kernel_probe_location_address>(); |
808cb744 | 109 | if (!location) { |
077192fd | 110 | PERROR("Error allocating userspace probe location."); |
808cb744 JR |
111 | goto end; |
112 | } | |
113 | ||
114 | location->address = address; | |
115 | ||
116 | ret = &location->parent; | |
117 | ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS; | |
118 | ret->equal = lttng_kernel_probe_location_address_is_equal; | |
119 | ret->serialize = lttng_kernel_probe_location_address_serialize; | |
959e3c66 | 120 | ret->hash = lttng_kernel_probe_location_address_hash; |
6a751b95 | 121 | ret->mi_serialize = lttng_kernel_probe_location_address_mi_serialize; |
808cb744 JR |
122 | |
123 | end: | |
124 | return ret; | |
125 | } | |
126 | ||
127 | struct lttng_kernel_probe_location * | |
28ab034a | 128 | lttng_kernel_probe_location_symbol_create(const char *symbol_name, uint64_t offset) |
808cb744 | 129 | { |
cd9adb8b JG |
130 | char *symbol_name_copy = nullptr; |
131 | struct lttng_kernel_probe_location *ret = nullptr; | |
808cb744 JR |
132 | struct lttng_kernel_probe_location_symbol *location; |
133 | ||
134 | if (!symbol_name || strlen(symbol_name) >= LTTNG_SYMBOL_NAME_LEN) { | |
135 | goto error; | |
136 | } | |
137 | ||
138 | symbol_name_copy = strdup(symbol_name); | |
139 | if (!symbol_name_copy) { | |
140 | PERROR("Failed to copy symbol name '%s'", symbol_name); | |
141 | goto error; | |
142 | } | |
143 | ||
64803277 | 144 | location = zmalloc<lttng_kernel_probe_location_symbol>(); |
808cb744 JR |
145 | if (!location) { |
146 | PERROR("Failed to allocate kernel symbol probe location"); | |
147 | goto error; | |
148 | } | |
149 | ||
150 | location->symbol_name = symbol_name_copy; | |
151 | location->offset = offset; | |
152 | ||
153 | ret = &location->parent; | |
154 | ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET; | |
155 | ret->equal = lttng_kernel_probe_location_symbol_is_equal; | |
156 | ret->serialize = lttng_kernel_probe_location_symbol_serialize; | |
959e3c66 | 157 | ret->hash = lttng_kernel_probe_location_symbol_hash; |
6a751b95 | 158 | ret->mi_serialize = lttng_kernel_probe_location_symbol_mi_serialize; |
808cb744 JR |
159 | goto end; |
160 | ||
161 | error: | |
162 | free(symbol_name_copy); | |
163 | end: | |
164 | return ret; | |
165 | } | |
166 | ||
167 | enum lttng_kernel_probe_location_status | |
28ab034a JG |
168 | lttng_kernel_probe_location_address_get_address(const struct lttng_kernel_probe_location *location, |
169 | uint64_t *offset) | |
808cb744 | 170 | { |
28ab034a | 171 | enum lttng_kernel_probe_location_status ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK; |
808cb744 JR |
172 | struct lttng_kernel_probe_location_address *address_location; |
173 | ||
a0377dfe | 174 | LTTNG_ASSERT(offset); |
808cb744 | 175 | |
28ab034a JG |
176 | if (!location || |
177 | lttng_kernel_probe_location_get_type(location) != | |
178 | LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS) { | |
808cb744 JR |
179 | ERR("Invalid argument(s) passed to '%s'", __FUNCTION__); |
180 | ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID; | |
181 | goto end; | |
182 | } | |
183 | ||
28ab034a JG |
184 | address_location = |
185 | lttng::utils::container_of(location, <tng_kernel_probe_location_address::parent); | |
808cb744 JR |
186 | *offset = address_location->address; |
187 | end: | |
188 | return ret; | |
189 | } | |
190 | ||
28ab034a JG |
191 | const char * |
192 | lttng_kernel_probe_location_symbol_get_name(const struct lttng_kernel_probe_location *location) | |
808cb744 | 193 | { |
cd9adb8b | 194 | const char *ret = nullptr; |
808cb744 JR |
195 | struct lttng_kernel_probe_location_symbol *symbol_location; |
196 | ||
28ab034a JG |
197 | if (!location || |
198 | lttng_kernel_probe_location_get_type(location) != | |
199 | LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) { | |
808cb744 JR |
200 | ERR("Invalid argument(s) passed to '%s'", __FUNCTION__); |
201 | goto end; | |
202 | } | |
203 | ||
28ab034a JG |
204 | symbol_location = |
205 | lttng::utils::container_of(location, <tng_kernel_probe_location_symbol::parent); | |
808cb744 JR |
206 | ret = symbol_location->symbol_name; |
207 | end: | |
208 | return ret; | |
209 | } | |
210 | ||
211 | enum lttng_kernel_probe_location_status | |
28ab034a JG |
212 | lttng_kernel_probe_location_symbol_get_offset(const struct lttng_kernel_probe_location *location, |
213 | uint64_t *offset) | |
808cb744 | 214 | { |
28ab034a | 215 | enum lttng_kernel_probe_location_status ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK; |
808cb744 JR |
216 | struct lttng_kernel_probe_location_symbol *symbol_location; |
217 | ||
a0377dfe | 218 | LTTNG_ASSERT(offset); |
808cb744 | 219 | |
28ab034a JG |
220 | if (!location || |
221 | lttng_kernel_probe_location_get_type(location) != | |
222 | LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) { | |
808cb744 JR |
223 | ERR("Invalid argument(s) passed to '%s'", __FUNCTION__); |
224 | ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID; | |
225 | goto end; | |
226 | } | |
227 | ||
28ab034a JG |
228 | symbol_location = |
229 | lttng::utils::container_of(location, <tng_kernel_probe_location_symbol::parent); | |
808cb744 JR |
230 | *offset = symbol_location->offset; |
231 | end: | |
232 | return ret; | |
233 | } | |
234 | ||
28ab034a JG |
235 | static int |
236 | lttng_kernel_probe_location_symbol_serialize(const struct lttng_kernel_probe_location *location, | |
237 | struct lttng_payload *payload) | |
808cb744 JR |
238 | { |
239 | int ret; | |
240 | size_t symbol_name_len; | |
241 | size_t original_payload_size; | |
242 | struct lttng_kernel_probe_location_symbol *location_symbol; | |
243 | struct lttng_kernel_probe_location_symbol_comm location_symbol_comm; | |
244 | ||
245 | if (!location || !payload) { | |
246 | ERR("Invalid argument(s) passed to '%s'", __FUNCTION__); | |
247 | ret = -LTTNG_ERR_INVALID; | |
248 | goto end; | |
249 | } | |
250 | ||
a0377dfe | 251 | LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location) == |
28ab034a | 252 | LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET); |
808cb744 JR |
253 | |
254 | original_payload_size = payload->buffer.size; | |
28ab034a JG |
255 | location_symbol = |
256 | lttng::utils::container_of(location, <tng_kernel_probe_location_symbol::parent); | |
808cb744 JR |
257 | |
258 | if (!location_symbol->symbol_name) { | |
259 | ret = -LTTNG_ERR_INVALID; | |
260 | goto end; | |
261 | } | |
262 | ||
263 | symbol_name_len = strlen(location_symbol->symbol_name); | |
264 | if (symbol_name_len == 0) { | |
265 | ret = -LTTNG_ERR_INVALID; | |
266 | goto end; | |
267 | } | |
268 | ||
269 | location_symbol_comm.symbol_len = symbol_name_len + 1; | |
270 | location_symbol_comm.offset = location_symbol->offset; | |
271 | ||
28ab034a JG |
272 | ret = lttng_dynamic_buffer_append( |
273 | &payload->buffer, &location_symbol_comm, sizeof(location_symbol_comm)); | |
808cb744 JR |
274 | if (ret) { |
275 | ret = -LTTNG_ERR_INVALID; | |
276 | goto end; | |
277 | } | |
278 | ||
28ab034a JG |
279 | ret = lttng_dynamic_buffer_append( |
280 | &payload->buffer, location_symbol->symbol_name, location_symbol_comm.symbol_len); | |
808cb744 JR |
281 | if (ret) { |
282 | ret = -LTTNG_ERR_INVALID; | |
283 | goto end; | |
284 | } | |
285 | ||
286 | ret = (int) (payload->buffer.size - original_payload_size); | |
287 | end: | |
288 | return ret; | |
289 | } | |
290 | ||
28ab034a JG |
291 | static int |
292 | lttng_kernel_probe_location_address_serialize(const struct lttng_kernel_probe_location *location, | |
293 | struct lttng_payload *payload) | |
808cb744 JR |
294 | { |
295 | int ret; | |
296 | size_t original_payload_size; | |
297 | struct lttng_kernel_probe_location_address *location_address; | |
298 | struct lttng_kernel_probe_location_address_comm location_address_comm; | |
299 | ||
a0377dfe FD |
300 | LTTNG_ASSERT(location); |
301 | LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location) == | |
28ab034a | 302 | LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS); |
808cb744 JR |
303 | |
304 | original_payload_size = payload->buffer.size; | |
28ab034a JG |
305 | location_address = |
306 | lttng::utils::container_of(location, <tng_kernel_probe_location_address::parent); | |
808cb744 JR |
307 | |
308 | location_address_comm.address = location_address->address; | |
309 | ||
28ab034a JG |
310 | ret = lttng_dynamic_buffer_append( |
311 | &payload->buffer, &location_address_comm, sizeof(location_address_comm)); | |
808cb744 JR |
312 | if (ret) { |
313 | ret = -LTTNG_ERR_INVALID; | |
314 | goto end; | |
315 | } | |
316 | ||
317 | ret = (int) (payload->buffer.size - original_payload_size); | |
318 | end: | |
319 | return ret; | |
320 | } | |
321 | ||
28ab034a JG |
322 | int lttng_kernel_probe_location_serialize(const struct lttng_kernel_probe_location *location, |
323 | struct lttng_payload *payload) | |
808cb744 JR |
324 | { |
325 | int ret; | |
326 | size_t original_payload_size; | |
327 | struct lttng_kernel_probe_location_comm location_generic_comm = {}; | |
328 | ||
329 | if (!location || !payload) { | |
330 | ERR("Invalid argument(s) passed to '%s'", __FUNCTION__); | |
331 | ret = -LTTNG_ERR_INVALID; | |
332 | goto end; | |
333 | } | |
334 | ||
335 | original_payload_size = payload->buffer.size; | |
336 | location_generic_comm.type = (int8_t) location->type; | |
28ab034a JG |
337 | ret = lttng_dynamic_buffer_append( |
338 | &payload->buffer, &location_generic_comm, sizeof(location_generic_comm)); | |
808cb744 JR |
339 | if (ret) { |
340 | goto end; | |
341 | } | |
342 | ||
343 | ret = location->serialize(location, payload); | |
344 | if (ret < 0) { | |
345 | goto end; | |
346 | } | |
347 | ||
348 | ret = (int) (payload->buffer.size - original_payload_size); | |
349 | end: | |
350 | return ret; | |
351 | } | |
352 | ||
28ab034a JG |
353 | static int lttng_kernel_probe_location_symbol_create_from_payload( |
354 | struct lttng_payload_view *view, struct lttng_kernel_probe_location **location) | |
808cb744 JR |
355 | { |
356 | struct lttng_kernel_probe_location_symbol_comm *location_symbol_comm; | |
357 | const char *symbol_name_src; | |
358 | ssize_t ret = 0; | |
359 | size_t expected_size; | |
360 | ||
a0377dfe | 361 | LTTNG_ASSERT(location); |
808cb744 JR |
362 | |
363 | if (view->buffer.size < sizeof(*location_symbol_comm)) { | |
364 | ret = -LTTNG_ERR_INVALID; | |
365 | goto end; | |
366 | } | |
367 | ||
28ab034a | 368 | location_symbol_comm = (typeof(location_symbol_comm)) view->buffer.data; |
808cb744 | 369 | |
28ab034a | 370 | expected_size = sizeof(*location_symbol_comm) + location_symbol_comm->symbol_len; |
808cb744 JR |
371 | |
372 | if (view->buffer.size < expected_size) { | |
373 | ret = -LTTNG_ERR_INVALID; | |
374 | goto end; | |
375 | } | |
376 | ||
377 | symbol_name_src = view->buffer.data + sizeof(*location_symbol_comm); | |
378 | ||
28ab034a JG |
379 | if (!lttng_buffer_view_contains_string( |
380 | &view->buffer, symbol_name_src, location_symbol_comm->symbol_len)) { | |
808cb744 JR |
381 | ret = -LTTNG_ERR_INVALID; |
382 | goto end; | |
383 | } | |
384 | ||
28ab034a JG |
385 | *location = lttng_kernel_probe_location_symbol_create(symbol_name_src, |
386 | location_symbol_comm->offset); | |
808cb744 JR |
387 | if (!(*location)) { |
388 | ret = -LTTNG_ERR_INVALID; | |
389 | goto end; | |
390 | } | |
391 | ||
392 | ret = (ssize_t) expected_size; | |
393 | end: | |
394 | return ret; | |
395 | } | |
396 | ||
28ab034a JG |
397 | static ssize_t lttng_kernel_probe_location_address_create_from_payload( |
398 | struct lttng_payload_view *view, struct lttng_kernel_probe_location **location) | |
808cb744 JR |
399 | { |
400 | struct lttng_kernel_probe_location_address_comm *location_address_comm; | |
401 | ssize_t ret = 0; | |
402 | size_t expected_size; | |
403 | ||
a0377dfe | 404 | LTTNG_ASSERT(location); |
808cb744 JR |
405 | |
406 | expected_size = sizeof(*location_address_comm); | |
407 | ||
408 | if (view->buffer.size < expected_size) { | |
409 | ret = -LTTNG_ERR_INVALID; | |
410 | goto end; | |
411 | } | |
412 | ||
28ab034a | 413 | location_address_comm = (typeof(location_address_comm)) view->buffer.data; |
808cb744 JR |
414 | |
415 | *location = lttng_kernel_probe_location_address_create(location_address_comm->address); | |
416 | if (!(*location)) { | |
417 | ret = -LTTNG_ERR_INVALID; | |
418 | goto end; | |
419 | } | |
420 | ||
421 | ret = (size_t) expected_size; | |
422 | end: | |
423 | return ret; | |
424 | } | |
425 | ||
28ab034a JG |
426 | ssize_t |
427 | lttng_kernel_probe_location_create_from_payload(struct lttng_payload_view *view, | |
428 | struct lttng_kernel_probe_location **location) | |
808cb744 | 429 | { |
808cb744 JR |
430 | enum lttng_kernel_probe_location_type type; |
431 | ssize_t consumed = 0; | |
432 | ssize_t ret; | |
3e6e0df2 JG |
433 | const struct lttng_kernel_probe_location_comm *probe_location_comm; |
434 | const struct lttng_payload_view probe_location_comm_view = | |
28ab034a | 435 | lttng_payload_view_from_view(view, 0, sizeof(*probe_location_comm)); |
808cb744 | 436 | |
a0377dfe FD |
437 | LTTNG_ASSERT(view); |
438 | LTTNG_ASSERT(location); | |
808cb744 | 439 | |
3e6e0df2 | 440 | if (!lttng_payload_view_is_valid(&probe_location_comm_view)) { |
808cb744 JR |
441 | ret = -LTTNG_ERR_INVALID; |
442 | goto end; | |
443 | } | |
444 | ||
3e6e0df2 | 445 | probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data; |
808cb744 JR |
446 | type = (enum lttng_kernel_probe_location_type) probe_location_comm->type; |
447 | consumed += sizeof(*probe_location_comm); | |
448 | ||
449 | switch (type) { | |
450 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
451 | { | |
452 | struct lttng_payload_view location_view = | |
28ab034a | 453 | lttng_payload_view_from_view(view, consumed, -1); |
808cb744 | 454 | |
28ab034a JG |
455 | ret = lttng_kernel_probe_location_symbol_create_from_payload(&location_view, |
456 | location); | |
808cb744 JR |
457 | break; |
458 | } | |
459 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
460 | { | |
461 | struct lttng_payload_view location_view = | |
28ab034a | 462 | lttng_payload_view_from_view(view, consumed, -1); |
808cb744 | 463 | |
28ab034a JG |
464 | ret = lttng_kernel_probe_location_address_create_from_payload(&location_view, |
465 | location); | |
808cb744 JR |
466 | break; |
467 | } | |
468 | default: | |
469 | ret = -LTTNG_ERR_INVALID; | |
470 | break; | |
471 | } | |
472 | ||
473 | if (ret < 0) { | |
474 | ret = -LTTNG_ERR_INVALID; | |
475 | goto end; | |
476 | } | |
477 | ||
478 | ret += consumed; | |
479 | ||
480 | end: | |
481 | return ret; | |
482 | } | |
483 | ||
28ab034a JG |
484 | static unsigned long |
485 | lttng_kernel_probe_location_address_hash(const struct lttng_kernel_probe_location *location) | |
959e3c66 | 486 | { |
28ab034a JG |
487 | unsigned long hash = |
488 | hash_key_ulong((void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS, lttng_ht_seed); | |
489 | struct lttng_kernel_probe_location_address *address_location = | |
490 | lttng::utils::container_of(location, <tng_kernel_probe_location_address::parent); | |
959e3c66 JR |
491 | |
492 | hash ^= hash_key_u64(&address_location->address, lttng_ht_seed); | |
493 | ||
494 | return hash; | |
495 | } | |
496 | ||
28ab034a JG |
497 | static bool |
498 | lttng_kernel_probe_location_address_is_equal(const struct lttng_kernel_probe_location *_a, | |
499 | const struct lttng_kernel_probe_location *_b) | |
808cb744 JR |
500 | { |
501 | bool is_equal = false; | |
502 | struct lttng_kernel_probe_location_address *a, *b; | |
503 | ||
0114db0e JG |
504 | a = lttng::utils::container_of(_a, <tng_kernel_probe_location_address::parent); |
505 | b = lttng::utils::container_of(_b, <tng_kernel_probe_location_address::parent); | |
808cb744 JR |
506 | |
507 | if (a->address != b->address) { | |
508 | goto end; | |
509 | } | |
510 | ||
511 | is_equal = true; | |
512 | ||
513 | end: | |
514 | return is_equal; | |
515 | } | |
516 | ||
28ab034a JG |
517 | static unsigned long |
518 | lttng_kernel_probe_location_symbol_hash(const struct lttng_kernel_probe_location *location) | |
959e3c66 | 519 | { |
28ab034a JG |
520 | unsigned long hash = hash_key_ulong((void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET, |
521 | lttng_ht_seed); | |
522 | struct lttng_kernel_probe_location_symbol *symbol_location = | |
523 | lttng::utils::container_of(location, <tng_kernel_probe_location_symbol::parent); | |
959e3c66 JR |
524 | |
525 | hash ^= hash_key_str(symbol_location->symbol_name, lttng_ht_seed); | |
526 | hash ^= hash_key_u64(&symbol_location->offset, lttng_ht_seed); | |
527 | ||
528 | return hash; | |
529 | } | |
530 | ||
28ab034a JG |
531 | static bool |
532 | lttng_kernel_probe_location_symbol_is_equal(const struct lttng_kernel_probe_location *_a, | |
533 | const struct lttng_kernel_probe_location *_b) | |
808cb744 JR |
534 | { |
535 | bool is_equal = false; | |
536 | struct lttng_kernel_probe_location_symbol *a, *b; | |
537 | ||
28ab034a JG |
538 | a = lttng::utils::container_of(_a, <tng_kernel_probe_location_symbol::parent); |
539 | b = lttng::utils::container_of(_b, <tng_kernel_probe_location_symbol::parent); | |
808cb744 | 540 | |
a0377dfe FD |
541 | LTTNG_ASSERT(a->symbol_name); |
542 | LTTNG_ASSERT(b->symbol_name); | |
5c7248cd | 543 | if (strcmp(a->symbol_name, b->symbol_name) != 0) { |
808cb744 JR |
544 | goto end; |
545 | } | |
546 | ||
547 | if (a->offset != b->offset) { | |
548 | goto end; | |
549 | } | |
550 | ||
551 | is_equal = true; | |
552 | ||
553 | end: | |
554 | return is_equal; | |
555 | } | |
556 | ||
28ab034a JG |
557 | bool lttng_kernel_probe_location_is_equal(const struct lttng_kernel_probe_location *a, |
558 | const struct lttng_kernel_probe_location *b) | |
808cb744 JR |
559 | { |
560 | bool is_equal = false; | |
561 | ||
562 | if (!a || !b) { | |
563 | goto end; | |
564 | } | |
565 | ||
566 | if (a == b) { | |
567 | is_equal = true; | |
568 | goto end; | |
569 | } | |
570 | ||
571 | if (a->type != b->type) { | |
572 | goto end; | |
573 | } | |
574 | ||
575 | is_equal = a->equal ? a->equal(a, b) : true; | |
576 | end: | |
577 | return is_equal; | |
578 | } | |
077192fd JR |
579 | |
580 | static struct lttng_kernel_probe_location * | |
28ab034a | 581 | lttng_kernel_probe_location_symbol_copy(const struct lttng_kernel_probe_location *location) |
077192fd | 582 | { |
cd9adb8b | 583 | struct lttng_kernel_probe_location *new_location = nullptr; |
077192fd | 584 | enum lttng_kernel_probe_location_status status; |
cd9adb8b | 585 | const char *symbol_name = nullptr; |
077192fd JR |
586 | uint64_t offset; |
587 | ||
a0377dfe FD |
588 | LTTNG_ASSERT(location); |
589 | LTTNG_ASSERT(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET); | |
077192fd | 590 | |
28ab034a | 591 | /* Get probe location offset */ |
077192fd JR |
592 | status = lttng_kernel_probe_location_symbol_get_offset(location, &offset); |
593 | if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) { | |
594 | ERR("Get kernel probe location offset failed."); | |
595 | goto error; | |
596 | } | |
597 | ||
598 | symbol_name = lttng_kernel_probe_location_symbol_get_name(location); | |
599 | if (!symbol_name) { | |
600 | ERR("Kernel probe symbol name is NULL."); | |
601 | goto error; | |
602 | } | |
603 | ||
604 | /* Create the probe_location */ | |
28ab034a | 605 | new_location = lttng_kernel_probe_location_symbol_create(symbol_name, offset); |
077192fd JR |
606 | |
607 | goto end; | |
608 | ||
609 | error: | |
cd9adb8b | 610 | new_location = nullptr; |
077192fd JR |
611 | end: |
612 | return new_location; | |
613 | } | |
614 | static struct lttng_kernel_probe_location * | |
28ab034a | 615 | lttng_kernel_probe_location_address_copy(const struct lttng_kernel_probe_location *location) |
077192fd | 616 | { |
cd9adb8b | 617 | struct lttng_kernel_probe_location *new_location = nullptr; |
077192fd JR |
618 | enum lttng_kernel_probe_location_status status; |
619 | uint64_t address; | |
620 | ||
a0377dfe FD |
621 | LTTNG_ASSERT(location); |
622 | LTTNG_ASSERT(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS); | |
077192fd | 623 | |
0114db0e | 624 | /* Get probe location fields */ |
077192fd JR |
625 | status = lttng_kernel_probe_location_address_get_address(location, &address); |
626 | if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) { | |
627 | ERR("Get kernel probe address failed."); | |
628 | goto error; | |
629 | } | |
630 | ||
631 | /* Create the probe_location */ | |
632 | new_location = lttng_kernel_probe_location_address_create(address); | |
633 | ||
634 | goto end; | |
635 | ||
636 | error: | |
cd9adb8b | 637 | new_location = nullptr; |
077192fd JR |
638 | end: |
639 | return new_location; | |
640 | } | |
641 | ||
28ab034a JG |
642 | struct lttng_kernel_probe_location * |
643 | lttng_kernel_probe_location_copy(const struct lttng_kernel_probe_location *location) | |
077192fd | 644 | { |
cd9adb8b | 645 | struct lttng_kernel_probe_location *new_location = nullptr; |
077192fd JR |
646 | enum lttng_kernel_probe_location_type type; |
647 | ||
648 | if (!location) { | |
649 | goto err; | |
650 | } | |
651 | ||
652 | type = lttng_kernel_probe_location_get_type(location); | |
653 | switch (type) { | |
654 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
28ab034a | 655 | new_location = lttng_kernel_probe_location_address_copy(location); |
077192fd JR |
656 | if (!new_location) { |
657 | goto err; | |
658 | } | |
659 | break; | |
660 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
28ab034a | 661 | new_location = lttng_kernel_probe_location_symbol_copy(location); |
077192fd JR |
662 | if (!new_location) { |
663 | goto err; | |
664 | } | |
665 | break; | |
666 | default: | |
cd9adb8b | 667 | new_location = nullptr; |
077192fd JR |
668 | goto err; |
669 | } | |
670 | err: | |
671 | return new_location; | |
672 | } | |
959e3c66 | 673 | |
28ab034a | 674 | unsigned long lttng_kernel_probe_location_hash(const struct lttng_kernel_probe_location *location) |
959e3c66 JR |
675 | { |
676 | return location->hash(location); | |
677 | } | |
6a751b95 | 678 | |
28ab034a JG |
679 | static enum lttng_error_code |
680 | lttng_kernel_probe_location_address_mi_serialize(const struct lttng_kernel_probe_location *location, | |
681 | struct mi_writer *writer) | |
6a751b95 JR |
682 | { |
683 | int ret; | |
684 | enum lttng_error_code ret_code; | |
685 | enum lttng_kernel_probe_location_status status; | |
686 | uint64_t address; | |
687 | ||
a0377dfe FD |
688 | LTTNG_ASSERT(location); |
689 | LTTNG_ASSERT(writer); | |
690 | LTTNG_ASSERT(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS); | |
6a751b95 | 691 | |
28ab034a | 692 | status = lttng_kernel_probe_location_address_get_address(location, &address); |
a0377dfe | 693 | LTTNG_ASSERT(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
6a751b95 JR |
694 | |
695 | /* Open kernel probe location address element. */ | |
28ab034a | 696 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_kernel_probe_location_address); |
6a751b95 JR |
697 | if (ret) { |
698 | goto mi_error; | |
699 | } | |
700 | ||
28ab034a JG |
701 | ret = mi_lttng_writer_write_element_unsigned_int( |
702 | writer, mi_lttng_element_kernel_probe_location_address_address, address); | |
6a751b95 JR |
703 | if (ret) { |
704 | goto mi_error; | |
705 | } | |
706 | ||
707 | /* Close kernel probe location address element. */ | |
708 | ret = mi_lttng_writer_close_element(writer); | |
709 | if (ret) { | |
710 | goto mi_error; | |
711 | } | |
712 | ||
713 | ret_code = LTTNG_OK; | |
714 | goto end; | |
715 | ||
716 | mi_error: | |
717 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
718 | end: | |
719 | return ret_code; | |
720 | } | |
721 | ||
28ab034a JG |
722 | static enum lttng_error_code |
723 | lttng_kernel_probe_location_symbol_mi_serialize(const struct lttng_kernel_probe_location *location, | |
724 | struct mi_writer *writer) | |
6a751b95 JR |
725 | { |
726 | int ret; | |
727 | enum lttng_error_code ret_code; | |
728 | enum lttng_kernel_probe_location_status status; | |
cd9adb8b | 729 | const char *name = nullptr; |
6a751b95 JR |
730 | uint64_t offset; |
731 | ||
a0377dfe FD |
732 | LTTNG_ASSERT(location); |
733 | LTTNG_ASSERT(writer); | |
28ab034a | 734 | LTTNG_ASSERT(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET); |
6a751b95 JR |
735 | |
736 | name = lttng_kernel_probe_location_symbol_get_name(location); | |
a0377dfe | 737 | LTTNG_ASSERT(name); |
6a751b95 | 738 | |
28ab034a | 739 | status = lttng_kernel_probe_location_symbol_get_offset(location, &offset); |
a0377dfe | 740 | LTTNG_ASSERT(status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
6a751b95 JR |
741 | |
742 | /* Open kernel probe location symbol offset element. */ | |
743 | ret = mi_lttng_writer_open_element(writer, | |
28ab034a | 744 | mi_lttng_element_kernel_probe_location_symbol_offset); |
6a751b95 JR |
745 | if (ret) { |
746 | goto mi_error; | |
747 | } | |
748 | ||
749 | /* Name. */ | |
28ab034a JG |
750 | ret = mi_lttng_writer_write_element_string( |
751 | writer, mi_lttng_element_kernel_probe_location_symbol_offset_name, name); | |
6a751b95 JR |
752 | if (ret) { |
753 | goto mi_error; | |
754 | } | |
755 | ||
756 | /* Offset. */ | |
28ab034a JG |
757 | ret = mi_lttng_writer_write_element_unsigned_int( |
758 | writer, mi_lttng_element_kernel_probe_location_symbol_offset_offset, offset); | |
6a751b95 JR |
759 | if (ret) { |
760 | goto mi_error; | |
761 | } | |
762 | ||
763 | /* Close kernel probe location symbol offset element. */ | |
764 | ret = mi_lttng_writer_close_element(writer); | |
765 | if (ret) { | |
766 | goto mi_error; | |
767 | } | |
768 | ||
769 | ret_code = LTTNG_OK; | |
770 | goto end; | |
771 | ||
772 | mi_error: | |
773 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
774 | end: | |
775 | return ret_code; | |
776 | } | |
777 | ||
28ab034a JG |
778 | enum lttng_error_code |
779 | lttng_kernel_probe_location_mi_serialize(const struct lttng_kernel_probe_location *location, | |
780 | struct mi_writer *writer) | |
6a751b95 JR |
781 | { |
782 | int ret; | |
783 | enum lttng_error_code ret_code; | |
784 | ||
a0377dfe FD |
785 | LTTNG_ASSERT(location); |
786 | LTTNG_ASSERT(writer); | |
6a751b95 JR |
787 | |
788 | /* Open kernel probe location element. */ | |
28ab034a | 789 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_kernel_probe_location); |
6a751b95 JR |
790 | if (ret) { |
791 | goto mi_error; | |
792 | } | |
793 | ||
794 | /* Serialize the location sub type. */ | |
795 | ret_code = location->mi_serialize(location, writer); | |
796 | if (ret_code != LTTNG_OK) { | |
797 | goto end; | |
798 | } | |
799 | ||
800 | /* Close kernel probe location element. */ | |
801 | ret = mi_lttng_writer_close_element(writer); | |
802 | if (ret) { | |
803 | goto mi_error; | |
804 | } | |
805 | ||
806 | ret_code = LTTNG_OK; | |
807 | goto end; | |
808 | ||
809 | mi_error: | |
810 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
811 | end: | |
812 | return ret_code; | |
813 | } |