]> git.cworth.org Git - apitrace/commitdiff
Add a new "apitrace trace" command to the command-line interface.
authorCarl Worth <cworth@cworth.org>
Wed, 2 Nov 2011 00:54:19 +0000 (17:54 -0700)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 3 Nov 2011 12:19:05 +0000 (12:19 +0000)
There is no code to support Windows yet, but there is specific code
for both Linux and Mac OS X. The documentation is also updated to
reflect the new command.

Signed-off-by: José Fonseca <jose.r.fonseca@gmail.com>
README.markdown
TODO.markdown
cli/CMakeLists.txt
cli/cli.hpp
cli/cli_main.cpp
cli/cli_trace.cpp [new file with mode: 0644]

index d35f2c46d9c96dfa702d3bb29339712c4a9dd0f9..2764c5939e947cca8422aa47f89d8d98bb4801a0 100644 (file)
@@ -16,12 +16,12 @@ Basic usage
 ===========
 
 
-Linux
------
+Linux and Mac OS X
+------------------
 
 Run the application you want to trace as
 
-     LD_PRELOAD=/path/to/glxtrace.so /path/to/application
+    apitrace trace application [args...]
 
 and it will generate a trace named `application.trace` in the current
 directory.  You can specify the written trace filename by setting the
@@ -42,15 +42,18 @@ Start the GUI as
 
     /path/to/qapitrace application.trace
 
+Special notes on "apitrace trace" for Linux
+-------------------------------------------
+The "apitrace trace" command uses the `LD_PRELOAD` mechanism which
+should work with most applications.  There are some applications,
+e.g., Unigine Heaven, which global function pointers with the same
+name as GL entrypoints, living in a shared object that wasn't linked
+with `-Bsymbolic` flag, so relocations to those globals function
+pointers get overwritten with the address to our wrapper library, and
+the application will segfault when trying to write to them.
 
-The `LD_PRELOAD` mechanism should work with most applications.  There are some
-applications, e.g., Unigine Heaven, which global function pointers with the
-same name as GL entrypoints, living in a shared object that wasn't linked with
-`-Bsymbolic` flag, so relocations to those globals function pointers get
-overwritten with the address to our wrapper library, and the application will
-segfault when trying to write to them.  For these applications it is possible
-to trace by using `glxtrace.so` as an ordinary `libGL.so` and injecting into
-`LD_LIBRARY_PATH`:
+For these applications it is possible to trace by using `glxtrace.so`
+as an ordinary `libGL.so` and injecting into `LD_LIBRARY_PATH`:
 
     ln -s glxtrace.so libGL.so
     ln -s glxtrace.so libGL.so.1
@@ -63,19 +66,18 @@ See the `ld.so` man page for more information about `LD_PRELOAD` and
 `LD_LIBRARY_PATH` environment flags.
 
 
+Special notes on "apitrace trace" for Mac OS X
+----------------------------------------------
+On Mac OS X the "apitrace trace" command sets the following
+environment variable before executing the program:
 
-Mac OS X
---------
-
-Usage on Mac OS X is similar to Linux above, except for the tracing procedure,
-which is instead:
-
-    DYLD_LIBRARY_PATH=/path/to/apitrace/wrappers /path/to/application
+    DYLD_LIBRARY_PATH=/path/to/apitrace/wrappers
 
 Note that although Mac OS X has an `LD_PRELOAD` equivalent,
-`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with
-`DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications.  See the `dyld` man
-page for more details about these environment flags.
+`DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works
+with `DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications.
+See the `dyld` man page for more details about these environment
+flags.
 
 
 Windows
index 679c5ade6177bcffe586efb4d2dccf95492fe6ed..e523b01b94b491211c4e80a13f5b7edc801191d8 100644 (file)
@@ -59,7 +59,6 @@ GUI
 CLI
 ---
 
-* Add trace:      Generate a new trace by executing the given program
 * Add retrace     Replay all the calls in a trace
 * Add trim        Trim a trace by including only the specified calls/frames
 * Add dump-state  Output the OpenGL state in JSON format
index c41cdb4bdec51e7633380c21aa5d5be4be0bde66..fc52527dfc91996a5a48a607edba38907a336a1a 100644 (file)
@@ -1,6 +1,7 @@
 add_executable (apitrace
     cli_main.cpp
     cli_dump.cpp
+    cli_trace.cpp
 )
 
 install (TARGETS apitrace RUNTIME DESTINATION bin)
index 5236d8bbd8bd58bce0cfca7895f51318ac3f072d..9ab160026e04d99b6f6d3df5807b7200d36dc942 100644 (file)
@@ -41,5 +41,6 @@ struct Command {
 };
 
 extern const Command dump_command;
+extern const Command trace_command;
 
 #endif /* _APITRACE_CLI_HPP_ */
index 981f39e416f2a514dc6de1123f3c0451835acf22..a3abf54a0d6daab8aee1a5e09c71d6af6bdfeb48 100644 (file)
@@ -67,6 +67,7 @@ const Command help_command = {
 
 static const Command * commands[] = {
     &dump_command,
+    &trace_command,
     &help_command
 };
 
diff --git a/cli/cli_trace.cpp b/cli/cli_trace.cpp
new file mode 100644 (file)
index 0000000..19739fd
--- /dev/null
@@ -0,0 +1,205 @@
+/*********************************************************************
+ *
+ * Copyright 2011 Intel Corporation
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *********************************************************************/
+
+#include <iostream>
+
+#include "cli.hpp"
+
+#include "os_path.hpp"
+
+
+static int verbose = 1;
+
+static const char *synopsis = "Generate a new trace by executing the given program.";
+
+static void
+usage(void)
+{
+    std::cout << "usage: apitrace trace <program> [<args> ...]\n"
+        << synopsis << "\n"
+        "\n"
+        "    The given program will be executed with the given arguments.\n"
+        "    During execution, all OpenGL calls will be captured to a trace\n"
+        "    file named <program>.trace. That trace file can then be used\n"
+        "    with other apitrace utilities for replay or analysis.\n";
+}
+
+/* We only support "apitrace trace" on POSIX-like systems (not WIN32) */
+#ifndef _WIN32
+
+#include <sys/stat.h>
+
+#ifdef __APPLE__
+#define CLI_TRACE_VARIABLE "DYLD_LIBRARY_PATH"
+#define CLI_TRACE_WRAPPER  "OpenGL"
+#else
+#define CLI_TRACE_VARIABLE "LD_PRELOAD"
+#define CLI_TRACE_WRAPPER  "glxtrace.so"
+#endif
+
+static int
+file_exists(const char *path)
+{
+    struct stat st;
+    int err;
+
+    err = stat(path, &st);
+    if (err)
+        return 0;
+
+    if (! S_ISREG(st.st_mode))
+        return 0;
+
+    return 1;
+}
+
+static os::Path
+find_wrapper(const char *filename)
+{
+    os::Path complete;
+
+    /* First look in the same directory from which this process is
+     * running, (to support developers running a compiled program that
+     * has not been installed. */
+#if 1
+    os::Path process_dir = os::getProcessName();
+
+    process_dir.trimFilename();
+
+    complete = process_dir;
+    complete.join("wrappers");
+    complete.join(filename);
+#else
+    complete = APITRACE_BINARY_DIR "/wrappers";
+    complete.join(filename);
+#endif
+
+    if (file_exists(complete))
+        return complete;
+
+    /* Second, look in the directory for installed wrappers. */
+    complete = APITRACE_WRAPPER_INSTALL_DIR;
+    complete.join(filename);
+
+    if (file_exists(complete))
+        return complete;
+
+    std::cerr << "error: cannot find " << filename << " (looked in " <<
+        APITRACE_WRAPPER_INSTALL_DIR << ")\n";
+    exit(1);
+
+    return "";
+}
+
+static int
+do_trace_posix(int argc, char *argv[])
+{
+    os::Path binary = find_wrapper(CLI_TRACE_WRAPPER);
+
+    /* On Mac OS X, using DYLD_LIBRARY_PATH, we actually set the
+     * directory, not the file. */
+#ifdef __APPLE__
+    binary.trimFilename();
+#endif
+
+    if (verbose) {
+        std::cerr << CLI_TRACE_VARIABLE << "=" << binary.str() << "\n";
+    }
+
+    setenv(CLI_TRACE_VARIABLE, binary.str(), 1);
+
+    if (verbose) {
+        const char *sep = "";
+        for (char **arg = argv; *arg; ++arg) {
+            std::cerr << *arg << sep;
+            sep = " ";
+        }
+        std::cerr << "\n";
+    }
+
+    execvp(argv[0], argv);
+
+    std::cerr << "Error: Failed to execute " << argv[0] << "\n";
+
+    return 1;
+}
+
+#endif
+
+static int
+command(int argc, char *argv[])
+{
+
+#ifdef _WIN32
+
+    std::cerr <<
+        "The 'apitrace trace' command is not supported for this operating system.\n"
+        "Instead, you will need to copy opengl32.dll, d3d8.dll, or d3d9.dll from\n"
+        APITRACE_WRAPPER_INSTALL_DIR "\n"
+        "to the directory with the application to trace, then run the application.\n";
+    return 1;
+
+#else
+
+    int i;
+
+    for (i = 0; i < argc; ++i) {
+        const char *arg = argv[i];
+
+        if (arg[0] != '-') {
+            break;
+        }
+
+        if (!strcmp(arg, "--")) {
+            i++;
+            break;
+        } else if (!strcmp(arg, "--help")) {
+            usage();
+            return 0;
+        } else {
+            std::cerr << "error: unknown option " << arg << "\n";
+            usage();
+            return 1;
+        }
+    }
+
+    if (i == argc) {
+        std::cerr << "Error: Need a command name to execute (see 'apitrace trace --help')\n";
+        return 1;
+    }
+
+    return do_trace_posix(argc - i, argv + i);
+
+#endif
+}
+
+const Command trace_command = {
+    "trace",
+    synopsis,
+    usage,
+    command
+};