libdebug
debug.c:
#include <glib.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
void ld_attach() __attribute((constructor));
static gboolean ld_read_cb(GIOChannel *source, GIOCondition cond,
gpointer data);
static gboolean ld_conn_cb(GIOChannel *source, GIOCondition cond,
gpointer data);
static int ld_create_socket();
static guint source_id = -1;
void
ld_attach()
{
int fd = ld_create_socket();
if (fd == -1) {
return;
}
GIOChannel *channel = g_io_channel_unix_new(fd);
source_id = g_io_add_watch(channel, G_IO_IN | G_IO_HUP, ld_conn_cb, NULL);
}
static gboolean
ld_conn_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
{
struct sockaddr_in in_addr;
socklen_t size = -1;
if (cond == G_IO_IN) {
int fd = g_io_channel_unix_get_fd(channel);
int new_fd = -1;
size = sizeof(in_addr);
if ((new_fd = accept(fd, (struct sockaddr *)&in_addr, &size)) == -1) {
perror("accept");
return TRUE;
}
GIOChannel *channel2 = g_io_channel_unix_new(new_fd);
source_id = g_io_add_watch(channel2, G_IO_IN | G_IO_HUP, ld_read_cb,
NULL);
}
return TRUE;
}
static gboolean
ld_read_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
{
int addr = 0;
char *line = NULL;
if (cond == G_IO_IN) {
while (g_io_channel_read_line(channel, &line, NULL, NULL, NULL) ==
G_IO_STATUS_NORMAL) {
if (sscanf(line, "%x\n", &addr) == 1) {
char *ptr = GINT_TO_POINTER(addr);
int i = 0;
printf("Reading address %p: ", ptr);
for (i = 0; i < 10 && *ptr; i++, ptr++) {
printf("%c", *ptr);
}
printf("\n");
}
}
} else if (cond == G_IO_ERR || cond == G_IO_HUP) {
g_io_channel_shutdown(channel, FALSE, NULL);
}
return TRUE;
}
static int
ld_create_socket()
{
int fd = -1;
struct sockaddr_in addr;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(34567);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("bind");
return -1;
}
if (listen(fd, 0) == -1) {
perror("listen");
return -1;
}
return fd;
}
main.c:
#include <stdio.h>
#include <glib.h>
int
main(int argc, char **argv)
{
GMainLoop *mainloop = g_main_loop_new(NULL, FALSE);
printf("%p: %s\n", argv[0], argv[0]);
g_main_loop_run(mainloop);
return 0;
}
Makefile:
LSRC= \
debug.c \
SRC= \
main.c \
LOBJ = $(LSRC:.c=.o)
OBJ = $(SRC:.c=.o)
CFLAGS += -Wall -g -Werror -Wextra -Wfloat-equal -Wbad-function-cast -Wcast-qual -Winline -Wno-unused-parameter
CFLAGS += `pkg-config --cflags glib-2.0` -I$(PWD)
LFLAGS += `pkg-config --libs glib-2.0`
LIBOUT = libdebug.so
OUT = test
all: $(LIBOUT) $(OUT)
$(OUT): $(OBJ)
$(CC) $(CFLAGS) $(LFLAGS) $(OBJ) -L$(PWD) -o $(OUT)
$(LIBOUT): $(LOBJ)
$(CC) -shared -Wl,-soname,$(LIBOUT) $(CFLAGS) $(LFLAGS) $(LOBJ) -o $(LIBOUT)
$(OBJ): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
$(LOBJ): %.o: %.c
$(CC) -fPIC $(CFLAGS) -c $< -o $@
clean:
$(RM) $(LOBJ) $(LIBOUT) $(OUT) $(OBJ)
To run:
$ make
$ LD_PRELOAD=./libdebug.so ./test
0xbfc5b9b7: ./test
Then in another terminal:
$ telnet 127.0.0.1 34567
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
0xbfc5b9b7
You should see this printed out in the original terminal:
$ LD_PRELOAD=./libdebug.so ./test
0xbfc5b9b7: ./test
Reading address 0xbfc5b9b7: ./test
Printing the result in the telnet window is left as an exercise for the reader.
by khc
on Sat Sep 30 21:44:59 2006
Permlink