English
/ 繁體中文
journal
album
book
about
Subscribe
Activities Elsewhere
This page is not available in 繁體中文, as a result the English (en_US) version is shown instead.
Title:
Body:
> debug.c: > > #include
> > #include
> #include
> #include
> #include
> #include
> > 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
> #include
> > 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.