[OpenMP][OMPD] Add symbol lookup helper for GDB plugin (#221956) On LLVM today, `libompd.so` exists with `dlopen`, finds each API with `dlsym` and checks error with `dlerror`. **Missing piece**: There is no single place that: load this library look up this name give me a real error string **Issues**: A later change would have to edit 30+ calls sites, `dlerror()` is easy to misuse, failures often drop the OS error string. **Fix**: Add these helpers: `ompd_load_library(path)` – load `libompd.so` `ompd_get_symbol(name)` – look up one function `ompd_get_dl_error()` – last error text or NULL The plugin still uses `dlopen/dlsym` inside that helper. No LLVM Support. No `setup.py`. GitOrigin-RevId: 14e941a0566ae06e982c5d8ddd085697c48fd413
diff --git a/libompd/gdb-plugin/CMakeLists.txt b/libompd/gdb-plugin/CMakeLists.txt index d4fd03d..bfa1128 100644 --- a/libompd/gdb-plugin/CMakeLists.txt +++ b/libompd/gdb-plugin/CMakeLists.txt
@@ -16,7 +16,7 @@ include_directories (${OMPD_INCLUDE_PATH}) include_directories (${LIBOMP_INCLUDE_DIR}) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/python-module/ompd/__init__.py - DEPENDS ompdModule.c ompdAPITests.c ompd/frame_filter.py ompd/__init__.py ompd/ompd_address_space.py ompd/ompd_callbacks.py ompd/ompd_handles.py ompd/ompd.py + DEPENDS ompdModule.c ompdDLService.c ompdAPITests.c ompd/frame_filter.py ompd/__init__.py ompd/ompd_address_space.py ompd/ompd_callbacks.py ompd/ompd_handles.py ompd/ompd.py COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/ompd ${CMAKE_CURRENT_BINARY_DIR}/python-module/ompd/ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) @@ -24,7 +24,7 @@ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/python-module/ompd/__init__.py COMMENT "Building the OMPD GDB plugin") -add_library (ompdModule MODULE ompdModule.c ompdAPITests.c) +add_library (ompdModule MODULE ompdModule.c ompdAPITests.c ompdDLService.c) include_directories ( ${LIBOMP_INCLUDE_DIR} ${LIBOMP_SRC_DIR}
diff --git a/libompd/gdb-plugin/ompd/ompd.py b/libompd/gdb-plugin/ompd/ompd.py index 8355865..a1250b6 100644 --- a/libompd/gdb-plugin/ompd/ompd.py +++ b/libompd/gdb-plugin/ompd/ompd.py
@@ -57,13 +57,15 @@ lib_list = gdb.parse_and_eval("(char**)ompd_dll_locations") i = 0 + last_dl_error = None while lib_list[i]: ret = ompdModule.ompd_open(lib_list[i].string()) if ret == -1: raise ValueError("Handle of OMPD library is not a valid string!") if ret == -2: + last_dl_error = ompdModule.ompd_get_dl_error() print("ret == -2") - pass # It's ok to fail on dlopen + pass # It's ok to fail on dlopen; try the next path if ret == -3: print("ret == -3") pass # It's ok to fail on dlsym @@ -80,6 +82,8 @@ return i = i + 1 + if last_dl_error: + raise ValueError("OMPD library could not be loaded: %s" % last_dl_error) raise ValueError("OMPD library could not be loaded!") except: traceback.print_exc()
diff --git a/libompd/gdb-plugin/ompdAPITests.c b/libompd/gdb-plugin/ompdAPITests.c index 912914c..c830c3f 100644 --- a/libompd/gdb-plugin/ompdAPITests.c +++ b/libompd/gdb-plugin/ompdAPITests.c
@@ -1,5 +1,6 @@ +#include "ompdDLService.h" + #include <Python.h> -#include <dlfcn.h> #include <errno.h> #include <omp-tools.h> #include <pthread.h> @@ -7,8 +8,6 @@ #include <stdlib.h> #include <string.h> -extern void *ompd_library; - struct _ompd_aspace_cont { int id; }; @@ -810,7 +809,11 @@ printf("Test: With Correct Arguments.\n"); ompd_rc_t (*my_ompd_init)(ompd_word_t version, ompd_callbacks_t *) = - dlsym(ompd_library, "ompd_initialize"); + ompd_get_symbol("ompd_initialize"); + if (!my_ompd_init) { + printf("Failed to look up ompd_initialize.\n"); + return Py_None; + } rc = my_ompd_init(version, &table); if (rc != ompd_rc_ok) { printf("Failed, with return code = %d\n", rc);
diff --git a/libompd/gdb-plugin/ompdDLService.c b/libompd/gdb-plugin/ompdDLService.c new file mode 100644 index 0000000..dc7a404 --- /dev/null +++ b/libompd/gdb-plugin/ompdDLService.c
@@ -0,0 +1,87 @@ +/* + * ompdDLService.c -- Load libompd and look up OMPD API symbols. + */ + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ompdDLService.h" + +#include <dlfcn.h> +#include <string.h> + +void *ompd_library = NULL; + +static char last_error[256]; + +static void set_error(const char *msg) { + if (!msg || !msg[0]) { + last_error[0] = '\0'; + return; + } + strncpy(last_error, msg, sizeof(last_error) - 1); + last_error[sizeof(last_error) - 1] = '\0'; +} + +static void clear_error(void) { + last_error[0] = '\0'; + (void)dlerror(); +} + +int ompd_load_library(const char *name) { + const char *dlerr; + + clear_error(); + if (!name || !name[0]) { + set_error("OMPD library path is empty"); + ompd_library = NULL; + return -1; + } + + ompd_library = dlopen(name, RTLD_LAZY); + dlerr = dlerror(); + if (dlerr) { + set_error(dlerr); + ompd_library = NULL; + return -1; + } + if (!ompd_library) { + set_error("dlopen returned NULL"); + return -1; + } + return 0; +} + +void *ompd_get_symbol(const char *name) { + const char *dlerr; + void *sym; + + clear_error(); + if (!ompd_library) { + set_error("OMPD library is not loaded"); + return NULL; + } + if (!name || !name[0]) { + set_error("OMPD symbol name is empty"); + return NULL; + } + + sym = dlsym(ompd_library, name); + dlerr = dlerror(); + if (dlerr) { + set_error(dlerr); + return NULL; + } + return sym; +} + +const char *ompd_get_dl_error(void) { + if (!last_error[0]) + return NULL; + return last_error; +}
diff --git a/libompd/gdb-plugin/ompdDLService.h b/libompd/gdb-plugin/ompdDLService.h new file mode 100644 index 0000000..6c95185 --- /dev/null +++ b/libompd/gdb-plugin/ompdDLService.h
@@ -0,0 +1,40 @@ +/* + * ompdDLService.h -- Load libompd and look up OMPD API symbols. + */ + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef OPENMP_LIBOMPD_GDB_PLUGIN_OMPD_DL_SERVICE_H +#define OPENMP_LIBOMPD_GDB_PLUGIN_OMPD_DL_SERVICE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Handle of the loaded OMPD library, or NULL if none is loaded. */ +extern void *ompd_library; + +/* Load the OMPD library at name. + * Returns 0 on success. On failure, returns -1 and ompd_get_dl_error() + * describes the problem. */ +int ompd_load_library(const char *name); + +/* Look up name in the loaded OMPD library. + * Returns the symbol address, or NULL on failure. */ +void *ompd_get_symbol(const char *name); + +/* Last load/lookup error, or NULL if the last helper call succeeded. + * The string stays valid until the next helper call. */ +const char *ompd_get_dl_error(void); + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/libompd/gdb-plugin/ompdModule.c b/libompd/gdb-plugin/ompdModule.c index 9078b24..d591824 100644 --- a/libompd/gdb-plugin/ompdModule.c +++ b/libompd/gdb-plugin/ompdModule.c
@@ -10,18 +10,17 @@ // //===----------------------------------------------------------------------===// +#include "ompdDLService.h" + #include <Python.h> #include <omp-tools.h> // #include <ompd.h> -#include <dlfcn.h> #include <errno.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -void *ompd_library; - #define OMPD_WEAK_ATTR __attribute__((weak)) struct _ompd_aspace_cont { @@ -41,8 +40,8 @@ OMPD_WEAK_ATTR ompd_rc_t ompd_get_api_version(ompd_word_t *addr) { static ompd_rc_t (*my_get_api_version)(ompd_word_t *) = NULL; if (!my_get_api_version) { - my_get_api_version = dlsym(ompd_library, "ompd_get_api_version"); - if (dlerror()) { + my_get_api_version = ompd_get_symbol("ompd_get_api_version"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -52,8 +51,8 @@ OMPD_WEAK_ATTR ompd_rc_t ompd_get_version_string(const char **string) { static ompd_rc_t (*my_get_version_string)(const char **) = NULL; if (!my_get_version_string) { - my_get_version_string = dlsym(ompd_library, "ompd_get_version_string"); - if (dlerror()) { + my_get_version_string = ompd_get_symbol("ompd_get_version_string"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -63,8 +62,8 @@ OMPD_WEAK_ATTR ompd_rc_t ompd_finalize(void) { static ompd_rc_t (*my_ompd_finalize)(void) = NULL; if (!my_ompd_finalize) { - my_ompd_finalize = dlsym(ompd_library, "ompd_finalize"); - if (dlerror()) { + my_ompd_finalize = ompd_get_symbol("ompd_finalize"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -77,8 +76,8 @@ static ompd_rc_t (*my_ompd_process_initialize)( ompd_address_space_context_t *, ompd_address_space_handle_t **) = NULL; if (!my_ompd_process_initialize) { - my_ompd_process_initialize = dlsym(ompd_library, "ompd_process_initialize"); - if (dlerror()) { + my_ompd_process_initialize = ompd_get_symbol("ompd_process_initialize"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -90,8 +89,8 @@ static ompd_rc_t (*my_ompd_get_omp_version)(ompd_address_space_handle_t *, ompd_word_t *) = NULL; if (!my_ompd_get_omp_version) { - my_ompd_get_omp_version = dlsym(ompd_library, "ompd_get_omp_version"); - if (dlerror()) { + my_ompd_get_omp_version = ompd_get_symbol("ompd_get_omp_version"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -104,8 +103,8 @@ ompd_address_space_handle_t *, const char **) = NULL; if (!my_ompd_get_omp_version_string) { my_ompd_get_omp_version_string = - dlsym(ompd_library, "ompd_get_omp_version_string"); - if (dlerror()) { + ompd_get_symbol("ompd_get_omp_version_string"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -119,8 +118,8 @@ ompd_address_space_handle_t *, ompd_thread_id_t, ompd_size_t, const void *, ompd_thread_handle_t **) = NULL; if (!my_get_thread_handle) { - my_get_thread_handle = dlsym(ompd_library, "ompd_get_thread_handle"); - if (dlerror()) { + my_get_thread_handle = ompd_get_symbol("ompd_get_thread_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -133,9 +132,8 @@ static ompd_rc_t (*my_get_thread_in_parallel)(ompd_parallel_handle_t *, int, ompd_thread_handle_t **) = NULL; if (!my_get_thread_in_parallel) { - my_get_thread_in_parallel = - dlsym(ompd_library, "ompd_get_thread_in_parallel"); - if (dlerror()) { + my_get_thread_in_parallel = ompd_get_symbol("ompd_get_thread_in_parallel"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -148,9 +146,8 @@ static ompd_rc_t (*my_thread_handle_compare)( ompd_thread_handle_t *, ompd_thread_handle_t *, int *) = NULL; if (!my_thread_handle_compare) { - my_thread_handle_compare = - dlsym(ompd_library, "ompd_thread_handle_compare"); - if (dlerror()) { + my_thread_handle_compare = ompd_get_symbol("ompd_thread_handle_compare"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -164,8 +161,8 @@ ompd_thread_handle_t *, ompd_parallel_handle_t **) = NULL; if (!my_get_current_parallel_handle) { my_get_current_parallel_handle = - dlsym(ompd_library, "ompd_get_curr_parallel_handle"); - if (dlerror()) { + ompd_get_symbol("ompd_get_curr_parallel_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -179,8 +176,8 @@ ompd_parallel_handle_t *, ompd_parallel_handle_t *, int *) = NULL; if (!my_parallel_handle_compare) { my_parallel_handle_compare = - dlsym(ompd_library, "ompd_parallel_handle_compare"); - if (dlerror()) { + ompd_get_symbol("ompd_parallel_handle_compare"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -195,8 +192,8 @@ ompd_parallel_handle_t *, ompd_parallel_handle_t **) = NULL; if (!my_get_enclosing_parallel_handle) { my_get_enclosing_parallel_handle = - dlsym(ompd_library, "ompd_get_enclosing_parallel_handle"); - if (dlerror()) { + ompd_get_symbol("ompd_get_enclosing_parallel_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -210,8 +207,8 @@ ompd_task_handle_t *, ompd_parallel_handle_t **) = NULL; if (!my_get_task_parallel_handle) { my_get_task_parallel_handle = - dlsym(ompd_library, "ompd_get_task_parallel_handle"); - if (dlerror()) { + ompd_get_symbol("ompd_get_task_parallel_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -223,9 +220,8 @@ static ompd_rc_t (*my_get_current_task_handle)(ompd_thread_handle_t *, ompd_task_handle_t **) = NULL; if (!my_get_current_task_handle) { - my_get_current_task_handle = - dlsym(ompd_library, "ompd_get_curr_task_handle"); - if (dlerror()) { + my_get_current_task_handle = ompd_get_symbol("ompd_get_curr_task_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -238,8 +234,8 @@ ompd_task_handle_t *, ompd_task_handle_t **) = NULL; if (!my_get_generating_task_handle) { my_get_generating_task_handle = - dlsym(ompd_library, "ompd_get_generating_task_handle"); - if (dlerror()) { + ompd_get_symbol("ompd_get_generating_task_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -252,8 +248,8 @@ ompd_task_handle_t *, ompd_task_handle_t **) = NULL; if (!my_get_scheduling_task_handle) { my_get_scheduling_task_handle = - dlsym(ompd_library, "ompd_get_scheduling_task_handle"); - if (dlerror()) { + ompd_get_symbol("ompd_get_scheduling_task_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -266,8 +262,8 @@ static ompd_rc_t (*my_get_task_in_parallel)(ompd_parallel_handle_t *, int, ompd_task_handle_t **) = NULL; if (!my_get_task_in_parallel) { - my_get_task_in_parallel = dlsym(ompd_library, "ompd_get_task_in_parallel"); - if (dlerror()) { + my_get_task_in_parallel = ompd_get_symbol("ompd_get_task_in_parallel"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -280,8 +276,8 @@ static ompd_rc_t (*my_get_task_frame)( ompd_task_handle_t *, ompd_frame_info_t *, ompd_frame_info_t *) = NULL; if (!my_get_task_frame) { - my_get_task_frame = dlsym(ompd_library, "ompd_get_task_frame"); - if (dlerror()) { + my_get_task_frame = ompd_get_symbol("ompd_get_task_frame"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -295,8 +291,8 @@ static ompd_rc_t (*my_get_icv_from_scope)(void *, ompd_scope_t, ompd_icv_id_t, ompd_word_t *) = NULL; if (!my_get_icv_from_scope) { - my_get_icv_from_scope = dlsym(ompd_library, "ompd_get_icv_from_scope"); - if (dlerror()) { + my_get_icv_from_scope = ompd_get_symbol("ompd_get_icv_from_scope"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -311,8 +307,8 @@ ompd_address_space_handle_t *, ompd_icv_id_t, ompd_icv_id_t *, const char **, ompd_scope_t *, int *) = NULL; if (!my_enumerate_icvs) { - my_enumerate_icvs = dlsym(ompd_library, "ompd_enumerate_icvs"); - if (dlerror()) { + my_enumerate_icvs = ompd_get_symbol("ompd_enumerate_icvs"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -327,8 +323,8 @@ ompd_word_t, ompd_word_t *, const char **, ompd_word_t *) = NULL; if (!my_enumerate_states) { - my_enumerate_states = dlsym(ompd_library, "ompd_enumerate_states"); - if (dlerror()) { + my_enumerate_states = ompd_get_symbol("ompd_enumerate_states"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -342,8 +338,8 @@ static ompd_rc_t (*my_get_state)(ompd_thread_handle_t *, ompd_word_t *, ompd_wait_id_t *) = NULL; if (!my_get_state) { - my_get_state = dlsym(ompd_library, "ompd_get_state"); - if (dlerror()) { + my_get_state = ompd_get_symbol("ompd_get_state"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -355,8 +351,8 @@ static ompd_rc_t (*my_get_task_function)(ompd_task_handle_t *, ompd_address_t *) = NULL; if (!my_get_task_function) { - my_get_task_function = dlsym(ompd_library, "ompd_get_task_function"); - if (dlerror()) { + my_get_task_function = ompd_get_symbol("ompd_get_task_function"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -369,8 +365,8 @@ static ompd_rc_t (*my_get_thread_id)(ompd_thread_handle_t *, ompd_thread_id_t, ompd_size_t, void *) = NULL; if (!my_get_thread_id) { - my_get_thread_id = dlsym(ompd_library, "ompd_get_thread_id"); - if (dlerror()) { + my_get_thread_id = ompd_get_symbol("ompd_get_thread_id"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -383,8 +379,8 @@ static ompd_rc_t (*my_get_tool_data)(void *, ompd_scope_t, ompd_word_t *, ompd_address_t *) = NULL; if (!my_get_tool_data) { - my_get_tool_data = dlsym(ompd_library, "ompd_get_tool_data"); - if (dlerror()) { + my_get_tool_data = ompd_get_symbol("ompd_get_tool_data"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -398,8 +394,8 @@ void *, ompd_scope_t, ompd_icv_id_t, const char **) = NULL; if (!my_get_icv_string_from_scope) { my_get_icv_string_from_scope = - dlsym(ompd_library, "ompd_get_icv_string_from_scope"); - if (dlerror()) { + ompd_get_symbol("ompd_get_icv_string_from_scope"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -410,8 +406,8 @@ ompd_rel_thread_handle(ompd_thread_handle_t *threadHandle) { static ompd_rc_t (*my_release_thread_handle)(ompd_thread_handle_t *) = NULL; if (!my_release_thread_handle) { - my_release_thread_handle = dlsym(ompd_library, "ompd_rel_thread_handle"); - if (dlerror()) { + my_release_thread_handle = ompd_get_symbol("ompd_rel_thread_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -423,9 +419,8 @@ static ompd_rc_t (*my_release_parallel_handle)(ompd_parallel_handle_t *) = NULL; if (!my_release_parallel_handle) { - my_release_parallel_handle = - dlsym(ompd_library, "ompd_rel_parallel_handle"); - if (dlerror()) { + my_release_parallel_handle = ompd_get_symbol("ompd_rel_parallel_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -435,8 +430,8 @@ OMPD_WEAK_ATTR ompd_rc_t ompd_rel_task_handle(ompd_task_handle_t *taskHandle) { static ompd_rc_t (*my_release_task_handle)(ompd_task_handle_t *) = NULL; if (!my_release_task_handle) { - my_release_task_handle = dlsym(ompd_library, "ompd_rel_task_handle"); - if (dlerror()) { + my_release_task_handle = ompd_get_symbol("ompd_rel_task_handle"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -449,8 +444,8 @@ static ompd_rc_t (*my_task_handle_compare)( ompd_task_handle_t *, ompd_task_handle_t *, int *) = NULL; if (!my_task_handle_compare) { - my_task_handle_compare = dlsym(ompd_library, "ompd_task_handle_compare"); - if (dlerror()) { + my_task_handle_compare = ompd_get_symbol("ompd_task_handle_compare"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -464,8 +459,8 @@ ompd_address_space_handle_t *, const char *const **) = NULL; if (!my_ompd_get_display_control_vars) { my_ompd_get_display_control_vars = - dlsym(ompd_library, "ompd_get_display_control_vars"); - if (dlerror()) { + ompd_get_symbol("ompd_get_display_control_vars"); + if (ompd_get_dl_error()) { return ompd_rc_error; } } @@ -475,22 +470,19 @@ /** * Loads the OMPD library (libompd.so). Returns an integer with the version if * the OMPD library could be loaded successfully. Error codes: -1: argument - * could not be converted to string -2: error when calling dlopen -3: error when - * fetching version of OMPD API else: see ompd return codes + * could not be converted to string -2: error when loading the library + * else: see ompd return codes */ static PyObject *ompd_open(PyObject *self, PyObject *args) { - const char *name, *dlerr; - dlerror(); + const char *name; if (!PyArg_ParseTuple(args, "s", &name)) { return Py_BuildValue("i", -1); } - ompd_library = dlopen(name, RTLD_LAZY); - if ((dlerr = dlerror())) { + if (ompd_load_library(name) != 0) { + /* Keep -2 so ompd.py can try the next ompd_dll_locations entry. + * The helper error stays in ompd_get_dl_error() for the caller. */ return Py_BuildValue("i", -2); } - if (dlerror()) { - return Py_BuildValue("i", -3); - } ompd_word_t version; ompd_rc_t rc = ompd_get_api_version(&version); if (rc != ompd_rc_ok) @@ -501,6 +493,16 @@ } /** + * Last load/lookup error from the symbol-lookup helper, or None. + */ +static PyObject *call_ompd_get_dl_error(PyObject *self, PyObject *noargs) { + const char *err = ompd_get_dl_error(); + if (!err) + Py_RETURN_NONE; + return Py_BuildValue("s", err); +} + +/** * Have the debugger print a string. */ ompd_rc_t _print(const char *str, int category) { @@ -825,7 +827,12 @@ NULL, _read_string, _endianess, _endianess, _thread_context}; ompd_rc_t (*my_ompd_init)(ompd_word_t version, ompd_callbacks_t *) = - dlsym(ompd_library, "ompd_initialize"); + ompd_get_symbol("ompd_initialize"); + if (!my_ompd_init) { + _printf("An error occurred when looking up ompd_initialize: %s", + ompd_get_dl_error() ? ompd_get_dl_error() : "unknown"); + Py_RETURN_NONE; + } ompd_rc_t returnInit = my_ompd_init(201811, &table); if (returnInit != ompd_rc_ok) { _printf("An error occurred when calling ompd_initialize! Error code: %d", @@ -834,7 +841,12 @@ ompd_address_space_handle_t *addr_space = NULL; ompd_rc_t (*my_proc_init)(ompd_address_space_context_t *, ompd_address_space_handle_t **) = - dlsym(ompd_library, "ompd_process_initialize"); + ompd_get_symbol("ompd_process_initialize"); + if (!my_proc_init) { + _printf("An error occurred when looking up ompd_process_initialize: %s", + ompd_get_dl_error() ? ompd_get_dl_error() : "unknown"); + Py_RETURN_NONE; + } ompd_rc_t retProcInit = my_proc_init(&acontext, &addr_space); if (retProcInit != ompd_rc_ok) { _printf("An error occurred when calling ompd_process_initialize! Error " @@ -968,7 +980,8 @@ if (retVal != ompd_rc_ok) { _printf("An error occurred when calling ompd_get_task_parallel_handle! " - "Error code: %d", retVal); + "Error code: %d", + retVal); return Py_BuildValue("l", retVal); } return PyCapsule_New(taskParallelHandle, "ParallelHandle", @@ -1482,7 +1495,9 @@ */ static PyMethodDef ompdModule_methods[] = { {"ompd_open", ompd_open, METH_VARARGS, - "Execute dlopen, return OMPD version."}, + "Load libompd, return OMPD version."}, + {"ompd_get_dl_error", call_ompd_get_dl_error, METH_NOARGS, + "Return the last OMPD library load/lookup error, or None."}, {"call_ompd_initialize", call_ompd_initialize, METH_NOARGS, "Initializes OMPD environment and callbacks."}, {"call_ompd_rel_thread_handle", call_ompd_rel_thread_handle, METH_VARARGS,
diff --git a/libompd/test/lit.cfg b/libompd/test/lit.cfg index df881d0..eed6279 100644 --- a/libompd/test/lit.cfg +++ b/libompd/test/lit.cfg
@@ -80,4 +80,21 @@ config.ompt_plugin)) config.substitutions.append(("FileCheck", config.test_filecheck)) +config.substitutions.append( + ("%ompd-lib", os.path.join(config.ompd_library_dir, "libompd.so")) +) +config.substitutions.append( + ( + "%ompd-dl-src", + os.path.normpath( + os.path.join(config.ompd_test_src, "..", "gdb-plugin", "ompdDLService.c") + ), + ) +) +config.substitutions.append( + ( + "%ompd-dl-inc", + os.path.normpath(os.path.join(config.ompd_test_src, "..", "gdb-plugin")), + ) +)
diff --git a/libompd/test/ompd_dl_service.c b/libompd/test/ompd_dl_service.c new file mode 100644 index 0000000..787cbdd --- /dev/null +++ b/libompd/test/ompd_dl_service.c
@@ -0,0 +1,55 @@ +// RUN: %test_c_compiler %s %ompd-dl-src -I%ompd-dl-inc -ldl -o %t +// RUN: %t %ompd-lib | FileCheck %s +// REQUIRES: linux + +#include "ompdDLService.h" + +#include <stdio.h> + +static const char *err_or_none(void) { + const char *err = ompd_get_dl_error(); + return err ? err : "none"; +} + +int main(int argc, char **argv) { + if (argc != 2) + return 1; + + if (ompd_load_library("") == 0) + return 2; + printf("empty: fail\n"); + printf("empty-err: %s\n", err_or_none()); + + if (ompd_load_library("/no/such/libompd.so") == 0) + return 3; + printf("missing: fail\n"); + printf("missing-err: %s\n", err_or_none()); + + if (ompd_load_library(argv[1]) != 0) + return 4; + printf("load: ok\n"); + printf("load-err: %s\n", err_or_none()); + + if (!ompd_get_symbol("ompd_initialize")) + return 5; + printf("init-sym: ok\n"); + printf("init-sym-err: %s\n", err_or_none()); + + if (ompd_get_symbol("no_such_ompd_symbol")) + return 6; + printf("missing-sym: fail\n"); + printf("missing-sym-err: %s\n", err_or_none()); + + return 0; +} + +// CHECK: empty: fail +// CHECK-NEXT: empty-err: OMPD library path is empty +// CHECK-NEXT: missing: fail +// CHECK-NEXT: missing-err: {{.+}} +// CHECK-NEXT: load: ok +// CHECK-NEXT: load-err: none +// CHECK-NEXT: init-sym: ok +// CHECK-NEXT: init-sym-err: none +// CHECK-NEXT: missing-sym: fail +// CHECK-NEXT: missing-sym-err: {{.+}}