Commit | Line | Data |
---|---|---|
55bb57e0 | 1 | /* |
f2b0325d | 2 | * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com> |
55bb57e0 | 3 | * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
55bb57e0 PP |
4 | * |
5 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | * of this software and associated documentation files (the "Software"), to deal | |
9 | * in the Software without restriction, including without limitation the rights | |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | * copies of the Software, and to permit persons to whom the Software is | |
12 | * furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be included in | |
15 | * all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
23 | * SOFTWARE. | |
24 | */ | |
25 | ||
b03487ab | 26 | #define BT_LOG_TAG "LIB/PLUGIN-SO" |
1633ef46 | 27 | #include "lib/logging.h" |
3fe0bf43 | 28 | |
57952005 MJ |
29 | #include "common/assert.h" |
30 | #include "lib/assert-pre.h" | |
31 | #include "compat/compiler.h" | |
71c5da58 | 32 | #include <babeltrace2/plugin/plugin-dev.h> |
57952005 | 33 | #include "lib/graph/component-class.h" |
71c5da58 MJ |
34 | #include <babeltrace2/graph/component-class.h> |
35 | #include <babeltrace2/graph/component-class-source.h> | |
36 | #include <babeltrace2/graph/component-class-filter.h> | |
37 | #include <babeltrace2/graph/component-class-sink.h> | |
38 | #include <babeltrace2/types.h> | |
57952005 | 39 | #include "common/list.h" |
55bb57e0 | 40 | #include <string.h> |
0fbb9a9f | 41 | #include <stdlib.h> |
55bb57e0 PP |
42 | #include <glib.h> |
43 | #include <gmodule.h> | |
44 | ||
57952005 MJ |
45 | #include "plugin.h" |
46 | #include "plugin-so.h" | |
fb25b9e3 PP |
47 | #include "lib/func-status.h" |
48 | #include "common/common.h" | |
57952005 | 49 | |
44a3451a | 50 | #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX |
55bb57e0 PP |
51 | #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX) |
52 | #define LIBTOOL_PLUGIN_SUFFIX ".la" | |
53 | #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX) | |
54 | ||
85e7137b | 55 | #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \ |
55bb57e0 PP |
56 | sizeof(LIBTOOL_PLUGIN_SUFFIX)) |
57 | ||
be3c4e36 | 58 | BT_PLUGIN_MODULE(); |
55bb57e0 PP |
59 | |
60 | /* | |
bfa9a4be MD |
61 | * This list, global to the library, keeps all component classes that |
62 | * have a reference to their shared library handles. It allows iteration | |
63 | * on all component classes still present when the destructor executes | |
64 | * to release the shared library handle references they might still have. | |
55bb57e0 | 65 | * |
bfa9a4be | 66 | * The list items are the component classes created with |
55bb57e0 PP |
67 | * bt_plugin_add_component_class(). They keep the shared library handle |
68 | * object created by their plugin alive so that the plugin's code is | |
69 | * not discarded when it could still be in use by living components | |
70 | * created from those component classes: | |
71 | * | |
bfa9a4be | 72 | * [component] --ref-> [component class]-> [shlib handle] |
55bb57e0 | 73 | * |
bfa9a4be | 74 | * It allows this use-case: |
55bb57e0 | 75 | * |
781ae911 | 76 | * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so"); |
55bb57e0 PP |
77 | * // instantiate components from a plugin's component classes |
78 | * // put plugins and free my_plugins here | |
79 | * // user code of instantiated components still exists | |
80 | * | |
bfa9a4be MD |
81 | * An entry is removed from this list when a component class is |
82 | * destroyed thanks to a custom destroy listener. When the entry is | |
83 | * removed, the entry is removed from the list, and we release the | |
84 | * reference on the shlib handle. Assuming the original plugin object | |
85 | * which contained some component classes is put first, when the last | |
86 | * component class is removed from this list, the shared library handle | |
87 | * object's reference count falls to zero and the shared library is | |
88 | * finally closed. | |
55bb57e0 | 89 | */ |
bfa9a4be | 90 | |
55bb57e0 | 91 | static |
bfa9a4be | 92 | BT_LIST_HEAD(component_class_list); |
55bb57e0 PP |
93 | |
94 | __attribute__((destructor)) static | |
bfa9a4be MD |
95 | void fini_comp_class_list(void) |
96 | { | |
97 | struct bt_component_class *comp_class, *tmp; | |
98 | ||
99 | bt_list_for_each_entry_safe(comp_class, tmp, &component_class_list, node) { | |
100 | bt_list_del(&comp_class->node); | |
8138bfe1 | 101 | BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle); |
55bb57e0 | 102 | } |
834e9996 | 103 | |
bfa9a4be | 104 | BT_LOGD_STR("Released references from all component classes to shared library handles."); |
55bb57e0 PP |
105 | } |
106 | ||
107 | static | |
108 | void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj) | |
109 | { | |
110 | struct bt_plugin_so_shared_lib_handle *shared_lib_handle; | |
111 | ||
8b45963b | 112 | BT_ASSERT(obj); |
55bb57e0 PP |
113 | shared_lib_handle = container_of(obj, |
114 | struct bt_plugin_so_shared_lib_handle, base); | |
3fe0bf43 PP |
115 | const char *path = shared_lib_handle->path ? |
116 | shared_lib_handle->path->str : NULL; | |
117 | ||
a684a357 | 118 | BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"", |
3fe0bf43 | 119 | shared_lib_handle, path); |
55bb57e0 PP |
120 | |
121 | if (shared_lib_handle->init_called && shared_lib_handle->exit) { | |
3fe0bf43 | 122 | BT_LOGD_STR("Calling user's plugin exit function."); |
0ae03127 PP |
123 | shared_lib_handle->exit(); |
124 | BT_LOGD_STR("User function returned."); | |
55bb57e0 PP |
125 | } |
126 | ||
127 | if (shared_lib_handle->module) { | |
46e751e1 | 128 | #ifndef BT_DEBUG_MODE |
f1447220 PP |
129 | /* |
130 | * Valgrind shows incomplete stack traces when | |
131 | * dynamically loaded libraries are closed before it | |
e17763ec | 132 | * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug |
f1447220 PP |
133 | * build to avoid this. |
134 | */ | |
e17763ec | 135 | const char *var = getenv("LIBBABELTRACE2_NO_DLCLOSE"); |
f1447220 PP |
136 | |
137 | if (!var || strcmp(var, "1") != 0) { | |
138 | #endif | |
a684a357 | 139 | BT_LOGI("Closing GModule: path=\"%s\"", path); |
3fe0bf43 | 140 | |
f1447220 | 141 | if (!g_module_close(shared_lib_handle->module)) { |
3fe0bf43 PP |
142 | BT_LOGE("Cannot close GModule: %s: path=\"%s\"", |
143 | g_module_error(), path); | |
f1447220 | 144 | } |
c6578b03 PP |
145 | |
146 | shared_lib_handle->module = NULL; | |
46e751e1 | 147 | #ifndef BT_DEBUG_MODE |
3fe0bf43 | 148 | } else { |
e17763ec | 149 | BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: " |
3fe0bf43 | 150 | "path=\"%s\"", path); |
55bb57e0 | 151 | } |
f1447220 | 152 | #endif |
55bb57e0 PP |
153 | } |
154 | ||
155 | if (shared_lib_handle->path) { | |
156 | g_string_free(shared_lib_handle->path, TRUE); | |
c6578b03 | 157 | shared_lib_handle->path = NULL; |
55bb57e0 PP |
158 | } |
159 | ||
160 | g_free(shared_lib_handle); | |
161 | } | |
162 | ||
163 | static | |
fb25b9e3 | 164 | int bt_plugin_so_shared_lib_handle_create( |
01f50d54 PP |
165 | const char *path, |
166 | struct bt_plugin_so_shared_lib_handle **shared_lib_handle) | |
55bb57e0 | 167 | { |
fb25b9e3 | 168 | int status = BT_FUNC_STATUS_OK; |
55bb57e0 | 169 | |
01f50d54 | 170 | BT_ASSERT(shared_lib_handle); |
a684a357 | 171 | BT_LOGI("Creating shared library handle: path=\"%s\"", path); |
01f50d54 PP |
172 | *shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1); |
173 | if (!*shared_lib_handle) { | |
3fe0bf43 | 174 | BT_LOGE_STR("Failed to allocate one shared library handle."); |
fb25b9e3 | 175 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
01f50d54 | 176 | goto end; |
55bb57e0 PP |
177 | } |
178 | ||
01f50d54 | 179 | bt_object_init_shared(&(*shared_lib_handle)->base, |
1d7bf349 | 180 | bt_plugin_so_shared_lib_handle_destroy); |
55bb57e0 PP |
181 | |
182 | if (!path) { | |
183 | goto end; | |
184 | } | |
185 | ||
01f50d54 PP |
186 | (*shared_lib_handle)->path = g_string_new(path); |
187 | if (!(*shared_lib_handle)->path) { | |
3fe0bf43 | 188 | BT_LOGE_STR("Failed to allocate a GString."); |
fb25b9e3 | 189 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
01f50d54 | 190 | goto end; |
55bb57e0 PP |
191 | } |
192 | ||
01f50d54 PP |
193 | (*shared_lib_handle)->module = g_module_open(path, G_MODULE_BIND_LOCAL); |
194 | if (!(*shared_lib_handle)->module) { | |
50ad9320 | 195 | /* |
a684a357 | 196 | * INFO-level logging because we're only _trying_ to |
50ad9320 PP |
197 | * open this file as a Babeltrace plugin: if it's not, |
198 | * it's not an error. And because this can be tried | |
a684a357 PP |
199 | * during bt_plugin_find_all_from_dir(), it's not even a |
200 | * warning. | |
50ad9320 | 201 | */ |
a684a357 | 202 | BT_LOGI("Cannot open GModule: %s: path=\"%s\"", |
3fe0bf43 | 203 | g_module_error(), path); |
01f50d54 | 204 | BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle); |
fb25b9e3 | 205 | status = BT_FUNC_STATUS_NOT_FOUND; |
01f50d54 | 206 | goto end; |
55bb57e0 PP |
207 | } |
208 | ||
209 | goto end; | |
210 | ||
55bb57e0 | 211 | end: |
fb25b9e3 | 212 | BT_ASSERT(*shared_lib_handle || status != BT_FUNC_STATUS_OK); |
01f50d54 | 213 | if (*shared_lib_handle) { |
a684a357 | 214 | BT_LOGI("Created shared library handle: path=\"%s\", addr=%p", |
01f50d54 | 215 | path, *shared_lib_handle); |
3fe0bf43 PP |
216 | } |
217 | ||
01f50d54 | 218 | return status; |
55bb57e0 PP |
219 | } |
220 | ||
6fbd4105 | 221 | static |
55bb57e0 PP |
222 | void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin) |
223 | { | |
224 | struct bt_plugin_so_spec_data *spec = plugin->spec_data; | |
225 | ||
226 | if (!plugin->spec_data) { | |
227 | return; | |
228 | } | |
229 | ||
8b45963b PP |
230 | BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO); |
231 | BT_ASSERT(spec); | |
8138bfe1 | 232 | BT_OBJECT_PUT_REF_AND_RESET(spec->shared_lib_handle); |
55bb57e0 PP |
233 | g_free(plugin->spec_data); |
234 | plugin->spec_data = NULL; | |
235 | } | |
236 | ||
237 | /* | |
238 | * This function does the following: | |
239 | * | |
240 | * 1. Iterate on the plugin descriptor attributes section and set the | |
241 | * plugin's attributes depending on the attribute types. This | |
242 | * includes the name of the plugin, its description, and its | |
243 | * initialization function, for example. | |
244 | * | |
245 | * 2. Iterate on the component class descriptors section and create one | |
246 | * "full descriptor" (temporary structure) for each one that is found | |
247 | * and attached to our plugin descriptor. | |
248 | * | |
249 | * 3. Iterate on the component class descriptor attributes section and | |
250 | * set the corresponding full descriptor's attributes depending on | |
251 | * the attribute types. This includes the description of the | |
252 | * component class, as well as its initialization and destroy | |
253 | * methods. | |
254 | * | |
255 | * 4. Call the user's plugin initialization function, if any is | |
256 | * defined. | |
257 | * | |
258 | * 5. For each full component class descriptor, create a component class | |
259 | * object, set its optional attributes, and add it to the plugin | |
260 | * object. | |
261 | * | |
262 | * 6. Freeze the plugin object. | |
263 | */ | |
264 | static | |
fb25b9e3 | 265 | int bt_plugin_so_init(struct bt_plugin *plugin, |
01f50d54 | 266 | bool fail_on_load_error, |
55bb57e0 PP |
267 | const struct __bt_plugin_descriptor *descriptor, |
268 | struct __bt_plugin_descriptor_attribute const * const *attrs_begin, | |
269 | struct __bt_plugin_descriptor_attribute const * const *attrs_end, | |
270 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin, | |
271 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end, | |
272 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin, | |
273 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end) | |
274 | { | |
275 | /* | |
276 | * This structure's members point to the plugin's memory | |
277 | * (do NOT free). | |
278 | */ | |
279 | struct comp_class_full_descriptor { | |
280 | const struct __bt_plugin_component_class_descriptor *descriptor; | |
281 | const char *description; | |
279b3f15 | 282 | const char *help; |
834e9996 PP |
283 | |
284 | union { | |
285 | struct { | |
7b53201c PP |
286 | bt_component_class_source_init_method init; |
287 | bt_component_class_source_finalize_method finalize; | |
288 | bt_component_class_source_query_method query; | |
7b53201c | 289 | bt_component_class_source_output_port_connected_method output_port_connected; |
b09a5592 PP |
290 | bt_component_class_source_message_iterator_init_method msg_iter_init; |
291 | bt_component_class_source_message_iterator_finalize_method msg_iter_finalize; | |
15a52f66 PP |
292 | bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin; |
293 | bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning; | |
294 | bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin; | |
295 | bt_component_class_source_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning; | |
834e9996 PP |
296 | } source; |
297 | ||
298 | struct { | |
7b53201c PP |
299 | bt_component_class_filter_init_method init; |
300 | bt_component_class_filter_finalize_method finalize; | |
301 | bt_component_class_filter_query_method query; | |
7b53201c PP |
302 | bt_component_class_filter_input_port_connected_method input_port_connected; |
303 | bt_component_class_filter_output_port_connected_method output_port_connected; | |
b09a5592 PP |
304 | bt_component_class_filter_message_iterator_init_method msg_iter_init; |
305 | bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize; | |
15a52f66 PP |
306 | bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin; |
307 | bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning; | |
308 | bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin; | |
309 | bt_component_class_filter_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning; | |
834e9996 PP |
310 | } filter; |
311 | ||
312 | struct { | |
7b53201c PP |
313 | bt_component_class_sink_init_method init; |
314 | bt_component_class_sink_finalize_method finalize; | |
315 | bt_component_class_sink_query_method query; | |
7b53201c | 316 | bt_component_class_sink_input_port_connected_method input_port_connected; |
1043fdea | 317 | bt_component_class_sink_graph_is_configured_method graph_is_configured; |
834e9996 PP |
318 | } sink; |
319 | } methods; | |
55bb57e0 PP |
320 | }; |
321 | ||
fb25b9e3 | 322 | int status = BT_FUNC_STATUS_OK; |
55bb57e0 PP |
323 | struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr; |
324 | struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr; | |
325 | struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr; | |
326 | struct bt_plugin_so_spec_data *spec = plugin->spec_data; | |
327 | GArray *comp_class_full_descriptors; | |
328 | size_t i; | |
329 | int ret; | |
330 | ||
a684a357 | 331 | BT_LOGI("Initializing plugin object from descriptors found in sections: " |
3fe0bf43 PP |
332 | "plugin-addr=%p, plugin-path=\"%s\", " |
333 | "attrs-begin-addr=%p, attrs-end-addr=%p, " | |
334 | "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, " | |
335 | "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p", | |
336 | plugin, | |
337 | spec->shared_lib_handle->path ? | |
338 | spec->shared_lib_handle->path->str : NULL, | |
339 | attrs_begin, attrs_end, | |
340 | cc_descriptors_begin, cc_descriptors_end, | |
341 | cc_descr_attrs_begin, cc_descr_attrs_end); | |
55bb57e0 PP |
342 | comp_class_full_descriptors = g_array_new(FALSE, TRUE, |
343 | sizeof(struct comp_class_full_descriptor)); | |
344 | if (!comp_class_full_descriptors) { | |
3fe0bf43 | 345 | BT_LOGE_STR("Failed to allocate a GArray."); |
fb25b9e3 | 346 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
55bb57e0 PP |
347 | goto end; |
348 | } | |
349 | ||
350 | /* Set mandatory attributes */ | |
351 | spec->descriptor = descriptor; | |
352 | bt_plugin_set_name(plugin, descriptor->name); | |
353 | ||
354 | /* | |
355 | * Find and set optional attributes attached to this plugin | |
356 | * descriptor. | |
357 | */ | |
358 | for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) { | |
359 | const struct __bt_plugin_descriptor_attribute *cur_attr = | |
360 | *cur_attr_ptr; | |
361 | ||
be3c4e36 MJ |
362 | if (cur_attr == NULL) { |
363 | continue; | |
364 | } | |
365 | ||
55bb57e0 PP |
366 | if (cur_attr->plugin_descriptor != descriptor) { |
367 | continue; | |
368 | } | |
369 | ||
370 | switch (cur_attr->type) { | |
371 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT: | |
372 | spec->init = cur_attr->value.init; | |
373 | break; | |
374 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT: | |
375 | spec->shared_lib_handle->exit = cur_attr->value.exit; | |
376 | break; | |
377 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR: | |
378 | bt_plugin_set_author(plugin, cur_attr->value.author); | |
379 | break; | |
380 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE: | |
381 | bt_plugin_set_license(plugin, cur_attr->value.license); | |
382 | break; | |
383 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION: | |
384 | bt_plugin_set_description(plugin, cur_attr->value.description); | |
385 | break; | |
386 | case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION: | |
387 | bt_plugin_set_version(plugin, | |
388 | (unsigned int) cur_attr->value.version.major, | |
389 | (unsigned int) cur_attr->value.version.minor, | |
390 | (unsigned int) cur_attr->value.version.patch, | |
391 | cur_attr->value.version.extra); | |
392 | break; | |
393 | default: | |
01f50d54 PP |
394 | BT_LOG_WRITE(fail_on_load_error ? |
395 | BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG, | |
396 | "%s plugin descriptor attribute: " | |
3fe0bf43 PP |
397 | "plugin-path=\"%s\", plugin-name=\"%s\", " |
398 | "attr-type-name=\"%s\", attr-type-id=%d", | |
01f50d54 PP |
399 | fail_on_load_error ? "Unknown" : |
400 | "Ignoring unknown", | |
3fe0bf43 PP |
401 | spec->shared_lib_handle->path ? |
402 | spec->shared_lib_handle->path->str : | |
403 | NULL, | |
404 | descriptor->name, cur_attr->type_name, | |
405 | cur_attr->type); | |
01f50d54 PP |
406 | |
407 | if (fail_on_load_error) { | |
fb25b9e3 | 408 | status = BT_FUNC_STATUS_LOADING_ERROR; |
01f50d54 PP |
409 | goto end; |
410 | } | |
411 | ||
55bb57e0 PP |
412 | break; |
413 | } | |
414 | } | |
415 | ||
416 | /* | |
417 | * Find component class descriptors attached to this plugin | |
418 | * descriptor and initialize corresponding full component class | |
419 | * descriptors in the array. | |
420 | */ | |
421 | for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) { | |
422 | const struct __bt_plugin_component_class_descriptor *cur_cc_descr = | |
423 | *cur_cc_descr_ptr; | |
424 | struct comp_class_full_descriptor full_descriptor = {0}; | |
425 | ||
be3c4e36 MJ |
426 | if (cur_cc_descr == NULL) { |
427 | continue; | |
428 | } | |
429 | ||
55bb57e0 PP |
430 | if (cur_cc_descr->plugin_descriptor != descriptor) { |
431 | continue; | |
432 | } | |
433 | ||
434 | full_descriptor.descriptor = cur_cc_descr; | |
435 | g_array_append_val(comp_class_full_descriptors, | |
436 | full_descriptor); | |
437 | } | |
438 | ||
439 | /* | |
440 | * Find component class descriptor attributes attached to this | |
441 | * plugin descriptor and update corresponding full component | |
442 | * class descriptors in the array. | |
443 | */ | |
444 | for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) { | |
445 | const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr = | |
446 | *cur_cc_descr_attr_ptr; | |
834e9996 | 447 | enum bt_component_class_type cc_type; |
55bb57e0 | 448 | |
be3c4e36 MJ |
449 | if (cur_cc_descr_attr == NULL) { |
450 | continue; | |
451 | } | |
452 | ||
55bb57e0 PP |
453 | if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor != |
454 | descriptor) { | |
455 | continue; | |
456 | } | |
457 | ||
834e9996 PP |
458 | cc_type = cur_cc_descr_attr->comp_class_descriptor->type; |
459 | ||
55bb57e0 PP |
460 | /* Find the corresponding component class descriptor entry */ |
461 | for (i = 0; i < comp_class_full_descriptors->len; i++) { | |
462 | struct comp_class_full_descriptor *cc_full_descr = | |
463 | &g_array_index(comp_class_full_descriptors, | |
464 | struct comp_class_full_descriptor, i); | |
465 | ||
834e9996 | 466 | if (cur_cc_descr_attr->comp_class_descriptor != |
55bb57e0 | 467 | cc_full_descr->descriptor) { |
834e9996 PP |
468 | continue; |
469 | } | |
470 | ||
471 | switch (cur_cc_descr_attr->type) { | |
472 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION: | |
473 | cc_full_descr->description = | |
474 | cur_cc_descr_attr->value.description; | |
475 | break; | |
476 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP: | |
477 | cc_full_descr->help = | |
478 | cur_cc_descr_attr->value.help; | |
479 | break; | |
480 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD: | |
481 | switch (cc_type) { | |
482 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
483 | cc_full_descr->methods.source.init = | |
484 | cur_cc_descr_attr->value.source_init_method; | |
55bb57e0 | 485 | break; |
834e9996 PP |
486 | case BT_COMPONENT_CLASS_TYPE_FILTER: |
487 | cc_full_descr->methods.filter.init = | |
488 | cur_cc_descr_attr->value.filter_init_method; | |
279b3f15 | 489 | break; |
834e9996 PP |
490 | case BT_COMPONENT_CLASS_TYPE_SINK: |
491 | cc_full_descr->methods.sink.init = | |
492 | cur_cc_descr_attr->value.sink_init_method; | |
55bb57e0 | 493 | break; |
834e9996 PP |
494 | default: |
495 | abort(); | |
496 | } | |
497 | break; | |
498 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD: | |
499 | switch (cc_type) { | |
500 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
501 | cc_full_descr->methods.source.finalize = | |
502 | cur_cc_descr_attr->value.source_finalize_method; | |
55bb57e0 | 503 | break; |
834e9996 PP |
504 | case BT_COMPONENT_CLASS_TYPE_FILTER: |
505 | cc_full_descr->methods.filter.finalize = | |
506 | cur_cc_descr_attr->value.filter_finalize_method; | |
8463eac2 | 507 | break; |
834e9996 PP |
508 | case BT_COMPONENT_CLASS_TYPE_SINK: |
509 | cc_full_descr->methods.sink.finalize = | |
510 | cur_cc_descr_attr->value.sink_finalize_method; | |
72b913fb | 511 | break; |
834e9996 PP |
512 | default: |
513 | abort(); | |
514 | } | |
515 | break; | |
516 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD: | |
517 | switch (cc_type) { | |
518 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
519 | cc_full_descr->methods.source.query = | |
520 | cur_cc_descr_attr->value.source_query_method; | |
0d8b4d8e | 521 | break; |
834e9996 PP |
522 | case BT_COMPONENT_CLASS_TYPE_FILTER: |
523 | cc_full_descr->methods.filter.query = | |
524 | cur_cc_descr_attr->value.filter_query_method; | |
55bb57e0 | 525 | break; |
834e9996 PP |
526 | case BT_COMPONENT_CLASS_TYPE_SINK: |
527 | cc_full_descr->methods.sink.query = | |
528 | cur_cc_descr_attr->value.sink_query_method; | |
55bb57e0 | 529 | break; |
834e9996 PP |
530 | default: |
531 | abort(); | |
532 | } | |
533 | break; | |
834e9996 PP |
534 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD: |
535 | switch (cc_type) { | |
536 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
537 | cc_full_descr->methods.filter.input_port_connected = | |
538 | cur_cc_descr_attr->value.filter_input_port_connected_method; | |
539 | break; | |
540 | case BT_COMPONENT_CLASS_TYPE_SINK: | |
541 | cc_full_descr->methods.sink.input_port_connected = | |
542 | cur_cc_descr_attr->value.sink_input_port_connected_method; | |
55bb57e0 | 543 | break; |
55bb57e0 | 544 | default: |
834e9996 PP |
545 | abort(); |
546 | } | |
547 | break; | |
548 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD: | |
549 | switch (cc_type) { | |
550 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
551 | cc_full_descr->methods.source.output_port_connected = | |
552 | cur_cc_descr_attr->value.source_output_port_connected_method; | |
553 | break; | |
554 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
555 | cc_full_descr->methods.filter.output_port_connected = | |
556 | cur_cc_descr_attr->value.filter_output_port_connected_method; | |
55bb57e0 | 557 | break; |
834e9996 PP |
558 | default: |
559 | abort(); | |
55bb57e0 | 560 | } |
834e9996 | 561 | break; |
1043fdea PP |
562 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD: |
563 | switch (cc_type) { | |
564 | case BT_COMPONENT_CLASS_TYPE_SINK: | |
565 | cc_full_descr->methods.sink.graph_is_configured = | |
566 | cur_cc_descr_attr->value.sink_graph_is_configured_method; | |
567 | break; | |
568 | default: | |
569 | abort(); | |
570 | } | |
571 | break; | |
b09a5592 | 572 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INIT_METHOD: |
834e9996 PP |
573 | switch (cc_type) { |
574 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
b09a5592 PP |
575 | cc_full_descr->methods.source.msg_iter_init = |
576 | cur_cc_descr_attr->value.source_msg_iter_init_method; | |
834e9996 PP |
577 | break; |
578 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
b09a5592 PP |
579 | cc_full_descr->methods.filter.msg_iter_init = |
580 | cur_cc_descr_attr->value.filter_msg_iter_init_method; | |
834e9996 PP |
581 | break; |
582 | default: | |
583 | abort(); | |
584 | } | |
585 | break; | |
b09a5592 | 586 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD: |
834e9996 PP |
587 | switch (cc_type) { |
588 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
b09a5592 PP |
589 | cc_full_descr->methods.source.msg_iter_finalize = |
590 | cur_cc_descr_attr->value.source_msg_iter_finalize_method; | |
834e9996 PP |
591 | break; |
592 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
b09a5592 PP |
593 | cc_full_descr->methods.filter.msg_iter_finalize = |
594 | cur_cc_descr_attr->value.filter_msg_iter_finalize_method; | |
834e9996 PP |
595 | break; |
596 | default: | |
597 | abort(); | |
598 | } | |
599 | break; | |
15a52f66 PP |
600 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD: |
601 | switch (cc_type) { | |
602 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
603 | cc_full_descr->methods.source.msg_iter_seek_ns_from_origin = | |
604 | cur_cc_descr_attr->value.source_msg_iter_seek_ns_from_origin_method; | |
605 | break; | |
606 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
607 | cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin = | |
608 | cur_cc_descr_attr->value.filter_msg_iter_seek_ns_from_origin_method; | |
609 | break; | |
610 | default: | |
611 | abort(); | |
612 | } | |
613 | break; | |
614 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD: | |
615 | switch (cc_type) { | |
616 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
617 | cc_full_descr->methods.source.msg_iter_seek_beginning = | |
618 | cur_cc_descr_attr->value.source_msg_iter_seek_beginning_method; | |
619 | break; | |
620 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
621 | cc_full_descr->methods.filter.msg_iter_seek_beginning = | |
622 | cur_cc_descr_attr->value.filter_msg_iter_seek_beginning_method; | |
623 | break; | |
624 | default: | |
625 | abort(); | |
626 | } | |
627 | break; | |
628 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD: | |
629 | switch (cc_type) { | |
630 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
631 | cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin = | |
632 | cur_cc_descr_attr->value.source_msg_iter_can_seek_ns_from_origin_method; | |
633 | break; | |
634 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
635 | cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin = | |
636 | cur_cc_descr_attr->value.filter_msg_iter_can_seek_ns_from_origin_method; | |
637 | break; | |
638 | default: | |
639 | abort(); | |
640 | } | |
641 | break; | |
642 | case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD: | |
643 | switch (cc_type) { | |
644 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
645 | cc_full_descr->methods.source.msg_iter_can_seek_beginning = | |
646 | cur_cc_descr_attr->value.source_msg_iter_can_seek_beginning_method; | |
647 | break; | |
648 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
649 | cc_full_descr->methods.filter.msg_iter_can_seek_beginning = | |
650 | cur_cc_descr_attr->value.filter_msg_iter_can_seek_beginning_method; | |
651 | break; | |
652 | default: | |
653 | abort(); | |
654 | } | |
655 | break; | |
834e9996 | 656 | default: |
01f50d54 PP |
657 | BT_LOG_WRITE(fail_on_load_error ? |
658 | BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG, | |
659 | "%s component class descriptor attribute: " | |
834e9996 PP |
660 | "plugin-path=\"%s\", " |
661 | "plugin-name=\"%s\", " | |
662 | "comp-class-name=\"%s\", " | |
663 | "comp-class-type=%s, " | |
664 | "attr-type-name=\"%s\", " | |
665 | "attr-type-id=%d", | |
01f50d54 PP |
666 | fail_on_load_error ? "Unknown" : |
667 | "Ignoring unknown", | |
834e9996 PP |
668 | spec->shared_lib_handle->path ? |
669 | spec->shared_lib_handle->path->str : | |
670 | NULL, | |
671 | descriptor->name, | |
672 | cur_cc_descr_attr->comp_class_descriptor->name, | |
673 | bt_component_class_type_string( | |
674 | cur_cc_descr_attr->comp_class_descriptor->type), | |
675 | cur_cc_descr_attr->type_name, | |
676 | cur_cc_descr_attr->type); | |
01f50d54 PP |
677 | |
678 | if (fail_on_load_error) { | |
fb25b9e3 | 679 | status = BT_FUNC_STATUS_LOADING_ERROR; |
01f50d54 PP |
680 | goto end; |
681 | } | |
682 | ||
834e9996 | 683 | break; |
55bb57e0 PP |
684 | } |
685 | } | |
686 | } | |
687 | ||
688 | /* Initialize plugin */ | |
689 | if (spec->init) { | |
fb25b9e3 | 690 | enum bt_plugin_init_func_status init_status; |
c8750769 | 691 | |
3fe0bf43 | 692 | BT_LOGD_STR("Calling user's plugin initialization function."); |
c8750769 | 693 | init_status = spec->init((void *) plugin); |
01f50d54 | 694 | BT_LOGD("User function returned: status=%s", |
fb25b9e3 | 695 | bt_common_func_status_string(init_status)); |
3fe0bf43 | 696 | |
0ae03127 | 697 | if (init_status < 0) { |
01f50d54 PP |
698 | BT_LOG_WRITE(fail_on_load_error ? |
699 | BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG, | |
700 | "User's plugin initialization function failed: " | |
701 | "status=%s", | |
fb25b9e3 | 702 | bt_common_func_status_string(init_status)); |
01f50d54 PP |
703 | |
704 | if (fail_on_load_error) { | |
fb25b9e3 | 705 | status = init_status; |
01f50d54 PP |
706 | goto end; |
707 | } | |
55bb57e0 PP |
708 | } |
709 | } | |
710 | ||
c55a9f58 | 711 | spec->shared_lib_handle->init_called = BT_TRUE; |
55bb57e0 PP |
712 | |
713 | /* Add described component classes to plugin */ | |
714 | for (i = 0; i < comp_class_full_descriptors->len; i++) { | |
715 | struct comp_class_full_descriptor *cc_full_descr = | |
716 | &g_array_index(comp_class_full_descriptors, | |
717 | struct comp_class_full_descriptor, i); | |
7b53201c PP |
718 | struct bt_component_class *comp_class = NULL; |
719 | struct bt_component_class_source *src_comp_class = NULL; | |
720 | struct bt_component_class_filter *flt_comp_class = NULL; | |
721 | struct bt_component_class_sink *sink_comp_class = NULL; | |
55bb57e0 | 722 | |
a684a357 | 723 | BT_LOGI("Creating and setting properties of plugin's component class: " |
3fe0bf43 PP |
724 | "plugin-path=\"%s\", plugin-name=\"%s\", " |
725 | "comp-class-name=\"%s\", comp-class-type=%s", | |
726 | spec->shared_lib_handle->path ? | |
727 | spec->shared_lib_handle->path->str : | |
728 | NULL, | |
729 | descriptor->name, | |
730 | cc_full_descr->descriptor->name, | |
731 | bt_component_class_type_string( | |
732 | cc_full_descr->descriptor->type)); | |
733 | ||
55bb57e0 PP |
734 | switch (cc_full_descr->descriptor->type) { |
735 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
7b53201c | 736 | src_comp_class = bt_component_class_source_create( |
55bb57e0 | 737 | cc_full_descr->descriptor->name, |
b09a5592 | 738 | cc_full_descr->descriptor->methods.source.msg_iter_next); |
7b53201c | 739 | comp_class = bt_component_class_source_as_component_class( |
834e9996 | 740 | src_comp_class); |
55bb57e0 PP |
741 | break; |
742 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
7b53201c | 743 | flt_comp_class = bt_component_class_filter_create( |
55bb57e0 | 744 | cc_full_descr->descriptor->name, |
b09a5592 | 745 | cc_full_descr->descriptor->methods.source.msg_iter_next); |
7b53201c | 746 | comp_class = bt_component_class_filter_as_component_class( |
834e9996 | 747 | flt_comp_class); |
55bb57e0 PP |
748 | break; |
749 | case BT_COMPONENT_CLASS_TYPE_SINK: | |
7b53201c | 750 | sink_comp_class = bt_component_class_sink_create( |
55bb57e0 PP |
751 | cc_full_descr->descriptor->name, |
752 | cc_full_descr->descriptor->methods.sink.consume); | |
7b53201c | 753 | comp_class = bt_component_class_sink_as_component_class( |
834e9996 | 754 | sink_comp_class); |
55bb57e0 PP |
755 | break; |
756 | default: | |
01f50d54 PP |
757 | BT_LOG_WRITE(fail_on_load_error ? |
758 | BT_LOG_WARN : BT_LOG_INFO, BT_LOG_TAG, | |
759 | "%s component class type: " | |
3fe0bf43 PP |
760 | "plugin-path=\"%s\", plugin-name=\"%s\", " |
761 | "comp-class-name=\"%s\", comp-class-type=%d", | |
01f50d54 PP |
762 | fail_on_load_error ? "Unknown" : |
763 | "Ignoring unknown", | |
3fe0bf43 PP |
764 | spec->shared_lib_handle->path->str ? |
765 | spec->shared_lib_handle->path->str : | |
766 | NULL, | |
767 | descriptor->name, | |
55bb57e0 | 768 | cc_full_descr->descriptor->name, |
3fe0bf43 | 769 | cc_full_descr->descriptor->type); |
01f50d54 PP |
770 | |
771 | if (fail_on_load_error) { | |
fb25b9e3 | 772 | status = BT_FUNC_STATUS_LOADING_ERROR; |
01f50d54 PP |
773 | goto end; |
774 | } | |
775 | ||
55bb57e0 PP |
776 | continue; |
777 | } | |
778 | ||
779 | if (!comp_class) { | |
3fe0bf43 | 780 | BT_LOGE_STR("Cannot create component class."); |
fb25b9e3 | 781 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
55bb57e0 PP |
782 | goto end; |
783 | } | |
784 | ||
785 | if (cc_full_descr->description) { | |
7b53201c | 786 | ret = bt_component_class_set_description( |
834e9996 | 787 | comp_class, cc_full_descr->description); |
55bb57e0 | 788 | if (ret) { |
3fe0bf43 | 789 | BT_LOGE_STR("Cannot set component class's description."); |
fb25b9e3 | 790 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
8138bfe1 | 791 | BT_OBJECT_PUT_REF_AND_RESET(comp_class); |
55bb57e0 PP |
792 | goto end; |
793 | } | |
794 | } | |
795 | ||
279b3f15 | 796 | if (cc_full_descr->help) { |
7b53201c | 797 | ret = bt_component_class_set_help(comp_class, |
279b3f15 PP |
798 | cc_full_descr->help); |
799 | if (ret) { | |
3fe0bf43 | 800 | BT_LOGE_STR("Cannot set component class's help string."); |
fb25b9e3 | 801 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
8138bfe1 | 802 | BT_OBJECT_PUT_REF_AND_RESET(comp_class); |
279b3f15 PP |
803 | goto end; |
804 | } | |
805 | } | |
806 | ||
834e9996 PP |
807 | switch (cc_full_descr->descriptor->type) { |
808 | case BT_COMPONENT_CLASS_TYPE_SOURCE: | |
809 | if (cc_full_descr->methods.source.init) { | |
7b53201c | 810 | ret = bt_component_class_source_set_init_method( |
834e9996 PP |
811 | src_comp_class, |
812 | cc_full_descr->methods.source.init); | |
813 | if (ret) { | |
814 | BT_LOGE_STR("Cannot set source component class's initialization method."); | |
fb25b9e3 | 815 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
816 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
817 | goto end; | |
818 | } | |
55bb57e0 | 819 | } |
55bb57e0 | 820 | |
834e9996 | 821 | if (cc_full_descr->methods.source.finalize) { |
7b53201c | 822 | ret = bt_component_class_source_set_finalize_method( |
834e9996 PP |
823 | src_comp_class, |
824 | cc_full_descr->methods.source.finalize); | |
825 | if (ret) { | |
826 | BT_LOGE_STR("Cannot set source component class's finalization method."); | |
fb25b9e3 | 827 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
828 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
829 | goto end; | |
830 | } | |
55bb57e0 | 831 | } |
55bb57e0 | 832 | |
834e9996 | 833 | if (cc_full_descr->methods.source.query) { |
7b53201c | 834 | ret = bt_component_class_source_set_query_method( |
834e9996 PP |
835 | src_comp_class, |
836 | cc_full_descr->methods.source.query); | |
837 | if (ret) { | |
838 | BT_LOGE_STR("Cannot set source component class's query method."); | |
fb25b9e3 | 839 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
840 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
841 | goto end; | |
842 | } | |
8463eac2 | 843 | } |
8463eac2 | 844 | |
834e9996 | 845 | if (cc_full_descr->methods.source.output_port_connected) { |
7b53201c | 846 | ret = bt_component_class_source_set_output_port_connected_method( |
834e9996 PP |
847 | src_comp_class, |
848 | cc_full_descr->methods.source.output_port_connected); | |
849 | if (ret) { | |
850 | BT_LOGE_STR("Cannot set source component class's \"output port connected\" method."); | |
fb25b9e3 | 851 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
852 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
853 | goto end; | |
854 | } | |
0d8b4d8e | 855 | } |
0d8b4d8e | 856 | |
b09a5592 PP |
857 | if (cc_full_descr->methods.source.msg_iter_init) { |
858 | ret = bt_component_class_source_set_message_iterator_init_method( | |
834e9996 | 859 | src_comp_class, |
b09a5592 | 860 | cc_full_descr->methods.source.msg_iter_init); |
55bb57e0 | 861 | if (ret) { |
b09a5592 | 862 | BT_LOGE_STR("Cannot set source component class's message iterator initialization method."); |
fb25b9e3 | 863 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 | 864 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
55bb57e0 PP |
865 | goto end; |
866 | } | |
867 | } | |
868 | ||
b09a5592 PP |
869 | if (cc_full_descr->methods.source.msg_iter_finalize) { |
870 | ret = bt_component_class_source_set_message_iterator_finalize_method( | |
834e9996 | 871 | src_comp_class, |
b09a5592 | 872 | cc_full_descr->methods.source.msg_iter_finalize); |
55bb57e0 | 873 | if (ret) { |
b09a5592 | 874 | BT_LOGE_STR("Cannot set source component class's message iterator finalization method."); |
fb25b9e3 | 875 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 | 876 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
55bb57e0 PP |
877 | goto end; |
878 | } | |
879 | } | |
834e9996 | 880 | |
15a52f66 PP |
881 | if (cc_full_descr->methods.source.msg_iter_seek_ns_from_origin) { |
882 | ret = bt_component_class_source_set_message_iterator_seek_ns_from_origin_method( | |
883 | src_comp_class, | |
884 | cc_full_descr->methods.source.msg_iter_seek_ns_from_origin); | |
885 | if (ret) { | |
886 | BT_LOGE_STR("Cannot set source component class's message iterator \"seek nanoseconds from origin\" method."); | |
fb25b9e3 | 887 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
888 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
889 | goto end; | |
890 | } | |
891 | } | |
892 | ||
893 | if (cc_full_descr->methods.source.msg_iter_seek_beginning) { | |
894 | ret = bt_component_class_source_set_message_iterator_seek_beginning_method( | |
895 | src_comp_class, | |
896 | cc_full_descr->methods.source.msg_iter_seek_beginning); | |
897 | if (ret) { | |
898 | BT_LOGE_STR("Cannot set source component class's message iterator \"seek beginning\" method."); | |
fb25b9e3 | 899 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
900 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
901 | goto end; | |
902 | } | |
903 | } | |
904 | ||
905 | if (cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin) { | |
906 | ret = bt_component_class_source_set_message_iterator_can_seek_ns_from_origin_method( | |
907 | src_comp_class, | |
908 | cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin); | |
909 | if (ret) { | |
910 | BT_LOGE_STR("Cannot set source component class's message iterator \"can seek nanoseconds from origin\" method."); | |
fb25b9e3 | 911 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
912 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
913 | goto end; | |
914 | } | |
915 | } | |
916 | ||
917 | if (cc_full_descr->methods.source.msg_iter_can_seek_beginning) { | |
918 | ret = bt_component_class_source_set_message_iterator_can_seek_beginning_method( | |
919 | src_comp_class, | |
920 | cc_full_descr->methods.source.msg_iter_can_seek_beginning); | |
921 | if (ret) { | |
922 | BT_LOGE_STR("Cannot set source component class's message iterator \"can seek beginning\" method."); | |
fb25b9e3 | 923 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
924 | BT_OBJECT_PUT_REF_AND_RESET(src_comp_class); |
925 | goto end; | |
926 | } | |
927 | } | |
928 | ||
55bb57e0 PP |
929 | break; |
930 | case BT_COMPONENT_CLASS_TYPE_FILTER: | |
834e9996 | 931 | if (cc_full_descr->methods.filter.init) { |
7b53201c | 932 | ret = bt_component_class_filter_set_init_method( |
834e9996 PP |
933 | flt_comp_class, |
934 | cc_full_descr->methods.filter.init); | |
935 | if (ret) { | |
936 | BT_LOGE_STR("Cannot set filter component class's initialization method."); | |
fb25b9e3 | 937 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
938 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
939 | goto end; | |
940 | } | |
941 | } | |
942 | ||
943 | if (cc_full_descr->methods.filter.finalize) { | |
7b53201c | 944 | ret = bt_component_class_filter_set_finalize_method( |
834e9996 PP |
945 | flt_comp_class, |
946 | cc_full_descr->methods.filter.finalize); | |
947 | if (ret) { | |
948 | BT_LOGE_STR("Cannot set filter component class's finalization method."); | |
fb25b9e3 | 949 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
950 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
951 | goto end; | |
952 | } | |
953 | } | |
954 | ||
955 | if (cc_full_descr->methods.filter.query) { | |
7b53201c | 956 | ret = bt_component_class_filter_set_query_method( |
834e9996 PP |
957 | flt_comp_class, |
958 | cc_full_descr->methods.filter.query); | |
959 | if (ret) { | |
960 | BT_LOGE_STR("Cannot set filter component class's query method."); | |
fb25b9e3 | 961 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
962 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
963 | goto end; | |
964 | } | |
965 | } | |
966 | ||
834e9996 | 967 | if (cc_full_descr->methods.filter.input_port_connected) { |
7b53201c | 968 | ret = bt_component_class_filter_set_input_port_connected_method( |
834e9996 PP |
969 | flt_comp_class, |
970 | cc_full_descr->methods.filter.input_port_connected); | |
971 | if (ret) { | |
972 | BT_LOGE_STR("Cannot set filter component class's \"input port connected\" method."); | |
fb25b9e3 | 973 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
974 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
975 | goto end; | |
976 | } | |
977 | } | |
978 | ||
979 | if (cc_full_descr->methods.filter.output_port_connected) { | |
7b53201c | 980 | ret = bt_component_class_filter_set_output_port_connected_method( |
834e9996 PP |
981 | flt_comp_class, |
982 | cc_full_descr->methods.filter.output_port_connected); | |
983 | if (ret) { | |
984 | BT_LOGE_STR("Cannot set filter component class's \"output port connected\" method."); | |
fb25b9e3 | 985 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
986 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
987 | goto end; | |
988 | } | |
989 | } | |
990 | ||
b09a5592 PP |
991 | if (cc_full_descr->methods.filter.msg_iter_init) { |
992 | ret = bt_component_class_filter_set_message_iterator_init_method( | |
834e9996 | 993 | flt_comp_class, |
b09a5592 | 994 | cc_full_descr->methods.filter.msg_iter_init); |
55bb57e0 | 995 | if (ret) { |
b09a5592 | 996 | BT_LOGE_STR("Cannot set filter component class's message iterator initialization method."); |
fb25b9e3 | 997 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 | 998 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
55bb57e0 PP |
999 | goto end; |
1000 | } | |
1001 | } | |
1002 | ||
b09a5592 PP |
1003 | if (cc_full_descr->methods.filter.msg_iter_finalize) { |
1004 | ret = bt_component_class_filter_set_message_iterator_finalize_method( | |
834e9996 | 1005 | flt_comp_class, |
b09a5592 | 1006 | cc_full_descr->methods.filter.msg_iter_finalize); |
55bb57e0 | 1007 | if (ret) { |
b09a5592 | 1008 | BT_LOGE_STR("Cannot set filter component class's message iterator finalization method."); |
fb25b9e3 | 1009 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 | 1010 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
55bb57e0 PP |
1011 | goto end; |
1012 | } | |
1013 | } | |
834e9996 | 1014 | |
15a52f66 PP |
1015 | if (cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin) { |
1016 | ret = bt_component_class_filter_set_message_iterator_seek_ns_from_origin_method( | |
1017 | flt_comp_class, | |
1018 | cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin); | |
1019 | if (ret) { | |
1020 | BT_LOGE_STR("Cannot set filter component class's message iterator \"seek nanoseconds from origin\" method."); | |
fb25b9e3 | 1021 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
1022 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
1023 | goto end; | |
1024 | } | |
1025 | } | |
1026 | ||
1027 | if (cc_full_descr->methods.filter.msg_iter_seek_beginning) { | |
1028 | ret = bt_component_class_filter_set_message_iterator_seek_beginning_method( | |
1029 | flt_comp_class, | |
1030 | cc_full_descr->methods.filter.msg_iter_seek_beginning); | |
1031 | if (ret) { | |
1032 | BT_LOGE_STR("Cannot set filter component class's message iterator \"seek beginning\" method."); | |
fb25b9e3 | 1033 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
1034 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
1035 | goto end; | |
1036 | } | |
1037 | } | |
1038 | ||
1039 | if (cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin) { | |
1040 | ret = bt_component_class_filter_set_message_iterator_can_seek_ns_from_origin_method( | |
1041 | flt_comp_class, | |
1042 | cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin); | |
1043 | if (ret) { | |
1044 | BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek nanoseconds from origin\" method."); | |
fb25b9e3 | 1045 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
1046 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
1047 | goto end; | |
1048 | } | |
1049 | } | |
1050 | ||
1051 | if (cc_full_descr->methods.filter.msg_iter_can_seek_beginning) { | |
1052 | ret = bt_component_class_filter_set_message_iterator_can_seek_beginning_method( | |
1053 | flt_comp_class, | |
1054 | cc_full_descr->methods.filter.msg_iter_can_seek_beginning); | |
1055 | if (ret) { | |
1056 | BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek beginning\" method."); | |
fb25b9e3 | 1057 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
15a52f66 PP |
1058 | BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class); |
1059 | goto end; | |
1060 | } | |
1061 | } | |
1062 | ||
55bb57e0 PP |
1063 | break; |
1064 | case BT_COMPONENT_CLASS_TYPE_SINK: | |
834e9996 | 1065 | if (cc_full_descr->methods.sink.init) { |
7b53201c | 1066 | ret = bt_component_class_sink_set_init_method( |
834e9996 PP |
1067 | sink_comp_class, |
1068 | cc_full_descr->methods.sink.init); | |
1069 | if (ret) { | |
1070 | BT_LOGE_STR("Cannot set sink component class's initialization method."); | |
fb25b9e3 | 1071 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
1072 | BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class); |
1073 | goto end; | |
1074 | } | |
1075 | } | |
1076 | ||
1077 | if (cc_full_descr->methods.sink.finalize) { | |
7b53201c | 1078 | ret = bt_component_class_sink_set_finalize_method( |
834e9996 PP |
1079 | sink_comp_class, |
1080 | cc_full_descr->methods.sink.finalize); | |
1081 | if (ret) { | |
1082 | BT_LOGE_STR("Cannot set sink component class's finalization method."); | |
fb25b9e3 | 1083 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
1084 | BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class); |
1085 | goto end; | |
1086 | } | |
1087 | } | |
1088 | ||
1089 | if (cc_full_descr->methods.sink.query) { | |
7b53201c | 1090 | ret = bt_component_class_sink_set_query_method( |
834e9996 PP |
1091 | sink_comp_class, |
1092 | cc_full_descr->methods.sink.query); | |
1093 | if (ret) { | |
1094 | BT_LOGE_STR("Cannot set sink component class's query method."); | |
fb25b9e3 | 1095 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
1096 | BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class); |
1097 | goto end; | |
1098 | } | |
1099 | } | |
1100 | ||
834e9996 | 1101 | if (cc_full_descr->methods.sink.input_port_connected) { |
7b53201c | 1102 | ret = bt_component_class_sink_set_input_port_connected_method( |
834e9996 PP |
1103 | sink_comp_class, |
1104 | cc_full_descr->methods.sink.input_port_connected); | |
1105 | if (ret) { | |
1106 | BT_LOGE_STR("Cannot set sink component class's \"input port connected\" method."); | |
fb25b9e3 | 1107 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
834e9996 PP |
1108 | BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class); |
1109 | goto end; | |
1110 | } | |
1111 | } | |
1112 | ||
1043fdea PP |
1113 | if (cc_full_descr->methods.sink.graph_is_configured) { |
1114 | ret = bt_component_class_sink_set_graph_is_configured_method( | |
1115 | sink_comp_class, | |
1116 | cc_full_descr->methods.sink.graph_is_configured); | |
1117 | if (ret) { | |
1118 | BT_LOGE_STR("Cannot set sink component class's \"graph is configured\" method."); | |
fb25b9e3 | 1119 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
1043fdea PP |
1120 | BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class); |
1121 | goto end; | |
1122 | } | |
1123 | } | |
1124 | ||
55bb57e0 PP |
1125 | break; |
1126 | default: | |
0fbb9a9f | 1127 | abort(); |
55bb57e0 PP |
1128 | } |
1129 | ||
1130 | /* | |
1131 | * Add component class to the plugin object. | |
1132 | * | |
1133 | * This will call back | |
1134 | * bt_plugin_so_on_add_component_class() so that we can | |
834e9996 PP |
1135 | * add a mapping in the component class list when we |
1136 | * know the component class is successfully added. | |
55bb57e0 PP |
1137 | */ |
1138 | status = bt_plugin_add_component_class(plugin, | |
834e9996 | 1139 | (void *) comp_class); |
8138bfe1 | 1140 | BT_OBJECT_PUT_REF_AND_RESET(comp_class); |
55bb57e0 | 1141 | if (status < 0) { |
3fe0bf43 | 1142 | BT_LOGE("Cannot add component class to plugin."); |
55bb57e0 PP |
1143 | goto end; |
1144 | } | |
1145 | } | |
1146 | ||
55bb57e0 PP |
1147 | end: |
1148 | g_array_free(comp_class_full_descriptors, TRUE); | |
1149 | return status; | |
1150 | } | |
1151 | ||
1152 | static | |
1153 | struct bt_plugin *bt_plugin_so_create_empty( | |
1154 | struct bt_plugin_so_shared_lib_handle *shared_lib_handle) | |
1155 | { | |
1156 | struct bt_plugin *plugin; | |
1157 | struct bt_plugin_so_spec_data *spec; | |
1158 | ||
1159 | plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO); | |
1160 | if (!plugin) { | |
1161 | goto error; | |
1162 | } | |
1163 | ||
6fbd4105 | 1164 | plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data; |
55bb57e0 PP |
1165 | plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1); |
1166 | if (!plugin->spec_data) { | |
3fe0bf43 | 1167 | BT_LOGE_STR("Failed to allocate one SO plugin specific data structure."); |
55bb57e0 PP |
1168 | goto error; |
1169 | } | |
1170 | ||
1171 | spec = plugin->spec_data; | |
4b70020d PP |
1172 | spec->shared_lib_handle = shared_lib_handle; |
1173 | bt_object_get_no_null_check(spec->shared_lib_handle); | |
55bb57e0 PP |
1174 | goto end; |
1175 | ||
1176 | error: | |
8138bfe1 | 1177 | BT_OBJECT_PUT_REF_AND_RESET(plugin); |
55bb57e0 PP |
1178 | |
1179 | end: | |
1180 | return plugin; | |
1181 | } | |
1182 | ||
be3c4e36 MJ |
1183 | static |
1184 | size_t count_non_null_items_in_section(const void *begin, const void *end) | |
1185 | { | |
1186 | size_t count = 0; | |
1187 | const int * const *begin_int = (const int * const *) begin; | |
1188 | const int * const *end_int = (const int * const *) end; | |
1189 | const int * const *iter; | |
1190 | ||
1191 | for (iter = begin_int; iter != end_int; iter++) { | |
1192 | if (*iter) { | |
1193 | count++; | |
1194 | } | |
1195 | } | |
1196 | ||
1197 | return count; | |
1198 | } | |
1199 | ||
55bb57e0 | 1200 | static |
fb25b9e3 | 1201 | int bt_plugin_so_create_all_from_sections( |
55bb57e0 | 1202 | struct bt_plugin_so_shared_lib_handle *shared_lib_handle, |
01f50d54 | 1203 | bool fail_on_load_error, |
55bb57e0 PP |
1204 | struct __bt_plugin_descriptor const * const *descriptors_begin, |
1205 | struct __bt_plugin_descriptor const * const *descriptors_end, | |
1206 | struct __bt_plugin_descriptor_attribute const * const *attrs_begin, | |
1207 | struct __bt_plugin_descriptor_attribute const * const *attrs_end, | |
1208 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin, | |
1209 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end, | |
1210 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin, | |
01f50d54 PP |
1211 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end, |
1212 | struct bt_plugin_set **plugin_set_out) | |
55bb57e0 | 1213 | { |
fb25b9e3 | 1214 | int status = BT_FUNC_STATUS_OK; |
55bb57e0 PP |
1215 | size_t descriptor_count; |
1216 | size_t attrs_count; | |
1217 | size_t cc_descriptors_count; | |
1218 | size_t cc_descr_attrs_count; | |
1219 | size_t i; | |
55bb57e0 | 1220 | |
01f50d54 PP |
1221 | BT_ASSERT(plugin_set_out); |
1222 | *plugin_set_out = NULL; | |
be3c4e36 MJ |
1223 | descriptor_count = count_non_null_items_in_section(descriptors_begin, descriptors_end); |
1224 | attrs_count = count_non_null_items_in_section(attrs_begin, attrs_end); | |
1225 | cc_descriptors_count = count_non_null_items_in_section(cc_descriptors_begin, cc_descriptors_end); | |
1226 | cc_descr_attrs_count = count_non_null_items_in_section(cc_descr_attrs_begin, cc_descr_attrs_end); | |
a684a357 | 1227 | BT_LOGI("Creating all SO plugins from sections: " |
3fe0bf43 PP |
1228 | "plugin-path=\"%s\", " |
1229 | "descr-begin-addr=%p, descr-end-addr=%p, " | |
1230 | "attrs-begin-addr=%p, attrs-end-addr=%p, " | |
1231 | "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, " | |
1232 | "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, " | |
1233 | "descr-count=%zu, attrs-count=%zu, " | |
1234 | "cc-descr-count=%zu, cc-descr-attrs-count=%zu", | |
1235 | shared_lib_handle->path ? shared_lib_handle->path->str : NULL, | |
1236 | descriptors_begin, descriptors_end, | |
1237 | attrs_begin, attrs_end, | |
1238 | cc_descriptors_begin, cc_descriptors_end, | |
1239 | cc_descr_attrs_begin, cc_descr_attrs_end, | |
1240 | descriptor_count, attrs_count, | |
1241 | cc_descriptors_count, cc_descr_attrs_count); | |
01f50d54 PP |
1242 | *plugin_set_out = bt_plugin_set_create(); |
1243 | if (!*plugin_set_out) { | |
3fe0bf43 | 1244 | BT_LOGE_STR("Cannot create empty plugin set."); |
fb25b9e3 | 1245 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
55bb57e0 PP |
1246 | goto error; |
1247 | } | |
1248 | ||
be3c4e36 | 1249 | for (i = 0; i < descriptors_end - descriptors_begin; i++) { |
55bb57e0 PP |
1250 | const struct __bt_plugin_descriptor *descriptor = |
1251 | descriptors_begin[i]; | |
1252 | struct bt_plugin *plugin; | |
1253 | ||
be3c4e36 MJ |
1254 | if (descriptor == NULL) { |
1255 | continue; | |
1256 | } | |
1257 | ||
a684a357 | 1258 | BT_LOGI("Creating plugin object for plugin: " |
3fe0bf43 PP |
1259 | "name=\"%s\", abi-major=%d, abi-minor=%d", |
1260 | descriptor->name, descriptor->major, descriptor->minor); | |
55bb57e0 PP |
1261 | |
1262 | if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) { | |
01f50d54 PP |
1263 | BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : |
1264 | BT_LOG_INFO, BT_LOG_TAG, | |
1265 | "Unknown ABI major version: abi-major=%d", | |
1266 | descriptor->major); | |
1267 | ||
1268 | if (fail_on_load_error) { | |
fb25b9e3 | 1269 | status = BT_FUNC_STATUS_LOADING_ERROR; |
01f50d54 PP |
1270 | goto error; |
1271 | } else { | |
1272 | continue; | |
1273 | } | |
55bb57e0 PP |
1274 | } |
1275 | ||
1276 | plugin = bt_plugin_so_create_empty(shared_lib_handle); | |
1277 | if (!plugin) { | |
3fe0bf43 | 1278 | BT_LOGE_STR("Cannot create empty shared library handle."); |
fb25b9e3 | 1279 | status = BT_FUNC_STATUS_MEMORY_ERROR; |
55bb57e0 PP |
1280 | goto error; |
1281 | } | |
1282 | ||
1283 | if (shared_lib_handle && shared_lib_handle->path) { | |
01f50d54 PP |
1284 | bt_plugin_set_path(plugin, |
1285 | shared_lib_handle->path->str); | |
55bb57e0 PP |
1286 | } |
1287 | ||
01f50d54 PP |
1288 | status = bt_plugin_so_init(plugin, fail_on_load_error, |
1289 | descriptor, attrs_begin, attrs_end, | |
1290 | cc_descriptors_begin, cc_descriptors_end, | |
55bb57e0 | 1291 | cc_descr_attrs_begin, cc_descr_attrs_end); |
fb25b9e3 | 1292 | if (status == BT_FUNC_STATUS_OK) { |
01f50d54 PP |
1293 | /* Add to plugin set */ |
1294 | bt_plugin_set_add_plugin(*plugin_set_out, plugin); | |
1295 | BT_OBJECT_PUT_REF_AND_RESET(plugin); | |
1296 | } else if (status < 0) { | |
50ad9320 | 1297 | /* |
01f50d54 PP |
1298 | * bt_plugin_so_init() handles |
1299 | * `fail_on_load_error`, so this is a "real" | |
1300 | * error. | |
50ad9320 | 1301 | */ |
01f50d54 | 1302 | BT_LOGW_STR("Cannot initialize SO plugin object from sections."); |
8138bfe1 | 1303 | BT_OBJECT_PUT_REF_AND_RESET(plugin); |
55bb57e0 PP |
1304 | goto error; |
1305 | } | |
1306 | ||
01f50d54 PP |
1307 | BT_ASSERT(!plugin); |
1308 | } | |
1309 | ||
1310 | BT_ASSERT(*plugin_set_out); | |
1311 | ||
1312 | if ((*plugin_set_out)->plugins->len == 0) { | |
1313 | BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out); | |
fb25b9e3 | 1314 | status = BT_FUNC_STATUS_NOT_FOUND; |
55bb57e0 PP |
1315 | } |
1316 | ||
1317 | goto end; | |
1318 | ||
1319 | error: | |
01f50d54 PP |
1320 | BT_ASSERT(status < 0); |
1321 | BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out); | |
55bb57e0 PP |
1322 | |
1323 | end: | |
01f50d54 | 1324 | return status; |
55bb57e0 PP |
1325 | } |
1326 | ||
1327 | BT_HIDDEN | |
fb25b9e3 | 1328 | int bt_plugin_so_create_all_from_static(bool fail_on_load_error, |
01f50d54 | 1329 | struct bt_plugin_set **plugin_set_out) |
55bb57e0 | 1330 | { |
fb25b9e3 | 1331 | int status; |
01f50d54 | 1332 | struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL; |
55bb57e0 | 1333 | |
01f50d54 PP |
1334 | BT_ASSERT(plugin_set_out); |
1335 | *plugin_set_out = NULL; | |
1336 | status = bt_plugin_so_shared_lib_handle_create(NULL, | |
1337 | &shared_lib_handle); | |
fb25b9e3 | 1338 | if (status != BT_FUNC_STATUS_OK) { |
01f50d54 | 1339 | BT_ASSERT(!shared_lib_handle); |
55bb57e0 PP |
1340 | goto end; |
1341 | } | |
1342 | ||
01f50d54 | 1343 | BT_ASSERT(shared_lib_handle); |
3fe0bf43 | 1344 | BT_LOGD_STR("Creating all SO plugins from built-in plugins."); |
01f50d54 PP |
1345 | status = bt_plugin_so_create_all_from_sections(shared_lib_handle, |
1346 | fail_on_load_error, | |
be3c4e36 MJ |
1347 | __bt_get_begin_section_plugin_descriptors(), |
1348 | __bt_get_end_section_plugin_descriptors(), | |
1349 | __bt_get_begin_section_plugin_descriptor_attributes(), | |
1350 | __bt_get_end_section_plugin_descriptor_attributes(), | |
1351 | __bt_get_begin_section_component_class_descriptors(), | |
1352 | __bt_get_end_section_component_class_descriptors(), | |
1353 | __bt_get_begin_section_component_class_descriptor_attributes(), | |
01f50d54 PP |
1354 | __bt_get_end_section_component_class_descriptor_attributes(), |
1355 | plugin_set_out); | |
fb25b9e3 | 1356 | BT_ASSERT((status == BT_FUNC_STATUS_OK && *plugin_set_out && |
01f50d54 | 1357 | (*plugin_set_out)->plugins->len > 0) || !*plugin_set_out); |
55bb57e0 PP |
1358 | |
1359 | end: | |
8138bfe1 | 1360 | BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle); |
01f50d54 | 1361 | return status; |
55bb57e0 PP |
1362 | } |
1363 | ||
1364 | BT_HIDDEN | |
fb25b9e3 | 1365 | int bt_plugin_so_create_all_from_file(const char *path, |
01f50d54 | 1366 | bool fail_on_load_error, struct bt_plugin_set **plugin_set_out) |
55bb57e0 PP |
1367 | { |
1368 | size_t path_len; | |
fb25b9e3 | 1369 | int status; |
55bb57e0 PP |
1370 | struct __bt_plugin_descriptor const * const *descriptors_begin = NULL; |
1371 | struct __bt_plugin_descriptor const * const *descriptors_end = NULL; | |
1372 | struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL; | |
1373 | struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL; | |
1374 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL; | |
1375 | struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL; | |
1376 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL; | |
1377 | struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL; | |
be3c4e36 MJ |
1378 | struct __bt_plugin_descriptor const * const *(*get_begin_section_plugin_descriptors)(void); |
1379 | struct __bt_plugin_descriptor const * const *(*get_end_section_plugin_descriptors)(void); | |
1380 | struct __bt_plugin_descriptor_attribute const * const *(*get_begin_section_plugin_descriptor_attributes)(void); | |
1381 | struct __bt_plugin_descriptor_attribute const * const *(*get_end_section_plugin_descriptor_attributes)(void); | |
1382 | struct __bt_plugin_component_class_descriptor const * const *(*get_begin_section_component_class_descriptors)(void); | |
1383 | struct __bt_plugin_component_class_descriptor const * const *(*get_end_section_component_class_descriptors)(void); | |
1384 | struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_begin_section_component_class_descriptor_attributes)(void); | |
1385 | struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_end_section_component_class_descriptor_attributes)(void); | |
c55a9f58 | 1386 | bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE; |
55bb57e0 PP |
1387 | struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL; |
1388 | ||
a684a357 | 1389 | BT_ASSERT(path); |
01f50d54 PP |
1390 | BT_ASSERT(plugin_set_out); |
1391 | *plugin_set_out = NULL; | |
55bb57e0 | 1392 | path_len = strlen(path); |
a684a357 PP |
1393 | BT_ASSERT_PRE(path_len > PLUGIN_SUFFIX_LEN, |
1394 | "Path length is too short: path-length=%zu, min-length=%zu", | |
1395 | path_len, PLUGIN_SUFFIX_LEN); | |
1396 | BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path); | |
55bb57e0 | 1397 | path_len++; |
a684a357 | 1398 | |
55bb57e0 | 1399 | /* |
a684a357 PP |
1400 | * Check if the file ends with a known plugin file type suffix |
1401 | * (i.e. .so or .la on Linux). | |
55bb57e0 PP |
1402 | */ |
1403 | is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX, | |
1404 | path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN, | |
1405 | LIBTOOL_PLUGIN_SUFFIX_LEN); | |
1406 | is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX, | |
1407 | path + path_len - NATIVE_PLUGIN_SUFFIX_LEN, | |
1408 | NATIVE_PLUGIN_SUFFIX_LEN); | |
1409 | if (!is_shared_object && !is_libtool_wrapper) { | |
3fe0bf43 | 1410 | /* Name indicates this is not a plugin file; not an error */ |
01f50d54 | 1411 | BT_LOGI("File is not an SO plugin file: path=\"%s\"", path); |
fb25b9e3 | 1412 | status = BT_FUNC_STATUS_NOT_FOUND; |
55bb57e0 PP |
1413 | goto end; |
1414 | } | |
1415 | ||
01f50d54 PP |
1416 | status = bt_plugin_so_shared_lib_handle_create(path, |
1417 | &shared_lib_handle); | |
fb25b9e3 | 1418 | if (status != BT_FUNC_STATUS_OK) { |
a684a357 | 1419 | /* bt_plugin_so_shared_lib_handle_create() logs more details */ |
01f50d54 PP |
1420 | BT_ASSERT(!shared_lib_handle); |
1421 | BT_LOGE_STR("Cannot create shared library handle."); | |
55bb57e0 PP |
1422 | goto end; |
1423 | } | |
1424 | ||
be3c4e36 MJ |
1425 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptors", |
1426 | (gpointer *) &get_begin_section_plugin_descriptors)) { | |
1427 | descriptors_begin = get_begin_section_plugin_descriptors(); | |
1428 | } else { | |
01f50d54 PP |
1429 | /* |
1430 | * Use this first symbol to know whether or not this | |
1431 | * shared object _looks like_ a Babeltrace plugin. Since | |
1432 | * g_module_symbol() failed, assume that this is not a | |
1433 | * Babeltrace plugin, so it's not an error. | |
1434 | */ | |
a684a357 | 1435 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1436 | "symbol=\"%s\"", path, |
be3c4e36 | 1437 | "__bt_get_begin_section_plugin_descriptors"); |
fb25b9e3 | 1438 | status = BT_FUNC_STATUS_NOT_FOUND; |
55bb57e0 PP |
1439 | goto end; |
1440 | } | |
1441 | ||
01f50d54 PP |
1442 | /* |
1443 | * If g_module_symbol() fails for any of the other symbols, fail | |
1444 | * if `fail_on_load_error` is true. | |
1445 | */ | |
be3c4e36 MJ |
1446 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptors", |
1447 | (gpointer *) &get_end_section_plugin_descriptors)) { | |
1448 | descriptors_end = get_end_section_plugin_descriptors(); | |
1449 | } else { | |
01f50d54 PP |
1450 | BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO, |
1451 | BT_LOG_TAG, | |
1452 | "Cannot resolve plugin symbol: path=\"%s\", " | |
3fe0bf43 | 1453 | "symbol=\"%s\"", path, |
be3c4e36 | 1454 | "__bt_get_end_section_plugin_descriptors"); |
fb25b9e3 PP |
1455 | status = fail_on_load_error ? BT_FUNC_STATUS_LOADING_ERROR : |
1456 | BT_FUNC_STATUS_NOT_FOUND; | |
55bb57e0 PP |
1457 | goto end; |
1458 | } | |
1459 | ||
be3c4e36 MJ |
1460 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptor_attributes", |
1461 | (gpointer *) &get_begin_section_plugin_descriptor_attributes)) { | |
1462 | attrs_begin = get_begin_section_plugin_descriptor_attributes(); | |
1463 | } else { | |
a684a357 | 1464 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1465 | "symbol=\"%s\"", path, |
be3c4e36 | 1466 | "__bt_get_begin_section_plugin_descriptor_attributes"); |
55bb57e0 PP |
1467 | } |
1468 | ||
be3c4e36 MJ |
1469 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptor_attributes", |
1470 | (gpointer *) &get_end_section_plugin_descriptor_attributes)) { | |
1471 | attrs_end = get_end_section_plugin_descriptor_attributes(); | |
1472 | } else { | |
a684a357 | 1473 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1474 | "symbol=\"%s\"", path, |
be3c4e36 | 1475 | "__bt_get_end_section_plugin_descriptor_attributes"); |
55bb57e0 PP |
1476 | } |
1477 | ||
1478 | if ((!!attrs_begin - !!attrs_end) != 0) { | |
01f50d54 PP |
1479 | BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO, |
1480 | BT_LOG_TAG, | |
1481 | "Found section start or end symbol, but not both: " | |
3fe0bf43 PP |
1482 | "path=\"%s\", symbol-start=\"%s\", " |
1483 | "symbol-end=\"%s\", symbol-start-addr=%p, " | |
1484 | "symbol-end-addr=%p", | |
be3c4e36 MJ |
1485 | path, "__bt_get_begin_section_plugin_descriptor_attributes", |
1486 | "__bt_get_end_section_plugin_descriptor_attributes", | |
3fe0bf43 | 1487 | attrs_begin, attrs_end); |
fb25b9e3 PP |
1488 | status = fail_on_load_error ? BT_FUNC_STATUS_LOADING_ERROR : |
1489 | BT_FUNC_STATUS_NOT_FOUND; | |
55bb57e0 PP |
1490 | goto end; |
1491 | } | |
1492 | ||
be3c4e36 MJ |
1493 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptors", |
1494 | (gpointer *) &get_begin_section_component_class_descriptors)) { | |
1495 | cc_descriptors_begin = get_begin_section_component_class_descriptors(); | |
1496 | } else { | |
a684a357 | 1497 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1498 | "symbol=\"%s\"", path, |
be3c4e36 | 1499 | "__bt_get_begin_section_component_class_descriptors"); |
55bb57e0 PP |
1500 | } |
1501 | ||
be3c4e36 MJ |
1502 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptors", |
1503 | (gpointer *) &get_end_section_component_class_descriptors)) { | |
1504 | cc_descriptors_end = get_end_section_component_class_descriptors(); | |
1505 | } else { | |
a684a357 | 1506 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1507 | "symbol=\"%s\"", path, |
be3c4e36 | 1508 | "__bt_get_end_section_component_class_descriptors"); |
55bb57e0 PP |
1509 | } |
1510 | ||
1511 | if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) { | |
01f50d54 PP |
1512 | BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO, |
1513 | BT_LOG_TAG, | |
1514 | "Found section start or end symbol, but not both: " | |
3fe0bf43 PP |
1515 | "path=\"%s\", symbol-start=\"%s\", " |
1516 | "symbol-end=\"%s\", symbol-start-addr=%p, " | |
1517 | "symbol-end-addr=%p", | |
be3c4e36 MJ |
1518 | path, "__bt_get_begin_section_component_class_descriptors", |
1519 | "__bt_get_end_section_component_class_descriptors", | |
3fe0bf43 | 1520 | cc_descriptors_begin, cc_descriptors_end); |
fb25b9e3 PP |
1521 | status = fail_on_load_error ? BT_FUNC_STATUS_LOADING_ERROR : |
1522 | BT_FUNC_STATUS_NOT_FOUND; | |
55bb57e0 PP |
1523 | goto end; |
1524 | } | |
1525 | ||
be3c4e36 MJ |
1526 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptor_attributes", |
1527 | (gpointer *) &get_begin_section_component_class_descriptor_attributes)) { | |
1528 | cc_descr_attrs_begin = get_begin_section_component_class_descriptor_attributes(); | |
1529 | } else { | |
a684a357 | 1530 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1531 | "symbol=\"%s\"", path, |
be3c4e36 | 1532 | "__bt_get_begin_section_component_class_descriptor_attributes"); |
55bb57e0 PP |
1533 | } |
1534 | ||
be3c4e36 MJ |
1535 | if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptor_attributes", |
1536 | (gpointer *) &get_end_section_component_class_descriptor_attributes)) { | |
1537 | cc_descr_attrs_end = get_end_section_component_class_descriptor_attributes(); | |
1538 | } else { | |
a684a357 | 1539 | BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", " |
3fe0bf43 | 1540 | "symbol=\"%s\"", path, |
be3c4e36 | 1541 | "__bt_get_end_section_component_class_descriptor_attributes"); |
55bb57e0 PP |
1542 | } |
1543 | ||
1544 | if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) { | |
01f50d54 PP |
1545 | BT_LOG_WRITE(fail_on_load_error ? BT_LOG_WARN : BT_LOG_INFO, |
1546 | BT_LOG_TAG, | |
1547 | "Found section start or end symbol, but not both: " | |
3fe0bf43 PP |
1548 | "path=\"%s\", symbol-start=\"%s\", " |
1549 | "symbol-end=\"%s\", symbol-start-addr=%p, " | |
1550 | "symbol-end-addr=%p", | |
be3c4e36 MJ |
1551 | path, "__bt_get_begin_section_component_class_descriptor_attributes", |
1552 | "__bt_get_end_section_component_class_descriptor_attributes", | |
3fe0bf43 | 1553 | cc_descr_attrs_begin, cc_descr_attrs_end); |
fb25b9e3 PP |
1554 | status = fail_on_load_error ? BT_FUNC_STATUS_LOADING_ERROR : |
1555 | BT_FUNC_STATUS_NOT_FOUND; | |
55bb57e0 PP |
1556 | goto end; |
1557 | } | |
1558 | ||
1559 | /* Initialize plugin */ | |
3fe0bf43 | 1560 | BT_LOGD_STR("Initializing plugin object."); |
01f50d54 PP |
1561 | status = bt_plugin_so_create_all_from_sections(shared_lib_handle, |
1562 | fail_on_load_error, | |
55bb57e0 PP |
1563 | descriptors_begin, descriptors_end, attrs_begin, attrs_end, |
1564 | cc_descriptors_begin, cc_descriptors_end, | |
01f50d54 | 1565 | cc_descr_attrs_begin, cc_descr_attrs_end, plugin_set_out); |
55bb57e0 PP |
1566 | |
1567 | end: | |
8138bfe1 | 1568 | BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle); |
01f50d54 | 1569 | return status; |
55bb57e0 PP |
1570 | } |
1571 | ||
1572 | static | |
1573 | void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class, | |
1574 | void *data) | |
1575 | { | |
bfa9a4be | 1576 | bt_list_del(&comp_class->node); |
8138bfe1 | 1577 | BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle); |
a684a357 | 1578 | BT_LOGD("Component class destroyed: removed entry from list: " |
3fe0bf43 | 1579 | "comp-cls-addr=%p", comp_class); |
55bb57e0 PP |
1580 | } |
1581 | ||
3230ee6b | 1582 | void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin, |
55bb57e0 PP |
1583 | struct bt_component_class *comp_class) |
1584 | { | |
55bb57e0 PP |
1585 | struct bt_plugin_so_spec_data *spec = plugin->spec_data; |
1586 | ||
8b45963b PP |
1587 | BT_ASSERT(plugin->spec_data); |
1588 | BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO); | |
55bb57e0 | 1589 | |
bfa9a4be | 1590 | bt_list_add(&comp_class->node, &component_class_list); |
4b70020d PP |
1591 | comp_class->so_handle = spec->shared_lib_handle; |
1592 | bt_object_get_no_null_check(comp_class->so_handle); | |
55bb57e0 PP |
1593 | |
1594 | /* Add our custom destroy listener */ | |
3230ee6b | 1595 | bt_component_class_add_destroy_listener(comp_class, |
55bb57e0 | 1596 | plugin_comp_class_destroy_listener, NULL); |
55bb57e0 | 1597 | } |