From 4420284125c7be582ff81799069d29e8a2429735 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 22 Feb 2020 11:01:37 +0100 Subject: [PATCH] profile: Allow launching a command with profiling enabled You can now profile a program from start to finish by doing: $ profile -c "cat /etc/passwd" The old "enable or disable profiling for a PID" mode is accessible via: $ profile -p -e # Enable profiling for PID $ profile -p -d # Disable profiling for PID The generated profile is available via /proc/profile like before. This is far from perfect, but it at least makes profiling a lot nicer to use since you don't have to hurry and attach to something when you want to profile the whole thing anyway. --- Userland/profile.cpp | 59 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/Userland/profile.cpp b/Userland/profile.cpp index 15031555835..cff8a5b7b8a 100644 --- a/Userland/profile.cpp +++ b/Userland/profile.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -31,25 +32,63 @@ int main(int argc, char** argv) { - if (argc != 3) { - printf("usage: profile \n"); + Core::ArgsParser args_parser; + + const char* pid_argument = nullptr; + const char* cmd_argument = nullptr; + bool enable = false; + bool disable = false; + + args_parser.add_option(pid_argument, "Target PID", nullptr, 'p', "PID"); + args_parser.add_option(enable, "Enable", nullptr, 'e'); + args_parser.add_option(disable, "Disable", nullptr, 'd'); + args_parser.add_option(cmd_argument, "Command", nullptr, 'c', "command"); + + args_parser.parse(argc, argv); + + if (!pid_argument && !cmd_argument) { + args_parser.print_usage(stdout, argv[0]); return 0; } - pid_t pid = atoi(argv[1]); - bool enabled = !strcmp(argv[2], "on"); - - if (enabled) { - if (profiling_enable(pid) < 0) { - perror("profiling_enable"); + if (pid_argument) { + if (!(enable ^ disable)) { + fprintf(stderr, "-p requires -e xor -d.\n"); return 1; } + + pid_t pid = atoi(pid_argument); + + if (enable) { + if (profiling_enable(pid) < 0) { + perror("profiling_enable"); + return 1; + } + return 0; + } + + if (profiling_disable(pid) < 0) { + perror("profiling_disable"); + return 1; + } + return 0; } - if (profiling_disable(pid) < 0) { - perror("profiling_disable"); + auto cmd_parts = String(cmd_argument).split(' '); + Vector cmd_argv; + + for (auto& part : cmd_parts) + cmd_argv.append(part.characters()); + + cmd_argv.append(nullptr); + + dbg() << "Enabling profiling for PID " << getpid(); + profiling_enable(getpid()); + if (execvp(cmd_argv[0], const_cast(cmd_argv.data())) < 0) { + perror("execv"); return 1; } + return 0; }