From 02f24d76e14feaddb9891f323991de019ce5947a Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 19 May 2014 21:04:32 +0900 Subject: [PATCH] Eo: Add function name to OP desc on Windows Match function names when the API pointer is out of range. Reviewed by TAsn and modified according to his comments :) Differential Revision: https://phab.enlightenment.org/D876 --- src/lib/eo/Eo.h | 19 ++++++++++++++----- src/lib/eo/eo.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index c37eeb5..26039b8 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -368,6 +368,9 @@ typedef enum _Eo_Class_Type Eo_Class_Type; typedef struct _Eo_Op_Description { void *api_func; /**< The EAPI function offering this op. */ +#ifdef _WIN32 + const char *api_name; /**< Full name of this API entry-point. Used to work around import indirection in DLL's. */ +#endif void *func; /**< The static function to call for the op. */ Eo_Op op; /**< The op. */ Eo_Op_Type op_type; /**< The type of the Op. */ @@ -547,11 +550,17 @@ EAPI extern Eo_Hook_Call eo_hook_call_post; // OP ID of an overriding function #define EO_OP_OVERRIDE ((Eo_Op) -1) -#define EO_OP_FUNC(_api, _private, _doc) {_api, _private, EO_NOOP, EO_OP_TYPE_REGULAR, _doc} -#define EO_OP_CLASS_FUNC(_api, _private, _doc) {_api, _private, EO_NOOP, EO_OP_TYPE_CLASS, _doc} -#define EO_OP_FUNC_OVERRIDE(_api, _private) {_api, _private, EO_OP_OVERRIDE, EO_OP_TYPE_REGULAR, NULL} -#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) {_api, _private, EO_OP_OVERRIDE, EO_OP_TYPE_CLASS, NULL} -#define EO_OP_SENTINEL { NULL, NULL, 0, EO_OP_TYPE_INVALID, NULL} +#ifndef _WIN32 +# define _EO_OP_API_ENTRY(a) a +#else +# define _EO_OP_API_ENTRY(a) a, #a +#endif + +#define EO_OP_FUNC(_api, _private, _doc) { _EO_OP_API_ENTRY(_api), _private, EO_NOOP, EO_OP_TYPE_REGULAR, _doc } +#define EO_OP_CLASS_FUNC(_api, _private, _doc) { _EO_OP_API_ENTRY(_api), _private, EO_NOOP, EO_OP_TYPE_CLASS, _doc } +#define EO_OP_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_OVERRIDE, EO_OP_TYPE_REGULAR, NULL } +#define EO_OP_CLASS_FUNC_OVERRIDE(_api, _private) { _EO_OP_API_ENTRY(_api), _private, EO_OP_OVERRIDE, EO_OP_TYPE_CLASS, NULL } +#define EO_OP_SENTINEL { _EO_OP_API_ENTRY(NULL), NULL, 0, EO_OP_TYPE_INVALID, NULL } // returns the OP id corresponding to the given api_func EAPI Eo_Op _eo_api_op_id_get(const void *api_func, const char *file, int line); diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 52ac9d5..36f3228 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -685,7 +685,7 @@ end2: static inline const Eo_Op_Description * -_eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class **extns) +_eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class **extns, const char *api_name) { int imin, imax, imid; const _Eo_Class *cur_klass; @@ -715,6 +715,22 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class * return op_desc; } +#ifdef _WIN32 + /* On Windows, DLL API's will be exported using the dllexport flag. + * When used by another library or executable, they will be declared + * using the dllimport flag. What happens really is that two symbols are + * created, at two different addresses. So it's impossible to match + * them. We fallback to plain string comparison based on the + * function name itself. Slow, but this should rarely happen. + */ + for (int i = 0; i < cur_klass->desc->ops.count; i++) + if (op_descs[i].api_name && !strcmp(api_name, op_descs[i].api_name)) + { + if (op_descs[i].api_func == NULL || op_descs[i].api_func == ((void (*)())-1)) + break; + return &op_descs[i]; + } +#endif } } @@ -723,7 +739,7 @@ _eo_api_desc_get(const void *api_func, const _Eo_Class *klass, const _Eo_Class * for (kls_itr = extns ; *kls_itr ; kls_itr++) { cur_klass = *kls_itr; - op_desc = _eo_api_desc_get(api_func, cur_klass, NULL); + op_desc = _eo_api_desc_get(api_func, cur_klass, NULL, api_name); if (op_desc) return op_desc; } } @@ -748,7 +764,10 @@ _eo_api_op_id_get(const void *api_func, const char *file, int line) else klass = stack->frame_ptr->o.obj->klass; - desc = _eo_api_desc_get(api_func, klass, klass->extensions); + // Win32 compatibility: api_name is NULL because we're assuming the + // function pointer is correct (it was referred to using the same + // dllimport vs. dllexport flags). + desc = _eo_api_desc_get(api_func, klass, klass->extensions, NULL); if (desc == NULL) { @@ -819,7 +838,11 @@ _eo_class_funcs_set(_Eo_Class *klass) } else if (op_desc->op == EO_OP_OVERRIDE) { - api_desc = _eo_api_desc_get(op_desc->api_func, klass->parent, klass->extensions); +#ifdef _WIN32 + api_desc = _eo_api_desc_get(op_desc->api_func, klass->parent, klass->extensions, op_desc->api_name); +#else + api_desc = _eo_api_desc_get(op_desc->api_func, klass->parent, klass->extensions, NULL); +#endif if (api_desc == NULL) { -- 2.7.4