2017-05-07 09:15:19 -07:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <dlfcn.h>
|
2017-05-27 10:43:23 -07:00
|
|
|
#include <ffi.h>
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
#include <Eina.h>
|
2017-05-07 09:15:19 -07:00
|
|
|
#include <Eo.h>
|
2017-05-27 10:43:23 -07:00
|
|
|
#include <Eolian.h>
|
|
|
|
#include <Ecore_X.h>
|
|
|
|
#include <Evas.h>
|
|
|
|
#include <Elementary.h>
|
|
|
|
#define ELM_INTERNAL_API_ARGESFSDFEFC
|
|
|
|
#include <elm_widget.h>
|
|
|
|
|
|
|
|
#include "Clouseau_Debug.h"
|
2017-05-07 09:15:19 -07:00
|
|
|
|
|
|
|
#ifdef EAPI
|
|
|
|
# undef EAPI
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
# ifdef DEBUG_BUILD
|
|
|
|
# ifdef DLL_EXPORT
|
|
|
|
# define EAPI __declspec(dllexport)
|
|
|
|
# else
|
|
|
|
# define EAPI
|
|
|
|
# endif /* ! DLL_EXPORT */
|
|
|
|
# else
|
|
|
|
# define EAPI __declspec(dllimport)
|
|
|
|
# endif /* ! DEBUG_BUILD */
|
|
|
|
#else
|
|
|
|
# ifdef __GNUC__
|
|
|
|
# if __GNUC__ >= 4
|
|
|
|
# define EAPI __attribute__ ((visibility("default")))
|
|
|
|
# else
|
|
|
|
# define EAPI
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# define EAPI
|
|
|
|
# endif
|
|
|
|
#endif /* ! _WIN32 */
|
|
|
|
|
2017-06-03 12:17:56 -07:00
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
|
#define SWAP_64(x) x
|
|
|
|
#define SWAP_32(x) x
|
|
|
|
#define SWAP_16(x) x
|
|
|
|
#define SWAP_DBL(x) x
|
|
|
|
#else
|
|
|
|
#define SWAP_64(x) eina_swap64(x)
|
|
|
|
#define SWAP_32(x) eina_swap32(x)
|
|
|
|
#define SWAP_16(x) eina_swap16(x)
|
|
|
|
#define SWAP_DBL(x) SWAP_64(x)
|
|
|
|
#endif
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
#define STORE(_buf, pval, sz) \
|
|
|
|
{ \
|
|
|
|
memcpy(_buf, pval, sz); \
|
|
|
|
_buf += sz; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EXTRACT(_buf, pval, sz) \
|
|
|
|
{ \
|
|
|
|
memcpy(pval, _buf, sz); \
|
|
|
|
_buf += sz; \
|
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
static int _snapshot_start_op = EINA_DEBUG_OPCODE_INVALID;
|
2017-05-07 09:15:19 -07:00
|
|
|
static int _snapshot_done_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
static int _klids_get_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
static int _eoids_get_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
static int _obj_info_op = EINA_DEBUG_OPCODE_INVALID;
|
2017-05-27 10:43:23 -07:00
|
|
|
static int _obj_highlight_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
static int _win_screenshot_op = EINA_DEBUG_OPCODE_INVALID;
|
2017-10-29 06:33:13 -07:00
|
|
|
static int _focus_manager_list_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
static int _focus_manager_detail_op = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
|
2018-02-04 09:46:34 -08:00
|
|
|
static Eolian *eos = NULL;
|
|
|
|
|
2017-11-29 01:15:32 -08:00
|
|
|
static Eet_Data_Descriptor *manager_details = NULL;
|
2017-10-29 06:33:13 -07:00
|
|
|
#include "clouseau_focus_serialization.x"
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
enum {
|
|
|
|
HIGHLIGHT_R = 255,
|
|
|
|
HIGHLIGHT_G = 128,
|
|
|
|
HIGHLIGHT_B = 128,
|
|
|
|
HIGHLIGHT_A = 255
|
|
|
|
};
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
Eolian_Type_Type etype;
|
|
|
|
const char *name;
|
|
|
|
Eolian_Debug_Basic_Type type;
|
2017-09-27 13:55:14 -07:00
|
|
|
} Eolian_Param_Info;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
Eolian_Debug_Basic_Type type;
|
2017-05-27 10:43:23 -07:00
|
|
|
const char *print_format;
|
|
|
|
void *ffi_type_p;//ffi_type
|
|
|
|
const unsigned int size;
|
2017-09-27 13:55:14 -07:00
|
|
|
} Debug_Param_Info;
|
|
|
|
|
|
|
|
const Eolian_Param_Info eolian_types[] =
|
|
|
|
{
|
|
|
|
{EOLIAN_TYPE_REGULAR, "", EOLIAN_DEBUG_INVALID_TYPE },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "pointer", EOLIAN_DEBUG_POINTER },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "string", EOLIAN_DEBUG_STRING },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "char", EOLIAN_DEBUG_CHAR },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "int", EOLIAN_DEBUG_INT },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "short", EOLIAN_DEBUG_SHORT },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "double", EOLIAN_DEBUG_DOUBLE },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "bool", EOLIAN_DEBUG_BOOLEAN },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "long", EOLIAN_DEBUG_LONG },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "uint", EOLIAN_DEBUG_UINT },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "list", EOLIAN_DEBUG_LIST },
|
|
|
|
{EOLIAN_TYPE_REGULAR, "iterator", EOLIAN_DEBUG_LIST },
|
|
|
|
{EOLIAN_TYPE_CLASS, "", EOLIAN_DEBUG_OBJECT },
|
|
|
|
{0, NULL, 0}
|
|
|
|
};
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
const Debug_Param_Info debug_types[] =
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-09-27 13:55:14 -07:00
|
|
|
{EOLIAN_DEBUG_INVALID_TYPE, "", &ffi_type_pointer, 0},
|
|
|
|
{EOLIAN_DEBUG_POINTER, "%p", &ffi_type_pointer, 8},
|
|
|
|
{EOLIAN_DEBUG_STRING, "%s", &ffi_type_pointer, 8},
|
|
|
|
{EOLIAN_DEBUG_CHAR, "%c", &ffi_type_uint, 1},
|
|
|
|
{EOLIAN_DEBUG_INT, "%d", &ffi_type_sint, 4},
|
|
|
|
{EOLIAN_DEBUG_SHORT, "%d", &ffi_type_sint, 4},
|
|
|
|
{EOLIAN_DEBUG_DOUBLE, "%f", &ffi_type_pointer, 8},
|
|
|
|
{EOLIAN_DEBUG_BOOLEAN, "%d", &ffi_type_uint, 1},
|
|
|
|
{EOLIAN_DEBUG_LONG, "%f", &ffi_type_pointer, 8},
|
|
|
|
{EOLIAN_DEBUG_UINT, "%u", &ffi_type_uint, 4},
|
|
|
|
{EOLIAN_DEBUG_LIST, "%p", &ffi_type_pointer, 8},
|
|
|
|
{EOLIAN_DEBUG_OBJECT, "%p", &ffi_type_pointer, 8},
|
|
|
|
{0, NULL, 0, 0}
|
2017-05-27 10:43:23 -07:00
|
|
|
};
|
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const Eolian_Unit *unit;
|
|
|
|
const Eolian_Class *kl;
|
|
|
|
} Eolian_Info;
|
|
|
|
|
|
|
|
static Eina_Hash *_eolian_kls_hash = NULL;
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
static Eolian_Debug_Basic_Type
|
2018-02-04 09:46:34 -08:00
|
|
|
_eolian_type_resolve(const Eolian_Type *eo_type)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
Eolian_Type_Type type = eolian_type_type_get(eo_type);
|
|
|
|
Eolian_Type_Type type_base = type;
|
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
if (type == EOLIAN_TYPE_CLASS) return EOLIAN_DEBUG_OBJECT;
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
if (type_base == EOLIAN_TYPE_REGULAR)
|
|
|
|
{
|
|
|
|
const char *full_name = eolian_type_full_name_get(eo_type);
|
2018-02-04 09:46:34 -08:00
|
|
|
const Eolian_Typedecl *alias = eolian_typedecl_alias_get_by_name((Eolian_Unit*) eos, full_name);
|
2017-05-27 10:43:23 -07:00
|
|
|
if (alias)
|
|
|
|
{
|
2017-09-27 13:55:14 -07:00
|
|
|
eo_type = eolian_typedecl_base_type_get(alias);
|
|
|
|
type_base = eolian_type_type_get(eo_type);
|
|
|
|
full_name = eolian_type_full_name_get(eo_type);
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
if (full_name)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-09-27 13:55:14 -07:00
|
|
|
int i;
|
|
|
|
for (i = 0; eolian_types[i].name; i++)
|
|
|
|
if (!strcmp(full_name, eolian_types[i].name) &&
|
|
|
|
eolian_types[i].etype == type) return i;
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EOLIAN_DEBUG_INVALID_TYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-02-04 09:46:34 -08:00
|
|
|
_function_invoke(Eo *ptr, const Eolian_Function *foo, Eolian_Function_Type foo_type,
|
2017-05-27 10:43:23 -07:00
|
|
|
Eolian_Debug_Parameter *params, Eolian_Debug_Return *ret)
|
|
|
|
{
|
|
|
|
/* The params table contains the keys and the values.
|
|
|
|
* This function doesn't allocate memory */
|
|
|
|
ffi_type *types[EOLIAN_DEBUG_MAXARGS]; /* FFI types */
|
|
|
|
void *values[EOLIAN_DEBUG_MAXARGS]; /* FFI Values */
|
|
|
|
void *pointers[EOLIAN_DEBUG_MAXARGS]; /* Used as values for out params, as we have to give a pointer to a pointer */
|
|
|
|
Eolian_Function_Parameter *eo_param;
|
|
|
|
Eina_Iterator *itr;
|
|
|
|
Eolian_Debug_Basic_Type ed_type;
|
|
|
|
int argc, ffi_argc = 0;
|
|
|
|
|
|
|
|
if (!foo) return -1;
|
|
|
|
if (foo_type == EOLIAN_PROPERTY) return -1;
|
|
|
|
|
|
|
|
/* Eo object storage */
|
|
|
|
types[ffi_argc] = &ffi_type_pointer;
|
|
|
|
values[ffi_argc] = &ptr;
|
|
|
|
ffi_argc++;
|
|
|
|
|
|
|
|
itr = eolian_property_keys_get(foo, foo_type);
|
|
|
|
argc = 0;
|
|
|
|
EINA_ITERATOR_FOREACH(itr, eo_param)
|
|
|
|
{
|
|
|
|
/* Not verified */
|
2018-02-04 09:46:34 -08:00
|
|
|
ed_type = _eolian_type_resolve(eolian_parameter_type_get(eo_param));
|
2017-05-27 10:43:23 -07:00
|
|
|
if (!ed_type) goto error;
|
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
types[ffi_argc] = debug_types[ed_type].ffi_type_p;
|
2017-05-27 10:43:23 -07:00
|
|
|
values[ffi_argc] = &(params[argc].value.value.value);
|
2017-06-18 00:10:40 -07:00
|
|
|
params[argc].eparam = eo_param;
|
2017-05-27 10:43:23 -07:00
|
|
|
ffi_argc++;
|
|
|
|
argc++;
|
|
|
|
}
|
|
|
|
|
|
|
|
itr = foo_type == EOLIAN_METHOD ? eolian_function_parameters_get(foo) :
|
|
|
|
eolian_property_values_get(foo, foo_type);
|
|
|
|
EINA_ITERATOR_FOREACH(itr, eo_param)
|
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
ed_type = _eolian_type_resolve(eolian_parameter_type_get(eo_param));
|
2017-05-27 10:43:23 -07:00
|
|
|
if (!ed_type) goto error;
|
2017-06-18 00:10:40 -07:00
|
|
|
params[argc].eparam = eo_param;
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
if (foo_type == EOLIAN_PROP_GET ||
|
|
|
|
(foo_type == EOLIAN_METHOD && eolian_parameter_direction_get(eo_param) == EOLIAN_OUT_PARAM))
|
|
|
|
{
|
|
|
|
/* Out parameter */
|
|
|
|
params[argc].value.value.value = 0;
|
|
|
|
params[argc].value.type = ed_type;
|
|
|
|
types[ffi_argc] = &ffi_type_pointer;
|
|
|
|
pointers[ffi_argc] = &(params[argc].value.value.value);
|
|
|
|
values[ffi_argc] = &pointers[ffi_argc];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* In parameter */
|
2017-09-27 13:55:14 -07:00
|
|
|
types[ffi_argc] = debug_types[ed_type].ffi_type_p;
|
2017-05-27 10:43:23 -07:00
|
|
|
values[ffi_argc] = &(params[argc].value.value.value);
|
|
|
|
}
|
|
|
|
ffi_argc++;
|
|
|
|
argc++;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Eolian_Type *eo_type = eolian_function_return_type_get(foo, foo_type);
|
|
|
|
ffi_type *ffi_ret_type = &ffi_type_void;
|
|
|
|
if (eo_type)
|
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
ed_type = _eolian_type_resolve(eo_type);
|
2017-05-27 10:43:23 -07:00
|
|
|
if (!ed_type) goto error;
|
|
|
|
|
2017-09-27 13:55:14 -07:00
|
|
|
ffi_ret_type = debug_types[ed_type].ffi_type_p;
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
else if (argc == 1 && foo_type == EOLIAN_PROP_GET)
|
|
|
|
{
|
|
|
|
/* If there is no return type but only one value is present, the value will
|
|
|
|
* be returned by the function.
|
|
|
|
* So we need FFI to not take it into account when invoking the function.
|
|
|
|
*/
|
2017-09-27 13:55:14 -07:00
|
|
|
ffi_ret_type = debug_types[params[0].value.type].ffi_type_p;
|
2017-05-27 10:43:23 -07:00
|
|
|
ffi_argc--;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *full_func_name = eolian_function_full_c_name_get(foo, EOLIAN_PROP_GET, EINA_FALSE);
|
|
|
|
void *eo_func = dlsym(RTLD_DEFAULT, full_func_name);
|
|
|
|
if (!eo_func) goto error;
|
|
|
|
ffi_cif cif;
|
|
|
|
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, ffi_argc,
|
|
|
|
ffi_ret_type, types) == FFI_OK)
|
|
|
|
{
|
|
|
|
void *result;
|
|
|
|
ffi_call(&cif, eo_func, &result, values);
|
|
|
|
if (ret) ret->value.type = EOLIAN_DEBUG_VOID;
|
|
|
|
if (eo_type)
|
|
|
|
{
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
ret->value.value.value = (uint64_t) result;
|
|
|
|
ret->value.type = ed_type;
|
2017-06-18 00:10:40 -07:00
|
|
|
ret->etype = eo_type;
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (argc == 1 && foo_type == EOLIAN_PROP_GET)
|
|
|
|
params[0].value.value.value = (uint64_t) result;
|
|
|
|
goto success;
|
|
|
|
}
|
|
|
|
|
|
|
|
error:
|
|
|
|
argc = -1;
|
|
|
|
success:
|
|
|
|
eina_iterator_free(itr);
|
|
|
|
return argc;
|
|
|
|
}
|
|
|
|
|
2017-07-09 13:28:19 -07:00
|
|
|
#if 0
|
|
|
|
/* Commented until we are sure it is not needed anymore */
|
2017-05-27 10:43:23 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_eolian_function_is_implemented(
|
|
|
|
const Eolian_Function *function_id, Eolian_Function_Type func_type,
|
2017-06-03 11:39:15 -07:00
|
|
|
const Eolian_Unit *unit, const Eolian_Class *klass)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
Eina_Iterator *impl_itr = NULL;
|
|
|
|
Eolian_Function_Type found_type = EOLIAN_UNRESOLVED;
|
|
|
|
Eina_Bool found = EINA_TRUE;
|
|
|
|
if (!function_id || !klass) return EINA_FALSE;
|
|
|
|
Eina_List *list = eina_list_append(NULL, klass), *list2, *itr;
|
|
|
|
EINA_LIST_FOREACH(list, itr, klass)
|
|
|
|
{
|
|
|
|
const char *inherit_name;
|
|
|
|
const Eolian_Implement *impl;
|
|
|
|
if (eolian_class_type_get(klass) == EOLIAN_CLASS_INTERFACE) continue;
|
|
|
|
impl_itr = eolian_class_implements_get(klass);
|
|
|
|
EINA_ITERATOR_FOREACH(impl_itr, impl)
|
|
|
|
{
|
|
|
|
if (eolian_implement_is_pure_virtual(impl, EOLIAN_PROP_SET)) continue;
|
|
|
|
Eolian_Function_Type impl_type = EOLIAN_UNRESOLVED;
|
|
|
|
const Eolian_Function *impl_func = eolian_implement_function_get(impl, &impl_type);
|
|
|
|
if (impl_func == function_id)
|
|
|
|
{
|
|
|
|
/* The type matches the requested or is not important for the caller */
|
|
|
|
if (func_type == EOLIAN_UNRESOLVED || impl_type == func_type) goto end;
|
|
|
|
if (impl_type == EOLIAN_METHOD) continue;
|
|
|
|
/* In case we search for a property type */
|
|
|
|
if (impl_type == EOLIAN_PROPERTY &&
|
|
|
|
(func_type == EOLIAN_PROP_GET || func_type == EOLIAN_PROP_SET))
|
|
|
|
goto end;
|
|
|
|
/* Property may be splitted on multiple implements */
|
|
|
|
if (func_type == EOLIAN_PROPERTY)
|
|
|
|
{
|
|
|
|
if (found_type == EOLIAN_UNRESOLVED) found_type = impl_type;
|
|
|
|
if ((found_type == EOLIAN_PROP_SET && impl_type == EOLIAN_PROP_GET) ||
|
|
|
|
(found_type == EOLIAN_PROP_GET && impl_type == EOLIAN_PROP_SET))
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eina_iterator_free(impl_itr);
|
|
|
|
impl_itr = NULL;
|
|
|
|
|
|
|
|
Eina_Iterator *inherits_itr = eolian_class_inherits_get(klass);
|
|
|
|
EINA_ITERATOR_FOREACH(inherits_itr, inherit_name)
|
|
|
|
{
|
2017-06-03 11:39:15 -07:00
|
|
|
const Eolian_Class *inherit = eolian_class_get_by_name(unit, inherit_name);
|
2017-05-27 10:43:23 -07:00
|
|
|
/* Avoid duplicates. */
|
|
|
|
if (!eina_list_data_find(list, inherit))
|
|
|
|
{
|
|
|
|
list2 = eina_list_append(list, inherit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eina_iterator_free(inherits_itr);
|
|
|
|
}
|
|
|
|
(void) list2;
|
|
|
|
found = EINA_FALSE;
|
|
|
|
end:
|
|
|
|
if (impl_itr) eina_iterator_free(impl_itr);
|
|
|
|
eina_list_free(list);
|
|
|
|
return found;
|
|
|
|
}
|
2017-07-09 13:28:19 -07:00
|
|
|
#endif
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-18 00:10:40 -07:00
|
|
|
static int
|
|
|
|
_param_buffer_fill(char *buf, uint64_t v, int size)
|
|
|
|
{
|
|
|
|
if (size == 8)
|
|
|
|
{
|
|
|
|
uint64_t value = SWAP_64(v);
|
|
|
|
memcpy(buf, &value, 8);
|
|
|
|
}
|
|
|
|
else if (size == 4)
|
|
|
|
{
|
|
|
|
int value = SWAP_32(v);
|
|
|
|
memcpy(buf, &value, 4);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(buf, &v, size);
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-02-04 09:46:34 -08:00
|
|
|
_complex_buffer_fill(char *buf, const Eolian_Type *eo_type, uint64_t value)
|
2017-06-18 00:10:40 -07:00
|
|
|
{
|
|
|
|
Eina_List *l = NULL;
|
|
|
|
const char *eo_tname = eolian_type_name_get(eo_type);
|
|
|
|
void *data;
|
|
|
|
int size = 0, count = -1;
|
|
|
|
Eolian_Debug_Basic_Type type;
|
|
|
|
if (!strcmp(eo_tname, "iterator"))
|
|
|
|
{
|
|
|
|
Eina_Iterator *iter = (Eina_Iterator *)value;
|
|
|
|
EINA_ITERATOR_FOREACH(iter, data)
|
|
|
|
{
|
|
|
|
l = eina_list_append(l, data);
|
|
|
|
}
|
|
|
|
eina_iterator_free(iter);
|
|
|
|
}
|
|
|
|
else if (!strcmp(eo_tname, "list"))
|
|
|
|
{
|
|
|
|
Eina_List *int_l = (Eina_List *)value;
|
|
|
|
Eina_Stringshare *free_foo_str = eolian_type_free_func_get(eo_type);
|
|
|
|
l = eina_list_clone(int_l);
|
|
|
|
if (free_foo_str)
|
|
|
|
{
|
|
|
|
void (*func)(Eina_List *) = dlsym(RTLD_DEFAULT, free_foo_str);
|
|
|
|
if (func) func(int_l);
|
|
|
|
else
|
|
|
|
printf("Function %s not found", free_foo_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-04 09:46:34 -08:00
|
|
|
type = _eolian_type_resolve(eolian_type_base_type_get(eo_type));
|
2017-06-18 00:10:40 -07:00
|
|
|
|
|
|
|
if (type != EOLIAN_DEBUG_INVALID_TYPE) count = SWAP_32(eina_list_count(l));
|
|
|
|
|
|
|
|
memcpy(buf + size, &count, 4);
|
|
|
|
size += 4;
|
|
|
|
|
|
|
|
EINA_LIST_FREE(l, data)
|
|
|
|
{
|
|
|
|
if (count == -1) continue;
|
2017-09-27 13:55:14 -07:00
|
|
|
size += _param_buffer_fill(buf+size, (uint64_t)data, debug_types[type].size);
|
2017-06-18 00:10:40 -07:00
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2017-07-09 13:28:19 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_api_resolvable(Eo *obj, const Eolian_Function *function)
|
|
|
|
{
|
|
|
|
Efl_Object_Op_Call_Data call_data = {};
|
2018-01-31 06:33:49 -08:00
|
|
|
Efl_Object_Op op;
|
2017-07-09 13:28:19 -07:00
|
|
|
const char *func_c_name;
|
|
|
|
void *func_api;
|
|
|
|
|
|
|
|
func_c_name = eolian_function_full_c_name_get(function, EOLIAN_PROP_GET, EINA_FALSE);
|
|
|
|
func_api = dlsym(RTLD_DEFAULT, func_c_name);
|
2018-01-31 06:33:49 -08:00
|
|
|
op = _efl_object_op_api_id_get(func_api, obj, func_c_name, __FILE__, __LINE__);
|
|
|
|
_efl_object_call_resolve(obj, func_c_name, &call_data, op, __FILE__, __LINE__);
|
2017-07-09 13:28:19 -07:00
|
|
|
|
|
|
|
return !!call_data.func;
|
|
|
|
}
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
static unsigned int
|
2018-02-04 09:46:34 -08:00
|
|
|
_class_buffer_fill(Eo *obj, const Eolian_Class *ekl, char *buf)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
unsigned int size = 0;
|
|
|
|
Eina_Iterator *funcs = eolian_class_functions_get(ekl, EOLIAN_PROPERTY);
|
|
|
|
const Eolian_Function *func;
|
|
|
|
EINA_ITERATOR_FOREACH(funcs, func)
|
|
|
|
{
|
2017-07-09 13:28:19 -07:00
|
|
|
if (eolian_function_type_get(func) == EOLIAN_PROP_SET) continue;
|
|
|
|
|
|
|
|
if (!_api_resolvable(obj, func)) continue;
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
Eina_Iterator *keys_itr = eolian_property_keys_get(func, EOLIAN_PROP_GET);
|
|
|
|
eina_iterator_free(keys_itr);
|
|
|
|
/* We dont support functions with key parameters */
|
|
|
|
if (keys_itr) continue;
|
|
|
|
|
|
|
|
Eolian_Debug_Parameter params[EOLIAN_DEBUG_MAXARGS];
|
|
|
|
Eolian_Debug_Return ret;
|
2018-02-04 09:46:34 -08:00
|
|
|
int argnum = _function_invoke(obj, func, EOLIAN_PROP_GET, params, &ret);
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
if (argnum == -1) continue;
|
|
|
|
|
|
|
|
int len, i;
|
|
|
|
if (!size) // only if its the first func to succeed
|
|
|
|
{
|
|
|
|
const char *class_name = eolian_class_full_name_get(ekl);
|
|
|
|
len = strlen(class_name) + 1;
|
|
|
|
memcpy(buf, class_name, len);
|
|
|
|
size += len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//write zero length string to mark that it's still the same class
|
|
|
|
buf[size] = '\0';
|
|
|
|
size++;
|
|
|
|
}
|
|
|
|
const char *func_name = eolian_function_name_get(func);
|
|
|
|
len = strlen(func_name) + 1;
|
|
|
|
memcpy(buf + size, func_name, len);
|
|
|
|
size += len;
|
|
|
|
for (i = 0; i < argnum; i++) //print params
|
|
|
|
{
|
|
|
|
// if its a string we wont copy the pointer but the value
|
|
|
|
if (params[i].value.type == EOLIAN_DEBUG_STRING)
|
|
|
|
{
|
|
|
|
if((char *)params[i].value.value.value == NULL)
|
|
|
|
params[i].value.value.value = (uint64_t)"";
|
|
|
|
len = strlen((char *)params[i].value.value.value) + 1;
|
|
|
|
memcpy(buf + size, (char *)params[i].value.value.value, len);
|
|
|
|
size += len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-18 00:10:40 -07:00
|
|
|
const Eolian_Type *eo_type = eolian_parameter_type_get(params[i].eparam);
|
|
|
|
size += _param_buffer_fill(buf+size, params[i].value.value.value,
|
2017-09-27 13:55:14 -07:00
|
|
|
debug_types[params[i].value.type].size);
|
|
|
|
if (params[i].value.type == EOLIAN_DEBUG_LIST)
|
2017-06-03 12:17:56 -07:00
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
size += _complex_buffer_fill(buf+size, eo_type,
|
2017-06-18 00:10:40 -07:00
|
|
|
params[i].value.value.value);
|
2017-06-03 12:17:56 -07:00
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
For Eolian funcs that dont define "pram type" for their
|
|
|
|
return value we dont have part of the info that we have on
|
|
|
|
normal Eolian param (such as name). Also the return value wont
|
|
|
|
be in the function params iterator - hence argnum = 0. For that
|
|
|
|
case we use Eolian_Debug_Return struct
|
|
|
|
*/
|
|
|
|
if (ret.value.type != EOLIAN_DEBUG_VOID)
|
|
|
|
{
|
|
|
|
//if its a string we wont copy the pointer but the values
|
|
|
|
if (ret.value.type == EOLIAN_DEBUG_STRING)
|
|
|
|
{
|
|
|
|
if((char *)ret.value.value.value == NULL)
|
|
|
|
ret.value.value.value = (uint64_t)"";
|
|
|
|
len = strlen((char *)ret.value.value.value) + 1;
|
|
|
|
memcpy(buf + size, (char *)ret.value.value.value, len);
|
|
|
|
size += len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-18 00:10:40 -07:00
|
|
|
size += _param_buffer_fill(buf+size, ret.value.value.value,
|
2017-09-27 13:55:14 -07:00
|
|
|
debug_types[ret.value.type].size);
|
|
|
|
if (ret.value.type == EOLIAN_DEBUG_LIST)
|
2017-06-03 12:17:56 -07:00
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
size += _complex_buffer_fill(buf+size,
|
2017-06-18 00:10:40 -07:00
|
|
|
ret.etype, ret.value.value.value);
|
2017-06-03 12:17:56 -07:00
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
eina_iterator_free(funcs);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2018-02-24 11:21:26 -08:00
|
|
|
/* Mapping from legacy classes to installed class files*/
|
|
|
|
static const char *legacy_installed_map[][2] =
|
|
|
|
{
|
|
|
|
{ "Efl.Ui.Bg_Widget_Legacy", "Efl.Ui.Bg_Widget" },
|
|
|
|
{ "Efl.Ui.Button_Legacy", "Efl.Ui.Button" },
|
|
|
|
{ "Efl.Ui.Check_Legacy", "Efl.Ui.Check" },
|
|
|
|
{ "Efl.Ui.Clock_Legacy", "Efl.Ui.Clock" },
|
|
|
|
{ "Efl.Ui.Flip_Legacy", "Efl.Ui.Flip" },
|
|
|
|
{ "Efl.Ui.Frame_Legacy", "Efl.Ui.Flip" },
|
|
|
|
{ "Efl.Ui.Image_Legacy", "Efl.Ui.Image" },
|
|
|
|
{ "Efl.Ui.Image_Zoomable_Legacy", "Efl.Ui.Image_Zoomable" },
|
|
|
|
{ "Efl.Ui.Layout_Legacy", "Efl.Ui.Layout" },
|
|
|
|
{ "Efl.Ui.Multibuttonentry_Legacy", "Efl.Ui.Multibuttonentry" },
|
|
|
|
{ "Efl.Ui.Panes_Legacy", "Efl.Ui.Panes" },
|
|
|
|
{ "Efl.Ui.Progressbar_Legacy", "Efl.Ui.Progressbar" },
|
|
|
|
{ "Efl.Ui.Radio_Legacy", "Efl.Ui.Radio" },
|
|
|
|
{ "Efl.Ui.Slider_Legacy", "Efl.Ui.Slider" },
|
|
|
|
{ "Efl.Ui.Video_Legacy", "Efl.Ui.Video" },
|
|
|
|
{ "Efl.Ui.Win_Legacy", "Efl.Ui.Win" },
|
|
|
|
{ "Elm.Code_Widget_Legacy", "Elm.Code_Widget" },
|
|
|
|
{ "Elm.Ctxpopup", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Entry", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Colorselector", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.List", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Photo", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Actionslider", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Box", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Table", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Thumb", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Menu", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Icon", "Efl.Ui.Image" },
|
|
|
|
{ "Elm.Prefs", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Map", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Glview", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Web", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Toolbar", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Grid", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Diskselector", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Notify", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Mapbuf", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Separator", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Calendar", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Inwin", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Gengrid", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Scroller", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Player", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Segment_Control", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Fileselector", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Fileselector_Button", "Efl.Ui.Button" },
|
|
|
|
{ "Elm.Fileselector_Entry", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Flipselector", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Hoversel", "Efl.Ui.Button" },
|
|
|
|
{ "Elm.Naviframe", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Popup", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Bubble", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Clock", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Conformant", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Dayselector", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Genlist", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Hover", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Index", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Label", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Panel", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Slideshow", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Spinner", "Efl.Ui.Layout" },
|
|
|
|
{ "Elm.Plug", "Efl.Ui.Widget" },
|
|
|
|
{ "Elm.Web.None", "Efl.Ui.Widget" },
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
static Eina_Bool
|
2017-05-27 10:43:23 -07:00
|
|
|
_obj_info_req_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size EINA_UNUSED)
|
|
|
|
{
|
|
|
|
uint64_t ptr64;
|
|
|
|
memcpy(&ptr64, buffer, sizeof(ptr64));
|
2017-06-03 12:17:56 -07:00
|
|
|
Eo *obj = (Eo *)SWAP_64(ptr64);
|
2018-02-24 11:21:26 -08:00
|
|
|
const char *class_name = NULL;
|
|
|
|
const Eolian_Class *kl, *okl;
|
2017-05-27 10:43:23 -07:00
|
|
|
unsigned int size_curr = 0;
|
2018-02-24 11:21:26 -08:00
|
|
|
char *buf;
|
|
|
|
|
|
|
|
if (!obj) return EINA_FALSE;
|
|
|
|
|
|
|
|
class_name = efl_class_name_get(obj);
|
|
|
|
|
|
|
|
if (efl_isa(obj, EFL_UI_LEGACY_INTERFACE))
|
|
|
|
{
|
|
|
|
for (int i = 0; legacy_installed_map[i][0]; ++i)
|
|
|
|
{
|
|
|
|
if (!strcmp(legacy_installed_map[i][0], class_name))
|
|
|
|
{
|
|
|
|
class_name = legacy_installed_map[i][1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
okl = eolian_class_get_by_name((Eolian_Unit*) eos, class_name);
|
2017-06-25 08:12:09 -07:00
|
|
|
if (!okl)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
printf("Class %s not found.\n", class_name);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
buf = malloc(100000);
|
|
|
|
memcpy(buf, &ptr64, sizeof(uint64_t));
|
|
|
|
size_curr = sizeof(uint64_t);
|
|
|
|
|
|
|
|
Eina_List *itr, *list2;
|
2017-06-25 08:12:09 -07:00
|
|
|
Eina_List *list = eina_list_append(NULL, okl);
|
2017-05-27 10:43:23 -07:00
|
|
|
EINA_LIST_FOREACH(list, itr, kl)
|
|
|
|
{
|
2018-02-24 11:52:10 -08:00
|
|
|
const Eolian_Class *inherit;
|
|
|
|
Eina_Iterator *inherits_itr;
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2018-02-24 11:52:10 -08:00
|
|
|
inherits_itr = eolian_class_inherits_get(kl);
|
2018-02-04 09:46:34 -08:00
|
|
|
size_curr += _class_buffer_fill(obj, kl, buf + size_curr);
|
2018-02-24 11:52:10 -08:00
|
|
|
|
|
|
|
EINA_ITERATOR_FOREACH(inherits_itr, inherit)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
/* Avoid duplicates in MRO list. */
|
|
|
|
if (!eina_list_data_find(list, inherit))
|
|
|
|
list2 = eina_list_append(list, inherit);
|
|
|
|
}
|
|
|
|
eina_iterator_free(inherits_itr);
|
|
|
|
}
|
|
|
|
(void) list2;
|
|
|
|
|
|
|
|
eina_debug_session_send(session, srcid, _obj_info_op, buf, size_curr);
|
2017-06-03 23:48:41 -07:00
|
|
|
free(buf);
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
end:
|
2017-05-30 04:24:49 -07:00
|
|
|
return EINA_TRUE;
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
static Eina_Bool
|
2017-06-01 14:53:59 -07:00
|
|
|
_snapshot_objs_get_req_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-06-01 14:53:59 -07:00
|
|
|
Eina_Iterator *iter;
|
|
|
|
Eina_List *itr;
|
2017-05-27 10:43:23 -07:00
|
|
|
char *buf, *tmp;
|
|
|
|
Eo *obj;
|
2017-06-01 14:53:59 -07:00
|
|
|
Eina_List *objs = NULL;
|
|
|
|
uint64_t *kls = buffer;
|
2017-06-03 12:17:56 -07:00
|
|
|
int nb_kls = size / sizeof(uint64_t), i;
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-03 12:17:56 -07:00
|
|
|
for (i = 0; i < nb_kls; i++) kls[i] = SWAP_64(kls[i]);
|
2017-06-01 14:53:59 -07:00
|
|
|
iter = eo_objects_iterator_new();
|
|
|
|
EINA_ITERATOR_FOREACH(iter, obj)
|
|
|
|
{
|
|
|
|
Eina_Bool klass_ok = EINA_FALSE;
|
|
|
|
for (i = 0; i < nb_kls && !klass_ok; i++)
|
|
|
|
{
|
|
|
|
if (efl_isa(obj, (Efl_Class *)kls[i])) klass_ok = EINA_TRUE;
|
|
|
|
if (klass_ok || !nb_kls) objs = eina_list_append(objs, obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eina_iterator_free(iter);
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-01 14:53:59 -07:00
|
|
|
size = eina_list_count(objs) * 3 * sizeof(uint64_t);
|
2017-05-27 10:43:23 -07:00
|
|
|
buf = tmp = malloc(size);
|
2017-06-01 14:53:59 -07:00
|
|
|
EINA_LIST_FOREACH(objs, itr, obj)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
Eo *parent;
|
2017-06-03 12:17:56 -07:00
|
|
|
uint64_t u64 = SWAP_64((uint64_t)obj);
|
2017-05-27 10:43:23 -07:00
|
|
|
STORE(tmp, &u64, sizeof(u64));
|
2017-06-03 12:17:56 -07:00
|
|
|
u64 = SWAP_64((uint64_t)efl_class_get(obj));
|
2017-05-27 10:43:23 -07:00
|
|
|
STORE(tmp, &u64, sizeof(u64));
|
|
|
|
parent = elm_object_parent_widget_get(obj);
|
|
|
|
if (!parent && efl_isa(obj, EFL_CANVAS_OBJECT_CLASS))
|
|
|
|
{
|
|
|
|
parent = evas_object_data_get(obj, "elm-parent");
|
|
|
|
if (!parent) parent = evas_object_smart_parent_get(obj);
|
|
|
|
}
|
|
|
|
if (!parent) parent = efl_parent_get(obj);
|
2017-06-03 12:17:56 -07:00
|
|
|
u64 = SWAP_64((uint64_t)parent);
|
2017-05-27 10:43:23 -07:00
|
|
|
STORE(tmp, &u64, sizeof(u64));
|
|
|
|
}
|
|
|
|
eina_debug_session_send(session, srcid, _eoids_get_op, buf, size);
|
2017-06-03 23:48:41 -07:00
|
|
|
free(buf);
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-01 14:53:59 -07:00
|
|
|
EINA_LIST_FREE(objs, obj)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-06-03 12:17:56 -07:00
|
|
|
uint64_t u64 = SWAP_64((uint64_t)obj);
|
2017-05-27 10:43:23 -07:00
|
|
|
_obj_info_req_cb(session, srcid, &u64, sizeof(uint64_t));
|
|
|
|
}
|
2017-05-30 04:24:49 -07:00
|
|
|
return EINA_TRUE;
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
static void
|
|
|
|
_main_loop_snapshot_start_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
|
2017-05-07 09:15:19 -07:00
|
|
|
{
|
2017-05-30 04:24:49 -07:00
|
|
|
char *all_kls_buf;
|
2017-05-22 15:47:20 -07:00
|
|
|
char *tmp;
|
2017-06-01 14:53:59 -07:00
|
|
|
Eina_Iterator *iter;
|
|
|
|
Efl_Class *kl;
|
|
|
|
uint64_t *kls;
|
|
|
|
Eina_List *kls_strs = NULL;
|
|
|
|
int nb_kls = 0;
|
2017-05-30 04:24:49 -07:00
|
|
|
|
2017-05-22 15:47:20 -07:00
|
|
|
tmp = buffer;
|
|
|
|
while (size > 0)
|
|
|
|
{
|
2017-06-01 14:53:59 -07:00
|
|
|
kls_strs = eina_list_append(kls_strs, tmp);
|
2017-05-22 15:47:20 -07:00
|
|
|
size -= strlen(tmp) + 1;
|
|
|
|
tmp += strlen(tmp) + 1;
|
2017-06-01 14:53:59 -07:00
|
|
|
nb_kls++;
|
2017-05-22 15:47:20 -07:00
|
|
|
}
|
2017-06-01 14:53:59 -07:00
|
|
|
size = nb_kls * sizeof(uint64_t);
|
2017-05-30 04:24:49 -07:00
|
|
|
if (size)
|
|
|
|
{
|
2017-06-01 14:53:59 -07:00
|
|
|
kls = alloca(size);
|
|
|
|
memset(kls, 0, size);
|
|
|
|
}
|
|
|
|
else kls = NULL;
|
|
|
|
|
|
|
|
all_kls_buf = tmp = malloc(10000);
|
|
|
|
iter = eo_classes_iterator_new();
|
|
|
|
EINA_ITERATOR_FOREACH(iter, kl)
|
|
|
|
{
|
|
|
|
Eina_List *itr;
|
|
|
|
const char *kl_name = efl_class_name_get(kl), *kl_str;
|
|
|
|
int len = strlen(kl_name) + 1;
|
2017-06-03 12:17:56 -07:00
|
|
|
uint64_t u64 = SWAP_64((uint64_t)kl);
|
2017-06-01 14:53:59 -07:00
|
|
|
Eina_Bool found = EINA_FALSE;
|
|
|
|
|
|
|
|
/* Fill the buffer with class id/name */
|
|
|
|
STORE(tmp, &u64, sizeof(u64));
|
|
|
|
STORE(tmp, kl_name, len);
|
|
|
|
|
|
|
|
/* Check for filtering */
|
|
|
|
if (!nb_kls) continue;
|
|
|
|
EINA_LIST_FOREACH(kls_strs, itr, kl_str)
|
|
|
|
{
|
|
|
|
if (found) continue;
|
|
|
|
if (!strcmp(kl_name, kl_str))
|
|
|
|
{
|
|
|
|
int i;
|
2017-06-05 03:08:34 -07:00
|
|
|
for (i = 0; i < nb_kls && !found; i++)
|
2017-06-01 14:53:59 -07:00
|
|
|
{
|
|
|
|
if (!kls[i])
|
|
|
|
{
|
|
|
|
kls[i] = (uint64_t)kl;
|
|
|
|
found = EINA_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-30 04:24:49 -07:00
|
|
|
}
|
2017-06-01 14:53:59 -07:00
|
|
|
eina_iterator_free(iter);
|
2017-05-30 04:24:49 -07:00
|
|
|
|
|
|
|
eina_debug_session_send(session, srcid,
|
2017-06-01 14:53:59 -07:00
|
|
|
_klids_get_op, all_kls_buf, tmp - all_kls_buf);
|
2017-05-27 10:43:23 -07:00
|
|
|
free(all_kls_buf);
|
2017-05-22 15:47:20 -07:00
|
|
|
|
2017-06-01 14:53:59 -07:00
|
|
|
_snapshot_objs_get_req_cb(session, srcid, kls, size);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
|
|
|
eina_debug_session_send(session, srcid, _snapshot_done_op, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_snapshot_start_cb)
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
/* Highlight functions. */
|
2017-05-07 09:15:19 -07:00
|
|
|
static Eina_Bool
|
2017-05-27 10:43:23 -07:00
|
|
|
_obj_highlight_fade(void *_rect)
|
2017-05-07 09:15:19 -07:00
|
|
|
{
|
2017-05-27 10:43:23 -07:00
|
|
|
Evas_Object *rect = _rect;
|
|
|
|
int r, g, b, a;
|
|
|
|
double na;
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
evas_object_color_get(rect, &r, &g, &b, &a);
|
|
|
|
if (a < 20)
|
2017-05-07 09:15:19 -07:00
|
|
|
{
|
2017-05-27 10:43:23 -07:00
|
|
|
evas_object_del(rect);
|
|
|
|
/* The del callback of the object will destroy the animator */
|
|
|
|
return EINA_TRUE;
|
2017-05-07 09:15:19 -07:00
|
|
|
}
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
na = a - 5;
|
|
|
|
r = na / a * r;
|
|
|
|
g = na / a * g;
|
|
|
|
b = na / a * b;
|
|
|
|
evas_object_color_set(rect, r, g, b, na);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
static void
|
|
|
|
_obj_highlight_del(void *data,
|
|
|
|
EINA_UNUSED Evas *e,
|
|
|
|
EINA_UNUSED Evas_Object *obj,
|
|
|
|
EINA_UNUSED void *event_info)
|
|
|
|
{ /* Delete timer for this rect */
|
|
|
|
ecore_animator_del(data);
|
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
static void
|
|
|
|
_main_loop_obj_highlight_cb(Eina_Debug_Session *session EINA_UNUSED, int srcid EINA_UNUSED, void *buffer, int size)
|
2017-05-07 09:15:19 -07:00
|
|
|
{
|
2017-05-27 10:43:23 -07:00
|
|
|
uint64_t ptr64;
|
2017-05-30 04:24:49 -07:00
|
|
|
if (size != sizeof(uint64_t)) return;
|
2017-05-27 10:43:23 -07:00
|
|
|
memcpy(&ptr64, buffer, sizeof(ptr64));
|
2017-06-03 12:17:56 -07:00
|
|
|
Eo *obj = (Eo *)SWAP_64(ptr64);
|
2017-11-07 11:14:42 -08:00
|
|
|
if (!efl_isa(obj, EFL_GFX_INTERFACE) && !efl_isa(obj, EFL_CANVAS_INTERFACE)) return;
|
2017-05-27 10:43:23 -07:00
|
|
|
Evas *e = evas_object_evas_get(obj);
|
|
|
|
Eo *rect = evas_object_polygon_add(e);
|
|
|
|
evas_object_move(rect, 0, 0);
|
2017-07-18 08:10:29 -07:00
|
|
|
if (efl_isa(obj, EFL_GFX_INTERFACE))
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-09-20 07:08:01 -07:00
|
|
|
Eina_Rect obj_geom = {.x = 0, .y = 0, .w = 0, .h = 0};
|
|
|
|
obj_geom = efl_gfx_geometry_get(obj);
|
|
|
|
if (efl_isa(obj, EFL_UI_WIN_CLASS)) obj_geom.x = obj_geom.y = 0;
|
|
|
|
|
|
|
|
evas_object_polygon_point_add(rect, obj_geom.x, obj_geom.y);
|
|
|
|
evas_object_polygon_point_add(rect, obj_geom.x + obj_geom.w, obj_geom.y);
|
|
|
|
evas_object_polygon_point_add(rect, obj_geom.x + obj_geom.w, obj_geom.y + obj_geom.h);
|
|
|
|
evas_object_polygon_point_add(rect, obj_geom.x, obj_geom.y + obj_geom.h);
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Evas_Coord w = 0, h = 0;
|
|
|
|
evas_output_size_get(obj, &w, &h);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
evas_object_polygon_point_add(rect, 0, 0);
|
|
|
|
evas_object_polygon_point_add(rect, w, 0);
|
|
|
|
evas_object_polygon_point_add(rect, w, h);
|
|
|
|
evas_object_polygon_point_add(rect, 0, h);
|
|
|
|
}
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
/* Put the object as high as possible. */
|
|
|
|
evas_object_layer_set(rect, EVAS_LAYER_MAX);
|
|
|
|
evas_object_color_set(rect, HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B, HIGHLIGHT_A);
|
|
|
|
evas_object_show(rect);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
/* Add Timer for fade and a callback to delete timer on obj del */
|
|
|
|
Ecore_Animator *t = ecore_animator_add(_obj_highlight_fade, rect);
|
|
|
|
evas_object_event_callback_add(rect, EVAS_CALLBACK_DEL, _obj_highlight_del, t);
|
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_obj_highlight_cb)
|
|
|
|
|
2017-06-25 01:02:19 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint64_t ptr64;
|
|
|
|
Eina_Debug_Session *session;
|
|
|
|
Evas_Object *snapshot;
|
|
|
|
int cid;
|
|
|
|
} Screenshot_Async_Info;
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
static void
|
2017-06-25 01:02:19 -07:00
|
|
|
_screenshot_pixels_cb(void *data, Evas *e, void *event_info)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2017-06-25 01:02:19 -07:00
|
|
|
unsigned int hdr_size = sizeof(uint64_t) + 5 * sizeof(int);
|
|
|
|
Evas_Event_Render_Post *post = event_info;
|
|
|
|
Screenshot_Async_Info *info = data;
|
|
|
|
Evas_Object *snapshot = info->snapshot;
|
2017-05-27 10:43:23 -07:00
|
|
|
struct tm *t = NULL;
|
|
|
|
time_t now = time(NULL);
|
|
|
|
unsigned char *resp = NULL, *tmp;
|
2017-06-25 01:02:19 -07:00
|
|
|
const void *pixels;
|
2017-06-03 12:17:56 -07:00
|
|
|
int w, h, val;
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-25 01:02:19 -07:00
|
|
|
// Nothing was updated, so let's not bother sending nothingness
|
|
|
|
if (!post->updated_area) return;
|
|
|
|
pixels = evas_object_image_data_get(snapshot, EINA_FALSE);
|
|
|
|
if (!pixels) return;
|
|
|
|
evas_object_geometry_get(snapshot, NULL, NULL, &w, &h);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
t = localtime(&now);
|
|
|
|
t->tm_zone = NULL;
|
|
|
|
|
|
|
|
resp = tmp = malloc(hdr_size + (w * h * sizeof(int)));
|
2017-06-03 12:17:56 -07:00
|
|
|
t->tm_sec = SWAP_32(t->tm_sec);
|
|
|
|
t->tm_min = SWAP_32(t->tm_min);
|
|
|
|
t->tm_hour = SWAP_32(t->tm_hour);
|
2017-06-25 01:02:19 -07:00
|
|
|
STORE(tmp, &info->ptr64, sizeof(uint64_t));
|
2017-05-27 10:43:23 -07:00
|
|
|
STORE(tmp, &t->tm_sec, sizeof(int));
|
|
|
|
STORE(tmp, &t->tm_min, sizeof(int));
|
|
|
|
STORE(tmp, &t->tm_hour, sizeof(int));
|
2017-06-03 12:17:56 -07:00
|
|
|
val = SWAP_32(w);
|
|
|
|
STORE(tmp, &val, sizeof(int));
|
|
|
|
val = SWAP_32(h);
|
|
|
|
STORE(tmp, &val, sizeof(int));
|
2017-06-25 01:02:19 -07:00
|
|
|
memcpy(tmp, pixels, (w * h * sizeof(int)));
|
2017-05-27 10:43:23 -07:00
|
|
|
|
2017-06-25 01:02:19 -07:00
|
|
|
eina_debug_session_send(info->session, info->cid, _win_screenshot_op, resp,
|
2017-05-27 10:43:23 -07:00
|
|
|
hdr_size + (w * h * sizeof(int)));
|
|
|
|
if (resp) free(resp);
|
2017-06-25 01:02:19 -07:00
|
|
|
evas_object_del(info->snapshot);
|
|
|
|
evas_event_callback_del_full(e, EVAS_CALLBACK_RENDER_POST, _screenshot_pixels_cb, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_main_loop_win_screenshot_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size)
|
|
|
|
{
|
|
|
|
uint64_t ptr64;
|
|
|
|
Screenshot_Async_Info *info;
|
|
|
|
Evas_Object *snapshot;
|
|
|
|
int w, h;
|
|
|
|
|
|
|
|
if (size != sizeof(uint64_t)) return;
|
|
|
|
memcpy(&ptr64, buffer, sizeof(ptr64));
|
|
|
|
Eo *e = (Eo *)SWAP_64(ptr64);
|
2017-11-07 11:14:42 -08:00
|
|
|
if (!efl_isa(e, EFL_CANVAS_INTERFACE)) return;
|
2017-06-25 01:02:19 -07:00
|
|
|
|
|
|
|
snapshot = evas_object_image_filled_add(e);
|
|
|
|
if (!snapshot) return;
|
|
|
|
evas_object_image_snapshot_set(snapshot, EINA_TRUE);
|
|
|
|
|
|
|
|
info = calloc(1, sizeof(*info));
|
|
|
|
info->ptr64 = ptr64;
|
|
|
|
info->snapshot = snapshot;
|
|
|
|
info->session = session;
|
|
|
|
info->cid = srcid;
|
|
|
|
|
|
|
|
evas_output_size_get(e, &w, &h);
|
|
|
|
evas_object_geometry_set(snapshot, 0, 0, w, h);
|
|
|
|
efl_gfx_visible_set(snapshot, EINA_TRUE);
|
|
|
|
evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, _screenshot_pixels_cb, info);
|
2017-05-07 09:15:19 -07:00
|
|
|
}
|
|
|
|
|
2017-05-30 04:24:49 -07:00
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_win_screenshot_cb)
|
|
|
|
|
2017-10-29 06:33:13 -07:00
|
|
|
static Eina_Bool
|
2017-11-29 01:15:32 -08:00
|
|
|
_only_manager(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
2017-10-29 06:33:13 -07:00
|
|
|
{
|
|
|
|
return efl_isa(data, EFL_UI_FOCUS_MANAGER_INTERFACE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-11-29 01:15:32 -08:00
|
|
|
_main_loop_focus_manager_list_cb(Eina_Debug_Session *session, int srcid, void *buffer EINA_UNUSED, int size EINA_UNUSED)
|
2017-10-29 06:33:13 -07:00
|
|
|
{
|
|
|
|
Eina_Iterator *obj_iterator, *manager_iterator;
|
|
|
|
Eina_Array *array;
|
|
|
|
Eo *obj;
|
|
|
|
|
|
|
|
array = eina_array_new(10);
|
|
|
|
obj_iterator = eo_objects_iterator_new();
|
|
|
|
manager_iterator = eina_iterator_filter_new(obj_iterator, _only_manager, NULL, NULL);
|
|
|
|
|
|
|
|
EINA_ITERATOR_FOREACH(manager_iterator, obj)
|
|
|
|
{
|
|
|
|
eina_array_push(array, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_debug_session_send(session, srcid, _focus_manager_list_op, array->data, array->count * sizeof(void*));
|
|
|
|
}
|
|
|
|
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_list_cb)
|
|
|
|
|
|
|
|
EAPI Efl_Dbg_Info*
|
|
|
|
clouseau_eo_info_find(Efl_Dbg_Info *root, const char *name)
|
|
|
|
{
|
|
|
|
Eina_Value_List eo_list;
|
|
|
|
Eina_List *n;
|
|
|
|
Efl_Dbg_Info *info;
|
|
|
|
|
|
|
|
if (!root) return NULL;
|
|
|
|
|
|
|
|
eina_value_pget(&(root->value), &eo_list);
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(eo_list.list, n, info)
|
|
|
|
{
|
|
|
|
if (!strcmp(info->name, name))
|
|
|
|
{
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_List*
|
|
|
|
_fetch_children(Efl_Ui_Focus_Manager *m)
|
|
|
|
{
|
|
|
|
Efl_Dbg_Info *manager_data, *children_data, *root;
|
|
|
|
Eina_List *lst = NULL, *n;
|
|
|
|
Eina_Value_List result;
|
|
|
|
Efl_Dbg_Info *elem;
|
|
|
|
|
|
|
|
root = EFL_DBG_INFO_LIST_APPEND(NULL, "Root");
|
|
|
|
|
|
|
|
efl_dbg_info_get(m, root);
|
|
|
|
|
|
|
|
manager_data = clouseau_eo_info_find(root, "Efl.Ui.Focus.Manager");
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(manager_data, NULL);
|
|
|
|
|
|
|
|
children_data = clouseau_eo_info_find(manager_data, "children");
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(children_data, NULL);
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_get(&children_data->value) == EINA_VALUE_TYPE_LIST, NULL);
|
|
|
|
|
|
|
|
eina_value_pget(&children_data->value, &result);
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(result.list, n, elem)
|
|
|
|
{
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_get(&elem->value) == EINA_VALUE_TYPE_UINT64, NULL);
|
|
|
|
eina_value_get(&elem->value, &ptr);
|
|
|
|
|
|
|
|
lst = eina_list_append(lst, ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
efl_dbg_info_free(root);
|
|
|
|
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2017-11-29 01:15:32 -08:00
|
|
|
_main_loop_focus_manager_detail_cb(Eina_Debug_Session *session, int srcid, void *buffer, int size EINA_UNUSED)
|
2017-10-29 06:33:13 -07:00
|
|
|
{
|
|
|
|
Clouseau_Focus_Manager_Data *res;
|
|
|
|
uint64_t ptr64;
|
|
|
|
Eo *elem, *manager;
|
|
|
|
|
|
|
|
if (!manager_details) _init_data_descriptors();
|
|
|
|
|
|
|
|
memcpy(&ptr64, buffer, sizeof(ptr64));
|
|
|
|
manager = (Eo *)SWAP_64(ptr64);
|
|
|
|
if (!efl_isa(manager, EFL_UI_FOCUS_MANAGER_INTERFACE)) return EINA_TRUE;
|
|
|
|
|
|
|
|
Eina_List *children = _fetch_children(manager);
|
|
|
|
|
|
|
|
res = alloca(sizeof(Clouseau_Focus_Manager_Data));
|
|
|
|
res->class_name = efl_class_name_get(manager);
|
|
|
|
res->relations = NULL;
|
|
|
|
res->focused = efl_ui_focus_manager_focus_get(manager);
|
|
|
|
res->redirect_manager = efl_ui_focus_manager_redirect_get(manager);
|
|
|
|
|
|
|
|
EINA_LIST_FREE(children, elem)
|
|
|
|
{
|
|
|
|
Clouseau_Focus_Relation *crel = calloc(1, sizeof(Clouseau_Focus_Relation));
|
|
|
|
Efl_Ui_Focus_Relations *rel;
|
|
|
|
|
|
|
|
rel = efl_ui_focus_manager_fetch(manager, elem);
|
2017-11-10 00:00:48 -08:00
|
|
|
if (rel)
|
|
|
|
{
|
|
|
|
memcpy(&crel->relation, rel, sizeof(Efl_Ui_Focus_Relations));
|
|
|
|
crel->class_name = efl_class_name_get(elem);
|
2017-10-29 06:33:13 -07:00
|
|
|
|
2017-11-10 00:00:48 -08:00
|
|
|
res->relations = eina_list_append(res->relations, crel);
|
2017-10-29 06:33:13 -07:00
|
|
|
|
2017-11-10 00:00:48 -08:00
|
|
|
free(rel);
|
|
|
|
}
|
2017-10-29 06:33:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int blob_size;
|
|
|
|
void *blob = eet_data_descriptor_encode(manager_details, res, &blob_size);
|
|
|
|
|
|
|
|
Clouseau_Focus_Manager_Data *aaah = eet_data_descriptor_decode(manager_details, blob, blob_size);
|
|
|
|
|
|
|
|
if (eina_list_count(aaah->relations) != eina_list_count(res->relations)) abort();
|
|
|
|
|
|
|
|
eina_debug_session_send(session, srcid, _focus_manager_detail_op, blob, blob_size);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
WRAPPER_TO_XFER_MAIN_LOOP(_focus_manager_detail_cb)
|
|
|
|
|
2017-06-03 12:28:06 -07:00
|
|
|
EINA_DEBUG_OPCODES_ARRAY_DEFINE(_debug_ops,
|
2017-06-03 11:39:55 -07:00
|
|
|
{"Clouseau/Object_Introspection/snapshot_start", &_snapshot_start_op, &_snapshot_start_cb},
|
|
|
|
{"Clouseau/Object_Introspection/snapshot_done", &_snapshot_done_op, NULL},
|
|
|
|
{"Clouseau/Eo/classes_ids_get", &_klids_get_op, NULL},
|
|
|
|
{"Clouseau/Eo/objects_ids_get", &_eoids_get_op, NULL},
|
|
|
|
{"Clouseau/Eolian/object/info_get", &_obj_info_op, &_obj_info_req_cb},
|
|
|
|
{"Clouseau/Evas/object/highlight", &_obj_highlight_op, &_obj_highlight_cb},
|
|
|
|
{"Clouseau/Evas/window/screenshot", &_win_screenshot_op, &_win_screenshot_cb},
|
2017-10-29 06:33:13 -07:00
|
|
|
{"Clouseau/Elementary_Focus/list", &_focus_manager_list_op, &_focus_manager_list_cb},
|
|
|
|
{"Clouseau/Elementary_Focus/detail", &_focus_manager_detail_op, &_focus_manager_detail_cb},
|
2017-05-07 09:15:19 -07:00
|
|
|
{NULL, NULL, NULL}
|
2017-06-03 12:28:06 -07:00
|
|
|
);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
clouseau_debug_init(void)
|
|
|
|
{
|
|
|
|
eina_init();
|
2017-05-27 10:43:23 -07:00
|
|
|
eolian_init();
|
|
|
|
evas_init();
|
|
|
|
|
2018-02-04 09:46:34 -08:00
|
|
|
eos = eolian_new();
|
2017-09-27 13:55:14 -07:00
|
|
|
_eolian_kls_hash = eina_hash_string_superfast_new(NULL);
|
|
|
|
|
2018-02-04 09:46:34 -08:00
|
|
|
eolian_system_directory_scan(eos);
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eolian_all_eo_files_parse(eos), EINA_FALSE);
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eolian_all_eot_files_parse(eos), EINA_FALSE);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
2017-06-03 12:28:06 -07:00
|
|
|
eina_debug_opcodes_register(NULL, _debug_ops(), NULL, NULL);
|
2017-05-07 09:15:19 -07:00
|
|
|
|
|
|
|
printf("%s - In\n", __FUNCTION__);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
clouseau_debug_shutdown(void)
|
|
|
|
{
|
2017-05-27 10:43:23 -07:00
|
|
|
evas_shutdown();
|
|
|
|
eolian_shutdown();
|
2017-05-07 09:15:19 -07:00
|
|
|
eina_shutdown();
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
EAPI void *
|
|
|
|
eo_debug_eoids_request_prepare(int *size, ...)
|
|
|
|
{
|
|
|
|
va_list list;
|
|
|
|
uint64_t kl;
|
|
|
|
int nb_kls = 0, max_kls = 0;
|
|
|
|
char *buf = NULL;
|
|
|
|
va_start(list, size);
|
|
|
|
kl = va_arg(list, uint64_t);
|
|
|
|
while (kl)
|
|
|
|
{
|
|
|
|
nb_kls++;
|
|
|
|
if (max_kls < nb_kls)
|
|
|
|
{
|
|
|
|
max_kls += 10;
|
|
|
|
buf = realloc(buf, max_kls * sizeof(uint64_t));
|
|
|
|
}
|
|
|
|
char *tmp = buf + (nb_kls-1) * sizeof(uint64_t);
|
2017-06-03 12:17:56 -07:00
|
|
|
kl = SWAP_64(kl);
|
2017-05-27 10:43:23 -07:00
|
|
|
STORE(tmp, &kl, sizeof(uint64_t));
|
|
|
|
kl = va_arg(list, uint64_t);
|
|
|
|
}
|
2017-05-30 05:37:36 -07:00
|
|
|
va_end(list);
|
2017-05-27 10:43:23 -07:00
|
|
|
*size = nb_kls * sizeof(uint64_t);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2017-05-30 04:24:49 -07:00
|
|
|
eo_debug_eoids_extract(void *buffer, int size, Eo_Debug_Object_Extract_Cb cb, void *data)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
|
|
|
if (!buffer || !size || !cb) return;
|
|
|
|
char *buf = buffer;
|
|
|
|
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
uint64_t obj, kl, parent;
|
|
|
|
EXTRACT(buf, &obj, sizeof(uint64_t));
|
|
|
|
EXTRACT(buf, &kl, sizeof(uint64_t));
|
|
|
|
EXTRACT(buf, &parent, sizeof(uint64_t));
|
2017-06-03 12:17:56 -07:00
|
|
|
cb(data, SWAP_64(obj), SWAP_64(kl), SWAP_64(parent));
|
2017-05-27 10:43:23 -07:00
|
|
|
size -= (3 * sizeof(uint64_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
eo_debug_klids_extract(void *buffer, int size, Eo_Debug_Class_Extract_Cb cb, void *data)
|
|
|
|
{
|
|
|
|
if (!buffer || !size || !cb) return;
|
|
|
|
char *buf = buffer;
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
uint64_t kl;
|
|
|
|
char *name;
|
|
|
|
EXTRACT(buf, &kl, sizeof(uint64_t));
|
|
|
|
name = buf;
|
2017-06-03 12:17:56 -07:00
|
|
|
cb(data, SWAP_64(kl), buf);
|
2017-05-27 10:43:23 -07:00
|
|
|
buf += (strlen(name) + 1);
|
|
|
|
size -= (strlen(name) + 1 + sizeof(uint64_t));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
eolian_debug_object_information_free(Eolian_Debug_Object_Information *main)
|
|
|
|
{
|
|
|
|
Eolian_Debug_Class *kl;
|
|
|
|
if (!main) return;
|
|
|
|
EINA_LIST_FREE(main->classes, kl)
|
|
|
|
{
|
|
|
|
Eolian_Debug_Function *func;
|
|
|
|
EINA_LIST_FREE(kl->functions, func)
|
|
|
|
{
|
|
|
|
Eolian_Debug_Parameter *param;
|
|
|
|
EINA_LIST_FREE(func->params, param)
|
|
|
|
{
|
|
|
|
if (param->value.type == EOLIAN_DEBUG_STRING)
|
|
|
|
eina_stringshare_del((char *)param->value.value.value);
|
|
|
|
free(param);
|
|
|
|
}
|
|
|
|
free(func);
|
|
|
|
}
|
|
|
|
free(kl);
|
|
|
|
}
|
|
|
|
free(main);
|
|
|
|
}
|
|
|
|
|
2017-06-18 00:10:40 -07:00
|
|
|
static int
|
2018-02-04 09:46:34 -08:00
|
|
|
_complex_buffer_decode(char *buffer, const Eolian_Type *eo_type,
|
2017-06-18 00:10:40 -07:00
|
|
|
Eolian_Debug_Value *v)
|
|
|
|
{
|
|
|
|
Eina_List *l = NULL;
|
|
|
|
int size = 0, count;
|
|
|
|
Eolian_Debug_Basic_Type type;
|
|
|
|
|
|
|
|
v->type = EOLIAN_DEBUG_LIST;
|
|
|
|
memcpy(&count, buffer, 4);
|
|
|
|
count = SWAP_32(count);
|
|
|
|
buffer += 4;
|
|
|
|
size += 4;
|
|
|
|
|
2018-02-04 09:46:34 -08:00
|
|
|
if (count > 0) type = _eolian_type_resolve(eolian_type_base_type_get(eo_type));
|
2017-06-18 00:10:40 -07:00
|
|
|
|
|
|
|
while (count > 0)
|
|
|
|
{
|
|
|
|
Eolian_Debug_Value *v2 = calloc(1, sizeof(*v2));
|
|
|
|
v2->type = type;
|
2017-09-27 13:55:14 -07:00
|
|
|
EXTRACT(buffer, &(v2->value), debug_types[type].size);
|
2017-06-18 00:10:40 -07:00
|
|
|
v2->value = SWAP_64(v2->value);
|
2017-09-27 13:55:14 -07:00
|
|
|
size += debug_types[type].size;
|
2017-06-18 00:10:40 -07:00
|
|
|
l = eina_list_append(l, v2);
|
|
|
|
count--;
|
|
|
|
}
|
|
|
|
v->complex_type_values = l;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2017-05-27 10:43:23 -07:00
|
|
|
/*
|
|
|
|
* receive buffer of the following format:
|
|
|
|
* Eo *pointer (uint64_t)
|
|
|
|
* followed by list of
|
|
|
|
* class_name, function. if class_name='\0' this function belongs to last correct class_name
|
|
|
|
*/
|
|
|
|
EAPI Eolian_Debug_Object_Information *
|
|
|
|
eolian_debug_object_information_decode(char *buffer, unsigned int size)
|
|
|
|
{
|
|
|
|
if (size < sizeof(uint64_t)) return NULL;
|
|
|
|
Eolian_Debug_Object_Information *ret = calloc(1, sizeof(*ret));
|
|
|
|
Eolian_Debug_Class *kl = NULL;
|
|
|
|
|
|
|
|
//get the Eo* pointer
|
|
|
|
EXTRACT(buffer, &(ret->obj), sizeof(uint64_t));
|
2017-06-03 12:17:56 -07:00
|
|
|
ret->obj = SWAP_64(ret->obj);
|
2017-05-27 10:43:23 -07:00
|
|
|
size -= sizeof(uint64_t);
|
|
|
|
|
|
|
|
while (size > 0)
|
|
|
|
{
|
2017-05-30 05:37:36 -07:00
|
|
|
Eolian_Debug_Function *func;
|
|
|
|
Eolian_Function_Parameter *eo_param;
|
|
|
|
Eina_Iterator *itr;
|
2017-06-18 00:10:40 -07:00
|
|
|
const Eolian_Type *eo_type;
|
2017-05-27 10:43:23 -07:00
|
|
|
int len = strlen(buffer) + 1;
|
|
|
|
if (len > 1) // if class_name is not NULL, we begin a new class
|
|
|
|
{
|
|
|
|
kl = calloc(1, sizeof(*kl));
|
2018-02-04 09:46:34 -08:00
|
|
|
kl->ekl = eolian_class_get_by_name((Eolian_Unit*) eos, buffer);
|
2017-05-27 10:43:23 -07:00
|
|
|
ret->classes = eina_list_append(ret->classes, kl);
|
|
|
|
}
|
2017-06-18 00:10:40 -07:00
|
|
|
if (!kl)
|
|
|
|
{
|
|
|
|
printf("Class %s not found!\n", buffer);
|
|
|
|
goto error;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
|
2017-05-30 05:37:36 -07:00
|
|
|
func = calloc(1, sizeof(*func));
|
2017-09-27 13:55:14 -07:00
|
|
|
// printf("Class name = %s function = %s\n", eolian_class_name_get(kl->ekl), buffer);
|
2017-05-27 10:43:23 -07:00
|
|
|
kl->functions = eina_list_append(kl->functions, func);
|
|
|
|
func->efunc = eolian_class_function_get_by_name(kl->ekl, buffer, EOLIAN_PROP_GET);
|
|
|
|
if(!func->efunc)
|
|
|
|
{
|
|
|
|
printf("Function %s not found!\n", buffer);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
len = strlen(buffer) + 1;
|
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
|
|
|
|
//go over function params using eolian
|
2017-05-30 05:37:36 -07:00
|
|
|
itr = eolian_property_values_get(func->efunc, EOLIAN_PROP_GET);
|
2017-05-27 10:43:23 -07:00
|
|
|
EINA_ITERATOR_FOREACH(itr, eo_param)
|
|
|
|
{
|
2017-06-18 00:10:40 -07:00
|
|
|
eo_type = eolian_parameter_type_get(eo_param);
|
2018-02-04 09:46:34 -08:00
|
|
|
Eolian_Debug_Basic_Type type = _eolian_type_resolve(eo_type);
|
2017-05-27 10:43:23 -07:00
|
|
|
|
|
|
|
if (type)
|
|
|
|
{
|
|
|
|
Eolian_Debug_Parameter *p = calloc(1, sizeof(*p));
|
|
|
|
p->eparam = eo_param;
|
|
|
|
p->value.type = type;
|
|
|
|
if (type == EOLIAN_DEBUG_STRING)
|
|
|
|
{
|
|
|
|
len = strlen(buffer) + 1;
|
|
|
|
p->value.value.value = (uint64_t) eina_stringshare_add(buffer);
|
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-18 00:10:40 -07:00
|
|
|
uint64_t value = 0;;
|
2017-09-27 13:55:14 -07:00
|
|
|
EXTRACT(buffer, &value, debug_types[type].size);
|
2017-06-03 12:17:56 -07:00
|
|
|
p->value.value.value = SWAP_64(value);
|
2017-09-27 13:55:14 -07:00
|
|
|
size -= debug_types[type].size;
|
|
|
|
if (type == EOLIAN_DEBUG_LIST)
|
2017-06-18 00:10:40 -07:00
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
len = _complex_buffer_decode(buffer, eo_type, &(p->value));
|
2017-06-18 00:10:40 -07:00
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
func->params = eina_list_append(func->params, p);
|
|
|
|
}
|
2017-06-18 00:10:40 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("Unknown parameter type %s\n", eolian_type_full_name_get(eo_type));
|
|
|
|
goto error;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
2017-06-18 00:10:40 -07:00
|
|
|
func->ret.etype = eo_type = eolian_function_return_type_get(
|
2017-05-27 10:43:23 -07:00
|
|
|
func->efunc, EOLIAN_PROP_GET);
|
2017-06-26 01:21:25 -07:00
|
|
|
func->ret.value.type = EOLIAN_DEBUG_VOID;
|
2017-06-18 00:10:40 -07:00
|
|
|
if(eo_type)
|
2017-05-27 10:43:23 -07:00
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
Eolian_Debug_Basic_Type type = _eolian_type_resolve(eo_type);
|
2017-05-27 10:43:23 -07:00
|
|
|
if (type)
|
|
|
|
{
|
|
|
|
func->ret.value.type = type;
|
|
|
|
if (type == EOLIAN_DEBUG_STRING)
|
|
|
|
{
|
|
|
|
len = strlen(buffer) + 1;
|
|
|
|
func->ret.value.value.value = (uint64_t) eina_stringshare_add(buffer);
|
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-06-03 12:17:56 -07:00
|
|
|
uint64_t value;
|
2017-09-27 13:55:14 -07:00
|
|
|
EXTRACT(buffer, &value, debug_types[type].size);
|
2017-06-03 12:17:56 -07:00
|
|
|
func->ret.value.value.value = SWAP_64(value);
|
2017-09-27 13:55:14 -07:00
|
|
|
size -= debug_types[type].size;
|
|
|
|
if (type == EOLIAN_DEBUG_LIST)
|
2017-06-18 00:10:40 -07:00
|
|
|
{
|
2018-02-04 09:46:34 -08:00
|
|
|
len = _complex_buffer_decode(buffer, eo_type, &(func->ret.value));
|
2017-06-18 00:10:40 -07:00
|
|
|
buffer += len;
|
|
|
|
size -= len;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
}
|
2017-06-18 00:10:40 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("Unknown parameter type %s\n", eolian_type_full_name_get(eo_type));
|
|
|
|
goto error;
|
|
|
|
}
|
2017-05-27 10:43:23 -07:00
|
|
|
}
|
|
|
|
eina_iterator_free(itr);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
error:
|
|
|
|
eolian_debug_object_information_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Evas_Debug_Screenshot *
|
|
|
|
evas_debug_screenshot_decode(char *buffer, unsigned int size)
|
|
|
|
{
|
|
|
|
Evas_Debug_Screenshot *s = NULL;
|
|
|
|
uint64_t obj;
|
|
|
|
int tm_sec, tm_min, tm_hour, w, h;
|
|
|
|
unsigned int hdr_size = sizeof(uint64_t) + 5 * sizeof(int);
|
|
|
|
if (size < hdr_size) return NULL;
|
|
|
|
EXTRACT(buffer, &obj, sizeof(uint64_t));
|
|
|
|
EXTRACT(buffer, &tm_sec, sizeof(int));
|
|
|
|
EXTRACT(buffer, &tm_min, sizeof(int));
|
|
|
|
EXTRACT(buffer, &tm_hour, sizeof(int));
|
|
|
|
EXTRACT(buffer, &w, sizeof(int));
|
|
|
|
EXTRACT(buffer, &h, sizeof(int));
|
|
|
|
size -= hdr_size;
|
|
|
|
if (size != (w * h * sizeof(int))) return NULL;
|
|
|
|
|
|
|
|
s = calloc(1, sizeof(*s));
|
2017-06-03 12:17:56 -07:00
|
|
|
s->obj = SWAP_64(obj);
|
|
|
|
s->w = SWAP_32(w);
|
|
|
|
s->h = SWAP_32(h);
|
|
|
|
s->tm_sec = SWAP_32(tm_sec);
|
|
|
|
s->tm_min = SWAP_32(tm_min);
|
|
|
|
s->tm_hour = SWAP_32(tm_hour);
|
2017-05-27 10:43:23 -07:00
|
|
|
s->img = malloc(size);
|
|
|
|
s->img_size = size;
|
|
|
|
memcpy(s->img, buffer, size);
|
|
|
|
return s;
|
|
|
|
}
|