├── .gitignore ├── LICENSE ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── passes ├── Makefile.am ├── dump.c └── example.c ├── protocols ├── wayland-drm-protocol.c └── xdg-shell-protocol.c ├── src ├── Makefile.am ├── debug.c ├── getopt.c ├── getopt.h ├── interactive │ ├── autocmd.c │ ├── breakpoints.c │ ├── edit.c │ ├── filters.c │ ├── info.c │ ├── input.c │ ├── input.h │ ├── interactive-commands.c │ ├── interactive-commands.h │ ├── interactive.c │ ├── interactive.h │ ├── objinfo-info.c │ ├── pass.c │ └── send.c ├── list-pass.c ├── loop.c ├── objinfo-pass.c ├── objinfo │ ├── objinfo-private.c │ ├── objinfo-private.h │ ├── objinfo.c │ ├── objinfo.h │ ├── wl_registry-objinfo.c │ ├── wl_seat-objinfo.c │ ├── wl_shm-objinfo.c │ ├── wl_surface-objinfo.c │ └── xdg-objinfo.c ├── parse-message.c ├── passes.c ├── passes.h ├── print.c ├── resolve-pass.c ├── resolve.c ├── resolve.h ├── sockets.c ├── sockets.h ├── util.c ├── util.h ├── wldbg-ids-map.c ├── wldbg-ids-map.h ├── wldbg-objects-info.h ├── wldbg-parse-message.h ├── wldbg-pass.h ├── wldbg-private.h ├── wldbg.c ├── wldbg.h └── wldbg.pc.in ├── tests ├── Makefile.am ├── map-test.c ├── parse-message-test.c └── util-test.c └── wayland ├── connection.c ├── test-helpers.c ├── test-runner.c ├── test-runner.h ├── wayland-os.c ├── wayland-os.h ├── wayland-private.h ├── wayland-util.c └── wayland-util.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | src/*.swp 3 | src/*.o 4 | src/*.la 5 | src/*.lo 6 | passes/*.swp 7 | passes/*.lo 8 | passes/*.o 9 | passes/*.la 10 | *.o *.lo 11 | src/wldbg 12 | m4/ 13 | config* 14 | .gitignore 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2014 - 2015 Marek Chalupa 3 | 4 | Permission is hereby granted, free of charge, to any person 5 | obtaining a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice (including the 13 | next paragraph) shall be included in all copies or substantial 14 | portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src tests passes 2 | 3 | ACLOCAL_AMFLAGS= -I m4 4 | EXTRA_DIST = autogen.sh 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### What is wldbg? 2 | 3 | Wldbg is a tool that allows you to debug or modify events in 4 | Wayland connections. It works on the man-in-the-middle basis. 5 | When a Wayland client is run under wldbg, every message to or 6 | from the client is handed out to a pipeline of passes that can 7 | process the message. Passes are simple-to-write plugins. 8 | Wldbg has also an interactive gdb-like mode. 9 | 10 | ### What is a pass? 11 | 12 | The passes in wldbg are inspired by LLVM passes. 13 | A pass is a plugin that defines two functions - one for 14 | messages going from the client to the server and the another for 15 | messages from server to the client. 16 | It can analyze or arbitriraly modify the message and 17 | then pass the message to the next pass (or stop the whole pipeline) 18 | and so on.. 19 | 20 | ### Using passes 21 | 22 | Run wldbg with passes is very easy, just type on command-line: 23 | 24 | ``` 25 | $ wldbg pass1 ARGUMENTS, pass2 ARGUMENTS -- wayland-client 26 | ``` 27 | 28 | pass1 and pass2 are names of the passes without .so extension 29 | (i. e. dump.so ~~> dump) 30 | 31 | If you do not know what passes are available, use: 32 | 33 | ``` 34 | $ wldbg list 35 | ``` 36 | 37 | To get better understanding how it works, there's an example pass 38 | in `passes/example.c`. This pass is also compiled by default, so 39 | you can try it out as follows: 40 | 41 | ``` 42 | $ wldbg example -- wayland_client 43 | ``` 44 | 45 | ### Using the interactive mode 46 | 47 | To run wldbg in the interactive mode, just do: 48 | 49 | ``` 50 | $ wldbg -i wayland-client 51 | ``` 52 | 53 | If everything goes well, you'll see: 54 | 55 | ``` 56 | Stopped on the first message 57 | C: wl_display@1.get_registry(new id wl_registry@2) 58 | (wldbg) 59 | ``` 60 | 61 | wldbg is now waiting for your input. By typing 'c' or 'continue', the program 62 | will continue running. Other usefull commands are: 63 | 64 | ``` 65 | 'help' -- show help message 66 | 'help COMMAND' -- show help to COMMAND 67 | 'b' or 'break' -- stop running on specified messages 68 | b id 10 --> stop on messages with id 10 69 | b re REGEXP --> stop on any message matching regexp) 70 | 'i' or 'info' -- show information about running state 71 | i b(reakpoints) --> info about breakpoints 72 | i objects --> info about objects 73 | i proc --> info about process 74 | 'autocmd' -- run command after messages of intereset 75 | autocmd add RE CMD --> run CMD on every message matching RE 76 | autocmd add '' i o --> display info about objects after every message 77 | 'h' or 'hide -- hide specified messages matching REGEXP, e. g.: 78 | h wl_pointer.* --> hide everything for/from wl_pointer 79 | h wl_display@.*done --> hide done messages from wl_display 80 | 'so' or 'showonly' -- show only messages matching REGEXP 81 | so wl_display.*done --> show only wl_display.done event 82 | 's' or 'send' -- send message to client/server (in wire format) 83 | 'e' or 'edit' -- edit message that we stopped at 84 | 'q' or 'quit' -- exit wldbg 85 | ``` 86 | 87 | When wldbg is run with -g (-objinfo) option, it gathers information about objects. 88 | User then can just type: 89 | 90 | ``` 91 | (wldbg) i o ID 92 | ``` 93 | 94 | where ID is the id of the object of interest and wldbg will dump information 95 | it gathered about it. NOTE: this is new and incomplete feature. At this 96 | moment wldbg gathers information about xdg_surface, wl_surface and wl_buffer objects. 97 | 98 | Ctrl-C interrupts the program and prompts user for input. 99 | 100 | ### Using server mode 101 | 102 | Wldbg can run in the server mode in which every new connection is redirected to wldbg and 103 | only then to the Wayland compositor. Upon the first connection, the user is prompted for an action, 104 | every other connection is then connected automatically without stopping. 105 | The server mode is interactive, so everything that works in the interactive mode, 106 | works in the server mode too. To start wldbg in the server mode, use the -s switch: 107 | 108 | ``` 109 | $ wldbg -s 110 | Listening for incoming connections... 111 | ``` 112 | 113 | when client connects, you'll see something like: 114 | 115 | ``` 116 | Stopped on the first message 117 | [weston-terminal: 7874] C: wl_display@1.get_registry(new id wl_registry@2) 118 | ``` 119 | 120 | After another client is connected, the messages from both are just interleaved: 121 | 122 | ``` 123 | [weston-terminal |7874] S: wl_pointer@3.motion(2739198098, 197.000000, 142.000000) 124 | [weston-terminal |7874] S: wl_pointer@3.frame() 125 | [weston-dnd |7930] S: wl_buffer@38.release() 126 | [weston-dnd |7930] S: wl_pointer@3.leave(166, wl_surface@14) 127 | [weston-dnd |7930] S: wl_pointer@3.frame() 128 | [weston-terminal |7874] C: wl_surface@10.attach(wl_buffer@17, 0, 0) 129 | [weston-terminal |7874] C: wl_surface@10.damage(0, 0, 9, 16) 130 | [weston-terminal |7874] C: wl_surface@10.commit() 131 | ``` 132 | 133 | Server mode is handy, for example, for debugging the interaction between two clients, 134 | like two weston-dnd instances dragging and dropping between them. 135 | 136 | ---------------------- 137 | 138 | An active development of Wldbg stopped some years ago, but it still should work. 139 | There are features missing and probably some bugs, but the features described above 140 | should mostly work. 141 | 142 | Author: Marek Chalupa 143 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # create missing directories 4 | test -d "config" || mkdir "config" 5 | test -d "m4" || mkdir "m4" 6 | 7 | test -n "$srcdir" || srcdir=`dirname "$0"` 8 | test -n "$srcdir" || srcdir=. 9 | ( 10 | cd "$srcdir" && 11 | autoreconf --force -v --install 12 | ) || exit 13 | test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" 14 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.64]) 2 | 3 | m4_define([wldbg_major_version], [0]) 4 | m4_define([wldbg_minor_version], [2]) 5 | m4_define([wldbg_micro_version], [0]) 6 | m4_define([wldbg_version], 7 | [wldbg_major_version.wldbg_minor_version.wldbg_micro_version]) 8 | 9 | AC_INIT([wldbg], 10 | [wldbg_version], 11 | [mchqwerty@gmail.com], 12 | [wldbg], 13 | [https://github.com/mchalupa/wldbg]) 14 | 15 | AC_SUBST([WLDBG_VERSION_MAJOR], [wldbg_major_version]) 16 | AC_SUBST([WLDBG_VERSION_MINOR], [wldbg_minor_version]) 17 | AC_SUBST([WLDBG_VERSION_MICRO], [wldbg_micro_version]) 18 | AC_SUBST([WLDBG_VERSION], [wldbg_version]) 19 | 20 | AC_CONFIG_HEADERS([config.h]) 21 | AC_CONFIG_AUX_DIR([config]) 22 | AC_CONFIG_MACRO_DIR([m4]) 23 | 24 | AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) 25 | 26 | AM_SILENT_RULES([yes]) 27 | 28 | # Check for programs 29 | AC_PROG_CC 30 | 31 | # Initialize libtool 32 | LT_PREREQ([2.2]) 33 | LT_INIT 34 | 35 | PKG_PROG_PKG_CONFIG() 36 | 37 | # future use 38 | TESTS_CFLAGS= 39 | TESTS_LIBS= 40 | COMPILER_CFLAGS= 41 | 42 | AX_LIB_READLINE 43 | 44 | # check wayland's presence 45 | PKG_CHECK_MODULES([WAYLAND_SERVER], [wayland-server],\ 46 | [HAVE_WAYLAND_SERVER=yes], [HAVE_WAYLAND_SERVER=no]) 47 | PKG_CHECK_MODULES([WAYLAND_CLIENT], [wayland-client],\ 48 | [HAVE_WAYLAND_CLIENT=yes], [HAVE_WAYLAND_CLIENT=no]) 49 | 50 | if test "x$HAVE_WAYLAND_SERVER" != "xyes"; then 51 | AC_MSG_ERROR([Need wayland-server libraries to compile]) 52 | fi 53 | 54 | if test "x$HAVE_WAYLAND_CLIENT" != "xyes"; then 55 | AC_MSG_ERROR([Need wayland-client libraries to compile]) 56 | fi 57 | 58 | AC_CHECK_HEADER([wayland-version.h],, 59 | AC_MSG_ERROR([Need wayland-version.h header file])) 60 | 61 | AC_ARG_ENABLE(debug, 62 | [AC_HELP_STRING([--disable-debug], 63 | [Disable debugging macros])], 64 | ,,enable_debug=yes) 65 | if test "x$enable_debug" != "xno"; then 66 | AC_DEFINE(DEBUG, 1, [Enable debugging macros]) 67 | CFLAGS="$CFLAGS -g -O" 68 | fi 69 | 70 | AM_CONDITIONAL(ENABLE_DEBUG, test "x$enable_debug" != "xno") 71 | 72 | #export options to makefiles 73 | AC_SUBST([TESTS_LIBS]) 74 | AC_SUBST([TESTS_CFLAGS]) 75 | 76 | AC_CONFIG_FILES([Makefile 77 | src/Makefile 78 | passes/Makefile 79 | tests/Makefile 80 | src/wldbg.pc]) 81 | 82 | AC_OUTPUT 83 | -------------------------------------------------------------------------------- /passes/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | pass_libdir=$(libdir)/wldbg 3 | pass_lib_LTLIBRARIES = dump.la example.la 4 | 5 | AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src 6 | 7 | dump_la_LDFLAGS = -module -avoid-version 8 | dump_la_SOURCES = dump.c 9 | 10 | example_la_LDFLAGS = -module -avoid-version 11 | example_la_SOURCES = example.c 12 | -------------------------------------------------------------------------------- /passes/dump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "wldbg.h" 33 | #include "wldbg-pass.h" 34 | #include "wldbg-parse-message.h" 35 | 36 | enum options { 37 | SEPARATE = 1 , 38 | DECIMAL = 1 << 1, 39 | DECODE = 1 << 2, 40 | TOFILE = 1 << 3, 41 | RAW = 1 << 4, 42 | CLIENTONLY = 1 << 5, 43 | SERVERONLY = 1 << 6, 44 | STATS = 1 << 7, 45 | NOOUT = 1 << 8, 46 | HUMAN = 1 << 9, 47 | }; 48 | 49 | struct dump { 50 | uint64_t options; 51 | const char *file; 52 | int file_fd; 53 | 54 | struct { 55 | uint64_t in_msg; 56 | uint64_t out_msg; 57 | uint64_t in_bytes; 58 | uint64_t out_bytes; 59 | } stats; 60 | }; 61 | 62 | static void 63 | dump_to_file(struct wldbg_message *message, struct dump *dump) 64 | { 65 | if (write(dump->file_fd, message->data, message->size) 66 | != (ssize_t) message->size) { 67 | perror("Dumping to file failed"); 68 | } 69 | } 70 | 71 | static void 72 | dump_message(struct wldbg_message *message, struct dump *dump) 73 | { 74 | uint32_t i; 75 | uint32_t *data = message->data; 76 | uint32_t options = dump->options; 77 | size_t size = 0; 78 | 79 | if (options & TOFILE) { 80 | dump_to_file(message, dump); 81 | 82 | /* if user want only dump to file, do not print anything */ 83 | if (!(options & (~TOFILE))) 84 | return; 85 | } 86 | 87 | if (options & NOOUT) 88 | return; 89 | 90 | if (options & DECODE) 91 | options |= SEPARATE; 92 | 93 | if (options & HUMAN) 94 | wldbg_message_print(message); 95 | 96 | if (!(options & RAW)) 97 | return; 98 | 99 | printf("%s: ", message->from == CLIENT ? "CLIENT" : "SERVER"); 100 | 101 | for (i = 0; i < message->size / sizeof(uint32_t) ; ++i) { 102 | if (options & SEPARATE) { 103 | if (size == 0 && message->size > i + 1) { 104 | size = data[i + 1] >> 16; 105 | 106 | if (options & DECODE) { 107 | printf("\n id: %u opcode: %u size: %lu:\n\t", 108 | data[i], data[i + 1] & 0xffff, 109 | size); 110 | } else { 111 | printf("\n | %2lu | ", size); 112 | } 113 | } 114 | 115 | size -= sizeof(uint32_t); 116 | } 117 | 118 | if (options & DECIMAL) 119 | printf("%d ", data[i]); 120 | else 121 | printf("%08x ", data[i]); 122 | } 123 | 124 | putchar('\n'); 125 | } 126 | 127 | static int 128 | dump_in(void *user_data, struct wldbg_message *message) 129 | { 130 | struct dump *dump = user_data; 131 | 132 | if (dump->options & STATS) { 133 | ++dump->stats.in_msg; 134 | dump->stats.in_bytes += message->size; 135 | } 136 | 137 | if (dump->options & CLIENTONLY && !(dump->options & SERVERONLY)) 138 | return PASS_NEXT; 139 | 140 | dump_message(message, dump); 141 | 142 | return PASS_NEXT; 143 | } 144 | 145 | static int 146 | dump_out(void *user_data, struct wldbg_message *message) 147 | { 148 | struct dump *dump = user_data; 149 | 150 | if (dump->options & STATS) { 151 | ++dump->stats.out_msg; 152 | dump->stats.out_bytes += message->size; 153 | } 154 | 155 | if (dump->options & SERVERONLY && !(dump->options & CLIENTONLY)) 156 | return PASS_NEXT; 157 | 158 | dump_message(message, dump); 159 | 160 | return PASS_NEXT; 161 | } 162 | 163 | 164 | static void 165 | print_help(void *user_data) 166 | { 167 | (void) user_data; 168 | 169 | printf(" --- Dump data going via wire --- \n" 170 | "\n" 171 | "Usage: wldbg dump arg1 arg2 ...\n" 172 | "\n" 173 | "Available arguments:\n" 174 | /* XXX what should raw mean anyway? */ 175 | " raw -- not implemented\n" 176 | " human -- print human readable output\n" 177 | " decode -- decode the header of message\n" 178 | " decimal -- print numbers in decimal format\n" 179 | " client -- dump only messages from client\n" 180 | " server -- dump only messages from server\n" 181 | " stats --\n" 182 | " statistics -- gather and print statistics on exit\n" 183 | " no-output -- do not print anything (except stats at exit)\n" 184 | " help -- print this help\n" 185 | " to-file -- dump raw data into file\n"); 186 | } 187 | 188 | static int 189 | dump_init(struct wldbg *wldbg, struct wldbg_pass *pass, int argc, const char *argv[]) 190 | { 191 | int i; 192 | uint64_t flags = 0; 193 | struct dump *dump = malloc(sizeof *dump); 194 | if (!dump) 195 | return -1; 196 | 197 | (void) wldbg; 198 | 199 | for (i = 1; i < argc; ++i) { 200 | if (strcmp(argv[i], "raw") == 0) 201 | flags |= RAW; 202 | else if (strcmp(argv[i], "decode") == 0) 203 | flags |= DECODE; 204 | else if (strcmp(argv[i], "human") == 0) 205 | flags |= HUMAN; 206 | else if (strcmp(argv[i], "separate") == 0) 207 | flags |= SEPARATE; 208 | else if (strcmp(argv[i], "decimal") == 0) 209 | flags |= DECIMAL; 210 | else if (strcmp(argv[i], "client") == 0) 211 | flags |= CLIENTONLY; 212 | else if (strcmp(argv[i], "server") == 0) 213 | flags |= SERVERONLY; 214 | else if (strcmp(argv[i], "stats") == 0) 215 | flags |= STATS; 216 | else if (strcmp(argv[i], "statistics") == 0) 217 | flags |= STATS; 218 | else if (strcmp(argv[i], "no-output") == 0) 219 | flags |= NOOUT; 220 | else if (strcmp(argv[i], "help") == 0) { 221 | print_help(NULL); 222 | /* let wldbg exit after loading the pass */ 223 | wldbg_exit(wldbg); 224 | } else if (strcmp(argv[i], "to-file") == 0) { 225 | flags |= TOFILE; 226 | dump->file = argv[i + 1]; 227 | } 228 | } 229 | 230 | /* if user did not explicitly requests 231 | * humand readable output AND raw output, assume 232 | * that she/he wants only raw or only human output */ 233 | if (!(flags & HUMAN)) 234 | flags |= RAW; 235 | 236 | if (flags & TOFILE) { 237 | dump->file_fd = open(dump->file, O_WRONLY | O_CREAT | O_EXCL, 0755); 238 | if (dump->file_fd == -1) { 239 | perror("Opening file for dumping"); 240 | free(dump); 241 | return -1; 242 | } 243 | } 244 | 245 | dump->options = flags; 246 | pass->user_data = dump; 247 | 248 | return 0; 249 | } 250 | 251 | static void 252 | dump_destroy(void *data) 253 | { 254 | struct dump *dump = data; 255 | 256 | fflush(stdout); 257 | if (dump->options & STATS) { 258 | printf("----------------------\n" 259 | "Messages from server: %lu (%lu bytes)\n" 260 | "Messages from client: %lu (%lu bytes)\n" 261 | "----------------------\n", 262 | dump->stats.in_msg, dump->stats.in_bytes, 263 | dump->stats.out_msg, dump->stats.out_bytes); 264 | } 265 | 266 | if (dump->options & TOFILE) { 267 | close(dump->file_fd); 268 | } 269 | 270 | free(dump); 271 | } 272 | 273 | struct wldbg_pass wldbg_pass = { 274 | .init = dump_init, 275 | .destroy = dump_destroy, 276 | .server_pass = dump_in, 277 | .client_pass = dump_out, 278 | .help = print_help, 279 | .description = "Dump data going through the wire", 280 | 0 281 | }; 282 | -------------------------------------------------------------------------------- /passes/example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Example pass for wldbg 5 | * 6 | * compile with: 7 | * 8 | * cc -Wall -fPIC -shared -o example.so example.c 9 | * (maybe will need to add -I../src) 10 | * 11 | * run with (in directory with example.so): 12 | * 13 | * wldbg example -- wayland-client 14 | * 15 | * Permission is hereby granted, free of charge, to any person 16 | * obtaining a copy of this software and associated documentation files 17 | * (the "Software"), to deal in the Software without restriction, 18 | * including without limitation the rights to use, copy, modify, merge, 19 | * publish, distribute, sublicense, and/or sell copies of the Software, 20 | * and to permit persons to whom the Software is furnished to do so, 21 | * subject to the following conditions: 22 | * 23 | * The above copyright notice and this permission notice (including the 24 | * next paragraph) shall be included in all copies or substantial 25 | * portions of the Software. 26 | * 27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | * SOFTWARE. 35 | */ 36 | 37 | #include 38 | #include 39 | 40 | #include "wldbg.h" 41 | #include "wldbg-pass.h" 42 | 43 | struct example_data { 44 | unsigned int incoming_number; 45 | unsigned int outcoming_number; 46 | unsigned int in_trasfered; 47 | unsigned int out_trasfered; 48 | }; 49 | 50 | static int 51 | example_in(void *user_data, struct wldbg_message *message) 52 | { 53 | struct example_data *data = user_data; 54 | 55 | data->incoming_number++; 56 | data->in_trasfered += message->size; 57 | 58 | printf("Got incoming message: %u, size: %lu bytes\n", 59 | data->incoming_number, message->size); 60 | 61 | /* run next pass, oposite is PASS_STOP */ 62 | return PASS_NEXT; 63 | } 64 | 65 | static int 66 | example_out(void *user_data, struct wldbg_message *message) 67 | { 68 | struct example_data *data = user_data; 69 | 70 | data->outcoming_number++; 71 | data->out_trasfered += message->size; 72 | 73 | printf("Got outcoming message: %u, size: %lu bytes\n", 74 | data->outcoming_number, message->size); 75 | 76 | /* run next pass, oposite is PASS_STOP */ 77 | return PASS_NEXT; 78 | } 79 | 80 | static void 81 | example_help(void *user_data) 82 | { 83 | (void) user_data; 84 | 85 | printf("This is an example pass!\n"); 86 | } 87 | 88 | static int 89 | example_init(struct wldbg *wldbg, struct wldbg_pass *pass, 90 | int argc, const char *argv[]) 91 | { 92 | int i; 93 | struct example_data *data = calloc(1, sizeof *data); 94 | if (!data) 95 | return -1; 96 | 97 | (void) wldbg; 98 | 99 | printf("-- Initializing example pass --\n\n"); 100 | for (i = 0; i < argc; ++i) 101 | printf("\targument[%d]: %s\n", i, argv[i]); 102 | 103 | printf("\n\n"); 104 | 105 | pass->user_data = data; 106 | 107 | return 0; 108 | } 109 | 110 | static void 111 | example_destroy(void *user_data) 112 | { 113 | struct example_data *data = user_data; 114 | 115 | printf(" -- Destroying example pass --\n\n"); 116 | printf("Totally trasfered %u bytes from client to server\n" 117 | "and %u bytes from server to client\n", 118 | data->out_trasfered, data->in_trasfered); 119 | 120 | free(data); 121 | } 122 | 123 | struct wldbg_pass wldbg_pass = { 124 | .init = example_init, 125 | .destroy = example_destroy, 126 | .server_pass = example_in, 127 | .client_pass = example_out, 128 | .help = example_help, 129 | .description = "Example wldbg pass" 130 | }; 131 | -------------------------------------------------------------------------------- /protocols/wayland-drm-protocol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008-2011 Kristian Høgsberg 3 | * Copyright © 2010-2011 Intel Corporation 4 | * 5 | * Permission to use, copy, modify, distribute, and sell this 6 | * software and its documentation for any purpose is hereby granted 7 | * without fee, provided that\n the above copyright notice appear in 8 | * all copies and that both that copyright notice and this permission 9 | * notice appear in supporting documentation, and that the name of 10 | * the copyright holders not be used in advertising or publicity 11 | * pertaining to distribution of the software without specific, 12 | * written prior permission. The copyright holders make no 13 | * representations about the suitability of this software for any 14 | * purpose. It is provided "as is" without express or implied 15 | * warranty. 16 | * 17 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 18 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 21 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 22 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 23 | * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 24 | * THIS SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include "wayland-util.h" 30 | 31 | extern const struct wl_interface wl_buffer_interface; 32 | 33 | static const struct wl_interface *types[] = { 34 | NULL, 35 | &wl_buffer_interface, 36 | NULL, 37 | NULL, 38 | NULL, 39 | NULL, 40 | NULL, 41 | &wl_buffer_interface, 42 | NULL, 43 | NULL, 44 | NULL, 45 | NULL, 46 | NULL, 47 | NULL, 48 | NULL, 49 | NULL, 50 | NULL, 51 | NULL, 52 | &wl_buffer_interface, 53 | NULL, 54 | NULL, 55 | NULL, 56 | NULL, 57 | NULL, 58 | NULL, 59 | NULL, 60 | NULL, 61 | NULL, 62 | NULL, 63 | }; 64 | 65 | static const struct wl_message wl_drm_requests[] = { 66 | { "authenticate", "u", types + 0 }, 67 | { "create_buffer", "nuiiuu", types + 1 }, 68 | { "create_planar_buffer", "nuiiuiiiiii", types + 7 }, 69 | { "create_prime_buffer", "2nhiiuiiiiii", types + 18 }, 70 | }; 71 | 72 | static const struct wl_message wl_drm_events[] = { 73 | { "device", "s", types + 0 }, 74 | { "format", "u", types + 0 }, 75 | { "authenticated", "", types + 0 }, 76 | { "capabilities", "u", types + 0 }, 77 | }; 78 | 79 | WL_EXPORT const struct wl_interface wl_drm_interface = { 80 | "wl_drm", 2, 81 | 4, wl_drm_requests, 82 | 4, wl_drm_events, 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /protocols/xdg-shell-protocol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008-2013 Kristian Høgsberg 3 | * Copyright © 2013 Rafael Antognolli 4 | * Copyright © 2013 Jasper St. Pierre 5 | * Copyright © 2010-2013 Intel Corporation 6 | * 7 | * Permission to use, copy, modify, distribute, and sell this 8 | * software and its documentation for any purpose is hereby granted 9 | * without fee, provided that the above copyright notice appear in 10 | * all copies and that both that copyright notice and this permission 11 | * notice appear in supporting documentation, and that the name of 12 | * the copyright holders not be used in advertising or publicity 13 | * pertaining to distribution of the software without specific, 14 | * written prior permission. The copyright holders make no 15 | * representations about the suitability of this software for any 16 | * purpose. It is provided "as is" without express or implied 17 | * warranty. 18 | * 19 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 20 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 24 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 25 | * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 26 | * THIS SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include "wayland-util.h" 32 | 33 | extern const struct wl_interface wl_output_interface; 34 | extern const struct wl_interface wl_seat_interface; 35 | extern const struct wl_interface wl_surface_interface; 36 | extern const struct wl_interface xdg_popup_interface; 37 | extern const struct wl_interface xdg_surface_interface; 38 | 39 | static const struct wl_interface *types[] = { 40 | NULL, 41 | NULL, 42 | NULL, 43 | NULL, 44 | &xdg_surface_interface, 45 | &wl_surface_interface, 46 | &xdg_popup_interface, 47 | &wl_surface_interface, 48 | &wl_surface_interface, 49 | &wl_seat_interface, 50 | NULL, 51 | NULL, 52 | NULL, 53 | &xdg_surface_interface, 54 | &wl_seat_interface, 55 | NULL, 56 | NULL, 57 | NULL, 58 | &wl_seat_interface, 59 | NULL, 60 | &wl_seat_interface, 61 | NULL, 62 | NULL, 63 | &wl_output_interface, 64 | }; 65 | 66 | static const struct wl_message xdg_shell_requests[] = { 67 | { "destroy", "", types + 0 }, 68 | { "use_unstable_version", "i", types + 0 }, 69 | { "get_xdg_surface", "no", types + 4 }, 70 | { "get_xdg_popup", "nooouii", types + 6 }, 71 | { "pong", "u", types + 0 }, 72 | }; 73 | 74 | static const struct wl_message xdg_shell_events[] = { 75 | { "ping", "u", types + 0 }, 76 | }; 77 | 78 | WL_EXPORT const struct wl_interface xdg_shell_interface = { 79 | "xdg_shell", 1, 80 | 5, xdg_shell_requests, 81 | 1, xdg_shell_events, 82 | }; 83 | 84 | static const struct wl_message xdg_surface_requests[] = { 85 | { "destroy", "", types + 0 }, 86 | { "set_parent", "?o", types + 13 }, 87 | { "set_title", "s", types + 0 }, 88 | { "set_app_id", "s", types + 0 }, 89 | { "show_window_menu", "ouii", types + 14 }, 90 | { "move", "ou", types + 18 }, 91 | { "resize", "ouu", types + 20 }, 92 | { "ack_configure", "u", types + 0 }, 93 | { "set_window_geometry", "iiii", types + 0 }, 94 | { "set_maximized", "", types + 0 }, 95 | { "unset_maximized", "", types + 0 }, 96 | { "set_fullscreen", "?o", types + 23 }, 97 | { "unset_fullscreen", "", types + 0 }, 98 | { "set_minimized", "", types + 0 }, 99 | }; 100 | 101 | static const struct wl_message xdg_surface_events[] = { 102 | { "configure", "iiau", types + 0 }, 103 | { "close", "", types + 0 }, 104 | }; 105 | 106 | WL_EXPORT const struct wl_interface xdg_surface_interface = { 107 | "xdg_surface", 1, 108 | 14, xdg_surface_requests, 109 | 2, xdg_surface_events, 110 | }; 111 | 112 | static const struct wl_message xdg_popup_requests[] = { 113 | { "destroy", "", types + 0 }, 114 | }; 115 | 116 | static const struct wl_message xdg_popup_events[] = { 117 | { "popup_done", "", types + 0 }, 118 | }; 119 | 120 | WL_EXPORT const struct wl_interface xdg_popup_interface = { 121 | "xdg_popup", 1, 122 | 1, xdg_popup_requests, 123 | 1, xdg_popup_events, 124 | }; 125 | 126 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | bin_PROGRAMS = wldbg 3 | lib_LTLIBRARIES = libwldbg.la 4 | 5 | wayland_files = \ 6 | ../wayland/connection.c \ 7 | ../wayland/wayland-os.c \ 8 | ../wayland/wayland-util.c \ 9 | ../wayland/wayland-os.h \ 10 | ../wayland/wayland-util.h \ 11 | ../wayland/wayland-private.h 12 | 13 | hardcoded_passes = \ 14 | list-pass.c \ 15 | resolve-pass.c \ 16 | objinfo-pass.c 17 | 18 | interactive_sources = \ 19 | interactive/interactive.c \ 20 | interactive/interactive.h \ 21 | interactive/input.c \ 22 | interactive/input.h \ 23 | interactive/interactive-commands.c \ 24 | interactive/interactive-commands.h \ 25 | interactive/breakpoints.c \ 26 | interactive/filters.c \ 27 | interactive/info.c \ 28 | interactive/objinfo-info.c \ 29 | interactive/pass.c \ 30 | interactive/edit.c \ 31 | interactive/send.c \ 32 | interactive/autocmd.c 33 | 34 | objinfo_sources = \ 35 | objinfo/objinfo.c \ 36 | objinfo/objinfo-private.c \ 37 | objinfo/objinfo-private.h \ 38 | objinfo/xdg-objinfo.c \ 39 | objinfo/wl_surface-objinfo.c \ 40 | objinfo/wl_shm-objinfo.c \ 41 | objinfo/wl_registry-objinfo.c \ 42 | objinfo/wl_seat-objinfo.c 43 | 44 | # XXX do it conditional 45 | hardcoded_interfaces = \ 46 | ../protocols/xdg-shell-protocol.c \ 47 | ../protocols/wayland-drm-protocol.c 48 | 49 | # libwldbg contains functions that we provide to 50 | # passses, like wldbg_parse_message etc. 51 | libwldbg_la_SOURCES = \ 52 | wldbg-ids-map.c \ 53 | wldbg-ids-map.h \ 54 | resolve.h \ 55 | resolve.c \ 56 | print.c \ 57 | loop.c \ 58 | parse-message.c 59 | 60 | include_HEADERS = \ 61 | wldbg.h \ 62 | wldbg-pass.h \ 63 | wldbg-objects-info.h \ 64 | wldbg-parse-message.h 65 | 66 | AM_CPPFLAGS = \ 67 | -I$(top_srcdir) \ 68 | -I$(top_srcdir)/src \ 69 | -DLIBDIR='"$(libdir)"' 70 | AM_CFLAGS = \ 71 | $(CFLAGS) \ 72 | $(WAYLAND_SERVER_CFLAGS) \ 73 | $(WAYLAND_CLIENT_CFLAGS) 74 | 75 | wldbg_LDFLAGS = -ldl -lwayland-client 76 | wldbg_LDADD = libwldbg.la 77 | wldbg_SOURCES = \ 78 | wldbg.c \ 79 | wldbg-private.h \ 80 | passes.c \ 81 | passes.h \ 82 | sockets.c \ 83 | sockets.h \ 84 | getopt.c \ 85 | getopt.h \ 86 | util.c \ 87 | util.h \ 88 | $(wayland_files) \ 89 | $(hardcoded_passes) \ 90 | $(hardcoded_interfaces) \ 91 | $(interactive_sources) \ 92 | $(objinfo_sources) 93 | 94 | if ENABLE_DEBUG 95 | # enable debugging fetures. That include debugging messages 96 | # backtraces and syscall checks 97 | wldbg_SOURCES += debug.c 98 | endif 99 | 100 | pkgconfigdir = $(libdir)/pkgconfig 101 | pkgconfig_DATA = wldbg.pc 102 | 103 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "config.h" 27 | 28 | #ifdef DEBUG 29 | 30 | #define _GNU_SOURCE 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | int debug = 0; 45 | int debug_verbose = 0; 46 | const char *debug_domain = NULL; 47 | 48 | static int abort_on_check_failure; 49 | static int dbg_on_check_failure; 50 | 51 | static void 52 | init_syscalls_check(void); 53 | 54 | void 55 | debug_init(void) 56 | { 57 | const char *dbg_env = getenv("WLDBG_DEBUG"); 58 | if (dbg_env) { 59 | debug = 1; 60 | 61 | if (strcmp(dbg_env, "verbose") == 0 62 | || strcmp(dbg_env, "v") == 0) { 63 | debug_verbose = 1; 64 | } else if (strncmp(dbg_env + strlen(dbg_env) - 2, ".c", 2) == 0) { 65 | debug_verbose = 1; 66 | debug_domain = dbg_env; 67 | } 68 | } 69 | 70 | init_syscalls_check(); 71 | } 72 | 73 | /* copied from weston, modified */ 74 | static void 75 | print_backtrace(void) 76 | { 77 | void *buffer[32]; 78 | int i, count; 79 | Dl_info info; 80 | 81 | count = backtrace(buffer, sizeof(buffer)/sizeof *buffer); 82 | for (i = 0; i < count; i++) { 83 | dladdr(buffer[i], &info); 84 | fprintf(stderr, " [%016lx] %s (%s)\n", 85 | (long) buffer[i], 86 | info.dli_sname ? info.dli_sname : "--", 87 | info.dli_fname); 88 | } 89 | } 90 | 91 | static int (*sys_close)(int fd); 92 | 93 | static void 94 | check_failed(const char *msg, ...) 95 | { 96 | va_list args; 97 | int err; 98 | 99 | if (abort_on_check_failure) 100 | abort(); 101 | else if (dbg_on_check_failure) 102 | #if defined(__amd64__) || defined(__i386__) 103 | asm("int3"); 104 | #else 105 | raise(SIGTRAP); 106 | #endif 107 | else { 108 | err = errno; /* save for sure */ 109 | 110 | fprintf(stderr, "wldbg - "); 111 | 112 | va_start(args, msg); 113 | vfprintf(stderr, msg, args); 114 | va_end(args); 115 | 116 | fprintf(stderr, ": %s\n", strerror(err)); 117 | 118 | print_backtrace(); 119 | } 120 | } 121 | 122 | __attribute__ ((visibility("default"))) int 123 | close(int fd) 124 | { 125 | int ret = sys_close(fd); 126 | if (ret == -1) 127 | check_failed("close fd %d", fd); 128 | 129 | return ret; 130 | } 131 | 132 | static void 133 | init_syscalls_check(void) 134 | { 135 | const char *env = getenv("WLDBG_SYSCALLS_CHECK"); 136 | if (env) { 137 | if (strcmp(env, "abort") == 0) 138 | abort_on_check_failure = 1; 139 | else if (strcmp(env, "trap") == 0) 140 | dbg_on_check_failure = 1; 141 | } 142 | 143 | sys_close = dlsym(RTLD_NEXT, "close"); 144 | } 145 | 146 | #endif /* DEBUG */ 147 | -------------------------------------------------------------------------------- /src/getopt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #define _GNU_SOURCE 27 | 28 | #include 29 | #include 30 | 31 | #include "wldbg-private.h" 32 | #include "getopt.h" 33 | 34 | static int 35 | is_prefix_of(const char *what, const char *src) 36 | { 37 | assert(what); 38 | assert(src); 39 | 40 | while (*what) { 41 | /* src is shorter than what */ 42 | if (!*src) 43 | return 0; 44 | 45 | if (*what != *src) 46 | return 0; 47 | 48 | ++what; 49 | ++src; 50 | } 51 | 52 | return 1; 53 | } 54 | 55 | static int 56 | set_opt(const char *arg, struct wldbg_options *opts) 57 | { 58 | int match = 0; 59 | 60 | if (*arg == '\0') { 61 | fprintf(stderr, "Error: empty option\n"); 62 | return 0; 63 | } 64 | 65 | if (is_prefix_of(arg, "help")) { 66 | return 0; 67 | } else if (is_prefix_of(arg, "interactive")) { 68 | dbg("Command line option: interactive\n"); 69 | opts->interactive = 1; 70 | match = 1; 71 | } else if (is_prefix_of(arg, "server-mode")) { 72 | dbg("Command line option: server-mode\n"); 73 | opts->server_mode = 1; 74 | match = 1; 75 | } else if (is_prefix_of(arg, "pass-whole-buffer")) { 76 | dbg("Command line option: pass-whole-buffer\n"); 77 | opts->pass_whole_buffer = 1; 78 | match = 1; 79 | } else if (is_prefix_of(arg, "objinfo")) { 80 | dbg("Command line option: objinfo\n"); 81 | opts->objinfo = 1; 82 | match = 1; 83 | } 84 | 85 | if (!match) { 86 | fprintf(stderr, "Ignoring unknown option: %s\n", arg); 87 | } 88 | 89 | return 1; 90 | } 91 | 92 | int get_opts(int argc, char *argv[], struct wldbg_options *opts) 93 | { 94 | int n = 1; 95 | for (; n < argc; ++n) { 96 | /* separator */ 97 | if (strcmp("--", argv[n]) == 0) { 98 | ++n; 99 | break; 100 | } 101 | 102 | /* options */ 103 | if (is_prefix_of("--", argv[n])) { 104 | if (!set_opt(argv[n] + 2, opts)) 105 | return -1; 106 | } else if (is_prefix_of("-", argv[n])) { 107 | /* -g is a synonym for objinfo */ 108 | if (argv[n][1] == 'g' && argv[n][2] == 0) { 109 | /* objinfo */ 110 | set_opt("objinfo", opts); 111 | continue; 112 | } 113 | 114 | if (!set_opt(argv[n] + 1, opts)) 115 | return -1; 116 | } else 117 | break; 118 | } 119 | 120 | dbg("Passes or programs are starting at %d\n", n); 121 | /* return how many options we have */ 122 | return n; 123 | } 124 | -------------------------------------------------------------------------------- /src/getopt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_GETOPT_H_ 27 | #define _WLDBG_GETOPT_H_ 28 | 29 | struct wldbg_options { 30 | unsigned int interactive : 1; 31 | unsigned int objinfo : 1; 32 | unsigned int server_mode : 1; 33 | unsigned int pass_whole_buffer : 1; 34 | 35 | /* parsed path to the program and 36 | * its arguments */ 37 | char *path; 38 | int argc; 39 | char **argv; 40 | }; 41 | 42 | int get_opts(int argc, char *argv[], struct wldbg_options *opts); 43 | 44 | #endif /* _WLDBG_GETOPT_H_ */ 45 | -------------------------------------------------------------------------------- /src/interactive/autocmd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "wayland/wayland-private.h" 33 | 34 | #include "wldbg-pass.h" 35 | #include "interactive.h" 36 | #include "passes.h" 37 | #include "wldbg-private.h" 38 | #include "interactive-commands.h" 39 | #include "util.h" 40 | 41 | void 42 | cmd_autocmd_help(int oneline) 43 | { 44 | if (oneline) { 45 | printf("Add, remove commands that are run automatically"); 46 | return; 47 | } 48 | 49 | printf("Possible arguments:\n"); 50 | printf("\tadd\t\t- add new autocmd\n"); 51 | printf("\t syntax: add FILTER COMMAND\n"); 52 | printf("\t where REGEXP is an regular expression that is matched against a message\n"); 53 | printf("\tremove ID\t- remove autocmd identified by ID\n"); 54 | } 55 | 56 | static struct autocmd * 57 | create_autocmd(const char *pattern, const char *cmd) 58 | { 59 | static unsigned int autocmd_id; 60 | struct autocmd *ac; 61 | 62 | ac = calloc(1, sizeof *ac); 63 | if (!ac) { 64 | fprintf(stderr, "No memory\n"); 65 | return NULL; 66 | } 67 | 68 | ac->filter = strdup(pattern); 69 | if (!ac->filter) { 70 | fprintf(stderr, "No memory\n"); 71 | goto err; 72 | } 73 | 74 | ac->cmd = strdup(cmd); 75 | if (!ac->cmd) { 76 | fprintf(stderr, "No memory\n"); 77 | goto err; 78 | } 79 | 80 | if (regcomp(&ac->regex, pattern, REG_EXTENDED) != 0) { 81 | fprintf(stderr, "Failed compiling regular expression\n"); 82 | goto err; 83 | } 84 | 85 | ac->id = autocmd_id++; 86 | 87 | return ac; 88 | 89 | err: 90 | free(ac->filter); 91 | free(ac->cmd); 92 | free(ac); 93 | return NULL; 94 | } 95 | 96 | char * 97 | split_buffer(char *buf, char terminator) 98 | { 99 | assert(buf); 100 | if (*buf == 0) 101 | return NULL; 102 | 103 | while (*buf != 0) { 104 | /* if the command has given start and end, 105 | * respect that */ 106 | if (terminator) { 107 | /* it is safe to access buf - 1 because in the buffer 108 | * there is at least "" in this case */ 109 | if (*buf == terminator && *(buf - 1) != '\\') 110 | break; 111 | } else { /* otherwise split on space */ 112 | if (isspace(*buf)) 113 | break; 114 | } 115 | 116 | ++buf; 117 | } 118 | 119 | *buf = 0; 120 | return skip_ws(buf+1); 121 | } 122 | 123 | void 124 | add_autocmd(struct wldbg_interactive *wldbgi, char *buf) 125 | { 126 | struct autocmd *ac; 127 | char *cmd; 128 | 129 | char terminator = 0; 130 | /* XXX some other terminators? */ 131 | /* this is the case when the regexp is covered 132 | * in "" or '' due to whitespaces */ 133 | if (*buf == '\"' || *buf == '\'') { 134 | terminator = *buf; 135 | ++buf; /* skip the terminator */ 136 | } 137 | 138 | cmd = split_buffer(buf, terminator); 139 | if (!cmd) { 140 | printf("Failed parsing command in: '%s'\n", buf); 141 | return; 142 | } 143 | 144 | ac = create_autocmd(buf, cmd); 145 | if (!ac) 146 | return; 147 | 148 | wl_list_insert(wldbgi->autocmds.next, &ac->link); 149 | printf("Added autocmd '%s' on '%s'\n", cmd, buf); 150 | } 151 | 152 | /* copied from breakpoints.c */ 153 | int 154 | message_match_autocmd(struct wldbg_message *msg, struct autocmd *ac) 155 | { 156 | char buf[128]; 157 | int ret; 158 | 159 | ret = wldbg_get_message_name(msg, buf, sizeof buf); 160 | if (ret >= (int) sizeof buf) { 161 | fprintf(stderr, "BUG: buffer too small for message name\n"); 162 | return 0; 163 | } 164 | 165 | /* run regular expression */ 166 | ret = regexec(&ac->regex, buf, 0, NULL, 0); 167 | 168 | /* got we match? */ 169 | if (ret == 0) { 170 | return 1; 171 | } else if (ret != REG_NOMATCH) 172 | fprintf(stderr, "Executing regexp failed!\n"); 173 | 174 | return 0; 175 | } 176 | 177 | /* FIXME - don't duplicate code with filters */ 178 | static void 179 | remove_autocmd(struct wldbg_interactive *wldbgi, char *buf) 180 | { 181 | unsigned int id; 182 | int found = 0; 183 | struct autocmd *ac, *tmp; 184 | 185 | if (!*buf) { 186 | cmd_filter_help(0); 187 | return; 188 | } 189 | 190 | if (sscanf(buf, "%u", &id) != 1) { 191 | printf("Failed parsing autocmds's id '%s'\n", buf); 192 | return; 193 | } 194 | 195 | wl_list_for_each_safe(ac, tmp, &wldbgi->autocmds, link) { 196 | if (ac->id == id) { 197 | found = 1; 198 | wl_list_remove(&ac->link); 199 | 200 | regfree(&ac->regex); 201 | free(ac->cmd); 202 | free(ac->filter); 203 | free(ac); 204 | break; 205 | } 206 | } 207 | 208 | if (!found) 209 | printf("Didn't find autocmd with id '%u'\n", id); 210 | } 211 | 212 | /* FIXME: implement it using breakpoints - add new private (?) API 213 | * wldbg_run_on_message() and implement breakpoints, filters and autocommands 214 | * on this (breakpoints will run function that will set wldbgi->stop and similar) 215 | */ 216 | int 217 | cmd_autocmd(struct wldbg_interactive *wldbgi, 218 | struct wldbg_message *message, 219 | char *buf) 220 | { 221 | (void) message; 222 | 223 | if (strncmp(buf, "add ", 4) == 0) { 224 | add_autocmd(wldbgi, skip_ws(buf + 4)); 225 | } else if (strncmp(buf, "remove ", 7) == 0) { 226 | remove_autocmd(wldbgi, skip_ws(buf + 7)); 227 | } else 228 | cmd_pass_help(0); 229 | 230 | return CMD_CONTINUE_QUERY; 231 | } 232 | 233 | -------------------------------------------------------------------------------- /src/interactive/edit.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "wayland/wayland-private.h" 34 | 35 | #include "wldbg-private.h" 36 | #include "wldbg-parse-message.h" 37 | #include "interactive.h" 38 | 39 | static char * 40 | store_message_to_tmpfile(struct wldbg_message *message) 41 | { 42 | int fd, ret; 43 | /* I don't suppose anybody would attack this program, 44 | * so use dangerous function */ 45 | char *file = tempnam(NULL, "wldbg-msg"); 46 | if (!file) { 47 | perror("Creating tmp file for storing a message"); 48 | return NULL; 49 | } 50 | 51 | vdbg("Created %s for storing message\n", file); 52 | 53 | fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0700); 54 | if (!fd) { 55 | perror("Opening tmp file for writing"); 56 | free(file); 57 | return NULL; 58 | } 59 | 60 | ret = write(fd, message->data, message->size); 61 | if ((size_t) ret != message->size) { 62 | if (ret < 0) 63 | perror("writing data to tmp file"); 64 | else 65 | fprintf(stderr, "Wrote less bytes than expected, taking" 66 | "it as an error (%d vs %lu)\n", ret, 67 | message->size); 68 | free(file); 69 | close(fd); 70 | return NULL; 71 | } 72 | 73 | close(fd); 74 | return file; 75 | } 76 | 77 | static int 78 | read_message_from_tmpfile(char *file, struct wldbg_message *message) 79 | { 80 | int fd, ret; 81 | assert(file); 82 | 83 | fd = open(file, O_RDONLY); 84 | if (!fd) { 85 | perror("Opening tmp file for reading"); 86 | return -1; 87 | } 88 | 89 | /* XXX do not use hard-coded numbers... */ 90 | /* size of the buffer is 4096 atm */ 91 | ret = read(fd, message->data, 4096); 92 | if (ret < 0) { 93 | perror("Reading tmp file\n"); 94 | close(fd); 95 | return -1; 96 | } 97 | 98 | assert(ret <= 4096); 99 | message->size = ret; 100 | 101 | close(fd); 102 | return 0; 103 | } 104 | 105 | static void 106 | destroy_message_tmpfile(char *file) 107 | { 108 | if (unlink(file) < 0) 109 | perror("Deleting tmp file"); 110 | free(file); 111 | } 112 | 113 | void 114 | cmd_edit_help(int oneline) 115 | { 116 | printf("Edit message"); 117 | if (oneline) 118 | return; 119 | 120 | printf(" :: edit [editor]\n\n" 121 | "Edit message wldbg stopped on. If no editor is given,\n" 122 | "wldbg looks for one in EDITOR env. variable.\n"); 123 | } 124 | 125 | int 126 | cmd_edit(struct wldbg_interactive *wldbgi, 127 | struct wldbg_message *message, 128 | char *buf) 129 | { 130 | const char *editor; 131 | char *cmd, *msg_file, edstr[128]; 132 | size_t size = 1024; 133 | int ret; 134 | 135 | (void) wldbgi; 136 | 137 | if (*buf != '\0') { 138 | sscanf(buf, "%127s", edstr); 139 | editor = edstr; 140 | } else 141 | editor = getenv("$EDITOR"); 142 | 143 | /* XXX add inline editing (just dump the message to command line 144 | * and edit it in place */ 145 | if (!editor) { 146 | fprintf(stderr, "No edtor to use. Use 'edit editor_name' or " 147 | "set $EDITOR environment variable\n"); 148 | return CMD_CONTINUE_QUERY; 149 | } 150 | 151 | msg_file = store_message_to_tmpfile(message); 152 | if (!msg_file) 153 | /* the error was written out in the function */ 154 | return CMD_CONTINUE_QUERY; 155 | 156 | do { 157 | cmd = malloc(sizeof(char) * size); 158 | if (!cmd) { 159 | fprintf(stderr, "No memory\n"); 160 | destroy_message_tmpfile(msg_file); 161 | return CMD_CONTINUE_QUERY; 162 | } 163 | 164 | ret = snprintf(cmd, size, "%s %s", editor, msg_file); 165 | if (ret < 0) { 166 | perror("Constituting a command"); 167 | destroy_message_tmpfile(msg_file); 168 | free(cmd); 169 | return CMD_CONTINUE_QUERY; 170 | } else if ((size_t) ret >= size) { /* cmd string too small */ 171 | size *= 2; 172 | free(cmd); 173 | cmd = NULL; 174 | } 175 | } while (!cmd); 176 | 177 | dbg("executing: %s\n", cmd); 178 | /* XXX maybe use popen? */ 179 | if (system(cmd) != 0) { 180 | fprintf(stderr, "Executing edit command has returned" 181 | " non-zero value\n"); 182 | } else { 183 | read_message_from_tmpfile(msg_file, message); 184 | } 185 | 186 | printf("message edited to: "); 187 | wldbg_message_print(message); 188 | 189 | free(cmd); 190 | destroy_message_tmpfile(msg_file); 191 | /* continue or end?? */ 192 | return CMD_CONTINUE_QUERY; 193 | } 194 | 195 | -------------------------------------------------------------------------------- /src/interactive/filters.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "wayland/wayland-private.h" 32 | 33 | #include "wldbg.h" 34 | #include "interactive.h" 35 | #include "util.h" 36 | 37 | static struct filter * 38 | create_filter(const char *pattern) 39 | { 40 | static unsigned int pf_id; 41 | struct filter *pf; 42 | 43 | pf = malloc(sizeof *pf); 44 | if (!pf) { 45 | fprintf(stderr, "No memory\n"); 46 | return NULL; 47 | } 48 | 49 | pf->filter = strdup(pattern); 50 | if (!pf->filter) { 51 | free(pf); 52 | fprintf(stderr, "No memory\n"); 53 | return NULL; 54 | } 55 | 56 | if (regcomp(&pf->regex, pattern, REG_EXTENDED) != 0) { 57 | fprintf(stderr, "Failed compiling regular expression\n"); 58 | free(pf->filter); 59 | free(pf); 60 | return NULL; 61 | } 62 | 63 | pf->id = pf_id++; 64 | 65 | return pf; 66 | } 67 | 68 | static int 69 | cmd_create_filter(struct wldbg_interactive *wldbgi, 70 | char *buf, int show_only) 71 | { 72 | struct filter *pf; 73 | char filter[128]; 74 | 75 | sscanf(buf, "%s", filter); 76 | 77 | pf = create_filter(filter); 78 | if (!pf) 79 | return CMD_CONTINUE_QUERY; 80 | 81 | pf->show_only = show_only; 82 | wl_list_insert(wldbgi->filters.next, &pf->link); 83 | 84 | printf("Filtering messages: %s%s\n", 85 | show_only ? "" : "hide ", filter); 86 | 87 | return CMD_CONTINUE_QUERY; 88 | } 89 | 90 | void 91 | cmd_hide_help(int oneline) 92 | { 93 | if (oneline) 94 | printf("Hide particular messages"); 95 | else 96 | printf("Hide messages matching given extended regular expression\n\n" 97 | "hide REGEXP\n"); 98 | } 99 | 100 | int 101 | cmd_hide(struct wldbg_interactive *wldbgi, 102 | struct wldbg_message *message, 103 | char *buf) 104 | { 105 | (void) message; 106 | 107 | buf = skip_ws(buf); 108 | if (!*buf) { 109 | cmd_hide_help(0); 110 | return CMD_CONTINUE_QUERY; 111 | } 112 | 113 | return cmd_create_filter(wldbgi, buf, 0); 114 | } 115 | 116 | void 117 | cmd_showonly_help(int oneline) 118 | { 119 | if (oneline) 120 | printf("Show only particular messages"); 121 | else 122 | printf("Show only messages matching given extended regular expression.\n" 123 | "Filters are accumulated, so the message is shown if\n" 124 | "it matches any of showonly commands\n\n" 125 | "showonly REGEXP\n"); 126 | } 127 | 128 | int 129 | cmd_showonly(struct wldbg_interactive *wldbgi, 130 | struct wldbg_message *message, 131 | char *buf) 132 | { 133 | (void) message; 134 | 135 | buf = skip_ws(buf); 136 | if (!*buf) { 137 | cmd_showonly_help(0); 138 | return CMD_CONTINUE_QUERY; 139 | } 140 | 141 | 142 | return cmd_create_filter(wldbgi, buf, 1); 143 | } 144 | 145 | void 146 | cmd_filter_help(int oneline) 147 | { 148 | printf("Mange filters created by showonly and hide commands"); 149 | if (oneline) 150 | return; 151 | 152 | printf("\n\n" 153 | " :: filter delete|remove|d|r ID\n"); 154 | } 155 | 156 | static void 157 | remove_filter(struct wldbg_interactive *wldbgi, char *buf) 158 | { 159 | unsigned int id; 160 | int found = 0; 161 | struct filter *pf, *tmp; 162 | 163 | if (!*buf) { 164 | cmd_filter_help(0); 165 | return; 166 | } 167 | 168 | if (sscanf(buf, "%u", &id) != 1) { 169 | printf("Failed parsing filter's id '%s'\n", buf); 170 | return; 171 | } 172 | 173 | wl_list_for_each_safe(pf, tmp, &wldbgi->filters, link) { 174 | if (pf->id == id) { 175 | found = 1; 176 | wl_list_remove(&pf->link); 177 | 178 | regfree(&pf->regex); 179 | free(pf->filter); 180 | free(pf); 181 | break; 182 | } 183 | } 184 | 185 | if (!found) 186 | printf("Didn't find filter with id '%u'\n", id); 187 | } 188 | 189 | int 190 | cmd_filter(struct wldbg_interactive *wldbgi, 191 | struct wldbg_message *message, char *buf) 192 | { 193 | (void) message; 194 | 195 | if (strncmp(buf, "delete", 6) == 0 196 | || strncmp(buf, "remove", 6) == 0) 197 | remove_filter(wldbgi, skip_ws(buf + 6)); 198 | else if ((*buf == 'd' || *buf == 'r') && isspace(buf[1])) 199 | remove_filter(wldbgi, skip_ws(buf + 1)); 200 | else 201 | cmd_filter_help(0); 202 | 203 | return CMD_CONTINUE_QUERY; 204 | } 205 | -------------------------------------------------------------------------------- /src/interactive/info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "wayland/wayland-private.h" 29 | 30 | #include "interactive.h" 31 | #include "interactive-commands.h" 32 | #include "wldbg-private.h" 33 | #include "util.h" 34 | 35 | static void 36 | print_object(uint32_t id, const struct wl_interface *intf, void *data) 37 | { 38 | (void) data; 39 | if (id >= WL_SERVER_ID_START) 40 | printf("\tSRV %u -> %s\n", 41 | id - WL_SERVER_ID_START, intf ? intf->name : "NULL"); 42 | else 43 | printf("\t%u -> %s\n", id, intf ? intf->name : "NULL"); 44 | } 45 | 46 | static void 47 | print_objects(struct wldbg_message *message) 48 | { 49 | wldbg_message_objects_iterate(message, print_object, NULL); 50 | } 51 | 52 | static void 53 | print_breakpoints(struct wldbg_interactive *wldbgi) 54 | { 55 | struct breakpoint *b; 56 | 57 | if (wl_list_empty(&wldbgi->breakpoints)) { 58 | printf("No breakpoints\n"); 59 | return; 60 | } 61 | 62 | wl_list_for_each(b, &wldbgi->breakpoints, link) { 63 | printf("%u: break on %s\n", b->id, b->description); 64 | } 65 | } 66 | 67 | static void 68 | print_autocmds(struct wldbg_interactive *wldbgi) 69 | { 70 | struct autocmd *ac; 71 | 72 | if (wl_list_empty(&wldbgi->autocmds)) { 73 | printf("No autocommands\n"); 74 | return; 75 | } 76 | 77 | wl_list_for_each(ac, &wldbgi->autocmds, link) { 78 | printf("%u: run '%s' on '%s'\n", ac->id, ac->cmd, ac->filter); 79 | } 80 | } 81 | 82 | static void 83 | print_filters(struct wldbg_interactive *wldbgi) 84 | { 85 | struct filter *pf; 86 | 87 | if (wl_list_empty(&wldbgi->filters)) { 88 | printf("No filters\n"); 89 | return; 90 | } 91 | 92 | wl_list_for_each(pf, &wldbgi->filters, link) { 93 | printf("%u: %s %s\n", pf->id, 94 | pf->show_only ? "show" : "hide", 95 | pf->filter); 96 | } 97 | } 98 | 99 | static void 100 | info_wldbg(struct wldbg_interactive *wldbgi) 101 | { 102 | struct wldbg *wldbg = wldbgi->wldbg; 103 | 104 | printf("\n-- Wldbg -- \n"); 105 | 106 | printf("Monitored fds num: %d\n", wl_list_length(&wldbg->monitored_fds)); 107 | printf("Resolving objects: %d\n", wldbg->resolving_objects); 108 | printf("Gathering objinfo: %d\n", wldbg->gathering_info); 109 | printf("Flags:" 110 | "\tpass_whole_buffer : %u\n" 111 | "\trunning : %u\n" 112 | "\terror : %u\n" 113 | "\texit : %u\n" 114 | "\tserver_mode : %u\n", 115 | wldbg->flags.pass_whole_buffer, 116 | wldbg->flags.running, 117 | wldbg->flags.error, 118 | wldbg->flags.exit, 119 | wldbg->flags.server_mode); 120 | 121 | if (!wldbg->flags.server_mode) 122 | return; 123 | 124 | printf("Server mode:\n" 125 | "\told socket name: \'%s\'\n" 126 | "\told socket path: \'%s\'\n" 127 | "\twldbg socket path: \'%s\'\n" 128 | "\twldbg socket path: \'%s\'\n" 129 | "\tlock address: \'%s\'\n" 130 | "\tconnect to: \'%s\'\n", 131 | wldbg->server_mode.old_socket_path, 132 | wldbg->server_mode.wldbg_socket_path, 133 | wldbg->server_mode.old_socket_name, 134 | wldbg->server_mode.wldbg_socket_name, 135 | wldbg->server_mode.lock_addr, 136 | wldbg->server_mode.connect_to); 137 | 138 | printf("Connections number: %d\n", wldbg->connections_num); 139 | } 140 | 141 | static void 142 | info_connections(struct wldbg_interactive *wldbgi) 143 | { 144 | struct wldbg *wldbg = wldbgi->wldbg; 145 | struct wldbg_connection *conn; 146 | int i; 147 | int n = 0; 148 | 149 | printf("\n-- Connections -- \n"); 150 | wl_list_for_each(conn, &wldbg->connections, link) { 151 | ++n; 152 | 153 | printf("%d.\n", n); 154 | printf("\tserver: pid=%d\n", conn->server.pid); 155 | printf("\tclient: pid=%d\n", conn->client.pid); 156 | printf("\t : program=\'%s\'\n", conn->client.program); 157 | printf("\t : path=\'%s\'\n", conn->client.path); 158 | printf("\t : argc=\'%d\'\n", conn->client.argc); 159 | for (i = 0; i < conn->client.argc; ++i) 160 | printf("\t : argv[%d]=\'%s\'\n", 161 | i, conn->client.argv[i]); 162 | 163 | } 164 | } 165 | 166 | void 167 | cmd_info_help(int oneline) 168 | { 169 | if (oneline) { 170 | printf("Show info about entities"); 171 | return; 172 | } 173 | 174 | printf("info WHAT (i WHAT)\n" 175 | "\n" 176 | "objects (o)\n" 177 | "objects (o) ID\n" 178 | "message (m)\n" 179 | "breakpoints (b)\n" 180 | "filters (f)\n" 181 | "process (proc, p)\n" 182 | "connection (conn, c)\n"); 183 | } 184 | 185 | void 186 | print_object_info(struct wldbg_message *msg, char *buf); 187 | 188 | static void 189 | print_objects_info(struct wldbg_message *message, char *buf) 190 | { 191 | char *id = skip_ws(buf); 192 | if (*id) 193 | print_object_info(message, id); 194 | else 195 | print_objects(message); 196 | } 197 | 198 | int 199 | cmd_info(struct wldbg_interactive *wldbgi, 200 | struct wldbg_message *message, char *buf) 201 | { 202 | #define MATCH(buf, str) (strncmp((buf), (str), (sizeof((str)) + 1)) == 0) 203 | 204 | if (MATCH(buf, "m") || MATCH(buf, "message")) { 205 | printf("Sender: %s (no. %lu), size: %lu\n", 206 | message->from == SERVER ? "server" : "client", 207 | message->from == SERVER ? wldbgi->statistics.server_msg_no 208 | : wldbgi->statistics.client_msg_no, 209 | message->size); 210 | } else if (strncmp(buf, "objects", 7) == 0) { 211 | print_objects_info(message, buf + 7); 212 | } else if (strncmp(buf, "object", 6) == 0) { 213 | print_objects_info(message, buf + 6); 214 | } else if (strncmp(buf, "o", 1) == 0) { 215 | print_objects_info(message, buf + 1); 216 | } else if (MATCH(buf, "b") || MATCH(buf, "breakpoints")) { 217 | print_breakpoints(wldbgi); 218 | } else if (MATCH(buf, "f") || MATCH(buf, "filters")) { 219 | print_filters(wldbgi); 220 | } else if (MATCH(buf, "ac") || MATCH(buf, "autocmd") 221 | || MATCH(buf, "autocommands")) { 222 | print_autocmds(wldbgi); 223 | } else if (MATCH(buf, "p") || MATCH(buf, "proc") 224 | || MATCH(buf, "process")) { 225 | info_wldbg(wldbgi); 226 | info_connections(wldbgi); 227 | } else if (MATCH(buf, "c") || MATCH(buf, "conn") 228 | || MATCH(buf, "connection")) { 229 | info_connections(wldbgi); 230 | } else { 231 | printf("Unknown arguments\n"); 232 | cmd_info_help(0); 233 | } 234 | 235 | return CMD_CONTINUE_QUERY; 236 | 237 | #undef MATCH 238 | } 239 | -------------------------------------------------------------------------------- /src/interactive/input.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "interactive.h" 8 | #include "input.h" 9 | #include "util.h" 10 | 11 | #define WLDBG_PROMPT "(wldbg)" 12 | 13 | #ifdef HAVE_LIBREADLINE 14 | 15 | #include 16 | #include 17 | 18 | char * 19 | wldbgi_read_input(void) 20 | { 21 | return readline(WLDBG_PROMPT " "); 22 | } 23 | 24 | #else /* HAVE_LIBREADLINE */ 25 | 26 | char * 27 | wldbgi_read_input(void) 28 | { 29 | #define DEFAULT_BUFFER_SIZE 1024 30 | char *buf = malloc(DEFAULT_BUFFER_SIZE); 31 | if (!buf) { 32 | fprintf(stderr, "Out of memory\n"); 33 | return NULL; 34 | } 35 | 36 | printf(WLDBG_PROMPT " "); 37 | if (fgets(buf, DEFAULT_BUFFER_SIZE, stdin) == NULL) { 38 | free(buf); 39 | return NULL; 40 | } 41 | 42 | return remove_newline(buf); 43 | } 44 | #endif /* HAVE_LIBREADLINE */ 45 | 46 | char * 47 | wldbgi_get_last_command(struct wldbg_interactive *wldbgi) 48 | { 49 | #if HAVE_READLINE_HISTORY 50 | (void) wldbgi; 51 | 52 | HIST_ENTRY *ent = history_get(where_history()); 53 | if (ent) 54 | return ent->line; 55 | 56 | return NULL; 57 | #else 58 | return wldbgi->last_command; 59 | #endif /* HAVE_READLINE_HISTORY */ 60 | } 61 | 62 | void 63 | wldbgi_add_history(struct wldbg_interactive *wldbgi, const char *cmd) 64 | { 65 | (void) wldbgi; 66 | #if HAVE_READLINE_HISTORY 67 | add_history(cmd); 68 | #else 69 | free(wldbgi->last_command); 70 | wldbgi->last_command = strdup(cmd); 71 | #endif 72 | } 73 | 74 | void 75 | wldbgi_clear_history(struct wldbg_interactive *wldbgi) 76 | { 77 | (void) wldbgi; 78 | #if HAVE_READLINE_HISTORY 79 | clear_history(); 80 | #else 81 | free(wldbgi->last_command); 82 | wldbgi->last_command = NULL; 83 | #endif 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/interactive/input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef WLDBG_INTERACTIVE_INPUT_H_ 27 | #define WLDBG_INTERACTIVE_INPUT_H_ 28 | 29 | char * 30 | wldbgi_read_input(void); 31 | 32 | char * 33 | wldbgi_get_last_command(struct wldbg_interactive *); 34 | 35 | void 36 | wldbgi_add_history(struct wldbg_interactive *, const char *); 37 | 38 | void 39 | wldbgi_clear_history(struct wldbg_interactive *); 40 | 41 | #endif /* WLDBG_INTERACTIVE_INPUT_H_ */ 42 | -------------------------------------------------------------------------------- /src/interactive/interactive-commands.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "interactive.h" 32 | #include "wldbg-private.h" 33 | #include "interactive-commands.h" 34 | #include "util.h" 35 | 36 | void 37 | terminate_client(struct wldbg_connection *conn) 38 | { 39 | pid_t pid = conn->client.pid; 40 | 41 | dbg("Terminating client %d\n", pid); 42 | 43 | kill(pid, SIGTERM); 44 | waitpid(pid, NULL, 0); 45 | } 46 | 47 | static void 48 | cmd_quit_help(int oneline) 49 | { 50 | if (oneline) 51 | printf("Quit wldbg"); 52 | 53 | } 54 | 55 | int 56 | cmd_quit(struct wldbg_interactive *wldbgi, 57 | struct wldbg_message *message, 58 | char *buf) 59 | { 60 | int chr; 61 | 62 | (void) message; 63 | (void) buf; 64 | 65 | if (wldbgi->wldbg->flags.running 66 | && !wldbgi->wldbg->flags.error 67 | && !wl_list_empty(&wldbgi->wldbg->connections)) { 68 | 69 | printf("Program seems running. " 70 | "Do you really want to quit? (y)\n"); 71 | 72 | chr = getchar(); 73 | if (chr == 'y') { 74 | wldbg_foreach_connection(wldbgi->wldbg, 75 | terminate_client); 76 | } else { 77 | /* clear buffer */ 78 | while (getchar() != '\n') 79 | ; 80 | 81 | return CMD_CONTINUE_QUERY; 82 | } 83 | } 84 | 85 | dbg("Exiting...\n"); 86 | 87 | wldbgi->wldbg->flags.exit = 1; 88 | 89 | return CMD_END_QUERY; 90 | } 91 | 92 | static void 93 | cmd_next_help(int oneline) 94 | { 95 | if (oneline) 96 | printf("Wait for next message and stop on it"); 97 | 98 | } 99 | 100 | static int 101 | cmd_next(struct wldbg_interactive *wldbgi, 102 | struct wldbg_message *message, 103 | char *buf) 104 | { 105 | (void) message; 106 | (void) buf; 107 | 108 | if (!wldbgi->wldbg->flags.running) { 109 | printf("Client is not running\n"); 110 | return CMD_CONTINUE_QUERY; 111 | } 112 | 113 | wldbgi->stop = 1; 114 | return CMD_END_QUERY; 115 | } 116 | 117 | static void 118 | cmd_continue_help(int oneline) 119 | { 120 | if (oneline) 121 | printf("Continue running program"); 122 | 123 | } 124 | 125 | static int 126 | cmd_continue(struct wldbg_interactive *wldbgi, 127 | struct wldbg_message *message, 128 | char *buf) 129 | { 130 | (void) message; 131 | (void) buf; 132 | 133 | if (!wldbgi->wldbg->flags.running) { 134 | printf("Client is not running\n"); 135 | return CMD_CONTINUE_QUERY; 136 | } 137 | 138 | return CMD_END_QUERY; 139 | } 140 | 141 | static int 142 | cmd_help(struct wldbg_interactive *wldbgi, 143 | struct wldbg_message *message, char *buf); 144 | 145 | static void 146 | cmd_help_help(int oneline) 147 | { 148 | if (oneline) 149 | printf("Show this help message"); 150 | else 151 | printf("Print help message. Given argument 'all', print " 152 | "comprehensive help about all commands.\n"); 153 | } 154 | 155 | /* XXX keep sorted! (in the future I'd like to do 156 | * binary search in this array */ 157 | const struct command commands[] = { 158 | {"autocmd", NULL, cmd_autocmd, cmd_autocmd_help}, 159 | {"break", "b", cmd_break, cmd_break_help}, 160 | {"continue", "c", cmd_continue, cmd_continue_help}, 161 | {"edit", "e", cmd_edit, cmd_edit_help}, 162 | {"filter", "f", cmd_filter, cmd_filter_help}, 163 | {"help", NULL, cmd_help, cmd_help_help}, 164 | {"hide", "h", cmd_hide, cmd_hide_help}, 165 | {"info", "i", cmd_info, cmd_info_help}, 166 | {"next", "n", cmd_next, cmd_next_help}, 167 | {"pass", NULL, cmd_pass, cmd_pass_help}, 168 | {"send", "s", cmd_send, cmd_send_help}, 169 | {"showonly", "so", cmd_showonly, cmd_showonly_help}, 170 | {"quit", "q", cmd_quit, cmd_quit_help}, 171 | 172 | }; 173 | 174 | static int 175 | is_the_cmd(char *buf, const struct command *cmd) 176 | { 177 | int len = 0; 178 | 179 | /* try short version first */ 180 | if (cmd->shortcut) 181 | len = strlen(cmd->shortcut); 182 | 183 | if (len && strncmp(buf, cmd->shortcut, len) == 0 184 | && (isspace(buf[len]) || buf[len] == '\0')) { 185 | vdbg("identifying command: short '%s' match\n", cmd->shortcut); 186 | return 1; 187 | } 188 | 189 | /* this must be set */ 190 | assert(cmd->name && "Each command must have long form"); 191 | 192 | len = strlen(cmd->name); 193 | assert(len); 194 | 195 | if (strncmp(buf, cmd->name, len) == 0 196 | && (isspace(buf[len]) || buf[len] == '\0')) { 197 | vdbg("identifying command: long '%s' match\n", cmd->name); 198 | return 1; 199 | } 200 | 201 | vdbg("identifying command: no match\n"); 202 | return 0; 203 | } 204 | 205 | static int 206 | cmd_help(struct wldbg_interactive *wldbgi, 207 | struct wldbg_message *message, char *buf) 208 | { 209 | size_t i; 210 | int all = 0, found = 0; 211 | 212 | (void) wldbgi; 213 | (void) message; 214 | 215 | if (strcmp(buf, "all") == 0) 216 | all = 1; 217 | 218 | buf = skip_ws(buf); 219 | if (!all && *buf) { 220 | for (i = 0; i < sizeof commands / sizeof *commands; ++i) { 221 | if (is_the_cmd(buf, &commands[i])) { 222 | found = 1; 223 | if (commands[i].help) 224 | commands[i].help(0); 225 | else 226 | printf("No help for this command\n"); 227 | } 228 | } 229 | 230 | if (!found) 231 | printf("No such command\n"); 232 | 233 | return CMD_CONTINUE_QUERY; 234 | } 235 | 236 | putchar ('\n'); 237 | 238 | if (!all) 239 | printf("Try 'help all' or 'help command_name' for verbose output\n\n"); 240 | 241 | for (i = 0; i < sizeof commands / sizeof *commands; ++i) { 242 | if (all) 243 | printf(" == "); 244 | else 245 | printf("\t"); 246 | 247 | printf("%-12s (%s)", 248 | commands[i].name, 249 | commands[i].shortcut ? commands[i].shortcut : "-"); 250 | 251 | if (all) 252 | printf(" ==\n\n"); 253 | 254 | if (commands[i].help) { 255 | if (all) { 256 | commands[i].help(0); 257 | } else { 258 | printf("\t -- "); 259 | commands[i].help(1); 260 | } 261 | } 262 | 263 | if (all) 264 | putchar('\n'); 265 | putchar('\n'); 266 | } 267 | 268 | fflush(stdout); 269 | return CMD_CONTINUE_QUERY; 270 | } 271 | 272 | static char * 273 | next_word(char *str) 274 | { 275 | int i = 0; 276 | 277 | /* skip the first word if anything left */ 278 | while(isalpha(*(str + i)) && *(str + i) != 0) 279 | ++i; 280 | /* skip whitespaces before the other word */ 281 | while (isspace(*(str + i)) && *(str + i) != 0) 282 | ++i; 283 | 284 | return str + i; 285 | } 286 | 287 | int 288 | run_command(char *buf, 289 | struct wldbg_interactive *wldbgi, struct wldbg_message *message) 290 | { 291 | size_t n; 292 | 293 | for (n = 0; n < (sizeof commands / sizeof *commands); ++n) { 294 | if (is_the_cmd(buf, &commands[n])) 295 | return commands[n].func(wldbgi, message, next_word(buf)); 296 | } 297 | 298 | return CMD_DONT_MATCH; 299 | } 300 | -------------------------------------------------------------------------------- /src/interactive/interactive-commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_INTERACTIVE_COMMANDS_H_ 27 | #define _WLDBG_INTERACTIVE_COMMANDS_H_ 28 | 29 | /* defined in breakpoints */ 30 | int 31 | cmd_break(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 32 | 33 | void 34 | cmd_break_help(int oneline); 35 | 36 | /* defined in filters.c */ 37 | int 38 | cmd_hide(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 39 | 40 | void 41 | cmd_hide_help(int oneline); 42 | 43 | int 44 | cmd_showonly(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 45 | 46 | void 47 | cmd_showonly_help(int oneline); 48 | 49 | void 50 | cmd_filter_help(int oneline); 51 | 52 | int 53 | cmd_filter(struct wldbg_interactive *wldbgi, 54 | struct wldbg_message *message, char *buf); 55 | 56 | /* defined in info.c */ 57 | int 58 | cmd_info(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 59 | 60 | void 61 | cmd_info_help(int oneline); 62 | 63 | /* defined in pass.c */ 64 | void 65 | cmd_pass_help(int oneline); 66 | 67 | int 68 | cmd_pass(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 69 | 70 | /* defined in edit.c */ 71 | int 72 | cmd_edit(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 73 | 74 | void 75 | cmd_edit_help(int); 76 | 77 | /* defined in send.c */ 78 | int 79 | cmd_send(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 80 | 81 | void 82 | cmd_send_help(int oneline); 83 | 84 | /* defined in autocmd.c */ 85 | void 86 | cmd_autocmd_help(int oneline); 87 | 88 | int 89 | cmd_autocmd(struct wldbg_interactive *wldbgi, struct wldbg_message *message, char *buf); 90 | 91 | #endif /* _WLDBG_INTERACTIVE_COMMANDS_H_ */ 92 | -------------------------------------------------------------------------------- /src/interactive/interactive.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_INTERACTIVE_H_ 27 | #define _WLDBG_INTERACTIVE_H_ 28 | 29 | #include 30 | #include 31 | 32 | #include "wldbg.h" 33 | #include "wayland/wayland-util.h" 34 | 35 | struct wldbg_interactive { 36 | struct wldbg *wldbg; 37 | 38 | struct { 39 | uint64_t client_msg_no; 40 | uint64_t server_msg_no; 41 | } statistics; 42 | 43 | /* when we run client from interactive mode, 44 | * we need to store it's credential here, so that 45 | * we can free the allocated memory */ 46 | struct { 47 | char *path; 48 | /* XXX 49 | * add arguments */ 50 | } client; 51 | 52 | int sigint_fd; 53 | 54 | /* query user on the next message */ 55 | int stop; 56 | int skip_first_query; 57 | 58 | /* commands history */ 59 | char *last_command; 60 | 61 | /* breakpoints */ 62 | struct wl_list breakpoints; 63 | 64 | /* filters for printing messages */ 65 | struct wl_list filters; 66 | 67 | /* auto commands */ 68 | struct wl_list autocmds; 69 | }; 70 | 71 | struct command { 72 | /* long form of a command i. e. 'continue' */ 73 | const char *name; 74 | /* short form of a command i. e. 'c' (continue) */ 75 | const char *shortcut; 76 | /* function to be called for the command. The last argument 77 | * is the rest of user's input */ 78 | int (*func)(struct wldbg_interactive *, struct wldbg_message *, char *); 79 | /* this function prints help for the command. 80 | * If argument is not zero, then print short, oneline description */ 81 | void (*help)(int oneline); 82 | }; 83 | 84 | /* exit state of command */ 85 | enum { 86 | CMD_DONT_MATCH, 87 | CMD_END_QUERY, 88 | CMD_CONTINUE_QUERY, 89 | }; 90 | 91 | /* array of all commands */ 92 | extern const struct command commands[]; 93 | 94 | int 95 | run_command(char *buf, 96 | struct wldbg_interactive *wldbgi, struct wldbg_message *message); 97 | 98 | 99 | struct breakpoint { 100 | unsigned int id; 101 | struct wl_list link; 102 | char *description; 103 | 104 | /* this function returns true if wldbg should stop 105 | * on given message */ 106 | int (*applies)(struct wldbg_message *, struct breakpoint *); 107 | void *data; 108 | uint64_t small_data; 109 | /* function to destroy data */ 110 | void (*data_destr)(void *); 111 | }; 112 | 113 | 114 | /* XXX we could use breakpoints to 115 | * implement this */ 116 | struct filter { 117 | char *filter; 118 | regex_t regex; 119 | struct wl_list link; 120 | int show_only; 121 | unsigned int id; 122 | }; 123 | 124 | struct autocmd { 125 | /* command to be run */ 126 | char *cmd; 127 | /* regexp that the messages must match to run this command, 128 | * stored both as a string and as a regex object */ 129 | char *filter; 130 | regex_t regex; 131 | 132 | struct wl_list link; 133 | unsigned int id; 134 | }; 135 | 136 | #endif /* _WLDBG_INTERACTIVE_H_ */ 137 | -------------------------------------------------------------------------------- /src/interactive/objinfo-info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "wayland/wayland-private.h" 32 | 33 | #include "interactive.h" 34 | #include "wldbg-private.h" 35 | #include "objinfo/objinfo-private.h" 36 | #include "wldbg-objects-info.h" 37 | #include "util.h" 38 | 39 | static void 40 | print_wl_buffer_info(struct wldbg_wl_buffer_info *info, int ind) 41 | { 42 | printf("%*s-- wl_buffer --\n", ind, ""); 43 | printf("%*s offset: %d\n", ind, "", info->offset); 44 | printf("%*s size: %dx%d\n", ind, "", info->width, info->height); 45 | printf("%*s stride: %d\n", ind, "", info->stride); 46 | printf("%*s format: %u\n", ind, "", info->format); 47 | } 48 | 49 | static void 50 | print_wl_surface_info(struct wldbg_objects_info *oi, 51 | struct wldbg_wl_surface_info *info, 52 | int ind) 53 | { 54 | printf("%*s-- wl_surface --\n", ind, ""); 55 | printf("%*sCurrent / pending ->\n\n", ind, ""); 56 | printf("%*s wl_buffer: %u\n", ind, "", info->wl_buffer_id); 57 | printf("%*s attached to: %ux%u\n", ind, "", 58 | info->attached_x, info->attached_y); 59 | printf("%*s buffer scale: %u\n", ind, "", info->buffer_scale); 60 | printf("%*s last frame id: %u\n", ind, "", info->last_frame_id); 61 | 62 | if (info->wl_buffer_id != 0) { 63 | printf("\n%*sAttached buffer ->\n", ind, ""); 64 | struct wldbg_object_info *bi 65 | = objects_info_get(oi, info->wl_buffer_id); 66 | if (!bi) 67 | printf("%*sNO BUFFER!\n", ind, ""); 68 | else 69 | print_wl_buffer_info(bi->info, ind + 2); 70 | } 71 | 72 | if (info->commited) { 73 | printf("\n%*sCommited ->\n", ind, ""); 74 | print_wl_surface_info(oi, info->commited, ind + 2); 75 | } 76 | } 77 | 78 | 79 | static void 80 | print_xdg_surface_info(struct wldbg_objects_info *oi, 81 | struct wldbg_xdg_surface_info *xdg_info) 82 | { 83 | uint8_t i = xdg_info->configures_num % 10; 84 | uint8_t ord = 0; 85 | 86 | printf(" -- xdg_surface --\n"); 87 | printf("Tile: '%s'\n", xdg_info->title); 88 | printf("App id: '%s'\n", xdg_info->app_id); 89 | printf("Last 10 configures (out of %lu):\n", xdg_info->configures_num); 90 | for (; ord < 10; ++i, ++ord) { 91 | i = i % 10; 92 | printf(" [%-2u]: width: %5u, height: %5u," 93 | " state: -- , serial: %5u, acked: %u\n", 94 | ord + 1, xdg_info->configures[i].width, 95 | xdg_info->configures[i].height, 96 | xdg_info->configures[i].serial, 97 | xdg_info->configures[i].acked); 98 | } 99 | 100 | struct wldbg_object_info *info 101 | = objects_info_get(oi, xdg_info->wl_surface_id); 102 | assert (info && "has no wl_surface info in xdg_surface"); 103 | 104 | print_wl_surface_info(oi, info->info, 2); 105 | } 106 | 107 | static void 108 | print_capabilities(uint32_t p) 109 | { 110 | int n = 0; 111 | if (p & WL_SEAT_CAPABILITY_KEYBOARD) { 112 | printf("keyboard"); 113 | n = 1; 114 | } 115 | 116 | if (p & WL_SEAT_CAPABILITY_POINTER) { 117 | printf("%spointer", n ? " | " : ""); 118 | n = 1; 119 | } 120 | 121 | if (p & WL_SEAT_CAPABILITY_TOUCH) { 122 | printf("%stouch", n ? " | " : ""); 123 | n = 1; 124 | } 125 | 126 | if (!n) 127 | printf("none"); 128 | } 129 | 130 | static void 131 | print_wl_seat_info(struct wldbg_wl_seat_info *info, int version, int ind) 132 | { 133 | printf("%*s-- wl_seat --\n", ind, ""); 134 | printf("%*s name: \"%s\"\n", ind, "", info->name); 135 | printf("%*s version: %u\n", ind, "", version); 136 | printf("%*s capabilities: ", ind, ""); 137 | print_capabilities(info->capabilities); 138 | putchar('\n'); 139 | } 140 | 141 | static void 142 | print_objinfo(struct wldbg_objects_info *oi, struct wldbg_object_info *info) 143 | { 144 | assert(oi); 145 | assert(info); 146 | 147 | const char *name = info->wl_interface->name; 148 | printf("Info about object: %u [%s]\n", info->id, name); 149 | 150 | if (strcmp(name, "xdg_surface") == 0) { 151 | print_xdg_surface_info(oi, info->info); 152 | } else if (strcmp(name, "wl_buffer") == 0) { 153 | print_wl_buffer_info(info->info, 0); 154 | } else if (strcmp(name, "wl_surface") == 0) { 155 | print_wl_surface_info(oi, info->info, 0); 156 | } else if (strcmp(name, "wl_seat") == 0) { 157 | print_wl_seat_info(info->info, info->version, 0); 158 | } else { 159 | fprintf(stderr, "Unhandled objinfo: %s\n", 160 | info->wl_interface ? info->wl_interface->name : 161 | "unknown interface"); 162 | } 163 | } 164 | 165 | static void 166 | print_all_objinfo(struct wldbg_objects_info *oi) 167 | { 168 | 169 | unsigned int i; 170 | struct wldbg_object_info *info; 171 | 172 | for (i = 0; i < oi->client_objects.count; ++i) { 173 | info = wldbg_ids_map_get(&oi->client_objects, i); 174 | if (info) 175 | print_objinfo(oi, info); 176 | } 177 | 178 | for (i = 0; i < oi->server_objects.count; ++i) { 179 | info = wldbg_ids_map_get(&oi->server_objects, i); 180 | if (info) 181 | print_objinfo(oi, info); 182 | } 183 | } 184 | 185 | void 186 | print_object_info(struct wldbg_message *msg, char *buf) 187 | { 188 | struct wldbg_object_info *info; 189 | struct wldbg_objects_info *oi = msg->connection->objects_info; 190 | int id; 191 | 192 | if (!msg->connection->wldbg->gathering_info) { 193 | printf("Not gathering information about objects, " 194 | "run wldbg with -g or -objinfo option ;)\n"); 195 | return; 196 | } 197 | 198 | if (strncmp(buf, "all", 4) == 0) { 199 | print_all_objinfo(oi); 200 | return; 201 | } 202 | 203 | id = str_to_uint(buf); 204 | if (id == -1) { 205 | fprintf(stderr, "Wrong id given\n"); 206 | return; 207 | } 208 | 209 | info = wldbg_message_get_object_info(msg, (uint32_t) id); 210 | if (!info) { 211 | printf("No information about %u\n", id); 212 | return; 213 | } 214 | 215 | print_objinfo(oi, info); 216 | } 217 | -------------------------------------------------------------------------------- /src/interactive/pass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "wayland/wayland-private.h" 31 | 32 | #include "wldbg-pass.h" 33 | #include "interactive.h" 34 | #include "passes.h" 35 | #include "wldbg-private.h" 36 | #include "interactive-commands.h" 37 | 38 | void 39 | cmd_pass_help(int oneline) 40 | { 41 | if (oneline) { 42 | printf("Add, remove, list passes"); 43 | return; 44 | } 45 | 46 | printf("Possible arguments:\n"); 47 | printf("\tlist\t\t- list available passes\n"); 48 | printf("\tloaded\t\t- list loaded passes\n"); 49 | printf("\tadd NAME\t- add pass NAME.so\n"); 50 | printf("\tremove NAME\t- remove pass NAME\n"); 51 | } 52 | 53 | static void 54 | add_pass(struct wldbg *wldbg, const char *name) 55 | { 56 | struct pass *pass; 57 | 58 | dbg("Adding pass '%s'\n", name); 59 | 60 | pass = create_pass(name); 61 | if (pass) { 62 | /* XXX add arguments */ 63 | if (pass_init(wldbg, pass, 0, NULL) != 0) { 64 | fprintf(stderr, "Failed initializing pass '%s'\n", 65 | name); 66 | dealloc_pass(pass); 67 | } else { 68 | /* insert always at the head */ 69 | wl_list_insert(wldbg->passes.next, &pass->link); 70 | 71 | dbg("Added pass '%s'\n", name); 72 | } 73 | } else { 74 | fprintf(stderr, "Failed adding pass '%s'\n", name); 75 | } 76 | } 77 | 78 | static void 79 | loaded_passes(struct wldbg *wldbg) 80 | { 81 | struct pass *pass; 82 | 83 | printf("Loaded passes:\n"); 84 | wl_list_for_each(pass, &wldbg->passes, link) { 85 | printf("\t - %s\n", pass->name); 86 | } 87 | } 88 | 89 | static void 90 | remove_pass(struct wldbg *wldbg, const char *name) 91 | { 92 | struct pass *pass, *tmp; 93 | 94 | dbg("Removing pass '%s'\n", name); 95 | 96 | wl_list_for_each_safe(pass, tmp, &wldbg->passes, link) { 97 | if (strcmp(pass->name, name) == 0) { 98 | wl_list_remove(&pass->link); 99 | 100 | free(pass->name); 101 | free(pass); 102 | 103 | dbg("Removed pass '%s'\n", name); 104 | return; 105 | } 106 | } 107 | 108 | fprintf(stderr, "Didn't find pass '%s'\n", name); 109 | } 110 | 111 | int 112 | cmd_pass(struct wldbg_interactive *wldbgi, 113 | struct wldbg_message *message, 114 | char *buf) 115 | { 116 | (void) message; 117 | (void) buf; 118 | 119 | if (strcmp(buf, "list") == 0) { 120 | list_passes(1); 121 | } else if (strcmp(buf, "loaded") == 0) { 122 | loaded_passes(wldbgi->wldbg); 123 | } else if (strncmp(buf, "add ", 4) == 0) { 124 | add_pass(wldbgi->wldbg, buf + 4); 125 | } else if (strncmp(buf, "remove ", 7) == 0) { 126 | remove_pass(wldbgi->wldbg, buf + 7); 127 | } else 128 | cmd_pass_help(0); 129 | 130 | return CMD_CONTINUE_QUERY; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/interactive/send.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "wayland/wayland-private.h" 32 | 33 | #include "wldbg-private.h" 34 | #include "wldbg-parse-message.h" 35 | #include "interactive.h" 36 | #include "util.h" 37 | 38 | void 39 | cmd_send_help(int oneline) 40 | { 41 | printf("Send message to server/client"); 42 | if (oneline) 43 | return; 44 | 45 | printf("\n\n"); 46 | printf(" :: send server|s|client|c [message]\n"); 47 | printf("\n" 48 | "Send command will prompt you for object id (where to send the message)\n" 49 | "and opcode (what is the message) and then for the data of the message.\n" 50 | "Id and opcode are scanned as unsigned decimal numbers and the data\n" 51 | "as a sequence of hexadecimal numbers. If the message is passed as an argument,\n" 52 | "it must contain the header (object id + opcode + size) and whole message\n" 53 | "is scanned as a sequence of hexadecimal nubers (i. e. this sequence of words\n" 54 | "will be send as it is given)\n"); 55 | } 56 | 57 | #define is_blank(c) ((c) == 0 || isspace(c)) 58 | int 59 | cmd_send(struct wldbg_interactive *wldbgi, 60 | struct wldbg_message *message, 61 | char *buf) 62 | { 63 | struct wl_connection *conn; 64 | uint32_t buffer[1024]; /* size of wl_connection buffer */ 65 | uint32_t size, opcode, i = 0; 66 | int where, interactive; 67 | struct wldbg_message send_message; 68 | char *endptr; 69 | long val; 70 | 71 | (void) message; 72 | (void) buf; 73 | (void) wldbgi; 74 | 75 | if (strncmp(buf, "server", 6) == 0) { 76 | where = SERVER; 77 | buf += 6; 78 | } else if (buf[0] == 's' && is_blank(buf[1])) { 79 | where = SERVER; 80 | ++buf; 81 | } else if (strncmp(buf, "client", 6) == 0) { 82 | where = CLIENT; 83 | buf += 6; 84 | } else if (buf[0] == 'c' && is_blank(buf[1])) { 85 | where = CLIENT; 86 | ++buf; 87 | } else { 88 | cmd_send_help(0); 89 | return CMD_CONTINUE_QUERY; 90 | } 91 | 92 | buf = skip_ws(buf); 93 | interactive = !*buf; 94 | 95 | if (where == SERVER) 96 | conn = message->connection->server.connection; 97 | else 98 | conn = message->connection->client.connection; 99 | 100 | /* XXX later do translation from interface@obj.request etc.. */ 101 | if (interactive) { 102 | printf("Id: "); 103 | scanf("%u", &buffer[0]); 104 | 105 | printf("Opcode: "); 106 | scanf("%u", &opcode); 107 | i = 2; 108 | 109 | printf("Data:\n"); 110 | while(scanf("%x", &buffer[i]) > 0) { 111 | ++i; 112 | if (i >= sizeof buffer) { 113 | printf("Data too big (buffer overflow)\n"); 114 | break; 115 | } 116 | } 117 | 118 | size = i * sizeof(uint32_t); 119 | buffer[1] = (size << 16) | (opcode & 0xffff); 120 | } else { 121 | while(*buf) { 122 | errno = 0; 123 | val = strtol(buf, &endptr, 16); 124 | if (errno != 0) { 125 | perror("Failed parsing data"); 126 | goto out; 127 | } 128 | 129 | if (buf == endptr) { 130 | printf("No hexadecimal nubers on position %d\n", i); 131 | goto out; 132 | } 133 | 134 | if (!isspace(*endptr) && *endptr != '\0' ) { 135 | printf("Invalid character in data\n"); 136 | goto out; 137 | } 138 | 139 | 140 | buffer[i] = (uint32_t) val; 141 | ++i; 142 | 143 | buf = skip_ws(endptr); 144 | } 145 | 146 | opcode = buffer[1] & 0xffff; 147 | size = buffer[1] >> 16; 148 | } 149 | 150 | 151 | if (size != 4 * i) 152 | printf("Warning: size given in header (%uB) does not match size of given message (%uB)\n", 153 | size, i * 4); 154 | 155 | if (size % 4) 156 | printf("Warning: size is not a multiple of 4, this is buggy\n"); 157 | 158 | if (size > 1024) 159 | printf("Warning: Message is too big...\n"); 160 | 161 | send_message.connection = message->connection; 162 | send_message.data = buffer; 163 | send_message.size = size; 164 | send_message.from = where == CLIENT ? SERVER : CLIENT; 165 | 166 | printf("resolved as: "); 167 | wldbg_message_print(&send_message); 168 | 169 | printf("Send this message? [y/n] "); 170 | if (getchar() != 'y') 171 | goto out; 172 | 173 | dbg("Sending id %u, opcode %u , size %u\n", buffer[0], opcode, size); 174 | if (wl_connection_write(conn, buffer, size) < 0) 175 | perror("Writing message to connection"); 176 | 177 | out: 178 | return CMD_CONTINUE_QUERY; 179 | } 180 | 181 | -------------------------------------------------------------------------------- /src/list-pass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "wldbg-private.h" 33 | 34 | static void 35 | list_dir(const char *path) 36 | { 37 | struct dirent *entry = NULL; 38 | DIR *dir; 39 | char *dot; 40 | 41 | if((dir = opendir(path))) { 42 | while((entry = readdir(dir))) { 43 | if (entry->d_type == DT_DIR) 44 | continue; 45 | 46 | if (!(dot = strrchr(entry->d_name, '.'))) 47 | continue; 48 | 49 | if (strcmp("so", dot + 1) == 0) 50 | printf(" %s (%s)\n", entry->d_name, path); 51 | } 52 | 53 | closedir(dir); 54 | } 55 | } 56 | 57 | void 58 | list_passes(void) 59 | { 60 | const char *env; 61 | char path[256]; 62 | 63 | printf(" list (hardcoded)\n resolve (hardcoded)\n"); 64 | 65 | list_dir("."); 66 | snprintf(path, sizeof path, "passes/%s", LT_OBJDIR); 67 | list_dir(path); 68 | 69 | if ((env = getenv("HOME"))) { 70 | snprintf(path, sizeof path, "%s/.wldbg", env); 71 | list_dir(path); 72 | } 73 | 74 | snprintf(path, sizeof path, "%s/wldbg", LIBDIR); 75 | list_dir(path); 76 | 77 | list_dir("/usr/local/lib/wldbg"); 78 | list_dir("/usr/lib/wldbg"); 79 | list_dir("/lib/wldbg"); 80 | } 81 | 82 | static int 83 | list_init(struct wldbg *wldbg, 84 | struct wldbg_pass *pass, 85 | int argc, const char *argv[]) 86 | { 87 | (void) pass; 88 | (void) argv; 89 | 90 | if (argc == 1) { 91 | list_passes(); 92 | } else { 93 | printf("Usage: wldbg list\n\n"); 94 | printf("List all available passes\n"); 95 | wldbg->flags.error = 1; 96 | exit(-1); 97 | } 98 | 99 | exit(0); 100 | } 101 | 102 | static int 103 | list_in(void *user_data, struct wldbg_message *message) 104 | { 105 | (void) user_data; 106 | (void) message; 107 | 108 | return PASS_STOP; 109 | } 110 | 111 | static int 112 | list_out(void *user_data, struct wldbg_message *message) 113 | { 114 | (void) user_data; 115 | (void) message; 116 | 117 | return PASS_STOP; 118 | } 119 | 120 | static void 121 | list_destroy(void *data) 122 | { 123 | (void) data; 124 | return; 125 | } 126 | 127 | struct wldbg_pass wldbg_pass_list = { 128 | .init = list_init, 129 | .destroy = list_destroy, 130 | .server_pass = list_in, 131 | .client_pass = list_out, 132 | }; 133 | -------------------------------------------------------------------------------- /src/loop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "wldbg.h" 6 | #include "wldbg-private.h" 7 | 8 | void 9 | wldbg_exit(struct wldbg *wldbg) 10 | { 11 | wldbg->flags.exit = 1; 12 | } 13 | 14 | void 15 | wldbg_error(struct wldbg *wldbg) 16 | { 17 | wldbg->flags.error = 1; 18 | } 19 | 20 | /** 21 | * Monitor filedescriptor for incoming events and 22 | * call set-up callbacks 23 | */ 24 | struct wldbg_fd_callback * 25 | wldbg_monitor_fd(struct wldbg *wldbg, int fd, 26 | int (*dispatch)(int fd, void *data), 27 | void *data) 28 | { 29 | struct epoll_event ev; 30 | struct wldbg_fd_callback *cb; 31 | 32 | cb = malloc(sizeof *cb); 33 | if (!cb) 34 | return NULL; 35 | 36 | ev.events = EPOLLIN; 37 | ev.data.ptr = cb; 38 | if (epoll_ctl(wldbg->epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) { 39 | perror("Failed adding fd to epoll"); 40 | free(cb); 41 | return NULL; 42 | } 43 | 44 | cb->fd = fd; 45 | cb->data = data; 46 | cb->dispatch = dispatch; 47 | 48 | wl_list_insert(&wldbg->monitored_fds, &cb->link); 49 | 50 | return cb; 51 | } 52 | 53 | /** 54 | * Stop monitoring filedescriptor and its callback 55 | */ 56 | int 57 | wldbg_remove_callback(struct wldbg *wldbg, struct wldbg_fd_callback *cb) 58 | { 59 | int fd = cb->fd; 60 | 61 | wl_list_remove(&cb->link); 62 | free(cb); 63 | 64 | if (epoll_ctl(wldbg->epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1) { 65 | perror("Failed removing fd from epoll"); 66 | return -1; 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | int 73 | wldbg_separate_messages(struct wldbg *wldbg, int state) 74 | { 75 | if (state == -1) 76 | return wldbg->flags.pass_whole_buffer; 77 | 78 | wldbg->flags.pass_whole_buffer = !!state; 79 | return wldbg->flags.pass_whole_buffer; 80 | } 81 | -------------------------------------------------------------------------------- /src/objinfo-pass.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* for WL_SERVER_ID_START */ 33 | #include "wayland/wayland-private.h" 34 | 35 | #include 36 | #include 37 | 38 | #include "wldbg.h" 39 | #include "wldbg-private.h" 40 | #include "wldbg-parse-message.h" 41 | #include "wldbg-ids-map.h" 42 | #include "wldbg-objects-info.h" 43 | #include "passes.h" 44 | #include "util.h" 45 | #include "resolve.h" 46 | 47 | void 48 | handle_shm_pool_message(struct wldbg_objects_info *oi, 49 | struct wldbg_resolved_message *rm, int from); 50 | void 51 | handle_wl_buffer_message(struct wldbg_objects_info *oi, 52 | struct wldbg_resolved_message *rm, int from); 53 | void 54 | handle_wl_compositor_message(struct wldbg_objects_info *oi, 55 | struct wldbg_resolved_message *rm, int from); 56 | 57 | void 58 | handle_wl_surface_message(struct wldbg_objects_info *oi, 59 | struct wldbg_resolved_message *rm, int from); 60 | void 61 | handle_xdg_shell_message(struct wldbg_objects_info *oi, 62 | struct wldbg_resolved_message *rm, int from); 63 | 64 | void 65 | handle_xdg_surface_message(struct wldbg_objects_info *oi, 66 | struct wldbg_resolved_message *rm, int from); 67 | 68 | void 69 | handle_wl_registry_message(struct wldbg_objects_info *oi, 70 | struct wldbg_resolved_message *rm, int from); 71 | 72 | void 73 | handle_wl_seat_message(struct wldbg_objects_info *oi, 74 | struct wldbg_resolved_message *rm, int from); 75 | 76 | static int 77 | gather_info(void *user_data, struct wldbg_message *message) 78 | { 79 | (void) user_data; 80 | struct wldbg_objects_info *oinf = message->connection->objects_info; 81 | struct wldbg_resolved_message rm; 82 | 83 | if (!wldbg_resolve_message(message, &rm)) { 84 | fprintf(stderr, "Failed resolving message, loosing info\n"); 85 | return PASS_NEXT; 86 | } 87 | 88 | if (strcmp(rm.wl_interface->name, "wl_surface") == 0) 89 | handle_wl_surface_message(oinf, &rm, message->from); 90 | else if (strcmp(rm.wl_interface->name, "xdg_surface") == 0) 91 | handle_xdg_surface_message(oinf, &rm, message->from); 92 | else if (strcmp(rm.wl_interface->name, "wl_buffer") == 0) 93 | handle_wl_buffer_message(oinf, &rm, message->from); 94 | else if (strcmp(rm.wl_interface->name, "wl_compositor") == 0) 95 | handle_wl_compositor_message(oinf, &rm, message->from); 96 | else if (strcmp(rm.wl_interface->name, "wl_shm_pool") == 0) 97 | handle_shm_pool_message(oinf, &rm, message->from); 98 | else if (strcmp(rm.wl_interface->name, "xdg_shell") == 0) 99 | handle_xdg_shell_message(oinf, &rm, message->from); 100 | else if (strcmp(rm.wl_interface->name, "wl_registry") == 0) 101 | handle_wl_registry_message(oinf, &rm, message->from); 102 | else if (strcmp(rm.wl_interface->name, "wl_seat") == 0) 103 | handle_wl_seat_message(oinf, &rm, message->from); 104 | 105 | return PASS_NEXT; 106 | } 107 | 108 | static struct pass * 109 | create_objinfo_pass(void) 110 | { 111 | struct pass *pass; 112 | 113 | pass = alloc_pass("objinfo"); 114 | if (!pass) 115 | return NULL; 116 | 117 | pass->wldbg_pass.init = NULL; 118 | pass->wldbg_pass.destroy = NULL; 119 | pass->wldbg_pass.server_pass = gather_info; 120 | pass->wldbg_pass.client_pass = gather_info; 121 | pass->wldbg_pass.description 122 | = "Gather additional information about objects"; 123 | 124 | return pass; 125 | } 126 | 127 | int 128 | wldbg_add_objinfo_pass(struct wldbg *wldbg) 129 | { 130 | if (wldbg->gathering_info) 131 | return 0; 132 | 133 | struct pass *pass = create_objinfo_pass(); 134 | if (!pass) 135 | return -1; 136 | 137 | wl_list_insert(wldbg->passes.next, &pass->link); 138 | wldbg->gathering_info = 1; 139 | 140 | return 0; 141 | } 142 | -------------------------------------------------------------------------------- /src/objinfo/objinfo-private.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | #include "wldbg.h" 29 | #include "wldbg-private.h" 30 | #include "wldbg-ids-map.h" 31 | #include "wldbg-objects-info.h" 32 | 33 | /* for WL_SERVER_ID_START */ 34 | #include "wayland/wayland-private.h" 35 | 36 | #include "objinfo-private.h" 37 | 38 | void 39 | objects_info_put(struct wldbg_objects_info *oi, 40 | uint32_t id, struct wldbg_object_info *info) 41 | { 42 | if (id >= WL_SERVER_ID_START) 43 | wldbg_ids_map_insert(&oi->server_objects, 44 | id - WL_SERVER_ID_START, info); 45 | else 46 | wldbg_ids_map_insert(&oi->client_objects, id, info); 47 | } 48 | 49 | void * 50 | objects_info_get(struct wldbg_objects_info *oi, uint32_t id) 51 | { 52 | if (id >= WL_SERVER_ID_START) 53 | return wldbg_ids_map_get(&oi->server_objects, 54 | id - WL_SERVER_ID_START); 55 | else 56 | return wldbg_ids_map_get(&oi->client_objects, id); 57 | } 58 | 59 | void 60 | wldbg_object_info_free(struct wldbg_objects_info *oi, struct wldbg_object_info *info) 61 | { 62 | objects_info_put(oi, info->id, NULL); 63 | 64 | if (info->destroy) 65 | info->destroy(info->info); 66 | free(info); 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/objinfo/objinfo-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_OBJINFO_PRIVATE_H_ 27 | #define _WLDBG_OBJINFO_PRIVATE_H_ 28 | 29 | #include 30 | 31 | struct wldbg_objects_info; 32 | struct wldbg_object_info; 33 | 34 | void 35 | objects_info_put(struct wldbg_objects_info *oi, 36 | uint32_t id, struct wldbg_object_info *info); 37 | 38 | void * 39 | objects_info_get(struct wldbg_objects_info *oi, uint32_t id); 40 | 41 | void 42 | wldbg_object_info_free(struct wldbg_objects_info *oi, struct wldbg_object_info *info); 43 | 44 | #endif /* _WLDBG_OBJINFO_PRIVATE_H_ */ 45 | -------------------------------------------------------------------------------- /src/objinfo/objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | 28 | /* for WL_SERVER_ID_START */ 29 | #include "wayland/wayland-private.h" 30 | 31 | #include "wldbg.h" 32 | #include "wldbg-private.h" 33 | #include "wldbg-ids-map.h" 34 | 35 | 36 | struct wldbg_objects_info * 37 | create_objects_info(void) 38 | { 39 | struct wldbg_objects_info *oi = malloc(sizeof *oi); 40 | if (!oi) { 41 | fprintf(stderr, "Out of memory\n"); 42 | return NULL; 43 | } 44 | 45 | wldbg_ids_map_init(&oi->client_objects); 46 | wldbg_ids_map_init(&oi->server_objects); 47 | 48 | return oi; 49 | } 50 | 51 | void 52 | destroy_objects_info(struct wldbg_objects_info *oi) 53 | { 54 | unsigned int i; 55 | struct wldbg_object_info *info; 56 | 57 | if (!oi) 58 | return; 59 | 60 | for (i = 0; i < oi->client_objects.count; ++i) { 61 | info = wldbg_ids_map_get(&oi->client_objects, i); 62 | if (!info) 63 | continue; 64 | 65 | if (info->destroy) 66 | info->destroy(info->info); 67 | free(info); 68 | } 69 | 70 | for (i = 0; i < oi->server_objects.count; ++i) { 71 | info = wldbg_ids_map_get(&oi->server_objects, i); 72 | if (!info) 73 | continue; 74 | 75 | if (info->destroy) 76 | info->destroy(info->info); 77 | free(info); 78 | } 79 | 80 | wldbg_ids_map_release(&oi->client_objects); 81 | wldbg_ids_map_release(&oi->server_objects); 82 | 83 | free(oi); 84 | } 85 | 86 | static void * 87 | wldbg_objects_info_get(struct wldbg_objects_info *oi, uint32_t id) 88 | { 89 | if (id >= WL_SERVER_ID_START) 90 | return wldbg_ids_map_get(&oi->server_objects, 91 | id - WL_SERVER_ID_START); 92 | else 93 | return wldbg_ids_map_get(&oi->client_objects, id); 94 | } 95 | 96 | struct wldbg_object_info * 97 | wldbg_message_get_object_info(struct wldbg_message *msg, uint32_t id) 98 | { 99 | struct wldbg_objects_info *oi = msg->connection->objects_info; 100 | if (!oi) 101 | return NULL; 102 | 103 | return wldbg_objects_info_get(oi, id); 104 | } 105 | -------------------------------------------------------------------------------- /src/objinfo/objinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_OBJINFO_H_ 27 | #define _WLDBG_OBJINFO_H_ 28 | 29 | #include 30 | 31 | struct wldbg_objects_info; 32 | struct wldbg_object_info; 33 | struct wldbg_message; 34 | 35 | struct wldbg_objects_info * 36 | create_objects_info(void); 37 | 38 | void 39 | destroy_objects_info(struct wldbg_objects_info *oi); 40 | 41 | struct wldbg_object_info * 42 | wldbg_message_get_object_info(struct wldbg_message *msg, uint32_t id); 43 | 44 | int 45 | wldbg_add_objinfo_pass(struct wldbg *wldbg); 46 | 47 | #endif /* _WLDBG_OBJINFO_H_ */ 48 | -------------------------------------------------------------------------------- /src/objinfo/wl_registry-objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "wldbg.h" 30 | #include "wldbg-private.h" 31 | #include "wldbg-parse-message.h" 32 | #include "wldbg-objects-info.h" 33 | 34 | #include "objinfo-private.h" 35 | 36 | 37 | struct wldbg_object_info * 38 | create_wl_seat_info(struct wldbg_resolved_message *rm); 39 | 40 | static void 41 | handle_bind(struct wldbg_objects_info *oi, 42 | struct wldbg_resolved_message *rm, const char *obj) 43 | { 44 | struct wldbg_object_info *info; 45 | 46 | if (strcmp(obj, "wl_seat") == 0) { 47 | info = create_wl_seat_info(rm); 48 | if (!info) { 49 | fprintf(stderr, "Out of memory, loosing informaiton\n"); 50 | return; 51 | } 52 | 53 | assert(info->id > 0); 54 | objects_info_put(oi, info->id, info); 55 | dbg("Created wl_seat info, id %u\n", info->id); 56 | } 57 | } 58 | 59 | void 60 | handle_wl_registry_message(struct wldbg_objects_info *oi, 61 | struct wldbg_resolved_message *rm, int from) 62 | { 63 | struct wldbg_resolved_arg *arg; 64 | 65 | if (from == CLIENT) { 66 | if (strcmp(rm->wl_message->name, "bind") == 0) { 67 | /* skip the global id */ 68 | wldbg_resolved_message_next_argument(rm); 69 | /* get the global name */ 70 | arg = wldbg_resolved_message_next_argument(rm); 71 | 72 | handle_bind(oi, rm, (const char *) arg->data); 73 | } 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/objinfo/wl_seat-objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "wldbg.h" 30 | #include "wldbg-private.h" 31 | #include "wldbg-parse-message.h" 32 | #include "wldbg-objects-info.h" 33 | 34 | #include "objinfo-private.h" 35 | 36 | static void 37 | free_seat(void *ptr) 38 | { 39 | struct wldbg_wl_seat_info *info = ptr; 40 | free(info->name); 41 | free(info); 42 | } 43 | 44 | struct wldbg_object_info * 45 | create_wl_seat_info(struct wldbg_resolved_message *rm) 46 | { 47 | struct wldbg_resolved_arg *arg; 48 | 49 | struct wldbg_object_info *oi = malloc(sizeof *oi); 50 | if (!oi) 51 | return NULL; 52 | 53 | struct wldbg_wl_seat_info *info = malloc(sizeof *info); 54 | if (!info) { 55 | free(oi); 56 | return NULL; 57 | } 58 | 59 | /* XXX: is this always valid */ 60 | extern const struct wl_interface wl_seat_interface; 61 | oi->wl_interface = &wl_seat_interface; 62 | oi->info = info; 63 | oi->destroy = free_seat; 64 | 65 | info->capabilities = 0; 66 | 67 | /* get version of the seat */ 68 | arg = wldbg_resolved_message_next_argument(rm); 69 | oi->version = *arg->data; 70 | 71 | /* get id of the seat */ 72 | arg = wldbg_resolved_message_next_argument(rm); 73 | oi->id = *arg->data; 74 | 75 | return oi; 76 | } 77 | 78 | void 79 | handle_wl_seat_message(struct wldbg_objects_info *oi, 80 | struct wldbg_resolved_message *rm, int from) 81 | { 82 | struct wldbg_object_info *i; 83 | struct wldbg_resolved_arg *arg; 84 | struct wldbg_wl_seat_info *info; 85 | 86 | i = objects_info_get(oi, rm->base.id); 87 | if (!i) { 88 | fprintf(stderr, "ERROR: no wl_seat with id %d\n", rm->base.id); 89 | return; 90 | } 91 | 92 | info = i->info; 93 | 94 | if (from == SERVER) { 95 | if (strcmp(rm->wl_message->name, "name") == 0) { 96 | arg = wldbg_resolved_message_next_argument(rm); 97 | if (arg->data) 98 | info->name = strdup((const char *) arg->data); 99 | } else if (strcmp(rm->wl_message->name, "capabilities") == 0) { 100 | arg = wldbg_resolved_message_next_argument(rm); 101 | info->capabilities = *arg->data; 102 | } 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/objinfo/wl_shm-objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "wldbg.h" 30 | #include "wldbg-private.h" 31 | #include "wldbg-parse-message.h" 32 | #include "wldbg-objects-info.h" 33 | 34 | #include "objinfo-private.h" 35 | 36 | static struct wldbg_object_info * 37 | create_wl_buffer_info(struct wldbg_resolved_message *rm) 38 | { 39 | struct wldbg_object_info *oi = malloc(sizeof *oi); 40 | if (!oi) 41 | return NULL; 42 | 43 | struct wldbg_wl_buffer_info *info = calloc(1, sizeof *info); 44 | if (!info) { 45 | free(oi); 46 | return NULL; 47 | } 48 | 49 | /* types[0] should be wl_buffer_interface */ 50 | oi->wl_interface = rm->wl_message->types[0]; 51 | oi->info = info; 52 | oi->destroy = free; 53 | 54 | return oi; 55 | } 56 | 57 | void 58 | handle_shm_pool_message(struct wldbg_objects_info *oi, 59 | struct wldbg_resolved_message *rm, int from) 60 | { 61 | struct wldbg_object_info *info; 62 | struct wldbg_resolved_arg *arg; 63 | struct wldbg_wl_buffer_info *buff_info; 64 | 65 | if (from == CLIENT) { 66 | if (strcmp(rm->wl_message->name, "create_buffer") == 0) { 67 | info = create_wl_buffer_info(rm); 68 | if (!info) { 69 | fprintf(stderr, "Out of memory, loosing informaiton\n"); 70 | return; 71 | } 72 | 73 | buff_info = (struct wldbg_wl_buffer_info *) info->info; 74 | 75 | /* new wl_buffer id */ 76 | arg = wldbg_resolved_message_next_argument(rm); 77 | info->id = *arg->data; 78 | 79 | /* offset */ 80 | arg = wldbg_resolved_message_next_argument(rm); 81 | buff_info->offset = (int32_t) *arg->data; 82 | 83 | /* width */ 84 | arg = wldbg_resolved_message_next_argument(rm); 85 | buff_info->width = (int32_t) *arg->data; 86 | 87 | /* height */ 88 | arg = wldbg_resolved_message_next_argument(rm); 89 | buff_info->height = (int32_t) *arg->data; 90 | 91 | /* stride */ 92 | arg = wldbg_resolved_message_next_argument(rm); 93 | buff_info->stride = (int32_t) *arg->data; 94 | 95 | /* format */ 96 | arg = wldbg_resolved_message_next_argument(rm); 97 | buff_info->format = *arg->data; 98 | 99 | objects_info_put(oi, info->id, info); 100 | dbg("Created wl_buffer, id %u\n", info->id); 101 | } 102 | } 103 | } 104 | 105 | void 106 | handle_wl_buffer_message(struct wldbg_objects_info *oi, 107 | struct wldbg_resolved_message *rm, int from) 108 | { 109 | struct wldbg_object_info *info = objects_info_get(oi, rm->base.id); 110 | if (!info) { 111 | fprintf(stderr, "ERROR: no wl_buffer with id %d\n", rm->base.id); 112 | return; 113 | } 114 | 115 | if (from == SERVER) { 116 | if (strcmp(rm->wl_message->name, "release") == 0) { 117 | struct wldbg_wl_buffer_info *buff_info = info->info; 118 | buff_info->released = 1; 119 | } 120 | } else { 121 | if (strcmp(rm->wl_message->name, "destroy") == 0) { 122 | wldbg_object_info_free(oi, info); 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /src/objinfo/wl_surface-objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "wldbg.h" 30 | #include "wldbg-private.h" 31 | #include "wldbg-parse-message.h" 32 | #include "wldbg-objects-info.h" 33 | 34 | #include "objinfo-private.h" 35 | 36 | static void 37 | destroy_wl_surface_info(void *data) 38 | { 39 | struct wldbg_wl_surface_info *info = data; 40 | if (!info) 41 | return; 42 | 43 | destroy_wl_surface_info(info->commited); 44 | free(info); 45 | } 46 | 47 | static struct wldbg_object_info * 48 | create_wl_surface_info(struct wldbg_resolved_message *rm) 49 | { 50 | struct wldbg_object_info *oi = malloc(sizeof *oi); 51 | if (!oi) 52 | return NULL; 53 | 54 | struct wldbg_wl_surface_info *info = calloc(1, sizeof *info); 55 | if (!info) { 56 | free(oi); 57 | return NULL; 58 | } 59 | 60 | /* type of new id - wl_surface_interface */ 61 | oi->wl_interface = rm->wl_message->types[0]; 62 | oi->info = info; 63 | oi->destroy = destroy_wl_surface_info; 64 | 65 | return oi; 66 | } 67 | 68 | static void 69 | make_wl_buffer_unreleased(struct wldbg_objects_info *oi, uint32_t id) 70 | { 71 | struct wldbg_object_info *info = objects_info_get(oi, id); 72 | if (!info) { 73 | fprintf(stderr, "ERROR: no wl_buffer with id %d\n", id); 74 | return; 75 | } 76 | 77 | ((struct wldbg_wl_buffer_info *) info->info)->released = 0; 78 | } 79 | 80 | void 81 | handle_wl_surface_message(struct wldbg_objects_info *oi, 82 | struct wldbg_resolved_message *rm, int from) 83 | { 84 | struct wldbg_wl_surface_info *surf_info; 85 | struct wldbg_resolved_arg *arg; 86 | struct wldbg_object_info *info = objects_info_get(oi, rm->base.id); 87 | if (!info) { 88 | fprintf(stderr, "ERROR: no wl_surface with id %d\n", 89 | rm->base.id); 90 | return; 91 | } 92 | 93 | surf_info = (struct wldbg_wl_surface_info *) info->info; 94 | if (from == CLIENT) { 95 | if (strcmp(rm->wl_message->name, "frame") == 0) { 96 | arg = wldbg_resolved_message_next_argument(rm); 97 | surf_info->last_frame_id = *arg->data; 98 | } else if (strcmp(rm->wl_message->name, "attach") == 0) { 99 | /* wl_buffer */ 100 | arg = wldbg_resolved_message_next_argument(rm); 101 | surf_info->wl_buffer_id = *arg->data; 102 | /* attached x, y */ 103 | arg = wldbg_resolved_message_next_argument(rm); 104 | surf_info->attached_x = *arg->data; 105 | arg = wldbg_resolved_message_next_argument(rm); 106 | surf_info->attached_y = *arg->data; 107 | 108 | make_wl_buffer_unreleased(oi, surf_info->wl_buffer_id); 109 | 110 | } else if (strcmp(rm->wl_message->name, "commit") == 0) { 111 | if (!surf_info->commited) { 112 | surf_info->commited = malloc(sizeof *surf_info); 113 | if (!surf_info->commited) { 114 | fprintf(stderr, "Out of memory, loosing info\n"); 115 | return; 116 | } 117 | } 118 | 119 | /* commit the state */ 120 | memcpy(surf_info->commited, surf_info, sizeof *surf_info); 121 | surf_info->commited->commited = NULL; 122 | 123 | /* reset current state */ 124 | void *tmp = surf_info->commited; 125 | memset(surf_info, 0, sizeof *surf_info); 126 | surf_info->commited = tmp; 127 | } else if (strcmp(rm->wl_message->name, "destroy") == 0) { 128 | wldbg_object_info_free(oi, info); 129 | } 130 | /* TODO damage */ 131 | } 132 | } 133 | 134 | void 135 | handle_wl_compositor_message(struct wldbg_objects_info *oi, 136 | struct wldbg_resolved_message *rm, int from) 137 | { 138 | struct wldbg_object_info *info; 139 | struct wldbg_resolved_arg *arg; 140 | 141 | if (from == CLIENT) { 142 | if (strcmp(rm->wl_message->name, "create_surface") == 0) { 143 | info = create_wl_surface_info(rm); 144 | if (!info) { 145 | fprintf(stderr, 146 | "Out of memory, loosing information\n"); 147 | return; 148 | } 149 | 150 | /* new wl_surface id */ 151 | arg = wldbg_resolved_message_next_argument(rm); 152 | info->id = *arg->data; 153 | 154 | objects_info_put(oi, info->id, info); 155 | dbg("Created wl_surface, id %u\n", info->id); 156 | } 157 | } 158 | } 159 | 160 | -------------------------------------------------------------------------------- /src/objinfo/xdg-objinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "wldbg.h" 30 | #include "wldbg-private.h" 31 | #include "wldbg-parse-message.h" 32 | #include "wldbg-objects-info.h" 33 | 34 | #include "objinfo-private.h" 35 | 36 | static void 37 | destroy_xdg_surface_info(void *info) 38 | { 39 | struct wldbg_xdg_surface_info *i = info; 40 | free(i->title); 41 | free(info); 42 | } 43 | 44 | static struct wldbg_object_info * 45 | create_xdg_surface_info(struct wldbg_resolved_message *rm) 46 | { 47 | struct wldbg_object_info *oi = malloc(sizeof *oi); 48 | if (!oi) 49 | return NULL; 50 | 51 | struct wldbg_xdg_surface_info *info = calloc(1, sizeof *info); 52 | if (!info) { 53 | free(oi); 54 | return NULL; 55 | } 56 | 57 | /* types[0] should be xdg_surface_interface */ 58 | oi->wl_interface = rm->wl_message->types[0]; 59 | oi->info = info; 60 | oi->destroy = destroy_xdg_surface_info; 61 | 62 | return oi; 63 | } 64 | 65 | void 66 | handle_xdg_shell_message(struct wldbg_objects_info *oi, 67 | struct wldbg_resolved_message *rm, int from) 68 | { 69 | struct wldbg_object_info *info; 70 | struct wldbg_resolved_arg *arg; 71 | 72 | if (from == CLIENT) { 73 | if (strcmp(rm->wl_message->name, "get_xdg_surface") == 0) { 74 | info = create_xdg_surface_info(rm); 75 | if (!info) { 76 | fprintf(stderr, "Out of memory, loosing informaiton\n"); 77 | return; 78 | } 79 | 80 | /* new xdg_surface id */ 81 | arg = wldbg_resolved_message_next_argument(rm); 82 | /* FIXME check for NULL */ 83 | info->id = *arg->data; 84 | 85 | /* just check -> do it an assertion */ 86 | if (objects_info_get(oi, info->id)) 87 | fprintf(stderr, "Already got an object on id %d, " 88 | "but now I'm creating xgd_surface\n", info->id); 89 | 90 | /* wl_surface id */ 91 | arg = wldbg_resolved_message_next_argument(rm); 92 | ((struct wldbg_xdg_surface_info *) info->info)->wl_surface_id = *arg->data; 93 | 94 | objects_info_put(oi, info->id, info); 95 | vdbg("Created xdg_surface, id %u\n", info->id); 96 | } 97 | } 98 | } 99 | 100 | void 101 | handle_xdg_surface_message(struct wldbg_objects_info *oi, 102 | struct wldbg_resolved_message *rm, int from) 103 | { 104 | struct wldbg_xdg_surface_info *xdg_info; 105 | struct wldbg_resolved_arg *arg; 106 | struct wldbg_object_info *info = objects_info_get(oi, rm->base.id); 107 | if (!info) { 108 | fprintf(stderr, "ERROR: no xdg_surface with id %d\n", rm->base.id); 109 | return; 110 | } 111 | 112 | xdg_info = (struct wldbg_xdg_surface_info *) info->info; 113 | if (from == SERVER) { 114 | if (strcmp(rm->wl_message->name, "configure") == 0) { 115 | uint8_t idx = xdg_info->configures_num % 10; 116 | struct xdg_configure *c = &xdg_info->configures[idx]; 117 | 118 | /* width */ 119 | arg = wldbg_resolved_message_next_argument(rm); 120 | c->width = *arg->data; 121 | /* height */ 122 | arg = wldbg_resolved_message_next_argument(rm); 123 | c->height = *arg->data; 124 | /* flags */ 125 | arg = wldbg_resolved_message_next_argument(rm); 126 | /* serial */ 127 | arg = wldbg_resolved_message_next_argument(rm); 128 | c->serial = *arg->data; 129 | 130 | /* reset acked flag with this configure, 131 | * we didn't get it yet */ 132 | c->acked = 0; 133 | 134 | ++xdg_info->configures_num; 135 | } 136 | } else { 137 | if (strcmp(rm->wl_message->name, "set_title") == 0) { 138 | arg = wldbg_resolved_message_next_argument(rm); 139 | if (arg && arg->data) { 140 | /* free on NULL is no-op */ 141 | free(xdg_info->title); 142 | xdg_info->title = strdup((const char *) arg->data); 143 | } 144 | } else if (strcmp(rm->wl_message->name, "ack_configure") == 0) { 145 | arg = wldbg_resolved_message_next_argument(rm); 146 | uint32_t serial = *arg->data; 147 | uint8_t idx; 148 | 149 | /* find serial */ 150 | for (idx = 0; idx < 10; ++idx) { 151 | struct xdg_configure *c = &xdg_info->configures[idx]; 152 | if (c->serial == serial) { 153 | c->acked = 1; 154 | break; 155 | } 156 | } 157 | } else if (strcmp(rm->wl_message->name, "destroy") == 0) { 158 | wldbg_object_info_free(oi, info); 159 | } 160 | 161 | } 162 | } 163 | 164 | 165 | -------------------------------------------------------------------------------- /src/parse-message.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "resolve.h" 32 | #include "util.h" 33 | 34 | #include "wldbg-private.h" 35 | #include "wldbg-parse-message.h" 36 | 37 | int 38 | wldbg_parse_message(struct wldbg_message *msg, struct wldbg_parsed_message *out) 39 | { 40 | uint32_t *p = msg->data; 41 | 42 | out->id = p[0]; 43 | out->opcode = p[1] & 0xffff; 44 | out->size = p[1] >> 16; 45 | out->data = p + 2; 46 | 47 | if (out->size < 8 || out->size % 4 != 0) 48 | return 0; 49 | 50 | return 1; 51 | } 52 | 53 | static inline int 54 | is_valid_interface(const struct wl_interface *intf) 55 | { 56 | if (!intf) 57 | return 0; 58 | 59 | /* out special interfaces 'unknown' and 'free' */ 60 | if (intf->version < 0) 61 | return 0; 62 | 63 | return 1; 64 | } 65 | 66 | int wldbg_resolve_message(struct wldbg_message *msg, 67 | struct wldbg_resolved_message *out) 68 | { 69 | const struct wl_interface *interface; 70 | 71 | /* clear out */ 72 | memset(out, 0, sizeof *out); 73 | if (!wldbg_parse_message(msg, &out->base)) 74 | return 0; 75 | 76 | assert(msg->connection && "Message has no connection set"); 77 | /* if we're not resolving objects, just 78 | * cease parsing here */ 79 | if (!msg->connection->resolved_objects) 80 | return 0; 81 | 82 | interface = wldbg_message_get_object(msg, out->base.id); 83 | /* if it is unknown interface to resolve or it is 84 | * "unknown" interface of FREE entry, bail out */ 85 | if (!is_valid_interface(interface)) 86 | return 0; 87 | 88 | out->wl_interface = interface; 89 | 90 | if (msg->from == SERVER) { 91 | if ((uint32_t) interface->event_count <= out->base.opcode) 92 | return 0; 93 | 94 | out->wl_message = &interface->events[out->base.opcode]; 95 | } else { 96 | if ((uint32_t) interface->method_count <= out->base.opcode) 97 | return 0; 98 | 99 | out->wl_message = &interface->methods[out->base.opcode]; 100 | } 101 | 102 | if (!out->wl_message || !out->wl_message->signature) 103 | return 0; 104 | 105 | return 1; 106 | } 107 | 108 | static const char * 109 | signature_get_type(const char *sig, unsigned int *nullable) 110 | { 111 | assert(sig); 112 | 113 | *nullable = 0; 114 | while(*sig && (*sig == '?' || isdigit(*sig))) { 115 | if (*sig == '?') 116 | *nullable = 1; 117 | ++sig; 118 | } 119 | 120 | return sig; 121 | } 122 | 123 | static uint32_t * 124 | get_data_ptr(struct wldbg_resolved_message *msg) 125 | { 126 | /* If this is a string or array that is empty, 127 | * set it to NULL, otherwise make it pointing 128 | * to the data */ 129 | if ((*msg->signature_position == 'a' 130 | || *msg->signature_position == 's')) { 131 | /* msg->data_position points to the size of the 132 | * array/string, so here we check if the size of 133 | * array/string is 0 */ 134 | if (*msg->data_position == 0) 135 | return NULL; 136 | else 137 | /* skip size argument and point 138 | * to the data itself */ 139 | return msg->data_position + 1; 140 | } else { 141 | /* if this is not a string or array, just 142 | * point to the data */ 143 | return msg->data_position; 144 | } 145 | 146 | assert(0 && "Should not be reached"); 147 | } 148 | 149 | static void 150 | initialize_iterator(struct wldbg_resolved_message *msg) 151 | { 152 | const char *sig = signature_get_type(msg->wl_message->signature, 153 | &msg->cur_arg.nullable); 154 | 155 | msg->signature_position = sig; 156 | msg->data_position = msg->base.data; 157 | 158 | msg->cur_arg.type = *sig; 159 | msg->cur_arg.data = get_data_ptr(msg); 160 | 161 | assert(!*sig || *sig == 'a' || *sig == 's' || msg->cur_arg.data); 162 | } 163 | 164 | void 165 | wldbg_resolved_message_reset_iterator(struct wldbg_resolved_message *msg) 166 | { 167 | msg->signature_position = NULL; 168 | msg->data_position = NULL; 169 | memset(&msg->cur_arg, 0, 170 | sizeof(struct wldbg_resolved_arg)); 171 | } 172 | 173 | struct wldbg_resolved_arg * 174 | wldbg_resolved_message_next_argument(struct wldbg_resolved_message *msg) 175 | { 176 | size_t size, off = 0; 177 | char type; 178 | 179 | /* first iteration */ 180 | if (msg->signature_position == NULL) { 181 | initialize_iterator(msg); 182 | /* message has no arguments? */ 183 | if (msg->cur_arg.type == 0) 184 | return NULL; 185 | 186 | return &msg->cur_arg; 187 | } 188 | 189 | /* need to store type before getting next argument, 190 | * so that we know where to shift in data */ 191 | type = *msg->signature_position; 192 | 193 | /* calling next_argument on iterator that reached 194 | * the end */ 195 | if (type == 0) 196 | return NULL; 197 | 198 | /* set new type and position in signature */ 199 | msg->signature_position 200 | = signature_get_type(msg->signature_position + 1, 201 | &msg->cur_arg.nullable); 202 | msg->cur_arg.type = *msg->signature_position; 203 | 204 | if (msg->cur_arg.type == 0) 205 | return NULL; 206 | 207 | /* find data of next argument */ 208 | switch (type) { 209 | case 'u': 210 | case 'i': 211 | case 'f': 212 | case 'o': 213 | case 'n': 214 | case 'h': 215 | ++msg->data_position; 216 | break; 217 | case 's': 218 | case 'a': 219 | /* msg->data_position now points to 220 | * size argument of previous string/array */ 221 | size = *msg->data_position; 222 | if (size == 0) { 223 | ++msg->data_position; 224 | } else { 225 | off = DIV_ROUNDUP(size, sizeof(uint32_t)); 226 | msg->data_position += (off + 1); 227 | } 228 | break; 229 | default: 230 | fprintf(stderr, "Warning: unhandled type: %d (%c)\n", type, type); 231 | } 232 | 233 | /* ok, we now have pointer to the data of 234 | * the current argument, so set it in the iterator */ 235 | msg->cur_arg.data = get_data_ptr(msg); 236 | 237 | return &msg->cur_arg; 238 | } 239 | 240 | char * 241 | wldbg_resolved_message_get_name(struct wldbg_resolved_message *msg, 242 | char *buff, size_t maxlen) 243 | { 244 | snprintf(buff, maxlen, "%s@%s", 245 | msg->wl_interface->name, 246 | msg->wl_message->name); 247 | 248 | return buff; 249 | } 250 | 251 | size_t 252 | wldbg_get_message_name(struct wldbg_message *message, char *buf, size_t maxsize) 253 | { 254 | struct wldbg_parsed_message pm; 255 | const struct wl_interface *interface; 256 | const struct wl_message *wl_message = NULL; 257 | int ret; 258 | size_t written; 259 | 260 | wldbg_parse_message(message, &pm); 261 | interface = wldbg_message_get_object(message, pm.id); 262 | 263 | if (is_valid_interface(interface)) { 264 | if (message->from == SERVER) 265 | wl_message = &interface->events[pm.opcode]; 266 | else 267 | wl_message = &interface->methods[pm.opcode]; 268 | 269 | /* put the interface name into the buffer */ 270 | ret = snprintf(buf, maxsize, "%s", interface->name); 271 | } else 272 | ret = snprintf(buf, maxsize, "unknown"); 273 | 274 | if (ret < 0) 275 | return 0; 276 | if (ret >= (int) maxsize) 277 | return ret; 278 | 279 | written = ret; 280 | 281 | /* create name of the message we got */ 282 | if (wl_message) { 283 | ret = snprintf(buf + ret, maxsize - written, 284 | "@%d.%s", pm.id, wl_message->name); 285 | 286 | } else { 287 | ret = snprintf(buf + ret, maxsize - written, 288 | "@%d.%d", pm.id, pm.opcode); 289 | } 290 | 291 | if (ret < 0) 292 | return written; 293 | 294 | written += ret; 295 | 296 | // return how many characters we wrote or how 297 | // many characters we'd wrote in the case of overflow 298 | return written; 299 | } 300 | 301 | -------------------------------------------------------------------------------- /src/passes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _PASSES_H_ 27 | #define _PASSES_H_ 28 | 29 | struct pass; 30 | 31 | void 32 | dealloc_pass(struct pass *pass); 33 | 34 | struct pass * 35 | alloc_pass(const char *name); 36 | 37 | struct pass * 38 | create_pass(const char *); 39 | 40 | int 41 | pass_init(struct wldbg *wldbg, struct pass *pass, 42 | int argc, const char *argv[]); 43 | 44 | /* defined in passes/list.c */ 45 | void 46 | list_passes(int lng); 47 | 48 | #endif /* _PASSES_H_ */ 49 | -------------------------------------------------------------------------------- /src/resolve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* for WL_SERVER_ID_START */ 33 | #include "wayland/wayland-private.h" 34 | 35 | #include 36 | #include 37 | 38 | #include "wldbg.h" 39 | #include "wldbg-private.h" 40 | #include "wldbg-ids-map.h" 41 | 42 | /* special interfaces that will be set to 43 | * id's that has been deleted or are unknown. 44 | * To differ them from others they have 45 | * negative versions */ 46 | const struct wl_interface free_entry = { 47 | "FREE", -0x3, 0, NULL, 0, NULL 48 | }; 49 | 50 | const struct wl_interface unknown_interface = { 51 | "unknown", -0xf00, 0, NULL, 0, NULL 52 | }; 53 | 54 | static const struct wl_interface * 55 | resolved_objects_get(struct resolved_objects *ro, uint32_t id) 56 | { 57 | if (id >= WL_SERVER_ID_START) 58 | return wldbg_ids_map_get(&ro->objects.server_objects, 59 | id - WL_SERVER_ID_START); 60 | else 61 | return wldbg_ids_map_get(&ro->objects.client_objects, id); 62 | } 63 | 64 | const struct wl_interface * 65 | wldbg_message_get_object(struct wldbg_message *msg, uint32_t id) 66 | { 67 | struct resolved_objects *ro = msg->connection->resolved_objects; 68 | if (!ro) 69 | return NULL; 70 | 71 | return resolved_objects_get(ro, id); 72 | } 73 | 74 | const struct wl_interface * 75 | wldbg_message_get_interface(struct wldbg_message *msg, const char *name) 76 | { 77 | unsigned int i; 78 | const struct wl_interface *intf; 79 | struct resolved_objects *ro = msg->connection->resolved_objects; 80 | 81 | for (i = 0; i < ro->objects.client_objects.count; ++i) { 82 | intf = wldbg_ids_map_get(&ro->objects.client_objects, i); 83 | if (intf && strcmp(intf->name, name) == 0) 84 | return intf; 85 | } 86 | 87 | for (i = 0; i < ro->objects.server_objects.count; ++i) { 88 | intf = wldbg_ids_map_get(&ro->objects.server_objects, 89 | WL_SERVER_ID_START + i); 90 | if (intf && strcmp(intf->name, name) == 0) 91 | return intf; 92 | } 93 | 94 | return NULL; 95 | } 96 | 97 | static void 98 | resolved_objects_iterate(struct resolved_objects *ro, 99 | void (*func)(uint32_t id, 100 | const struct wl_interface *intf, 101 | void *data), 102 | void *data) 103 | { 104 | unsigned int i; 105 | const struct wl_interface *intf; 106 | 107 | for (i = 0; i < ro->objects.client_objects.count; ++i) { 108 | intf = wldbg_ids_map_get(&ro->objects.client_objects, i); 109 | func(i, intf, data); 110 | } 111 | 112 | for (i = 0; i < ro->objects.server_objects.count; ++i) { 113 | intf = wldbg_ids_map_get(&ro->objects.server_objects, 114 | WL_SERVER_ID_START + i); 115 | func( WL_SERVER_ID_START + i, intf, data); 116 | } 117 | } 118 | 119 | void 120 | wldbg_message_objects_iterate(struct wldbg_message *message, 121 | void (*func)(uint32_t id, 122 | const struct wl_interface *intf, 123 | void *data), 124 | void *data) 125 | { 126 | struct resolved_objects *ro = message->connection->resolved_objects; 127 | if (!ro) 128 | return; 129 | 130 | resolved_objects_iterate(ro, func, data); 131 | } 132 | -------------------------------------------------------------------------------- /src/resolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_RESOLVE_H_ 27 | #define _WLDBG_RESOLVE_H_ 28 | 29 | #include 30 | 31 | struct wldbg; 32 | struct resolved_objects; 33 | struct wldbg_connection; 34 | 35 | struct resolved_objects * 36 | wldbg_connection_get_resolved_objects(struct wldbg_connection *connection); 37 | 38 | int 39 | wldbg_add_resolve_pass(struct wldbg *wldbg); 40 | 41 | const struct wl_interface * 42 | resolved_objects_get(struct resolved_objects *ro, uint32_t id); 43 | 44 | const struct wl_interface * 45 | resolved_objects_get_interface(struct resolved_objects *ro, const char *name); 46 | 47 | void 48 | resolved_objects_iterate(struct resolved_objects *ro, 49 | void (*func)(uint32_t id, 50 | const struct wl_interface *intf, 51 | void *data), 52 | void *data); 53 | 54 | void 55 | resolved_objects_interate(struct resolved_objects *ro, 56 | void (*func)(uint32_t id, 57 | const struct wl_interface *intf, 58 | void *data), 59 | void *data); 60 | 61 | struct resolved_objects * 62 | create_resolved_objects(void); 63 | 64 | void 65 | destroy_resolved_objects(struct resolved_objects *ro); 66 | 67 | extern const struct wl_interface free_entry; 68 | extern const struct wl_interface unknown_interface; 69 | 70 | #endif /* _WLDBG_RESOLVE_H_ */ 71 | -------------------------------------------------------------------------------- /src/sockets.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_SOCKETS_H_ 27 | #define _WLDBG_SOCKETS_H_ 28 | 29 | int 30 | connect_to_wayland_server(struct wldbg_connection *conn, const char *display); 31 | 32 | int 33 | get_pid_for_socket(int fd); 34 | 35 | char * 36 | get_program_for_pid(pid_t pid); 37 | 38 | int 39 | server_mode_change_sockets(struct wldbg *wldbg); 40 | 41 | int 42 | server_mode_change_sockets_back(struct wldbg *wldbg); 43 | 44 | int 45 | server_mode_add_socket(struct wldbg *wldbg, const char *name); 46 | 47 | /* this version will use $XDG_RUNTIME_DIR as a root dir when 48 | * creating socket and will lock the socket the same way 49 | * as compositors do */ 50 | int 51 | server_mode_add_socket_with_lock(struct wldbg *wldbg, const char *name); 52 | 53 | #endif /* _WLDBG_SOCKETS_H_ */ 54 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | 37 | /* duplicate argv array */ 38 | int 39 | copy_arguments(char ***to, int argc, const char*argv[]) 40 | { 41 | int i, num = 0; 42 | char **tmp = calloc(argc + 1, sizeof(char *)); 43 | if (!tmp) 44 | return -1; 45 | 46 | while(*argv != NULL) { 47 | tmp[num] = strdup(*argv); 48 | if (!tmp[num]) { 49 | for (i = 0; i < num; ++i) 50 | free(tmp[num]); 51 | free(tmp); 52 | return -1; 53 | } 54 | 55 | ++num; 56 | ++argv; 57 | } 58 | 59 | /* calloc did this for us */ 60 | assert(tmp[num] == NULL); 61 | assert(argc == num); 62 | 63 | *to = tmp; 64 | 65 | return num; 66 | } 67 | 68 | void 69 | free_arguments(char **argv) 70 | { 71 | char **arg_tmp = argv; 72 | 73 | while(*argv != NULL) { 74 | free(*argv); 75 | ++argv; 76 | } 77 | 78 | free(arg_tmp); 79 | } 80 | 81 | /* skip white-space characters */ 82 | char * 83 | skip_ws(char *str) 84 | { 85 | char *p = str; 86 | while (*p && isspace(*p)) 87 | ++p; 88 | 89 | return p; 90 | } 91 | 92 | /* convert unsigned decimal number given in string 93 | * to integer. Return -1 if the string is not 94 | * unsigned decimal number. String can be prefixed and 95 | * suffixed with whitespaces */ 96 | int str_to_uint(char *str) 97 | { 98 | char *num, *numtmp; 99 | 100 | /* skip ws to first digit or newline */ 101 | numtmp = num = skip_ws(str); 102 | if (!*num) 103 | return -1; 104 | 105 | /* check that following sequence of characters 106 | * is a number */ 107 | while (*numtmp) { 108 | /* once we reach a space, we require 109 | * that there are spaces to the end of 110 | * string */ 111 | if (isspace(*numtmp)) { 112 | if (*skip_ws(numtmp) != 0) 113 | return -1; 114 | else 115 | break; 116 | } else if (!isdigit(*numtmp)) 117 | return -1; 118 | 119 | ++numtmp; 120 | } 121 | 122 | return atoi(num); 123 | } 124 | 125 | /* possibly inefficient, but easy implementation */ 126 | char * 127 | strdupf(const char *fmt, ...) 128 | { 129 | char *str; 130 | char dummy[2]; 131 | int size, size2; 132 | va_list vl; 133 | 134 | va_start(vl, fmt); 135 | /* get size of the string we'll create */ 136 | size = vsnprintf(dummy, sizeof dummy, fmt, vl); 137 | va_end(vl); 138 | if (size < 0) 139 | return NULL; 140 | /* if the string has size that fits to dummy, 141 | * just strdup it */ 142 | if (size < (int) sizeof dummy) 143 | return strdup(dummy); 144 | 145 | /* else create new string with desired size 146 | * and print into it. size is without terminating 0, 147 | * thus +1*/ 148 | size += 1; 149 | str = malloc(size); 150 | if (!str) 151 | return NULL; 152 | 153 | va_start(vl, fmt); 154 | size2 = vsnprintf(str, size, fmt, vl); 155 | va_end(vl); 156 | 157 | if (size2 < 0) { 158 | free(str); 159 | return NULL; 160 | } else if (size2 >= size) { 161 | free(str); 162 | return NULL; 163 | } 164 | 165 | 166 | return str; 167 | } 168 | 169 | char * 170 | remove_newline(char *str) 171 | { 172 | char *p = str; 173 | if (!p) 174 | return NULL; 175 | 176 | while (*p) { 177 | if (*p == '\n') { 178 | *p = 0; 179 | break; 180 | } 181 | 182 | ++p; 183 | } 184 | 185 | return str; 186 | } 187 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_UTIL_H_ 27 | #define _WLDBG_UTIL_H_ 28 | 29 | #include 30 | 31 | #ifndef DIV_ROUNDUP 32 | #define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) ) 33 | #endif 34 | 35 | struct wldbg; 36 | struct wldbg_connection; 37 | struct wldbg_message; 38 | 39 | /* defined in wldbg.c */ 40 | void 41 | wldbg_foreach_connection(struct wldbg *wldbg, 42 | void (*func)(struct wldbg_connection *)); 43 | 44 | /* defined in print.c */ 45 | size_t 46 | wldbg_get_message_name(struct wldbg_message *message, char *buf, size_t maxsize); 47 | 48 | /* defined in util.c */ 49 | int 50 | copy_arguments(char ***to, int argc, const char*argv[]); 51 | 52 | void 53 | free_arguments(char **argv); 54 | 55 | char * 56 | skip_ws(char *str); 57 | 58 | int 59 | str_to_uint(char *str); 60 | 61 | char * 62 | strdupf(const char *fmt, ...); 63 | 64 | char * 65 | remove_newline(char *str); 66 | 67 | #endif /* _WLDBG_UTIL_H_ */ 68 | -------------------------------------------------------------------------------- /src/wldbg-ids-map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "wldbg.h" 32 | #include "wldbg-pass.h" 33 | #include "wldbg-ids-map.h" 34 | 35 | void 36 | wldbg_ids_map_init(struct wldbg_ids_map *map) 37 | { 38 | map->count = 0; 39 | wl_array_init(&map->data); 40 | } 41 | 42 | void 43 | wldbg_ids_map_release(struct wldbg_ids_map *map) 44 | { 45 | map->count = 0; 46 | wl_array_release(&map->data); 47 | } 48 | 49 | void 50 | wldbg_ids_map_insert(struct wldbg_ids_map *map, uint32_t id, 51 | void *data) 52 | { 53 | void **p; 54 | size_t size; 55 | 56 | if (id >= map->count) { 57 | size = (id - map->count + 1) * sizeof(void *); 58 | p = wl_array_add(&map->data, size); 59 | if (!p) { 60 | /* this function is supposed to always succeed, 61 | * so in this case we cannot do nothing better 62 | * than abort(). We can't pass this slicently */ 63 | fprintf(stderr, "Out of memory"); 64 | abort(); 65 | } 66 | 67 | /* set newly allocated memory to 0s */ 68 | memset(p, 0, size); 69 | } 70 | 71 | p = ((void **) map->data.data) + id; 72 | assert(p); 73 | 74 | map->count = map->data.size / sizeof(void *); 75 | *p = data; 76 | } 77 | 78 | void * 79 | wldbg_ids_map_get(struct wldbg_ids_map *map, uint32_t id) 80 | { 81 | if (id < map->count) 82 | return ((void **) map->data.data)[id]; 83 | 84 | return NULL; 85 | } 86 | -------------------------------------------------------------------------------- /src/wldbg-ids-map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_IDS_MAP_H_ 27 | #define _WLDBG_IDS_MAP_H_ 28 | 29 | #include "wayland/wayland-util.h" 30 | 31 | /* we need just something like dynamic array. Wl_map is pain in the ass 32 | * for our purpose - belive me, I tried it ;) */ 33 | struct wldbg_ids_map { 34 | uint32_t count; 35 | struct wl_array data; 36 | }; 37 | 38 | void 39 | wldbg_ids_map_init(struct wldbg_ids_map *map); 40 | 41 | void 42 | wldbg_ids_map_release(struct wldbg_ids_map *map); 43 | 44 | void 45 | wldbg_ids_map_insert(struct wldbg_ids_map *map, uint32_t id, void *data); 46 | 47 | void * 48 | wldbg_ids_map_get(struct wldbg_ids_map *map, uint32_t id); 49 | 50 | #endif /* _WLDBG_IDS_MAP_H_ */ 51 | -------------------------------------------------------------------------------- /src/wldbg-objects-info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_OBJECTS_INFO_H_ 27 | #define _WLDBG_OBJECTS_INFO_H_ 28 | 29 | #include 30 | 31 | struct wl_interface; 32 | 33 | struct wldbg_object_info * 34 | wldbg_message_get_object_info(struct wldbg_message *msg, uint32_t id); 35 | 36 | struct wldbg_object_info { 37 | const struct wl_interface *wl_interface; 38 | /* this is a key to map, but we need it as well 39 | * when we have just pointer to this struct */ 40 | uint32_t id; 41 | /* every object has a version, so we can 42 | * keep it here, instead of in the real info. 43 | * NOTE: the version may not be set, 44 | * it depends solely on the object handler */ 45 | uint32_t version; 46 | /* the real info (according to interface) */ 47 | void *info; 48 | /* destroy data that are stored in info pointer */ 49 | void (*destroy)(void *); 50 | }; 51 | 52 | struct wldbg_wl_buffer_info 53 | { 54 | int32_t width, height, offset, stride; 55 | uint32_t format; 56 | unsigned int released : 1; 57 | }; 58 | 59 | struct wldbg_wl_surface_info { 60 | struct wldbg_wl_surface_info *commited; 61 | 62 | uint32_t wl_buffer_id; 63 | uint32_t attached_x, attached_y; 64 | uint32_t buffer_scale; 65 | /* XXX do it a callback info */ 66 | uint32_t last_frame_id; 67 | }; 68 | 69 | struct wldbg_xdg_surface_info { 70 | /* store last 10 configures */ 71 | struct xdg_configure { 72 | uint32_t width, height; 73 | uint32_t serial; 74 | unsigned int acked : 1; 75 | } configures[10]; 76 | uint64_t configures_num; 77 | 78 | char *title, *app_id; 79 | /* store only ids. It is more safe and simpler. 80 | * Instead of dangling pointers on some improper 81 | * object destruction, we'll get NULL from map */ 82 | uint32_t wl_surface_id; 83 | uint32_t parent_id; 84 | }; 85 | 86 | struct wldbg_wl_seat_info { 87 | uint32_t capabilities; 88 | char *name; 89 | 90 | /* FIXME: client can ask for more these objects 91 | uint32_t pointer_id; 92 | uint32_t keyboard_id; 93 | uint32_t touch_id; 94 | */ 95 | }; 96 | 97 | struct wldbg_wl_keyboard_info { 98 | /* store last 20 keys */ 99 | uint32_t last_keys[20]; 100 | 101 | /* modifiers state */ 102 | struct modifiers { 103 | uint32_t depressed; 104 | uint32_t latched; 105 | uint32_t locked; 106 | } modifiers; 107 | }; 108 | 109 | #endif /* _WLDBG_OBJECTS_INFO_H_ */ 110 | -------------------------------------------------------------------------------- /src/wldbg-parse-message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_PARSED_MESSAGE_H_ 27 | #define _WLDBG_PARSED_MESSAGE_H_ 28 | 29 | #include /* size_t */ 30 | #include 31 | 32 | struct wldbg_message; 33 | struct wl_message; 34 | struct wl_interface; 35 | struct wldbg_connection; 36 | 37 | struct wldbg_parsed_message { 38 | uint32_t id; 39 | uint32_t opcode; 40 | uint32_t size; 41 | /* data without header - that is raw_data + 2*sizeof(uint32_t) */ 42 | uint32_t *data; 43 | }; 44 | 45 | struct wldbg_resolved_arg { 46 | /* type of argument */ 47 | char type; 48 | /* can be null? */ 49 | unsigned int nullable; 50 | /* pointer to the data of argument in the message. 51 | * In the case of string or array, it points to 52 | * the data itself, not to the size (which is the first byte 53 | * of this data type) or is set to NULL if the string/array 54 | * is empty */ 55 | uint32_t *data; 56 | }; 57 | 58 | struct wldbg_resolved_message { 59 | struct wldbg_parsed_message base; 60 | const struct wl_interface *wl_interface; 61 | const struct wl_message *wl_message; 62 | 63 | /* position of arguments iterator */ 64 | struct wldbg_resolved_arg cur_arg; 65 | const char *signature_position; 66 | uint32_t *data_position; 67 | }; 68 | 69 | int wldbg_parse_message(struct wldbg_message *msg, struct wldbg_parsed_message *out); 70 | 71 | int wldbg_resolve_message(struct wldbg_message *msg, 72 | struct wldbg_resolved_message *out); 73 | 74 | struct wldbg_resolved_arg * 75 | wldbg_resolved_message_next_argument(struct wldbg_resolved_message *msg); 76 | 77 | void 78 | wldbg_resolved_message_reset_iterator(struct wldbg_resolved_message *msg); 79 | 80 | char * 81 | wldbg_resolved_message_get_name(struct wldbg_resolved_message *msg, 82 | char *buff, size_t maxlen); 83 | 84 | size_t 85 | wldbg_get_message_name(struct wldbg_message *message, char *buff, size_t maxsize); 86 | 87 | void 88 | wldbg_message_print(struct wldbg_message *message); 89 | 90 | #endif /* _WLDBG_PARSED_MESSAGE_H_ */ 91 | -------------------------------------------------------------------------------- /src/wldbg-pass.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_PASS_H_ 27 | #define _WLDBG_PASS_H_ 28 | 29 | #include 30 | 31 | struct wldbg_message; 32 | struct wldbg; 33 | 34 | /* flags for passes */ 35 | enum { 36 | /* suppress multiple loads of this pass */ 37 | WLDBG_PASS_LOAD_ONCE = 1, 38 | }; 39 | 40 | struct wldbg_pass { 41 | int (*init)(struct wldbg *wldbg, struct wldbg_pass *pass, 42 | int argc, const char *argv[]); 43 | 44 | void (*destroy)(void *user_data); 45 | 46 | /* function that will be run for messages from server */ 47 | int (*server_pass)(void *user_data, struct wldbg_message *message); 48 | 49 | /* function that will be run for messages from client */ 50 | int (*client_pass)(void *user_data, struct wldbg_message *message); 51 | 52 | /* print help for the pass */ 53 | void (*help)(void *user_data); 54 | 55 | void *user_data; 56 | const char *description; 57 | 58 | /* flags for the pass, i. e. WLDBG_PASS_LOAD_ONCE, etc */ 59 | uint64_t flags; 60 | }; 61 | 62 | enum { 63 | PASS_NEXT, /* process next pass */ 64 | PASS_STOP /* stop processing passes */ 65 | }; 66 | 67 | #endif /* _WLDBG_PASS_H_ */ 68 | -------------------------------------------------------------------------------- /src/wldbg-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | /* private functions used across the wldbg */ 27 | 28 | #ifndef _WLDBG_PRIVATE_H_ 29 | #define _WLDBG_PRIVATE_H_ 30 | 31 | #include "config.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "wldbg.h" 40 | #include "wayland/wayland-util.h" 41 | #include "wldbg-pass.h" 42 | #include "wldbg-ids-map.h" 43 | 44 | #ifdef DEBUG 45 | 46 | extern int debug; 47 | extern int debug_verbose; 48 | extern const char *debug_domain; 49 | 50 | #define vdbg(...) \ 51 | do { \ 52 | if (!debug_verbose) break; \ 53 | if (debug_domain \ 54 | && strcmp(debug_domain, __FILE__) != 0) \ 55 | break; \ 56 | fprintf(stderr, "[%d | %s: %d] ", getpid(), \ 57 | __FILE__, __LINE__); \ 58 | fprintf(stderr, __VA_ARGS__); \ 59 | } while (0) 60 | 61 | 62 | 63 | #define dbg(...) \ 64 | do { \ 65 | if (!debug) break; \ 66 | if (debug_domain \ 67 | && strcmp(debug_domain, __FILE__) != 0) \ 68 | break; \ 69 | fprintf(stderr, "[%d | %s: %d] ", getpid(), \ 70 | __FILE__, __LINE__); \ 71 | fprintf(stderr, __VA_ARGS__); \ 72 | } while (0) 73 | 74 | #define ifdbg(cond, ...) \ 75 | do { \ 76 | if (!debug) break; \ 77 | if (cond) \ 78 | dbg(__VA_ARGS__); \ 79 | } while (0) 80 | 81 | #else /* DEBUG */ 82 | 83 | #define dbg(...) 84 | #define vdbg(...) 85 | #define ifdbg(cond, ...) 86 | 87 | #endif /* DEBUG */ 88 | 89 | struct wldbg_connection; 90 | struct resolved_objects; 91 | 92 | struct wldbg { 93 | int epoll_fd; 94 | int signals_fd; 95 | 96 | struct wldbg_message message; 97 | char *buffer; 98 | 99 | sigset_t handled_signals; 100 | struct wl_list passes; 101 | struct wl_list monitored_fds; 102 | 103 | unsigned int resolving_objects : 1; 104 | unsigned int gathering_info : 1; 105 | 106 | struct { 107 | /* pass whole buffer to passes instead of just messages */ 108 | unsigned int pass_whole_buffer : 1; 109 | /* wldbg is running in main loop */ 110 | unsigned int running : 1; 111 | /* some pass raised error */ 112 | unsigned int error : 1; 113 | /* some pass asked to exit */ 114 | unsigned int exit : 1; 115 | /* running in server mode */ 116 | unsigned int server_mode : 1; 117 | } flags; 118 | 119 | struct { 120 | int fd; 121 | struct sockaddr_un addr; 122 | char *old_socket_path; 123 | char *wldbg_socket_path; 124 | char *old_socket_name; 125 | char *wldbg_socket_name; 126 | 127 | char *lock_addr; 128 | int fd_lock; 129 | 130 | const char *connect_to; 131 | 132 | /* Alignment width of the names of clients. 133 | * It is computed based on the longest name of clients out there */ 134 | int client_name_width; 135 | } server_mode; 136 | 137 | /* this will be list later */ 138 | struct wl_list connections; 139 | int connections_num; 140 | }; 141 | 142 | struct pass { 143 | struct wldbg_pass wldbg_pass; 144 | struct wl_list link; 145 | char *name; 146 | }; 147 | 148 | struct wldbg_connection { 149 | struct wldbg *wldbg; 150 | 151 | struct { 152 | int fd; 153 | /* TODO get rid of connection??? */ 154 | struct wl_connection *connection; 155 | pid_t pid; 156 | } server; 157 | 158 | struct { 159 | int fd; 160 | struct wl_connection *connection; 161 | 162 | char *program; 163 | /* path to the binary */ 164 | char *path; 165 | /* pointer to arguments and number of arguments */ 166 | int argc; 167 | char **argv; 168 | 169 | pid_t pid; 170 | } client; 171 | 172 | struct resolved_objects *resolved_objects; 173 | struct wldbg_objects_info *objects_info; 174 | struct wl_list link; 175 | }; 176 | 177 | struct wldbg_fd_callback { 178 | int fd; 179 | void *data; 180 | int (*dispatch)(int fd, void *data); 181 | struct wl_list link; 182 | }; 183 | 184 | struct resolved_objects_ids { 185 | /* id's allocated by client */ 186 | struct wldbg_ids_map client_objects; 187 | /* id's allocated by server */ 188 | struct wldbg_ids_map server_objects; 189 | }; 190 | 191 | struct resolved_objects { 192 | struct resolved_objects_ids objects; 193 | 194 | /* these are shared between connections */ 195 | struct wl_list *interfaces; 196 | 197 | /* these are specific for connection */ 198 | struct wl_list additional_interfaces; 199 | }; 200 | 201 | struct wldbg_objects_info { 202 | /* id's allocated by client */ 203 | struct wldbg_ids_map client_objects; 204 | /* id's allocated by server */ 205 | struct wldbg_ids_map server_objects; 206 | }; 207 | 208 | #endif /* _WLDBG_PRIVATE_H_ */ 209 | -------------------------------------------------------------------------------- /src/wldbg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 - 2015 Marek Chalupa 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation files 6 | * (the "Software"), to deal in the Software without restriction, 7 | * including without limitation the rights to use, copy, modify, merge, 8 | * publish, distribute, sublicense, and/or sell copies of the Software, 9 | * and to permit persons to whom the Software is furnished to do so, 10 | * subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the 13 | * next paragraph) shall be included in all copies or substantial 14 | * portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 20 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 21 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef _WLDBG_H_ 27 | #define _WLDBG_H_ 28 | 29 | #include "wldbg-pass.h" 30 | #include "wldbg-objects-info.h" 31 | 32 | struct wldbg; 33 | struct wldbg_connection; 34 | 35 | struct wldbg_message { 36 | /* raw data in message */ 37 | void *data; 38 | 39 | /* size of the message in bytes */ 40 | size_t size; 41 | 42 | /* whether it is a message from server or client */ 43 | enum { 44 | SERVER, 45 | CLIENT 46 | } from; 47 | 48 | /* pointer to connectoin structure */ 49 | struct wldbg_connection *connection; 50 | }; 51 | 52 | const struct wl_interface * 53 | wldbg_message_get_object(struct wldbg_message *msg, uint32_t id); 54 | 55 | const struct wl_interface * 56 | wldbg_message_get_interface(struct wldbg_message *msg, const char *name); 57 | 58 | void 59 | wldbg_message_objects_iterate(struct wldbg_message *message, 60 | void (*func)(uint32_t id, 61 | const struct wl_interface *intf, 62 | void *data), 63 | void *data); 64 | 65 | /* mercifully exit wldbg from the pass 66 | * and let it clean after itself */ 67 | void 68 | wldbg_exit(struct wldbg *wldbg); 69 | 70 | /* set error flag, wldbg will clean up 71 | * and exit with error on next iteration */ 72 | void 73 | wldbg_error(struct wldbg *wldbg); 74 | 75 | /* 76 | * Set pass_whole_buffer flag in wldbg. If this flag is 77 | * set, wldbg won't call passes on single messages but 78 | * on whole buffer that it gots from server or client 79 | * if state is 0 or 1, then the function sets the flag 80 | * accordingly. If the state is -1, then the function 81 | * returns current setting. Other state values are invalid */ 82 | int 83 | wldbg_separate_messages(struct wldbg *wldbg, int state); 84 | 85 | struct wldbg_fd_callback; 86 | 87 | struct wldbg_fd_callback * 88 | wldbg_monitor_fd(struct wldbg *wldbg, int fd, 89 | int (*dispatch)(int fd, void *data), 90 | void *data); 91 | int 92 | wldbg_remove_callback(struct wldbg *wldbg, struct wldbg_fd_callback *cb); 93 | 94 | #endif /* _WLDBG_H_ */ 95 | -------------------------------------------------------------------------------- /src/wldbg.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | datarootdir=@datarootdir@ 4 | pkgdatadir=@datadir@/@PACKAGE@ 5 | libdir=@libdir@ 6 | includedir=@includedir@ 7 | 8 | Name: Wldbg 9 | Description: Wldbg exported functions for passes 10 | Version: @WLDBG_VERSION@ 11 | Cflags: -I${includedir} 12 | Libs: -L${libdir} -lwldbg -lwayland-client 13 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | test_runner = \ 3 | $(top_builddir)/wayland/test-runner.c \ 4 | $(top_builddir)/wayland/test-runner.h \ 5 | $(top_builddir)/wayland/test-helpers.c 6 | 7 | 8 | check_PROGRAMS = \ 9 | map-test \ 10 | parse-message-test \ 11 | util-test 12 | 13 | TESTS = $(check_PROGRAMS) 14 | 15 | AM_LDFLAGS = -no-install -ldl 16 | AM_CPPFLAGS = \ 17 | -I$(top_srcdir) \ 18 | -I$(top_srcdir)/src \ 19 | -I$(top_srcdir)/wayland 20 | 21 | map_test_SOURCES = \ 22 | $(test_runner) \ 23 | map-test.c \ 24 | $(top_builddir)/src/wldbg-ids-map.h \ 25 | $(top_builddir)/src/wldbg-ids-map.c \ 26 | $(top_builddir)/wayland/wayland-util.h \ 27 | $(top_builddir)/wayland/wayland-util.c 28 | 29 | parse_message_test_LDADD = \ 30 | $(top_builddir)/src/libwldbg.la 31 | parse_message_test_LDFLAGS = \ 32 | -lwayland-client \ 33 | $(AM_LDFLAGS) 34 | 35 | parse_message_test_SOURCES = \ 36 | $(test_runner) \ 37 | parse-message-test.c 38 | 39 | util_test_SOURCES = \ 40 | $(test_runner) \ 41 | util-test.c \ 42 | $(top_builddir)/src/util.c 43 | -------------------------------------------------------------------------------- /tests/map-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "wldbg-ids-map.h" 3 | #include "test-runner.h" 4 | 5 | TEST(map_create) 6 | { 7 | struct wldbg_ids_map m; 8 | 9 | wldbg_ids_map_init(&m); 10 | wldbg_ids_map_release(&m); 11 | /* leaks? */ 12 | } 13 | 14 | TEST(map_insert) 15 | { 16 | struct wldbg_ids_map m; 17 | 18 | wldbg_ids_map_init(&m); 19 | assert(wldbg_ids_map_get(&m, 0) == NULL); 20 | 21 | wldbg_ids_map_insert(&m, 0, (void *) 0x1); 22 | assert(wldbg_ids_map_get(&m, 0) == (void *) 0x1); 23 | wldbg_ids_map_insert(&m, 1, (void *) 0x2); 24 | assert(wldbg_ids_map_get(&m, 1) == (void *) 0x2); 25 | 26 | /* rewrite first value */ 27 | wldbg_ids_map_insert(&m, 0, (void *) 0x3); 28 | assert(wldbg_ids_map_get(&m, 0) == (void *) 0x3); 29 | assert(wldbg_ids_map_get(&m, 1) == (void *) 0x2); 30 | 31 | wldbg_ids_map_insert(&m, 10, (void *) 0x10); 32 | assert(m.count == 11); 33 | assert(wldbg_ids_map_get(&m, 11) == NULL); 34 | assert(wldbg_ids_map_get(&m, 10) == (void *) 0x10); 35 | 36 | wldbg_ids_map_insert(&m, 0x55, (void *) 0x55); 37 | assert(m.count == 0x55 + 1); 38 | assert(wldbg_ids_map_get(&m, 0x55) == (void *) 0x55); 39 | 40 | wldbg_ids_map_release(&m); 41 | } 42 | -------------------------------------------------------------------------------- /tests/parse-message-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "test-runner.h" 3 | 4 | #include "wldbg-parse-message.h" 5 | #include "wldbg.h" 6 | #include "wayland/wayland-util.h" 7 | 8 | TEST(parse_base_message) 9 | { 10 | int ret; 11 | uint32_t data[] = { 123, 0x0040feef, 0xd00d, 0xdeed }; 12 | struct wldbg_message msg = { 13 | .data = data 14 | }; 15 | 16 | struct wldbg_parsed_message pm; 17 | ret = wldbg_parse_message(&msg, &pm); 18 | assert(ret != 0 && "failed parsing message"); 19 | assert(pm.id == 123 && "wrong id"); 20 | assert(pm.opcode = 0xfeef && "wrong opcode"); 21 | assert(pm.size = 0x0040 && "wrong opcode"); 22 | assert(*pm.data == 0xd00d); 23 | assert(*(pm.data + 1) == 0xdeed); 24 | } 25 | 26 | TEST(parse_base_message_fail) 27 | { 28 | int ret; 29 | uint32_t data[] = { 123, 0x0002feef, 0xd00d, 0xdeed }; 30 | struct wldbg_message msg = { 31 | .data = data 32 | }; 33 | 34 | struct wldbg_parsed_message pm; 35 | ret = wldbg_parse_message(&msg, &pm); 36 | /* size is less than 8, we should fail */ 37 | assert(ret == 0 && "succeed parsing message"); 38 | 39 | data[1] = 0x0041feef; 40 | ret = wldbg_parse_message(&msg, &pm); 41 | /* size is not divisible by 4 (sizeof uint32_t), 42 | * we should fail */ 43 | assert(ret == 0 && "succeed parsing message"); 44 | } 45 | 46 | static const struct wl_message dummy_requests[] = { 47 | { "foo", "4i?o2ih", NULL }, 48 | { "empty", "", NULL }, 49 | }; 50 | 51 | static const struct wl_message dummy_events[] = { 52 | { "foo", "1s?a?sa?2s", NULL }, 53 | { "foo2", "1usu", NULL }, 54 | }; 55 | 56 | static const struct wl_interface dummy_interface = { 57 | .name = "dummy_interface", 1, 58 | 1, dummy_requests, 59 | 1, dummy_events, 60 | }; 61 | 62 | TEST(resolved_message_iterator_types) 63 | { 64 | uint32_t data[] = {1,2,3,4}; 65 | struct wldbg_resolved_message rm = { 66 | .wl_interface = &dummy_interface, 67 | .wl_message = &dummy_requests[0], 68 | .base.data = data, 69 | }; 70 | 71 | wldbg_resolved_message_reset_iterator(&rm); 72 | struct wldbg_resolved_arg *arg; 73 | 74 | arg = wldbg_resolved_message_next_argument(&rm); 75 | assert(arg != NULL); 76 | assert(arg->type == 'i'); 77 | assert(!arg->nullable); 78 | 79 | arg = wldbg_resolved_message_next_argument(&rm); 80 | assert(arg != NULL); 81 | assert(arg->type == 'o'); 82 | assert(arg->nullable); 83 | 84 | arg = wldbg_resolved_message_next_argument(&rm); 85 | assert(arg != NULL); 86 | assert(arg->type == 'i'); 87 | assert(!arg->nullable); 88 | 89 | arg = wldbg_resolved_message_next_argument(&rm); 90 | assert(arg != NULL); 91 | assert(arg->type == 'h'); 92 | assert(!arg->nullable); 93 | 94 | arg = wldbg_resolved_message_next_argument(&rm); 95 | assert(arg == NULL); 96 | } 97 | 98 | TEST(resolved_iterator_test) 99 | { 100 | /* { "foo", "1s?a?sa?2s", NULL } */ 101 | uint32_t data[] = { 16 /* string size */, 102 | 0xdee1, 0xdee2, 0xdee3, 0xdee4, 103 | 0 /* array size */, 104 | 0 /* string size */, 105 | 12 /* array size */, 106 | 0xaaa1, 0xaaa2, 0xaaa3, 107 | 0}; 108 | struct wldbg_resolved_message rm = { 109 | .wl_interface = &dummy_interface, 110 | .wl_message = &dummy_events[0], 111 | .base.data = data 112 | }; 113 | 114 | wldbg_resolved_message_reset_iterator(&rm); 115 | struct wldbg_resolved_arg *arg; 116 | 117 | arg = wldbg_resolved_message_next_argument(&rm); 118 | assert(arg != NULL); 119 | assert(arg->type == 's'); 120 | assert(!arg->nullable); 121 | assert(arg->data == data + 1); 122 | assert(*arg->data == 0xdee1); 123 | 124 | arg = wldbg_resolved_message_next_argument(&rm); 125 | assert(arg != NULL); 126 | assert(arg->type == 'a'); 127 | assert(arg->nullable); 128 | assert(arg->data == NULL); 129 | 130 | arg = wldbg_resolved_message_next_argument(&rm); 131 | assert(arg != NULL); 132 | assert(arg->type == 's'); 133 | assert(arg->nullable); 134 | assert(arg->data == NULL); 135 | 136 | arg = wldbg_resolved_message_next_argument(&rm); 137 | assert(arg != NULL); 138 | assert(arg->type == 'a'); 139 | assert(!arg->nullable); 140 | assert(arg->data == data + 8); 141 | assert(*arg->data == 0xaaa1); 142 | 143 | arg = wldbg_resolved_message_next_argument(&rm); 144 | assert(arg != NULL); 145 | assert(arg->type == 's'); 146 | assert(arg->nullable); 147 | assert(arg->data == NULL); 148 | 149 | arg = wldbg_resolved_message_next_argument(&rm); 150 | assert(arg == NULL); 151 | arg = wldbg_resolved_message_next_argument(&rm); 152 | assert(arg == NULL); 153 | 154 | /* try reset iterator, we should be at the begginging again */ 155 | wldbg_resolved_message_reset_iterator(&rm); 156 | arg = wldbg_resolved_message_next_argument(&rm); 157 | assert(arg != NULL); 158 | assert(arg->type == 's'); 159 | assert(!arg->nullable); 160 | assert(arg->data == data + 1); 161 | assert(*arg->data == 0xdee1); 162 | 163 | arg = wldbg_resolved_message_next_argument(&rm); 164 | assert(arg != NULL); 165 | assert(arg->type == 'a'); 166 | assert(arg->nullable); 167 | assert(arg->data == NULL); 168 | 169 | arg = wldbg_resolved_message_next_argument(&rm); 170 | assert(arg != NULL); 171 | assert(arg->type == 's'); 172 | assert(arg->nullable); 173 | assert(arg->data == NULL); 174 | 175 | arg = wldbg_resolved_message_next_argument(&rm); 176 | assert(arg != NULL); 177 | assert(arg->type == 'a'); 178 | assert(!arg->nullable); 179 | assert(arg->data == data + 8); 180 | assert(*arg->data == 0xaaa1); 181 | 182 | arg = wldbg_resolved_message_next_argument(&rm); 183 | assert(arg != NULL); 184 | assert(arg->type == 's'); 185 | assert(arg->nullable); 186 | assert(arg->data == NULL); 187 | 188 | arg = wldbg_resolved_message_next_argument(&rm); 189 | assert(arg == NULL); 190 | arg = wldbg_resolved_message_next_argument(&rm); 191 | assert(arg == NULL); 192 | } 193 | 194 | TEST(resolve_message_test2) 195 | { 196 | /* { "foo2", "1usu", NULL } */ 197 | uint32_t data[] = { 123, 198 | 17 /* string size */, 199 | 0xdee1, 0xdee2, 0xdee3, 0xdee4, 0xdee5, 200 | 12 }; 201 | struct wldbg_resolved_message rm = { 202 | .wl_interface = &dummy_interface, 203 | .wl_message = &dummy_events[1], 204 | .base.data = data 205 | }; 206 | 207 | wldbg_resolved_message_reset_iterator(&rm); 208 | struct wldbg_resolved_arg *arg; 209 | 210 | arg = wldbg_resolved_message_next_argument(&rm); 211 | assert(arg != NULL); 212 | assert(arg->type == 'u'); 213 | assert(!arg->nullable); 214 | assert(arg->data == data + 0); 215 | assert(*arg->data == 123); 216 | 217 | arg = wldbg_resolved_message_next_argument(&rm); 218 | assert(arg != NULL); 219 | assert(arg->type == 's'); 220 | assert(!arg->nullable); 221 | assert(arg->data == data + 2); 222 | assert(*(arg->data - 1) == 17); 223 | 224 | arg = wldbg_resolved_message_next_argument(&rm); 225 | assert(arg != NULL); 226 | assert(arg->type == 'u'); 227 | assert(!arg->nullable); 228 | assert(arg->data == data + 7); 229 | assert(*arg->data == 12); 230 | 231 | arg = wldbg_resolved_message_next_argument(&rm); 232 | assert(arg == NULL); 233 | arg = wldbg_resolved_message_next_argument(&rm); 234 | assert(arg == NULL); 235 | } 236 | 237 | TEST(message_no_arguments) 238 | { 239 | /* test message with signature "" */ 240 | struct wldbg_resolved_message rm = { 241 | .wl_interface = &dummy_interface, 242 | .wl_message = &dummy_requests[1], 243 | }; 244 | 245 | wldbg_resolved_message_reset_iterator(&rm); 246 | struct wldbg_resolved_arg *arg; 247 | 248 | arg = wldbg_resolved_message_next_argument(&rm); 249 | assert(arg == NULL); 250 | arg = wldbg_resolved_message_next_argument(&rm); 251 | assert(arg == NULL); 252 | } 253 | -------------------------------------------------------------------------------- /tests/util-test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test-runner.h" 4 | #include "util.h" 5 | 6 | TEST(skip_ws_test) 7 | { 8 | char *str; 9 | 10 | str = " hell"; 11 | assert(skip_ws(str) == str + 2); 12 | str = "a hell"; 13 | assert(skip_ws(str) == str); 14 | str = "hell "; 15 | assert(skip_ws(str) == str); 16 | str = " hell "; 17 | assert(skip_ws(str) == str + 1); 18 | str = ""; 19 | assert(skip_ws(str) == str); 20 | char str2[] = {'\0', 'a', 'h'}; 21 | assert(skip_ws(str2) == str2); 22 | char str3[] = {' ', ' ', ' ', '\0'}; 23 | assert(skip_ws(str3) == str3 + 3); 24 | } 25 | 26 | TEST(str_to_uint_test) 27 | { 28 | assert(str_to_uint("0") == 0); 29 | assert(str_to_uint("1") == 1); 30 | assert(str_to_uint("a") == -1); 31 | assert(str_to_uint("1a") == -1); 32 | assert(str_to_uint("a1") == -1); 33 | assert(str_to_uint("") == -1); 34 | assert(str_to_uint("0 ") == 0); 35 | assert(str_to_uint(" 0") == 0); 36 | assert(str_to_uint(" 0 ") == 0); 37 | assert(str_to_uint(" ") == -1); 38 | assert(str_to_uint(" 0 a") == -1); 39 | assert(str_to_uint("a 123 ") == -1); 40 | assert(str_to_uint(" 123 a") == -1); 41 | assert(str_to_uint(" 123 a") == -1); 42 | assert(str_to_uint(" 123 ") == 123); 43 | assert(str_to_uint(" 123 ") == 123); 44 | assert(str_to_uint("123") == 123); 45 | assert(str_to_uint("0x123") == -1); 46 | } 47 | -------------------------------------------------------------------------------- /wayland/test-helpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Collabora, Ltd. 3 | * 4 | * Permission to use, copy, modify, distribute, and sell this software and its 5 | * documentation for any purpose is hereby granted without fee, provided that 6 | * the above copyright notice appear in all copies and that both that copyright 7 | * notice and this permission notice appear in supporting documentation, and 8 | * that the name of the copyright holders not be used in advertising or 9 | * publicity pertaining to distribution of the software without specific, 10 | * written prior permission. The copyright holders make no representations 11 | * about the suitability of this software for any purpose. It is provided "as 12 | * is" without express or implied warranty. 13 | * 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 | * OF THIS SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "test-runner.h" 30 | 31 | int 32 | count_open_fds(void) 33 | { 34 | DIR *dir; 35 | struct dirent *ent; 36 | int count = 0; 37 | 38 | dir = opendir("/proc/self/fd"); 39 | assert(dir && "opening /proc/self/fd failed."); 40 | 41 | errno = 0; 42 | while ((ent = readdir(dir))) { 43 | const char *s = ent->d_name; 44 | if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0))) 45 | continue; 46 | count++; 47 | } 48 | assert(errno == 0 && "reading /proc/self/fd failed."); 49 | 50 | closedir(dir); 51 | 52 | return count; 53 | } 54 | 55 | void 56 | exec_fd_leak_check(int nr_expected_fds) 57 | { 58 | const char *exe = "./exec-fd-leak-checker"; 59 | char number[16] = { 0 }; 60 | 61 | snprintf(number, sizeof number - 1, "%d", nr_expected_fds); 62 | execl(exe, exe, number, (char *)NULL); 63 | assert(0 && "execing fd leak checker failed"); 64 | } 65 | -------------------------------------------------------------------------------- /wayland/test-runner.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * 4 | * Permission to use, copy, modify, distribute, and sell this software and its 5 | * documentation for any purpose is hereby granted without fee, provided that 6 | * the above copyright notice appear in all copies and that both that copyright 7 | * notice and this permission notice appear in supporting documentation, and 8 | * that the name of the copyright holders not be used in advertising or 9 | * publicity pertaining to distribution of the software without specific, 10 | * written prior permission. The copyright holders make no representations 11 | * about the suitability of this software for any purpose. It is provided "as 12 | * is" without express or implied warranty. 13 | * 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 | * OF THIS SOFTWARE. 21 | */ 22 | 23 | #define _GNU_SOURCE 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "test-runner.h" 35 | 36 | static int num_alloc; 37 | static void* (*sys_malloc)(size_t); 38 | static void (*sys_free)(void*); 39 | static void* (*sys_realloc)(void*, size_t); 40 | static void* (*sys_calloc)(size_t, size_t); 41 | 42 | int leak_check_enabled; 43 | 44 | /* default timeout in seconds. If it is set to 0, it is turned off */ 45 | static int timeout = 10; 46 | 47 | extern const struct test __start_test_section, __stop_test_section; 48 | 49 | __attribute__ ((visibility("default"))) void * 50 | malloc(size_t size) 51 | { 52 | num_alloc++; 53 | return sys_malloc(size); 54 | } 55 | 56 | __attribute__ ((visibility("default"))) void 57 | free(void* mem) 58 | { 59 | if (mem != NULL) 60 | num_alloc--; 61 | sys_free(mem); 62 | } 63 | 64 | __attribute__ ((visibility("default"))) void * 65 | realloc(void* mem, size_t size) 66 | { 67 | if (mem == NULL) 68 | num_alloc++; 69 | return sys_realloc(mem, size); 70 | } 71 | 72 | __attribute__ ((visibility("default"))) void * 73 | calloc(size_t nmemb, size_t size) 74 | { 75 | if (sys_calloc == NULL) 76 | return NULL; 77 | 78 | num_alloc++; 79 | 80 | return sys_calloc(nmemb, size); 81 | } 82 | 83 | static const struct test * 84 | find_test(const char *name) 85 | { 86 | const struct test *t; 87 | 88 | for (t = &__start_test_section; t < &__stop_test_section; t++) 89 | if (strcmp(t->name, name) == 0) 90 | return t; 91 | 92 | return NULL; 93 | } 94 | 95 | static void 96 | usage(const char *name, int status) 97 | { 98 | const struct test *t; 99 | 100 | fprintf(stderr, "Usage: %s [TEST]\n\n" 101 | "With no arguments, run all test. Specify test case to run\n" 102 | "only that test without forking. Available tests:\n\n", 103 | name); 104 | 105 | for (t = &__start_test_section; t < &__stop_test_section; t++) 106 | fprintf(stderr, " %s\n", t->name); 107 | 108 | fprintf(stderr, "\n"); 109 | 110 | exit(status); 111 | } 112 | 113 | void 114 | test_set_timeout(int sec) 115 | { 116 | if (!timeout) { 117 | fprintf(stderr, "Timeout is disabled. " 118 | "Setting new timeout to %d suppressed\n", sec); 119 | return; 120 | } 121 | 122 | alarm(sec); 123 | fprintf(stderr, "Timeout set to %d sec from now.\n", sec); 124 | } 125 | 126 | static void 127 | run_test(const struct test *t) 128 | { 129 | int cur_alloc = num_alloc; 130 | int cur_fds, num_fds; 131 | struct sigaction sa; 132 | 133 | /* XXX add sigalrm_handler */ 134 | 135 | cur_fds = count_open_fds(); 136 | t->run(); 137 | if (leak_check_enabled) { 138 | if (cur_alloc != num_alloc) { 139 | fprintf(stderr, "Memory leak detected in test. " 140 | "Allocated %d blocks, unfreed %d\n", num_alloc, 141 | num_alloc - cur_alloc); 142 | abort(); 143 | } 144 | num_fds = count_open_fds(); 145 | if (cur_fds != num_fds) { 146 | fprintf(stderr, "fd leak detected in test. " 147 | "Opened %d files, unclosed %d\n", num_fds, 148 | num_fds - cur_fds); 149 | abort(); 150 | } 151 | } 152 | exit(EXIT_SUCCESS); 153 | } 154 | 155 | int main(int argc, char *argv[]) 156 | { 157 | const struct test *t; 158 | pid_t pid; 159 | int total, pass; 160 | siginfo_t info; 161 | const char *to_env; 162 | 163 | /* Load system malloc, free, and realloc */ 164 | sys_calloc = dlsym(RTLD_NEXT, "calloc"); 165 | sys_realloc = dlsym(RTLD_NEXT, "realloc"); 166 | sys_malloc = dlsym(RTLD_NEXT, "malloc"); 167 | sys_free = dlsym(RTLD_NEXT, "free"); 168 | 169 | leak_check_enabled = !getenv("NO_ASSERT_LEAK_CHECK"); 170 | if ((to_env = getenv("WAYLAND_TEST_TIMEOUT"))) { 171 | /* XXX use strtol */ 172 | timeout = atoi(to_env); 173 | } 174 | 175 | if (argc == 2 && strcmp(argv[1], "--help") == 0) 176 | usage(argv[0], EXIT_SUCCESS); 177 | 178 | if (argc == 2) { 179 | t = find_test(argv[1]); 180 | if (t == NULL) { 181 | fprintf(stderr, "unknown test: \"%s\"\n", argv[1]); 182 | usage(argv[0], EXIT_FAILURE); 183 | } 184 | 185 | run_test(t); 186 | } 187 | 188 | pass = 0; 189 | for (t = &__start_test_section; t < &__stop_test_section; t++) { 190 | int success = 0; 191 | 192 | pid = fork(); 193 | assert(pid >= 0); 194 | 195 | if (pid == 0) 196 | run_test(t); /* never returns */ 197 | 198 | if (waitid(P_ALL, 0, &info, WEXITED)) { 199 | fprintf(stderr, "waitid failed: %m\n"); 200 | abort(); 201 | } 202 | 203 | fprintf(stderr, "test \"%s\":\t", t->name); 204 | switch (info.si_code) { 205 | case CLD_EXITED: 206 | fprintf(stderr, "exit status %d", info.si_status); 207 | if (info.si_status == EXIT_SUCCESS) 208 | success = 1; 209 | break; 210 | case CLD_KILLED: 211 | case CLD_DUMPED: 212 | fprintf(stderr, "signal %d", info.si_status); 213 | break; 214 | } 215 | 216 | if (t->must_fail) 217 | success = !success; 218 | 219 | if (success) { 220 | pass++; 221 | fprintf(stderr, ", pass.\n"); 222 | } else 223 | fprintf(stderr, ", fail.\n"); 224 | } 225 | 226 | total = &__stop_test_section - &__start_test_section; 227 | fprintf(stderr, "%d tests, %d pass, %d fail\n", 228 | total, pass, total - pass); 229 | 230 | return pass == total ? EXIT_SUCCESS : EXIT_FAILURE; 231 | } 232 | -------------------------------------------------------------------------------- /wayland/test-runner.h: -------------------------------------------------------------------------------- 1 | #ifndef _TEST_RUNNER_H_ 2 | #define _TEST_RUNNER_H_ 3 | 4 | #ifdef NDEBUG 5 | #error "Tests must not be built with NDEBUG defined, they rely on assert()." 6 | #endif 7 | 8 | struct test { 9 | const char *name; 10 | void (*run)(void); 11 | int must_fail; 12 | } __attribute__ ((aligned (16))); 13 | 14 | #define TEST(name) \ 15 | static void name(void); \ 16 | \ 17 | const struct test test##name \ 18 | __attribute__ ((section ("test_section"))) = { \ 19 | #name, name, 0 \ 20 | }; \ 21 | \ 22 | static void name(void) 23 | 24 | #define FAIL_TEST(name) \ 25 | static void name(void); \ 26 | \ 27 | const struct test test##name \ 28 | __attribute__ ((section ("test_section"))) = { \ 29 | #name, name, 1 \ 30 | }; \ 31 | \ 32 | static void name(void) 33 | 34 | int 35 | count_open_fds(void); 36 | 37 | void 38 | exec_fd_leak_check(int nr_expected_fds); /* never returns */ 39 | 40 | void 41 | test_set_timeout(int sec); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /wayland/wayland-os.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Collabora, Ltd. 3 | * 4 | * Permission to use, copy, modify, distribute, and sell this software and its 5 | * documentation for any purpose is hereby granted without fee, provided that 6 | * the above copyright notice appear in all copies and that both that copyright 7 | * notice and this permission notice appear in supporting documentation, and 8 | * that the name of the copyright holders not be used in advertising or 9 | * publicity pertaining to distribution of the software without specific, 10 | * written prior permission. The copyright holders make no representations 11 | * about the suitability of this software for any purpose. It is provided "as 12 | * is" without express or implied warranty. 13 | * 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 | * OF THIS SOFTWARE. 21 | */ 22 | 23 | #define _GNU_SOURCE 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "../config.h" 33 | #include "wayland-os.h" 34 | 35 | static int 36 | set_cloexec_or_close(int fd) 37 | { 38 | long flags; 39 | 40 | if (fd == -1) 41 | return -1; 42 | 43 | flags = fcntl(fd, F_GETFD); 44 | if (flags == -1) 45 | goto err; 46 | 47 | if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) 48 | goto err; 49 | 50 | return fd; 51 | 52 | err: 53 | close(fd); 54 | return -1; 55 | } 56 | 57 | int 58 | wl_os_socket_cloexec(int domain, int type, int protocol) 59 | { 60 | int fd; 61 | 62 | fd = socket(domain, type | SOCK_CLOEXEC, protocol); 63 | if (fd >= 0) 64 | return fd; 65 | if (errno != EINVAL) 66 | return -1; 67 | 68 | fd = socket(domain, type, protocol); 69 | return set_cloexec_or_close(fd); 70 | } 71 | 72 | int 73 | wl_os_dupfd_cloexec(int fd, long minfd) 74 | { 75 | int newfd; 76 | 77 | newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); 78 | if (newfd >= 0) 79 | return newfd; 80 | if (errno != EINVAL) 81 | return -1; 82 | 83 | newfd = fcntl(fd, F_DUPFD, minfd); 84 | return set_cloexec_or_close(newfd); 85 | } 86 | 87 | static ssize_t 88 | recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags) 89 | { 90 | ssize_t len; 91 | struct cmsghdr *cmsg; 92 | unsigned char *data; 93 | int *fd; 94 | int *end; 95 | 96 | len = recvmsg(sockfd, msg, flags); 97 | if (len == -1) 98 | return -1; 99 | 100 | if (!msg->msg_control || msg->msg_controllen == 0) 101 | return len; 102 | 103 | cmsg = CMSG_FIRSTHDR(msg); 104 | for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { 105 | if (cmsg->cmsg_level != SOL_SOCKET || 106 | cmsg->cmsg_type != SCM_RIGHTS) 107 | continue; 108 | 109 | data = CMSG_DATA(cmsg); 110 | end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0)); 111 | for (fd = (int *)data; fd < end; ++fd) 112 | *fd = set_cloexec_or_close(*fd); 113 | } 114 | 115 | return len; 116 | } 117 | 118 | ssize_t 119 | wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) 120 | { 121 | ssize_t len; 122 | 123 | len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); 124 | if (len >= 0) 125 | return len; 126 | if (errno != EINVAL) 127 | return -1; 128 | 129 | return recvmsg_cloexec_fallback(sockfd, msg, flags); 130 | } 131 | 132 | int 133 | wl_os_epoll_create_cloexec(void) 134 | { 135 | int fd; 136 | 137 | #ifdef EPOLL_CLOEXEC 138 | fd = epoll_create1(EPOLL_CLOEXEC); 139 | if (fd >= 0) 140 | return fd; 141 | if (errno != EINVAL) 142 | return -1; 143 | #endif 144 | 145 | fd = epoll_create(1); 146 | return set_cloexec_or_close(fd); 147 | } 148 | 149 | int 150 | wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) 151 | { 152 | int fd; 153 | 154 | #ifdef HAVE_ACCEPT4 155 | fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); 156 | if (fd >= 0) 157 | return fd; 158 | if (errno != ENOSYS) 159 | return -1; 160 | #endif 161 | 162 | fd = accept(sockfd, addr, addrlen); 163 | return set_cloexec_or_close(fd); 164 | } 165 | -------------------------------------------------------------------------------- /wayland/wayland-os.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Collabora, Ltd. 3 | * 4 | * Permission to use, copy, modify, distribute, and sell this software and its 5 | * documentation for any purpose is hereby granted without fee, provided that 6 | * the above copyright notice appear in all copies and that both that copyright 7 | * notice and this permission notice appear in supporting documentation, and 8 | * that the name of the copyright holders not be used in advertising or 9 | * publicity pertaining to distribution of the software without specific, 10 | * written prior permission. The copyright holders make no representations 11 | * about the suitability of this software for any purpose. It is provided "as 12 | * is" without express or implied warranty. 13 | * 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 | * OF THIS SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_OS_H 24 | #define WAYLAND_OS_H 25 | 26 | int 27 | wl_os_socket_cloexec(int domain, int type, int protocol); 28 | 29 | int 30 | wl_os_dupfd_cloexec(int fd, long minfd); 31 | 32 | ssize_t 33 | wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); 34 | 35 | int 36 | wl_os_epoll_create_cloexec(void); 37 | 38 | int 39 | wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 40 | 41 | 42 | /* 43 | * The following are for wayland-os.c and the unit tests. 44 | * Do not use them elsewhere. 45 | */ 46 | 47 | #ifdef __linux__ 48 | 49 | #ifndef SOCK_CLOEXEC 50 | #define SOCK_CLOEXEC 02000000 51 | #endif 52 | 53 | #ifndef F_DUPFD_CLOEXEC 54 | #define F_DUPFD_CLOEXEC 1030 55 | #endif 56 | 57 | #ifndef MSG_CMSG_CLOEXEC 58 | #define MSG_CMSG_CLOEXEC 0x40000000 59 | #endif 60 | 61 | #endif /* __linux__ */ 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /wayland/wayland-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008-2011 Kristian Høgsberg 3 | * Copyright © 2011 Intel Corporation 4 | * Copyright © 2013 Jason Ekstrand 5 | * 6 | * Permission to use, copy, modify, distribute, and sell this software and its 7 | * documentation for any purpose is hereby granted without fee, provided that 8 | * the above copyright notice appear in all copies and that both that copyright 9 | * notice and this permission notice appear in supporting documentation, and 10 | * that the name of the copyright holders not be used in advertising or 11 | * publicity pertaining to distribution of the software without specific, 12 | * written prior permission. The copyright holders make no representations 13 | * about the suitability of this software for any purpose. It is provided "as 14 | * is" without express or implied warranty. 15 | * 16 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 22 | * OF THIS SOFTWARE. 23 | */ 24 | 25 | #ifndef WAYLAND_PRIVATE_H 26 | #define WAYLAND_PRIVATE_H 27 | 28 | #include 29 | 30 | #define WL_HIDE_DEPRECATED 1 31 | 32 | #include "wayland-util.h" 33 | 34 | #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) 35 | 36 | #define container_of(ptr, type, member) ({ \ 37 | const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ 38 | (type *)( (char *)__mptr - offsetof(type,member) );}) 39 | 40 | #define WL_MAP_SERVER_SIDE 0 41 | #define WL_MAP_CLIENT_SIDE 1 42 | #define WL_SERVER_ID_START 0xff000000 43 | #define WL_CLOSURE_MAX_ARGS 20 44 | 45 | struct wl_object { 46 | const struct wl_interface *interface; 47 | const void *implementation; 48 | uint32_t id; 49 | }; 50 | 51 | extern struct wl_object global_zombie_object; 52 | #define WL_ZOMBIE_OBJECT ((void*)&global_zombie_object) 53 | 54 | /* Flags for wl_map_insert_new and wl_map_insert_at. Flags can be queried with 55 | * wl_map_lookup_flags. The current implementation has room for 1 bit worth of 56 | * flags. If more flags are ever added, the implementation of wl_map will have 57 | * to change to allow for new flags */ 58 | enum wl_map_entry_flags { 59 | WL_MAP_ENTRY_LEGACY = (1 << 0) 60 | }; 61 | 62 | struct wl_map { 63 | struct wl_array client_entries; 64 | struct wl_array server_entries; 65 | uint32_t side; 66 | uint32_t free_list; 67 | }; 68 | 69 | typedef void (*wl_iterator_func_t)(void *element, void *data); 70 | 71 | void wl_map_init(struct wl_map *map, uint32_t side); 72 | void wl_map_release(struct wl_map *map); 73 | uint32_t wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data); 74 | int wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data); 75 | int wl_map_reserve_new(struct wl_map *map, uint32_t i); 76 | void wl_map_remove(struct wl_map *map, uint32_t i); 77 | void *wl_map_lookup(struct wl_map *map, uint32_t i); 78 | uint32_t wl_map_lookup_flags(struct wl_map *map, uint32_t i); 79 | void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data); 80 | 81 | struct wl_connection; 82 | struct wl_closure; 83 | struct wl_proxy; 84 | 85 | int wl_interface_equal(const struct wl_interface *iface1, 86 | const struct wl_interface *iface2); 87 | 88 | struct wl_connection *wl_connection_create(int fd); 89 | void wl_connection_destroy(struct wl_connection *connection); 90 | void wl_connection_copy(struct wl_connection *connection, void *data, size_t size); 91 | void wl_connection_consume(struct wl_connection *connection, size_t size); 92 | int wl_connection_copy_fds(struct wl_connection *conn1, struct wl_connection *conn2); 93 | 94 | int wl_connection_flush(struct wl_connection *connection); 95 | int wl_connection_read(struct wl_connection *connection); 96 | 97 | int wl_connection_write(struct wl_connection *connection, const void *data, size_t count); 98 | int wl_connection_queue(struct wl_connection *connection, 99 | const void *data, size_t count); 100 | 101 | struct wl_closure { 102 | int count; 103 | const struct wl_message *message; 104 | uint32_t opcode; 105 | uint32_t sender_id; 106 | union wl_argument args[WL_CLOSURE_MAX_ARGS]; 107 | struct wl_list link; 108 | struct wl_proxy *proxy; 109 | struct wl_array extra[0]; 110 | }; 111 | 112 | struct argument_details { 113 | char type; 114 | int nullable; 115 | }; 116 | 117 | const char * 118 | get_next_argument(const char *signature, struct argument_details *details); 119 | 120 | int 121 | arg_count_for_signature(const char *signature); 122 | 123 | int 124 | wl_message_get_since(const struct wl_message *message); 125 | 126 | void 127 | wl_argument_from_va_list(const char *signature, union wl_argument *args, 128 | int count, va_list ap); 129 | 130 | struct wl_closure * 131 | wl_closure_marshal(struct wl_object *sender, 132 | uint32_t opcode, union wl_argument *args, 133 | const struct wl_message *message); 134 | struct wl_closure * 135 | wl_closure_vmarshal(struct wl_object *sender, 136 | uint32_t opcode, va_list ap, 137 | const struct wl_message *message); 138 | 139 | struct wl_closure * 140 | wl_connection_demarshal(struct wl_connection *connection, 141 | uint32_t size, 142 | struct wl_map *objects, 143 | const struct wl_message *message); 144 | 145 | int 146 | wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects); 147 | 148 | int 149 | wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); 150 | int 151 | wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection); 152 | void 153 | wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send); 154 | void 155 | wl_closure_destroy(struct wl_closure *closure); 156 | 157 | extern wl_log_func_t wl_log_handler; 158 | 159 | void wl_log(const char *fmt, ...); 160 | 161 | struct wl_display; 162 | 163 | struct wl_array * 164 | wl_display_get_additional_shm_formats(struct wl_display *display); 165 | 166 | #endif 167 | --------------------------------------------------------------------------------