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
This commit is contained in:
Jean-Philippe Andre 2014-05-19 21:04:32 +09:00
parent 0405d8e9a5
commit 02f24d76e1
2 changed files with 41 additions and 9 deletions

View File

@ -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);

View File

@ -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)
{