Skip to content

Commit

Permalink
libdrgn: examples: add --pre-exec and --post-exec options to load_deb…
Browse files Browse the repository at this point in the history
…ug_info

These can be used for benchmarking.

Signed-off-by: Omar Sandoval <[email protected]>
  • Loading branch information
osandov committed Aug 3, 2023
1 parent c8406e1 commit a21355e
Showing 1 changed file with 65 additions and 8 deletions.
73 changes: 65 additions & 8 deletions libdrgn/examples/load_debug_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,50 @@

#include <errno.h>
#include <getopt.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include "drgn.h"
#include "util.h"

extern char **environ;

static struct drgn_error *run_command(const char *which, const char *command)
{
if (!command)
return NULL;

char pid_arg[max_decimal_length(long)];
sprintf(pid_arg, "%ld", (long)getpid());
const char * const argv[] = {"sh", "-c", command, "sh", pid_arg, NULL};

pid_t pid;
int errnum =
posix_spawnp(&pid, "sh", NULL, NULL, (char **)argv, environ);
if (errnum)
return drgn_error_create_os("posix_spawnp", errnum, "sh");

int wstatus;
if (waitpid(pid, &wstatus, 0) < 0)
return drgn_error_create_os("waitpid", errno, NULL);

if (!WIFEXITED(wstatus)) {
return drgn_error_format(DRGN_ERROR_OTHER,
"%s-exec command exited abnormally: %d",
which, wstatus);
}
if (WEXITSTATUS(wstatus) != 0) {
return drgn_error_format(DRGN_ERROR_OTHER,
"%s-exec command exited with status %d",
which, WEXITSTATUS(wstatus));
}
return NULL;
}

static inline struct timespec timespec_sub(struct timespec a, struct timespec b)
{
Expand All @@ -29,7 +66,7 @@ static inline struct timespec timespec_sub(struct timespec a, struct timespec b)
noreturn static void usage(bool error)
{
fprintf(error ? stderr : stdout,
"usage: load_debug_info [-k|-c CORE|-p PID] [PATH...]\n"
"usage: load_debug_info [OPTION...] [-k|-c CORE|-p PID] [PATH...]\n"
"\n"
"Example libdrgn program that loads default debug information\n"
"\n"
Expand All @@ -38,6 +75,10 @@ noreturn static void usage(bool error)
" -c PATH, --core PATH debug the given core dump\n"
" -p PID, --pid PID debug the running process with the given PID\n"
" -T, --time print how long loading debug info took in seconds\n"
" --pre-exec CMD before loading debug info, execute shell command with\n"
" PID of this process as argument\n"
" --post-exec CMD after loading debug info, execute shell command with\n"
" PID of this process as argument\n"
" -h, --help display this help message and exit\n");
exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
}
Expand All @@ -49,13 +90,17 @@ int main(int argc, char **argv)
{"core", required_argument, NULL, 'c'},
{"pid", required_argument, NULL, 'p'},
{"time", no_argument, NULL, 'T'},
{"pre-exec", required_argument, NULL, 'x'},
{"post-exec", required_argument, NULL, 'X'},
{"help", no_argument, NULL, 'h'},
{},
};
bool kernel = false;
const char *core = NULL;
const char *pid = NULL;
bool print_time = false;
const char *pre_exec = NULL;
const char *post_exec = NULL;
for (;;) {
int c = getopt_long(argc, argv, "kc:p:Th", long_options, NULL);
if (c == -1)
Expand All @@ -73,6 +118,12 @@ int main(int argc, char **argv)
case 'T':
print_time = true;
break;
case 'x':
pre_exec = optarg;
break;
case 'X':
post_exec = optarg;
break;
case 'h':
usage(false);
default:
Expand All @@ -98,6 +149,10 @@ int main(int argc, char **argv)
if (err)
goto out;

err = run_command("pre", pre_exec);
if (err)
goto out;

struct timespec start, end;
if (print_time && clock_gettime(CLOCK_MONOTONIC, &start))
abort();
Expand All @@ -110,18 +165,20 @@ int main(int argc, char **argv)
struct timespec diff = timespec_sub(end, start);
printf("%lld.%09ld\n", (long long)diff.tv_sec, diff.tv_nsec);
}
if (err && err->code == DRGN_ERROR_MISSING_DEBUG_INFO) {
drgn_error_fwrite(stderr, err);
drgn_error_destroy(err);
}

err = run_command("post", post_exec);
if (err)
goto out;

out:;
int status;
int status = err ? EXIT_FAILURE : EXIT_SUCCESS;
if (err) {
if (err->code == DRGN_ERROR_MISSING_DEBUG_INFO)
status = EXIT_SUCCESS;
else
status = EXIT_FAILURE;
drgn_error_fwrite(stderr, err);
drgn_error_destroy(err);
} else {
status = EXIT_SUCCESS;
}
drgn_program_destroy(prog);
return status;
Expand Down

0 comments on commit a21355e

Please sign in to comment.