first step: let the tracee connect before the remote tracer and let's have a "no wait" mode where the local tracer starts the tracee before the remote tracer is connected
159 lines
3.9 KiB
C
159 lines
3.9 KiB
C
#include "T.h"
|
|
#include "T_messages.txt.h"
|
|
#include <string.h>
|
|
#include <netinet/ip.h>
|
|
#include <arpa/inet.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
/* array used to activate/disactivate a log */
|
|
static int T_IDs[T_NUMBER_OF_IDS];
|
|
int *T_active = T_IDs;
|
|
|
|
static int T_socket;
|
|
|
|
/* T_cache
|
|
* - the T macro picks up the head of freelist and marks it busy
|
|
* - the T sender thread periodically wakes up and sends what's to be sent
|
|
*/
|
|
volatile int _T_freelist_head;
|
|
volatile int *T_freelist_head = &_T_freelist_head;
|
|
int T_busylist_head;
|
|
T_cache_t _T_cache[T_CACHE_SIZE];
|
|
T_cache_t *T_cache = _T_cache;
|
|
|
|
static void get_message(int s)
|
|
{
|
|
char t;
|
|
int l;
|
|
int id;
|
|
int is_on;
|
|
|
|
if (read(s, &t, 1) != 1) abort();
|
|
printf("got mess %d\n", t);
|
|
switch (t) {
|
|
case 0:
|
|
/* toggle all those IDs */
|
|
/* optimze? (too much syscalls) */
|
|
if (read(s, &l, sizeof(int)) != sizeof(int)) abort();
|
|
while (l) {
|
|
if (read(s, &id, sizeof(int)) != sizeof(int)) abort();
|
|
T_IDs[id] = 1 - T_IDs[id];
|
|
l--;
|
|
}
|
|
break;
|
|
case 1:
|
|
/* set IDs as given */
|
|
/* optimize? */
|
|
if (read(s, &l, sizeof(int)) != sizeof(int)) abort();
|
|
id = 0;
|
|
while (l) {
|
|
if (read(s, &is_on, sizeof(int)) != sizeof(int)) abort();
|
|
T_IDs[id] = is_on;
|
|
id++;
|
|
l--;
|
|
}
|
|
break;
|
|
case 2: break; /* do nothing, this message is to wait for local tracer */
|
|
}
|
|
}
|
|
|
|
static void *T_receive_thread(void *_)
|
|
{
|
|
while (1) get_message(T_socket);
|
|
return NULL;
|
|
}
|
|
|
|
static void new_thread(void *(*f)(void *), void *data)
|
|
{
|
|
pthread_t t;
|
|
pthread_attr_t att;
|
|
|
|
if (pthread_attr_init(&att))
|
|
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
|
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
|
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
|
if (pthread_create(&t, &att, f, data))
|
|
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
|
if (pthread_attr_destroy(&att))
|
|
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
|
}
|
|
|
|
void T_connect_to_tracer(char *addr, int port)
|
|
{
|
|
struct sockaddr_in a;
|
|
int s;
|
|
int T_shm_fd;
|
|
unsigned char *buf;
|
|
int len;
|
|
|
|
if (strcmp(addr, "127.0.0.1") != 0) {
|
|
printf("error: local tracer must be on same host\n");
|
|
abort();
|
|
}
|
|
|
|
printf("connecting to local tracer on port %d\n", port);
|
|
again:
|
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (s == -1) { perror("socket"); exit(1); }
|
|
|
|
a.sin_family = AF_INET;
|
|
a.sin_port = htons(port);
|
|
a.sin_addr.s_addr = inet_addr("127.0.0.1");
|
|
|
|
if (connect(s, (struct sockaddr *)&a, sizeof(a)) == -1) {
|
|
perror("connect");
|
|
close(s);
|
|
printf("trying again in 1s\n");
|
|
sleep(1);
|
|
goto again;
|
|
}
|
|
|
|
/* wait for first message - initial list of active T events */
|
|
get_message(s);
|
|
|
|
T_socket = s;
|
|
|
|
/* setup shared memory */
|
|
T_shm_fd = shm_open(T_SHM_FILENAME, O_RDWR /*| O_SYNC*/, 0666);
|
|
shm_unlink(T_SHM_FILENAME);
|
|
if (T_shm_fd == -1) { perror(T_SHM_FILENAME); abort(); }
|
|
T_cache = mmap(NULL, T_CACHE_SIZE * sizeof(T_cache_t),
|
|
PROT_READ | PROT_WRITE, MAP_SHARED, T_shm_fd, 0);
|
|
if (T_cache == NULL)
|
|
{ perror(T_SHM_FILENAME); abort(); }
|
|
close(T_shm_fd);
|
|
|
|
new_thread(T_receive_thread, NULL);
|
|
|
|
/* trace T_message.txt
|
|
* Send several messages -1 with content followed by message -2.
|
|
* We can't use the T macro directly, events -1 and -2 are special.
|
|
*/
|
|
buf = T_messages_txt;
|
|
len = T_messages_txt_len;
|
|
while (len) {
|
|
int send_size = len;
|
|
if (send_size > T_PAYLOAD_MAXSIZE - sizeof(int))
|
|
send_size = T_PAYLOAD_MAXSIZE - sizeof(int);
|
|
do {
|
|
T_LOCAL_DATA
|
|
T_HEADER(T_ID(-1));
|
|
T_PUT_buffer(1, ((T_buffer){addr:(buf), length:(len)}));
|
|
T_COMMIT();
|
|
} while (0);
|
|
buf += send_size;
|
|
len -= send_size;
|
|
}
|
|
do {
|
|
T_LOCAL_DATA
|
|
T_HEADER(T_ID(-2));
|
|
T_COMMIT();
|
|
} while (0);
|
|
}
|