@@ -50,6 +50,7 @@ static int (*libc_close)(int fd) = close_init_helper;
static int (*libc_ioctl)(int fd, unsigned long request, ...) = ioctl_init_helper;
static int drm_fd = -1;
+static char *command;
static char *filename;
static FILE *file;
static int gen = 0;
@@ -113,6 +114,76 @@ fail_if(int cond, const char *format, ...)
raise(SIGTRAP);
}
+static FILE *
+launch_command(void)
+{
+ int i = 0, fds[2];
+ char **args = calloc(strlen(command), sizeof(char *));
+ char *iter = command;
+
+ args[i++] = iter = command;
+
+ while ((iter = strstr(iter, ",")) != NULL) {
+ *iter = '\0';
+ iter += 1;
+ args[i++] = iter;
+ }
+
+ if (pipe(fds) == -1)
+ return NULL;
+
+ switch (fork()) {
+ case 0:
+ dup2(fds[0], 0);
+ fail_if(execv(args[0], args) == -1,
+ "intel_aubdump: fail to launch child command\n");
+ return NULL;
+
+ default:
+ free(args);
+ return fdopen(fds[1], "w");
+
+ case -1:
+ return NULL;
+ }
+}
+
+static void
+maybe_init_output(void)
+{
+ const char *args;
+ static bool initialized = false;
+ int nb_args;
+
+ if (initialized)
+ return;
+
+ args = getenv("INTEL_AUBDUMP_ARGS");
+
+ nb_args = sscanf(args, "verbose=%d;file=%m[^;];device=%i;command=%m[^;];",
+ &verbose, &filename, &device, &command);
+ fail_if(nb_args != 4, "intel_aubdump: invalid number of arguments");
+ fail_if(filename == NULL || command == NULL,
+ "intel_aubdump: out of memory\n");
+ if (device)
+ device_override = true;
+
+ bos = malloc(MAX_BO_COUNT * sizeof(bos[0]));
+ fail_if(bos == NULL, "intel_aubdump: out of memory\n");
+
+ if (strlen(command) != 0) {
+ file = launch_command();
+ fail_if(file == NULL,
+ "intel_aubdump: failed to launch command '%s'\n", command);
+ } else {
+ file = fopen(filename, "w+");
+ fail_if(file == NULL,
+ "intel_aubdump: failed to open file '%s'\n", filename);
+ }
+
+ initialized = true;
+}
+
static struct bo *
get_bo(uint32_t handle)
{
@@ -140,13 +211,18 @@ align_u64(uint64_t v, uint64_t a)
static void
dword_out(uint32_t data)
{
- fwrite(&data, 1, 4, file);
+ fail_if(fwrite(&data, 1, 4, file) == 0,
+ "Writing to output failed\n");
}
static void
data_out(const void *data, size_t size)
{
- fwrite(data, 1, size, file);
+ if (size == 0)
+ return;
+
+ fail_if(fwrite(data, 1, size, file) == 0,
+ "Writing to output failed\n");
}
static void
@@ -447,6 +523,8 @@ ioctl(int fd, unsigned long request, ...)
}
if (fd == drm_fd) {
+ maybe_init_output();
+
switch (request) {
case DRM_IOCTL_I915_GETPARAM: {
struct drm_i915_getparam *getparam = argp;
@@ -550,26 +628,8 @@ ioctl(int fd, unsigned long request, ...)
static void
init(void)
{
- const char *args = getenv("INTEL_AUBDUMP_ARGS");
-
libc_close = dlsym(RTLD_NEXT, "close");
libc_ioctl = dlsym(RTLD_NEXT, "ioctl");
- fail_if(libc_close == NULL || libc_ioctl == NULL,
- "intel_aubdump: failed to get libc ioctl or close\n");
-
- if (sscanf(args, "verbose=%d;file=%m[^;];device=%i",
- &verbose, &filename, &device) != 3)
- filename = strdup("intel.aub");
- fail_if(filename == NULL, "intel_aubdump: out of memory\n");
-
- if (device)
- device_override = true;
-
- bos = malloc(MAX_BO_COUNT * sizeof(bos[0]));
- fail_if(bos == NULL, "intel_aubdump: out of memory\n");
-
- file = fopen(filename, "w+");
- fail_if(file == NULL, "intel_aubdump: failed to open file '%s'\n", filename);
}
static int
@@ -596,6 +656,7 @@ ioctl_init_helper(int fd, unsigned long request, ...)
static void __attribute__ ((destructor))
fini(void)
{
+ free(command);
free(filename);
if (file)
fclose(file);
@@ -10,6 +10,9 @@ contents and execution of the GEM application.
-o, --output=FILE Name of AUB file. Defaults to COMMAND.aub
+ -c, --command=CMD Execute CMD and write the AUB file's content to its
+ standard input
+
--device=ID Override PCI ID of the reported device
-v Enable verbose output
@@ -23,6 +26,19 @@ EOF
verbose=0
device=0
+file="intel.aub"
+command=""
+
+build_command () {
+ command=""
+ for i in $1; do
+ if [ -z $command ]; then
+ command=$i
+ else
+ command="$command,$i"
+ fi;
+ done
+}
while true; do
case "$1" in
@@ -38,6 +54,14 @@ while true; do
file=${1##--output=}
shift
;;
+ -c)
+ build_command "$2"
+ shift 2
+ ;;
+ --command=*)
+ build_command "${1##--command=}"
+ shift
+ ;;
--device=*)
device=${1##--device=}
shift
@@ -69,5 +93,5 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
LD_PRELOAD=${libdir}/intel_aubdump.so${LD_PPRELOAD:+:${LD_PRELOAD}} \
- INTEL_AUBDUMP_ARGS="verbose=$verbose;file=$file;device=$device" \
+ INTEL_AUBDUMP_ARGS="verbose=$verbose;file=$file;device=$device;command=$command;" \
exec -- "$@"
This comes handy if you want to look at your application output without having to save it into a file. For example, use this with aubinator from Mesa : $ intel_aubdump -c '/path/to/aubinator --gen=hsw' my_gl_app Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Cc: Kristian Høgsberg <krh@bitplanet.net> --- tools/aubdump.c | 101 +++++++++++++++++++++++++++++++++++++++---------- tools/intel_aubdump.in | 26 ++++++++++++- 2 files changed, 106 insertions(+), 21 deletions(-)