2015-05-13 23:41:11 -07:00
|
|
|
/* EINA - EFL data type library
|
|
|
|
* Copyright (C) 2015 Carsten Haitzler
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library;
|
|
|
|
* if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2016-11-26 21:48:10 -08:00
|
|
|
# ifndef _GNU_SOURCE
|
|
|
|
# define _GNU_SOURCE 1
|
|
|
|
# endif
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2016-11-26 21:48:10 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifdef HAVE_SYS_EPOLL_H
|
|
|
|
# include <sys/epoll.h>
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
# include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
|
|
# include <sys/un.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ARPA_INET_H
|
|
|
|
# include <arpa/inet.h>
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifdef _WIN32
|
2017-10-01 09:07:02 -07:00
|
|
|
# include <ws2tcpip.h>
|
2019-05-16 10:48:59 -07:00
|
|
|
# include <evil_private.h> /* fcntl */
|
2017-06-04 06:11:16 -07:00
|
|
|
#endif
|
|
|
|
|
2017-09-14 09:59:02 -07:00
|
|
|
#include "eina_alloca.h"
|
2015-05-04 19:35:16 -07:00
|
|
|
#include "eina_debug.h"
|
2017-09-11 04:45:18 -07:00
|
|
|
#include "eina_cpu.h"
|
2015-05-08 00:55:12 -07:00
|
|
|
#include "eina_types.h"
|
2016-11-26 21:48:10 -08:00
|
|
|
#include "eina_list.h"
|
|
|
|
#include "eina_mempool.h"
|
|
|
|
#include "eina_util.h"
|
|
|
|
#include "eina_evlog.h"
|
|
|
|
#include "eina_hash.h"
|
2017-05-04 00:17:05 -07:00
|
|
|
#include "eina_stringshare.h"
|
2016-11-26 21:48:10 -08:00
|
|
|
#include "eina_debug_private.h"
|
2018-08-20 09:59:15 -07:00
|
|
|
#include "eina_vpath.h"
|
|
|
|
#include "eina_internal.h"
|
2015-05-04 19:35:16 -07:00
|
|
|
|
2017-06-08 13:36:23 -07:00
|
|
|
#ifdef EINA_HAVE_PTHREAD_SETNAME
|
|
|
|
# ifndef __linux__
|
|
|
|
# include <pthread_np.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#if defined(__CYGWIN__) || defined (_WIN32)
|
2016-11-26 21:48:10 -08:00
|
|
|
# define LIBEXT ".dll"
|
|
|
|
#else
|
|
|
|
# define LIBEXT ".so"
|
|
|
|
#endif
|
|
|
|
|
2017-06-03 09:33:58 -07:00
|
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
|
|
#define SWAP_64(x) x
|
|
|
|
#define SWAP_32(x) x
|
|
|
|
#define SWAP_16(x) x
|
|
|
|
#else
|
|
|
|
#define SWAP_64(x) eina_swap64(x)
|
|
|
|
#define SWAP_32(x) eina_swap32(x)
|
|
|
|
#define SWAP_16(x) eina_swap16(x)
|
|
|
|
#endif
|
|
|
|
|
2015-05-04 19:35:16 -07:00
|
|
|
// yes - a global debug spinlock. i expect contention to be low for now, and
|
|
|
|
// when needed we can split this up into mroe locks to reduce contention when
|
|
|
|
// and if that day comes
|
|
|
|
Eina_Spinlock _eina_debug_lock;
|
|
|
|
|
2017-05-16 00:16:22 -07:00
|
|
|
#ifdef __linux__
|
|
|
|
extern char *__progname;
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
extern Eina_Bool eina_module_init(void);
|
|
|
|
extern Eina_Bool eina_mempool_init(void);
|
|
|
|
extern Eina_Bool eina_list_init(void);
|
|
|
|
|
|
|
|
extern Eina_Spinlock _eina_debug_thread_lock;
|
2018-06-15 13:51:03 -07:00
|
|
|
static Eina_List *sessions;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
static Eina_Bool _debug_disabled = EINA_FALSE;
|
|
|
|
|
|
|
|
/* Local session */
|
|
|
|
/* __thread here to allow debuggers to be master and slave by using two different threads */
|
|
|
|
static Eina_Debug_Session *_last_local_session = NULL;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const Eina_Debug_Opcode *ops;
|
|
|
|
Eina_Debug_Opcode_Status_Cb status_cb;
|
2017-05-18 22:59:56 -07:00
|
|
|
void *status_data;
|
2017-06-08 15:09:38 -07:00
|
|
|
Eina_Bool sent : 1;
|
2016-11-26 21:48:10 -08:00
|
|
|
} _opcode_reply_info;
|
|
|
|
|
|
|
|
struct _Eina_Debug_Session
|
|
|
|
{
|
|
|
|
Eina_List **cbs; /* Table of callbacks lists indexed by opcode id */
|
|
|
|
Eina_List *opcode_reply_infos;
|
|
|
|
Eina_Debug_Dispatch_Cb dispatch_cb; /* Session dispatcher */
|
2017-05-18 22:59:56 -07:00
|
|
|
void *data; /* User data */
|
2016-11-26 21:48:10 -08:00
|
|
|
int cbs_length; /* cbs table size */
|
2017-05-25 03:26:41 -07:00
|
|
|
int fd; /* File descriptor */
|
2018-07-02 11:14:32 -07:00
|
|
|
Eina_Lock lock; /* deletion lock */
|
|
|
|
Eina_Bool deleted : 1; /* set if session is dead */
|
2016-11-26 21:48:10 -08:00
|
|
|
};
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifndef _WIN32
|
2017-05-04 00:17:05 -07:00
|
|
|
static void _opcodes_register_all(Eina_Debug_Session *session);
|
2017-06-04 06:11:16 -07:00
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
static void _thread_start(Eina_Debug_Session *session);
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API int
|
2017-05-30 04:14:59 -07:00
|
|
|
eina_debug_session_send(Eina_Debug_Session *session, int dest, int op, void *data, int size)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
|
|
|
Eina_Debug_Packet_Header hdr;
|
|
|
|
|
|
|
|
if (!session) return -1;
|
|
|
|
if (op == EINA_DEBUG_OPCODE_INVALID) return -1;
|
|
|
|
/* Preparation of the packet header */
|
2017-06-03 09:33:58 -07:00
|
|
|
hdr.size = SWAP_32(size + sizeof(Eina_Debug_Packet_Header));
|
|
|
|
hdr.opcode = SWAP_32(op);
|
|
|
|
hdr.cid = SWAP_32(dest);
|
2017-05-25 03:26:41 -07:00
|
|
|
e_debug("socket: %d / opcode %X / bytes to send: %d",
|
2017-06-03 09:33:58 -07:00
|
|
|
session->fd, op, size + sizeof(*hdr));
|
2017-05-04 00:17:05 -07:00
|
|
|
#ifndef _WIN32
|
2017-05-25 03:26:41 -07:00
|
|
|
eina_spinlock_take(&_eina_debug_lock);
|
|
|
|
/* Sending header */
|
2017-09-28 19:39:39 -07:00
|
|
|
if (write(session->fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto err;
|
2017-05-25 03:26:41 -07:00
|
|
|
/* Sending payload */
|
2017-09-28 19:39:39 -07:00
|
|
|
if (size)
|
|
|
|
{
|
|
|
|
if (write(session->fd, data, size) != size) goto err;
|
|
|
|
}
|
2017-05-25 03:26:41 -07:00
|
|
|
eina_spinlock_release(&_eina_debug_lock);
|
2017-06-04 06:11:16 -07:00
|
|
|
#else
|
|
|
|
(void)data;
|
2017-05-04 00:17:05 -07:00
|
|
|
#endif
|
2017-06-03 09:33:58 -07:00
|
|
|
return size;
|
2017-09-28 19:39:39 -07:00
|
|
|
#ifndef _WIN32
|
|
|
|
err:
|
2017-10-01 00:04:35 -07:00
|
|
|
eina_spinlock_release(&_eina_debug_lock);
|
2017-09-28 19:39:39 -07:00
|
|
|
e_debug("Cannot write to eina debug session");
|
|
|
|
return 0;
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifndef _WIN32
|
2016-11-26 21:48:10 -08:00
|
|
|
static void
|
|
|
|
_daemon_greet(Eina_Debug_Session *session)
|
|
|
|
{
|
|
|
|
/* say hello to our debug daemon - tell them our PID and protocol
|
|
|
|
version we speak */
|
|
|
|
/* Version + Pid + App name */
|
2017-05-16 00:16:22 -07:00
|
|
|
#ifdef __linux__
|
|
|
|
char *app_name = __progname;
|
|
|
|
#else
|
|
|
|
char *app_name = NULL;
|
|
|
|
#endif
|
|
|
|
int size = 8 + (app_name ? strlen(app_name) : 0) + 1;
|
2016-11-26 21:48:10 -08:00
|
|
|
unsigned char *buf = alloca(size);
|
2017-06-03 09:33:58 -07:00
|
|
|
int version = SWAP_32(1); // version of protocol we speak
|
2016-11-26 21:48:10 -08:00
|
|
|
int pid = getpid();
|
2017-06-03 09:33:58 -07:00
|
|
|
pid = SWAP_32(pid);
|
2016-11-26 21:48:10 -08:00
|
|
|
memcpy(buf + 0, &version, 4);
|
|
|
|
memcpy(buf + 4, &pid, 4);
|
2017-05-16 00:16:22 -07:00
|
|
|
if (app_name)
|
|
|
|
memcpy(buf + 8, app_name, strlen(app_name) + 1);
|
2016-11-26 21:48:10 -08:00
|
|
|
else
|
|
|
|
buf[8] = '\0';
|
|
|
|
eina_debug_session_send(session, 0, EINA_DEBUG_OPCODE_HELLO, buf, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-05-25 01:10:53 -07:00
|
|
|
_packet_receive(Eina_Debug_Session *session, unsigned char **buffer)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-05-25 03:26:41 -07:00
|
|
|
unsigned char *packet_buf = NULL;
|
|
|
|
int rret = -1;
|
|
|
|
unsigned int size = 0;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2018-06-15 13:51:03 -07:00
|
|
|
rret = read(session->fd, &size, 4);
|
|
|
|
if (rret == 4)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-06-03 09:33:58 -07:00
|
|
|
size = SWAP_32(size);
|
2017-05-09 00:36:15 -07:00
|
|
|
if (size > EINA_DEBUG_MAX_PACKET_SIZE)
|
|
|
|
{
|
|
|
|
e_debug("Packet too big: %d. The maximum allowed is %d", size, EINA_DEBUG_MAX_PACKET_SIZE);
|
|
|
|
rret = -1;
|
|
|
|
goto end;
|
2017-05-04 00:17:05 -07:00
|
|
|
}
|
|
|
|
e_debug("Begin to receive a packet of %d bytes", size);
|
2016-11-26 21:48:10 -08:00
|
|
|
// allocate a buffer for the next bytes to receive
|
|
|
|
packet_buf = malloc(size);
|
|
|
|
if (packet_buf)
|
|
|
|
{
|
2017-05-25 03:26:41 -07:00
|
|
|
unsigned int cur_packet_size = 4;
|
|
|
|
memcpy(packet_buf, &size, 4);
|
2016-11-26 21:48:10 -08:00
|
|
|
/* Receive all the remaining packet bytes */
|
|
|
|
while (cur_packet_size < size)
|
|
|
|
{
|
2017-05-25 03:26:41 -07:00
|
|
|
rret = read(session->fd, packet_buf + cur_packet_size, size - cur_packet_size);
|
2017-05-04 00:17:05 -07:00
|
|
|
if (rret <= 0)
|
|
|
|
{
|
|
|
|
e_debug("Error on read: %d", rret);
|
|
|
|
perror("Read");
|
|
|
|
goto end;
|
|
|
|
}
|
2016-11-26 21:48:10 -08:00
|
|
|
cur_packet_size += rret;
|
|
|
|
}
|
|
|
|
*buffer = packet_buf;
|
|
|
|
rret = cur_packet_size;
|
2017-05-04 00:17:05 -07:00
|
|
|
e_debug("Received a packet of %d bytes", cur_packet_size);
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-16 00:16:22 -07:00
|
|
|
// we couldn't allocate memory for payload buffer
|
2016-11-26 21:48:10 -08:00
|
|
|
// internal memory limit error
|
2017-05-09 00:36:15 -07:00
|
|
|
e_debug("Cannot allocate %u bytes for op", size);
|
2016-11-26 21:48:10 -08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
e_debug("Invalid size read %i != %i", rret, size_sz);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
if (rret <= 0 && packet_buf) free(packet_buf);
|
|
|
|
return rret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2016-11-26 21:48:10 -08:00
|
|
|
eina_debug_disable()
|
|
|
|
{
|
|
|
|
_debug_disabled = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2016-11-26 21:48:10 -08:00
|
|
|
eina_debug_session_terminate(Eina_Debug_Session *session)
|
|
|
|
{
|
2017-03-05 23:22:02 -08:00
|
|
|
/* Close fd here so the thread terminates its own session by itself */
|
2016-11-26 21:48:10 -08:00
|
|
|
if (!session) return;
|
2017-05-25 03:26:41 -07:00
|
|
|
close(session->fd);
|
2018-07-02 11:14:32 -07:00
|
|
|
eina_lock_take(&session->lock);
|
|
|
|
if (session->deleted)
|
|
|
|
{
|
|
|
|
eina_lock_release(&session->lock);
|
|
|
|
free(session);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
session->deleted = 1;
|
|
|
|
eina_lock_release(&session->lock);
|
|
|
|
}
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2016-11-26 21:48:10 -08:00
|
|
|
eina_debug_session_dispatch_override(Eina_Debug_Session *session, Eina_Debug_Dispatch_Cb disp_cb)
|
|
|
|
{
|
|
|
|
if (!session) return;
|
|
|
|
if (!disp_cb) disp_cb = eina_debug_dispatch;
|
|
|
|
session->dispatch_cb = disp_cb;
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API Eina_Debug_Dispatch_Cb
|
2017-05-18 22:56:54 -07:00
|
|
|
eina_debug_session_dispatch_get(Eina_Debug_Session *session)
|
|
|
|
{
|
|
|
|
if (session) return session->dispatch_cb;
|
|
|
|
else return NULL;
|
|
|
|
}
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifndef _WIN32
|
2016-11-26 21:48:10 -08:00
|
|
|
static void
|
|
|
|
_static_opcode_register(Eina_Debug_Session *session,
|
|
|
|
int op_id, Eina_Debug_Cb cb)
|
|
|
|
{
|
|
|
|
if(session->cbs_length < op_id + 1)
|
|
|
|
{
|
|
|
|
int i = session->cbs_length;
|
|
|
|
session->cbs_length = op_id + 16;
|
|
|
|
session->cbs = realloc(session->cbs, session->cbs_length * sizeof(Eina_List *));
|
|
|
|
for(; i < session->cbs_length; i++) session->cbs[i] = NULL;
|
|
|
|
}
|
|
|
|
if (cb)
|
|
|
|
{
|
|
|
|
session->cbs[op_id] = eina_list_append(session->cbs[op_id], cb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Response of the daemon containing the ids of the requested opcodes.
|
|
|
|
* PTR64 + (opcode id)*
|
|
|
|
*/
|
2017-05-30 04:14:59 -07:00
|
|
|
static Eina_Bool
|
2016-11-26 21:48:10 -08:00
|
|
|
_callbacks_register_cb(Eina_Debug_Session *session, int src_id EINA_UNUSED, void *buffer, int size)
|
|
|
|
{
|
|
|
|
_opcode_reply_info *info = NULL, *info2;
|
|
|
|
Eina_List *itr;
|
|
|
|
int *os;
|
|
|
|
unsigned int count, i;
|
|
|
|
|
|
|
|
uint64_t info_64;
|
|
|
|
memcpy(&info_64, buffer, sizeof(uint64_t));
|
2017-08-02 17:08:04 -07:00
|
|
|
// cast to a ptr, so on 32bit we just take the lower 32bits and on 64
|
|
|
|
// we take all of it so we're fine
|
2018-11-08 13:14:58 -08:00
|
|
|
info = (_opcode_reply_info *)(uintptr_t)info_64;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-30 04:14:59 -07:00
|
|
|
if (!info) return EINA_FALSE;
|
2016-11-26 21:48:10 -08:00
|
|
|
EINA_LIST_FOREACH(session->opcode_reply_infos, itr, info2)
|
|
|
|
{
|
|
|
|
if (info2 == info)
|
|
|
|
{
|
|
|
|
os = (int *)((unsigned char *)buffer + sizeof(uint64_t));
|
|
|
|
count = (size - sizeof(uint64_t)) / sizeof(int);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2017-06-03 09:33:58 -07:00
|
|
|
int op = SWAP_32(os[i]);
|
|
|
|
if (info->ops[i].opcode_id) *(info->ops[i].opcode_id) = op;
|
|
|
|
_static_opcode_register(session, op, info->ops[i].cb);
|
|
|
|
e_debug("Opcode %s -> %d", info->ops[i].opcode_name, op);
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
2017-05-18 22:59:56 -07:00
|
|
|
if (info->status_cb) info->status_cb(info->status_data, EINA_TRUE);
|
2017-05-30 04:14:59 -07:00
|
|
|
return EINA_TRUE;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-30 04:14:59 -07:00
|
|
|
return EINA_FALSE;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
2017-06-04 06:11:16 -07:00
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
static void
|
|
|
|
_opcodes_registration_send(Eina_Debug_Session *session,
|
|
|
|
_opcode_reply_info *info)
|
|
|
|
{
|
|
|
|
unsigned char *buf;
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
int size = sizeof(uint64_t);
|
2017-06-08 15:09:38 -07:00
|
|
|
Eina_Bool already_sent;
|
|
|
|
|
|
|
|
eina_spinlock_take(&_eina_debug_lock);
|
|
|
|
already_sent = info->sent;
|
|
|
|
info->sent = EINA_TRUE;
|
|
|
|
eina_spinlock_release(&_eina_debug_lock);
|
|
|
|
if (already_sent) return;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-16 00:16:22 -07:00
|
|
|
while (info->ops[count].opcode_name)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
|
|
|
size += strlen(info->ops[count].opcode_name) + 1;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2017-06-01 09:59:40 -07:00
|
|
|
buf = malloc(size);
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-08-02 17:08:04 -07:00
|
|
|
// cast to a ptr, so on 32bit we just pad out the upper 32bits with 0
|
|
|
|
// and on 64bit we are fine as we use all of it
|
2017-06-04 06:11:16 -07:00
|
|
|
uint64_t info_64 = (uint64_t)(uintptr_t)info;
|
2016-11-26 21:48:10 -08:00
|
|
|
memcpy(buf, &info_64, sizeof(uint64_t));
|
|
|
|
int size_curr = sizeof(uint64_t);
|
|
|
|
|
|
|
|
count = 0;
|
2017-05-16 00:16:22 -07:00
|
|
|
while (info->ops[count].opcode_name)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
|
|
|
int len = strlen(info->ops[count].opcode_name) + 1;
|
|
|
|
memcpy(buf + size_curr, info->ops[count].opcode_name, len);
|
|
|
|
size_curr += len;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_debug_session_send(session, 0, EINA_DEBUG_OPCODE_REGISTER, buf, size);
|
2017-06-01 09:59:40 -07:00
|
|
|
free(buf);
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifndef _WIN32
|
2016-11-26 21:48:10 -08:00
|
|
|
static void
|
|
|
|
_opcodes_register_all(Eina_Debug_Session *session)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
_opcode_reply_info *info = NULL;
|
|
|
|
|
|
|
|
_static_opcode_register(session,
|
|
|
|
EINA_DEBUG_OPCODE_REGISTER, _callbacks_register_cb);
|
|
|
|
EINA_LIST_FOREACH(session->opcode_reply_infos, l, info)
|
|
|
|
_opcodes_registration_send(session, info);;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_opcodes_unregister_all(Eina_Debug_Session *session)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
int i;
|
|
|
|
_opcode_reply_info *info = NULL;
|
|
|
|
|
|
|
|
if (!session) return;
|
|
|
|
for (i = 0; i < session->cbs_length; i++)
|
|
|
|
eina_list_free(session->cbs[i]);
|
|
|
|
free(session->cbs);
|
2017-07-30 18:03:59 -07:00
|
|
|
session->cbs_length = 0;
|
2016-11-26 21:48:10 -08:00
|
|
|
session->cbs = NULL;
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(session->opcode_reply_infos, l, info)
|
|
|
|
{
|
|
|
|
const Eina_Debug_Opcode *op = info->ops;
|
|
|
|
while(!op->opcode_name)
|
|
|
|
{
|
|
|
|
if (op->opcode_id) *(op->opcode_id) = EINA_DEBUG_OPCODE_INVALID;
|
|
|
|
op++;
|
|
|
|
}
|
2017-05-18 22:59:56 -07:00
|
|
|
if (info->status_cb) info->status_cb(info->status_data, EINA_FALSE);
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LENGTH_OF_SOCKADDR_UN(s) \
|
|
|
|
(strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
|
|
|
|
#endif
|
|
|
|
|
2017-05-25 03:26:41 -07:00
|
|
|
static Eina_Debug_Session *
|
|
|
|
_session_create(int fd)
|
|
|
|
{
|
|
|
|
Eina_Debug_Session *session = calloc(1, sizeof(*session));
|
2017-07-28 17:59:59 -07:00
|
|
|
if (!session) return NULL;
|
2017-05-25 03:26:41 -07:00
|
|
|
session->dispatch_cb = eina_debug_dispatch;
|
|
|
|
session->fd = fd;
|
2018-07-02 11:14:32 -07:00
|
|
|
eina_lock_new(&session->lock);
|
2018-06-15 13:51:03 -07:00
|
|
|
sessions = eina_list_append(sessions, session);
|
2017-05-25 03:26:41 -07:00
|
|
|
// start the monitor thread
|
|
|
|
_thread_start(session);
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API Eina_Debug_Session *
|
2017-05-25 03:26:41 -07:00
|
|
|
eina_debug_remote_connect(int port)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct sockaddr_in server;
|
|
|
|
|
|
|
|
//Create socket
|
|
|
|
fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (fd < 0) goto err;
|
|
|
|
// set the socket to close when we exec things so they don't inherit it
|
|
|
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) goto err;
|
|
|
|
|
|
|
|
//Prepare the sockaddr_in structure
|
|
|
|
server.sin_family = AF_INET;
|
2017-07-23 02:40:04 -07:00
|
|
|
if (inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr) != 1) goto err;
|
2019-02-01 03:04:17 -08:00
|
|
|
server.sin_port = eina_htons(port);
|
2017-05-25 03:26:41 -07:00
|
|
|
|
|
|
|
if (connect(fd, (struct sockaddr *)&server, sizeof(server)) < 0)
|
|
|
|
{
|
|
|
|
perror("connect failed. Error");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return _session_create(fd);
|
|
|
|
err:
|
|
|
|
// some kind of connection failure here, so close a valid socket and
|
|
|
|
// get out of here
|
|
|
|
if (fd >= 0) close(fd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API Eina_Debug_Session *
|
2016-11-26 21:48:10 -08:00
|
|
|
eina_debug_local_connect(Eina_Bool is_master)
|
|
|
|
{
|
|
|
|
#ifndef _WIN32
|
|
|
|
int fd, socket_unix_len, curstate = 0;
|
|
|
|
struct sockaddr_un socket_unix;
|
2018-11-06 08:52:01 -08:00
|
|
|
char buf[sizeof(socket_unix.sun_path)];
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-25 03:26:41 -07:00
|
|
|
if (is_master) return eina_debug_remote_connect(REMOTE_SERVER_PORT);
|
|
|
|
|
2016-11-26 21:48:10 -08:00
|
|
|
// try this socket file - it will likely be:
|
|
|
|
// ~/.ecore/efl_debug/0
|
|
|
|
// or maybe
|
|
|
|
// /var/run/UID/.ecore/efl_debug/0
|
2018-08-20 09:59:15 -07:00
|
|
|
eina_vpath_resolve_snprintf(buf, sizeof(buf), "(:usr.run:)/%s/%s/%i",
|
2017-05-25 03:26:41 -07:00
|
|
|
LOCAL_SERVER_PATH, LOCAL_SERVER_NAME, LOCAL_SERVER_PORT);
|
2016-11-26 21:48:10 -08:00
|
|
|
// create the socket
|
|
|
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
|
|
if (fd < 0) goto err;
|
|
|
|
// set the socket to close when we exec things so they don't inherit it
|
|
|
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) goto err;
|
|
|
|
// set up some socket options on addr re-use
|
|
|
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
|
|
|
|
sizeof(curstate)) < 0)
|
|
|
|
goto err;
|
|
|
|
// sa that it's a unix socket and where the path is
|
2017-10-28 19:19:48 -07:00
|
|
|
memset(&socket_unix, 0, sizeof(socket_unix));
|
2016-11-26 21:48:10 -08:00
|
|
|
socket_unix.sun_family = AF_UNIX;
|
2018-11-06 08:52:01 -08:00
|
|
|
strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
|
|
|
|
socket_unix.sun_path[sizeof(socket_unix.sun_path) - 1] = 0;
|
2016-11-26 21:48:10 -08:00
|
|
|
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
|
|
|
|
// actually connect to efl_debugd service
|
|
|
|
if (connect(fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
|
|
|
|
goto err;
|
|
|
|
|
2017-05-25 03:26:41 -07:00
|
|
|
_last_local_session = _session_create(fd);
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-25 03:26:41 -07:00
|
|
|
return _last_local_session;
|
2016-11-26 21:48:10 -08:00
|
|
|
err:
|
|
|
|
// some kind of connection failure here, so close a valid socket and
|
|
|
|
// get out of here
|
|
|
|
if (fd >= 0) close(fd);
|
|
|
|
#else
|
2017-05-16 00:16:22 -07:00
|
|
|
(void) is_master;
|
2016-11-26 21:48:10 -08:00
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this is a DEDICATED debug thread to monitor the application so it works
|
|
|
|
// even if the mainloop is blocked or the app otherwise deadlocked in some
|
|
|
|
// way. this is an alternative to using external debuggers so we can get
|
|
|
|
// users or developers to get useful information about an app at all times
|
2017-06-04 06:11:16 -07:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
2016-11-26 21:48:10 -08:00
|
|
|
static void *
|
|
|
|
_monitor(void *_data)
|
|
|
|
{
|
2017-05-25 01:10:53 -07:00
|
|
|
Eina_Debug_Session *session = _data;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-25 22:52:52 -07:00
|
|
|
_daemon_greet(session);
|
|
|
|
_opcodes_register_all(session);
|
|
|
|
|
2016-11-26 21:48:10 -08:00
|
|
|
// set a name for this thread for system debugging
|
|
|
|
#ifdef EINA_HAVE_PTHREAD_SETNAME
|
|
|
|
# ifndef __linux__
|
|
|
|
pthread_set_name_np
|
|
|
|
# else
|
|
|
|
pthread_setname_np
|
|
|
|
# endif
|
|
|
|
(pthread_self(), "Edbg-mon");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// sit forever processing commands or timeouts in the debug monitor
|
|
|
|
// thread - this is separate to the rest of the app so it shouldn't
|
|
|
|
// impact the application specifically
|
2018-06-15 13:51:03 -07:00
|
|
|
while (1)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-06-05 11:15:23 -07:00
|
|
|
unsigned char *buffer = NULL;
|
2017-05-16 00:16:22 -07:00
|
|
|
int size;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
2017-05-25 01:10:53 -07:00
|
|
|
size = _packet_receive(session, &buffer);
|
2017-05-08 12:26:44 -07:00
|
|
|
// if not negative - we have a real message
|
|
|
|
if (size > 0)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-06-03 09:33:58 -07:00
|
|
|
Eina_Debug_Packet_Header *hdr = (Eina_Debug_Packet_Header *)buffer;
|
|
|
|
hdr->cid = SWAP_32(hdr->cid);
|
|
|
|
hdr->opcode = SWAP_32(hdr->opcode);
|
2017-05-30 04:14:59 -07:00
|
|
|
if (EINA_TRUE != session->dispatch_cb(session, buffer))
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-05-08 12:26:44 -07:00
|
|
|
// something we don't understand
|
|
|
|
e_debug("EINA DEBUG ERROR: Unknown command");
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
2017-05-08 12:26:44 -07:00
|
|
|
/* Free the buffer only if the default dispatcher is used */
|
2017-05-25 01:10:53 -07:00
|
|
|
if (session->dispatch_cb == eina_debug_dispatch)
|
2017-05-08 12:26:44 -07:00
|
|
|
free(buffer);
|
|
|
|
}
|
2016-11-26 21:48:10 -08:00
|
|
|
else
|
|
|
|
{
|
2017-05-25 01:10:53 -07:00
|
|
|
_opcodes_unregister_all(session);
|
2018-07-02 11:14:32 -07:00
|
|
|
eina_debug_session_terminate(session);
|
2018-06-15 13:51:03 -07:00
|
|
|
break;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-06-04 06:11:16 -07:00
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
// start up the debug monitor if we haven't already
|
|
|
|
static void
|
|
|
|
_thread_start(Eina_Debug_Session *session)
|
|
|
|
{
|
2017-06-04 06:11:16 -07:00
|
|
|
#ifndef _WIN32
|
2016-11-26 21:48:10 -08:00
|
|
|
pthread_t monitor_thread;
|
|
|
|
int err;
|
|
|
|
sigset_t oldset, newset;
|
|
|
|
|
|
|
|
sigemptyset(&newset);
|
|
|
|
sigaddset(&newset, SIGPIPE);
|
|
|
|
sigaddset(&newset, SIGALRM);
|
|
|
|
sigaddset(&newset, SIGCHLD);
|
|
|
|
sigaddset(&newset, SIGUSR1);
|
|
|
|
sigaddset(&newset, SIGUSR2);
|
|
|
|
sigaddset(&newset, SIGHUP);
|
|
|
|
sigaddset(&newset, SIGQUIT);
|
|
|
|
sigaddset(&newset, SIGINT);
|
|
|
|
sigaddset(&newset, SIGTERM);
|
|
|
|
#ifdef SIGPWR
|
|
|
|
sigaddset(&newset, SIGPWR);
|
|
|
|
#endif
|
2018-01-02 20:02:39 -08:00
|
|
|
pthread_sigmask(SIG_BLOCK, &newset, &oldset);
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
err = pthread_create(&monitor_thread, NULL, _monitor, session);
|
|
|
|
|
2018-01-02 20:02:39 -08:00
|
|
|
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
2016-11-26 21:48:10 -08:00
|
|
|
if (err != 0)
|
|
|
|
{
|
|
|
|
e_debug("EINA DEBUG ERROR: Can't create monitor debug thread!");
|
|
|
|
abort();
|
|
|
|
}
|
2017-06-04 06:11:16 -07:00
|
|
|
#else
|
|
|
|
(void)session;
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sends to daemon:
|
|
|
|
* - Pointer to ops: returned in the response to determine which opcodes have been added
|
2017-05-16 00:16:22 -07:00
|
|
|
* - List of opcode names separated by \0
|
2016-11-26 21:48:10 -08:00
|
|
|
*/
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2016-11-26 21:48:10 -08:00
|
|
|
eina_debug_opcodes_register(Eina_Debug_Session *session, const Eina_Debug_Opcode ops[],
|
2017-05-18 22:59:56 -07:00
|
|
|
Eina_Debug_Opcode_Status_Cb status_cb, void *data)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
|
|
|
if (!session) session = _last_local_session;
|
|
|
|
if (!session) return;
|
|
|
|
|
|
|
|
_opcode_reply_info *info = malloc(sizeof(*info));
|
|
|
|
info->ops = ops;
|
|
|
|
info->status_cb = status_cb;
|
2017-05-18 22:59:56 -07:00
|
|
|
info->status_data = data;
|
2017-06-08 15:09:38 -07:00
|
|
|
info->sent = EINA_FALSE;
|
2016-11-26 21:48:10 -08:00
|
|
|
|
|
|
|
session->opcode_reply_infos = eina_list_append(
|
|
|
|
session->opcode_reply_infos, info);
|
|
|
|
|
2017-05-25 01:10:53 -07:00
|
|
|
/* Send only if session's fd connected.
|
2017-05-16 00:16:22 -07:00
|
|
|
* Otherwise, it will be sent when connected */
|
2017-05-25 03:26:41 -07:00
|
|
|
if(session && session->fd!= -1)
|
2016-11-26 21:48:10 -08:00
|
|
|
_opcodes_registration_send(session, info);
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API Eina_Bool
|
2017-05-30 04:14:59 -07:00
|
|
|
eina_debug_dispatch(Eina_Debug_Session *session, void *buffer)
|
2016-11-26 21:48:10 -08:00
|
|
|
{
|
2017-06-03 09:33:58 -07:00
|
|
|
Eina_Debug_Packet_Header *hdr = buffer;
|
2016-11-26 21:48:10 -08:00
|
|
|
Eina_List *itr;
|
|
|
|
int opcode = hdr->opcode;
|
|
|
|
Eina_Debug_Cb cb = NULL;
|
|
|
|
|
|
|
|
if (opcode >= session->cbs_length)
|
|
|
|
{
|
|
|
|
e_debug("Invalid opcode %d", opcode);
|
2017-05-30 04:14:59 -07:00
|
|
|
return EINA_FALSE;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EINA_LIST_FOREACH(session->cbs[opcode], itr, cb)
|
|
|
|
{
|
|
|
|
if (!cb) continue;
|
2017-05-30 04:14:59 -07:00
|
|
|
Eina_Bool ret = cb(session, hdr->cid,
|
2016-11-26 21:48:10 -08:00
|
|
|
(unsigned char *)buffer + sizeof(*hdr),
|
|
|
|
hdr->size - sizeof(*hdr));
|
2017-05-30 04:14:59 -07:00
|
|
|
if (ret == EINA_FALSE) return ret;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
2017-05-30 04:14:59 -07:00
|
|
|
return EINA_TRUE;
|
2016-11-26 21:48:10 -08:00
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2017-05-18 22:59:51 -07:00
|
|
|
eina_debug_session_data_set(Eina_Debug_Session *session, void *data)
|
|
|
|
{
|
|
|
|
if (session) session->data = data;
|
|
|
|
}
|
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void *
|
2017-05-18 22:59:51 -07:00
|
|
|
eina_debug_session_data_get(Eina_Debug_Session *session)
|
|
|
|
{
|
|
|
|
if (session) return session->data;
|
|
|
|
else return NULL;
|
|
|
|
}
|
|
|
|
|
2015-05-04 19:35:16 -07:00
|
|
|
Eina_Bool
|
|
|
|
eina_debug_init(void)
|
|
|
|
{
|
|
|
|
pthread_t self;
|
|
|
|
|
2018-06-15 13:42:29 -07:00
|
|
|
eina_threads_init();
|
2016-11-26 21:48:10 -08:00
|
|
|
// For Windows support GetModuleFileName can be used
|
2015-05-08 01:18:38 -07:00
|
|
|
// set up thread things
|
2015-05-04 19:35:16 -07:00
|
|
|
eina_spinlock_new(&_eina_debug_lock);
|
|
|
|
eina_spinlock_new(&_eina_debug_thread_lock);
|
|
|
|
self = pthread_self();
|
|
|
|
_eina_debug_thread_mainloop_set(&self);
|
2016-11-09 03:57:07 -08:00
|
|
|
_eina_debug_thread_add(&self);
|
2018-06-26 22:13:00 -07:00
|
|
|
_eina_debug_cpu_init();
|
|
|
|
_eina_debug_bt_init();
|
|
|
|
_eina_debug_timer_init();
|
2016-11-26 21:48:10 -08:00
|
|
|
#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
|
2015-05-04 19:35:16 -07:00
|
|
|
// if we are setuid - don't debug!
|
|
|
|
if (getuid() != geteuid()) return EINA_TRUE;
|
|
|
|
#endif
|
2016-11-26 21:48:10 -08:00
|
|
|
// if someone uses the EFL_NODEBUG env var or disabled debug - do not do
|
|
|
|
// debugging. handy for when this debug code is buggy itself
|
|
|
|
|
|
|
|
if (!getenv("EFL_NODEBUG") && !_debug_disabled)
|
|
|
|
{
|
|
|
|
eina_debug_local_connect(EINA_FALSE);
|
2015-05-04 19:35:16 -07:00
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
eina_debug_shutdown(void)
|
|
|
|
{
|
2018-06-15 13:51:03 -07:00
|
|
|
Eina_Debug_Session *session;
|
|
|
|
pthread_t self = pthread_self();
|
|
|
|
|
2018-07-02 11:14:32 -07:00
|
|
|
EINA_LIST_FREE(sessions, session)
|
2018-06-15 13:51:03 -07:00
|
|
|
eina_debug_session_terminate(session);
|
|
|
|
|
2017-05-08 12:26:44 -07:00
|
|
|
_eina_debug_timer_shutdown();
|
2016-11-26 21:48:10 -08:00
|
|
|
_eina_debug_bt_shutdown();
|
|
|
|
_eina_debug_cpu_shutdown();
|
2018-06-15 13:51:03 -07:00
|
|
|
_eina_debug_thread_del(&self);
|
|
|
|
eina_spinlock_free(&_eina_debug_lock);
|
|
|
|
eina_spinlock_free(&_eina_debug_thread_lock);
|
2018-06-15 13:42:29 -07:00
|
|
|
eina_threads_shutdown();
|
2015-05-04 19:35:16 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2018-06-15 13:56:06 -07:00
|
|
|
|
eina: Rename EAPI macro to EINA_API in Eina library
Summary:
Patch from a series of patches to rename EAPI symbols to specific
library DSOs.
EAPI was designed to be able to pass
`__attribute__ ((visibility ("default")))` for symbols with
GCC, which would mean that even if -fvisibility=hidden was used
when compiling the library, the needed symbols would get exported.
MSVC __almost__ works like GCC (or mingw) in which you can
declare everything as export and it will just work (slower, but
it will work). But there's a caveat: global variables will not
work the same way for MSVC, but works for mingw and GCC.
For global variables (as opposed to functions), MSVC requires
correct DSO visibility for MSVC: instead of declaring a symbol as
export for everything, you need to declare it as import when
importing from another DSO and export when defining it locally.
With current EAPI definitions, we get the following example
working in mingw and MSVC (observe it doesn't define any global
variables as exported symbols).
Example 1:
dll1:
```
EAPI void foo(void);
EAPI void bar()
{
foo();
}
```
dll2:
```
EAPI void foo()
{
printf ("foo\n");
}
```
This works fine with API defined as __declspec(dllexport) in both
cases and for gcc defining as
`__atttribute__((visibility("default")))`
However, the following:
Example 2:
dll1:
```
EAPI extern int foo;
EAPI void foobar(void);
EAPI void bar()
{
foo = 5;
foobar();
}
```
dll2:
```
EAPI int foo = 0;
EAPI void foobar()
{
printf ("foo %d\n", foo);
}
```
This will work on mingw but will not work for MSVC. And that's why
EAPI is the only solution that worked for MSVC.
Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com>
Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev>
Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com>
Reviewers: jptiz, lucas, woohyun, vtorri, raster
Reviewed By: jptiz, lucas, vtorri
Subscribers: ProhtMeyhet, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12188
2020-11-25 04:35:48 -08:00
|
|
|
EINA_API void
|
2018-06-15 13:56:06 -07:00
|
|
|
eina_debug_fork_reset(void)
|
|
|
|
{
|
|
|
|
extern Eina_Bool fork_resetting;
|
|
|
|
|
|
|
|
fork_resetting = EINA_TRUE;
|
|
|
|
eina_debug_shutdown();
|
|
|
|
eina_debug_init();
|
|
|
|
fork_resetting = EINA_FALSE;
|
|
|
|
}
|