usb-gadget: access external symbol using dlsym(), not extern keyword 43/272943/1 accepted/tizen/6.5/unified/20220330.000717 submit/tizen_6.5/20220328.084953
authorYoungjae Cho <y0.cho@samsung.com>
Mon, 28 Mar 2022 05:07:25 +0000 (22:07 -0700)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Mon, 28 Mar 2022 08:33:46 +0000 (08:33 +0000)
The variable declared as extern storage class must be resolved when the
symbol is loaded onto memory regardless of lazy binding. Therefore if
a symbol doesn't exist on being loaded, the whole library loading will
fail. To avoid this, explicitly load a symbol using dlsym(), which is
able to handle undefined symbol error.

This is mainly because the device-common shared library contains both
of udev and usb-gadget, making them always be loaded onto memory
together even if a caller only wants to use udev, not usb-gadget. This
structure should be revamped later.

Change-Id: Ia2bd7801123c812976ce79f0e0b880e6f1e67463
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
(cherry picked from commit 8634169cbcf0ddbe90adbf7babf0ff37745d72d5)

CMakeLists.txt
src/usb_gadget/usb_gadget.h
src/usb_gadget/usb_gadget_common.c

index 5d24f59..2a9ed4d 100644 (file)
@@ -20,6 +20,7 @@ ENDFOREACH(flag)
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 
+ADD_DEFINITIONS("-D_GNU_SOURCE")
 ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
 
 IF(ENABLE_DLOG STREQUAL on)
index 1f66457..466753f 100644 (file)
 #ifndef __HW_USB_GADGET_H__
 #define __HW_USB_GADGET_H__
 
-/**************************************
- * Those symbols must be initialized first in deviced
- *
- * The usb-gadget source code have been scattered throughout the deviced and device-common.
- * Because of this, it might have been implemented that totally same data structure on the
- * both side. To avoid this inefficiency, define/initialize the data structure on the
- * deviced first, and device-common refer it through extern keyword. The deviced must have
- * cflag -rdynamic or ldflag --export-dynamic so that the dlopen-ed device-common can refer
- * those variables with extern keyword.
- *
- * Accessing symbol in this way would be removed when the usb-gadget of the device-common
- * is integrated into the deviced.
- */
-#include <glib.h>
-#include <hal/device/hal-usb_gadget-interface.h>
-
-struct _usb_mode_mapping_table {
-       int          mode_v; /* Integer defined by vconf */
-       unsigned int mode;   /* Bitmap of usb function combination */
-       struct usb_gadget_attrs attrs;
-};
-extern GList *usb_mode_mapping_table_custom;
-
-struct service_config {
-       char name[128];
-       int remain_after_disable;
-};
-extern GList *service_config_list;
-/**************************************/
 
 struct usb_function *find_usb_function_by_id(int id);
 struct usb_function *find_usb_function_by_name(const char *name);
index 3233604..02a92ed 100644 (file)
@@ -19,6 +19,8 @@
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <dlfcn.h>
+
 #include <libsyscommon/libsystemd.h>
 #include <libsyscommon/list.h>
 #include <hal/device/hal-usb_gadget-interface.h>
 
 static struct usb_function *_available_funcs[];
 
+/**************************************
+ * Those symbols must be initialized first in deviced
+ *
+ * The usb-gadget source code have been scattered throughout the deviced and device-common.
+ * Because of this, it might have been implemented that totally same data structure on the
+ * both side. To avoid this inefficiency, define/initialize the data structure on the
+ * deviced first, and device-common refer it through dlsym(). The deviced must have
+ * cflag -rdynamic or ldflag --export-dynamic so that the dlopen-ed device-common can refer
+ * those variables with dlsym().
+ *
+ * Accessing symbol in this way would be removed when the usb-gadget of the device-common
+ * is integrated into the deviced.
+ */
+#include <glib.h>
+#include <hal/device/hal-usb_gadget-interface.h>
+
+struct _usb_mode_mapping_table {
+       int          mode_v; /* Integer defined by vconf */
+       unsigned int mode;   /* Bitmap of usb function combination */
+       struct usb_gadget_attrs attrs;
+};
+static GList *usb_mode_mapping_table_custom;
+
+struct service_config {
+       char name[128];
+       int remain_after_disable;
+};
+static GList *service_config_list;
+/**************************************/
+
 struct usb_function *find_usb_function_by_id(int id);
 
 static void simple_cleanup_config(struct usb_configuration *config)
@@ -382,9 +414,27 @@ static void set_service_config(gpointer data, gpointer udata)
 EXPORT
 int simple_translator_open(hal_backend_usb_gadget_funcs *usb_gadget_funcs)
 {
+       char *dlerr;
+
        if (!usb_gadget_funcs)
                return -EINVAL;
 
+       dlerror(); // clear any existing dl error
+
+       usb_mode_mapping_table_custom = *(GList **) dlsym(RTLD_DEFAULT, "usb_mode_mapping_table_custom");
+       dlerr = dlerror();
+       if (dlerr) {
+               _E("%s", dlerr);
+               return -ENOTSUP;
+       }
+
+       service_config_list = *(GList **) dlsym(RTLD_DEFAULT, "service_config_list");
+       dlerr = dlerror();
+       if (dlerr) {
+               _E("%s", dlerror());
+               return -ENOTSUP;
+       }
+
        /* e.g.
         * /hal/etc/deviced/usb_gadget.conf
         *