Abspath printing with -A

Zubin Mithra zubin.mithra at gmail.com
Wed Sep 24 09:05:46 UTC 2014


Hello,

Please find below a diff that implements the abspath feature. Using the -A
flag now resolves the relative paths to absolute ones.

Usage examples can be seen here :-
https://gist.github.com/eQu1NoX/350ef0fa371aad26c7c6

diff --git a/defs.h b/defs.h
index cd9817b..d7434fe 100644
--- a/defs.h
+++ b/defs.h
@@ -563,6 +563,7 @@ extern bool count_wallclock;
 extern unsigned int qflag;
 extern bool not_failing_only;
 extern unsigned int show_fd_path;
+extern bool show_abs_path;
 extern bool hide_log_until_execve;
 /* are we filtering traces based on paths? */
 extern const char **paths_selected;
@@ -625,10 +626,10 @@ extern void get_regs(pid_t pid);
 # define clear_regs()  ((void)0)
 # define get_regs(pid) ((void)0)
 #endif
-extern int umoven(struct tcb *, long, int, char *);
+extern int umoven(struct tcb *, long, unsigned int, char *);
 #define umove(pid, addr, objp) \
  umoven((pid), (addr), sizeof(*(objp)), (char *) (objp))
-extern int umovestr(struct tcb *, long, int, char *);
+extern int umovestr(struct tcb *, long, unsigned int, char *);
 extern int upeek(int pid, long, long *);
 #if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
 extern long getrval2(struct tcb *);
@@ -679,6 +680,7 @@ extern void printstr(struct tcb *, long, long);
 extern void printnum(struct tcb *, long, const char *);
 extern void printnum_int(struct tcb *, long, const char *);
 extern void printpath(struct tcb *, long);
+extern void printpathat(struct tcb *, int, long);
 extern void printpathn(struct tcb *, long, unsigned int);
 #define TIMESPEC_TEXT_BUFSIZE (sizeof(long)*3 * 2 + sizeof("{%u, %u}"))
 #define TIMEVAL_TEXT_BUFSIZE  TIMESPEC_TEXT_BUFSIZE
diff --git a/file.c b/file.c
index c2bf6d3..6bff088 100644
--- a/file.c
+++ b/file.c
@@ -283,7 +283,10 @@ static int
 decode_open(struct tcb *tcp, int offset)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 1)
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
+ else
+ printpath(tcp, tcp->u_arg[offset]);
  tprints(", ");
  /* flags */
  tprint_open_modes(tcp->u_arg[offset + 1]);
@@ -346,7 +349,10 @@ static int
 decode_access(struct tcb *tcp, int offset)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprints(", ");
  printflags(access_flags, tcp->u_arg[offset + 1], "?_OK");
  }
@@ -1184,7 +1190,7 @@ sys_newfstatat(struct tcb *tcp)
 {
  if (entering(tcp)) {
  print_dirfd(tcp, tcp->u_arg[0]);
- printpath(tcp, tcp->u_arg[1]);
+ printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
  tprints(", ");
  } else {
 #ifdef POWERPC64
@@ -1424,7 +1430,10 @@ static int
 decode_mkdir(struct tcb *tcp, int offset)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprintf(", %#lo", tcp->u_arg[offset + 1]);
  }
  return 0;
@@ -1460,10 +1469,10 @@ sys_linkat(struct tcb *tcp)
 {
  if (entering(tcp)) {
  print_dirfd(tcp, tcp->u_arg[0]);
- printpath(tcp, tcp->u_arg[1]);
+ printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
  tprints(", ");
  print_dirfd(tcp, tcp->u_arg[2]);
- printpath(tcp, tcp->u_arg[3]);
+ printpathat(tcp, tcp->u_arg[2], tcp->u_arg[3]);
  tprints(", ");
  printflags(at_flags, tcp->u_arg[4], "AT_???");
  }
@@ -1475,7 +1484,7 @@ sys_unlinkat(struct tcb *tcp)
 {
  if (entering(tcp)) {
  print_dirfd(tcp, tcp->u_arg[0]);
- printpath(tcp, tcp->u_arg[1]);
+ printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
  tprints(", ");
  printflags(at_flags, tcp->u_arg[2], "AT_???");
  }
@@ -1489,7 +1498,7 @@ sys_symlinkat(struct tcb *tcp)
  printpath(tcp, tcp->u_arg[0]);
  tprints(", ");
  print_dirfd(tcp, tcp->u_arg[1]);
- printpath(tcp, tcp->u_arg[2]);
+ printpathat(tcp, tcp->u_arg[1], tcp->u_arg[2]);
  }
  return 0;
 }
@@ -1498,7 +1507,10 @@ static int
 decode_readlink(struct tcb *tcp, int offset)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprints(", ");
  } else {
  if (syserror(tcp))
@@ -1535,10 +1547,10 @@ static void
 decode_renameat(struct tcb *tcp)
 {
  print_dirfd(tcp, tcp->u_arg[0]);
- printpath(tcp, tcp->u_arg[1]);
+ printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
  tprints(", ");
  print_dirfd(tcp, tcp->u_arg[2]);
- printpath(tcp, tcp->u_arg[3]);
+ printpathat(tcp, tcp->u_arg[2], tcp->u_arg[3]);
 }

 int
@@ -1579,7 +1591,7 @@ sys_fchownat(struct tcb *tcp)
 {
  if (entering(tcp)) {
  print_dirfd(tcp, tcp->u_arg[0]);
- printpath(tcp, tcp->u_arg[1]);
+ printpathat(tcp, tcp->u_arg[0], tcp->u_arg[1]);
  printuid(", ", tcp->u_arg[2]);
  printuid(", ", tcp->u_arg[3]);
  tprints(", ");
@@ -1603,7 +1615,10 @@ static int
 decode_chmod(struct tcb *tcp, int offset)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprintf(", %#lo", tcp->u_arg[offset + 1]);
  }
  return 0;
@@ -1650,7 +1665,10 @@ static int
 decode_utimes(struct tcb *tcp, int offset, int special)
 {
  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprints(", ");
  if (tcp->u_arg[offset + 1] == 0)
  tprints("NULL");
@@ -1736,7 +1754,10 @@ decode_mknod(struct tcb *tcp, int offset)
  int mode = tcp->u_arg[offset + 1];

  if (entering(tcp)) {
- printpath(tcp, tcp->u_arg[offset]);
+ if (offset == 0)
+ printpath(tcp, tcp->u_arg[offset]);
+ else
+ printpathat(tcp, tcp->u_arg[offset-1], tcp->u_arg[offset]);
  tprintf(", %s", sprintmode(mode));
  switch (mode & S_IFMT) {
  case S_IFCHR:
diff --git a/strace.1 b/strace.1
index 1e69217..773ead5 100644
--- a/strace.1
+++ b/strace.1
@@ -205,6 +205,9 @@ Here the second argument represents the full set of all
signals.
 .SH OPTIONS
 .TP 12
 .TP
+.B \-A
+Print absolute paths instead of relative paths everywhere.
+.TP
 .B \-c
 Count time, calls, and errors for each system call and report a summary on
 program exit.  On Linux, this attempts to show system time (CPU time spent
diff --git a/strace.c b/strace.c
index cb96758..e70849e 100644
--- a/strace.c
+++ b/strace.c
@@ -1,4 +1,4 @@
-/*
+      /*
  * Copyright (c) 1991, 1992 Paul Kranenburg <pk at cs.few.eur.nl>
  * Copyright (c) 1993 Branko Lankester <branko at hacktic.nl>
  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs at world.std.com>
@@ -130,6 +130,7 @@ bool not_failing_only = 0;

 /* Show path associated with fd arguments */
 unsigned int show_fd_path = 0;
+bool show_abs_path = 0;

 static bool detach_on_execve = 0;
 /* Are we "strace PROG" and need to skip detach on first execve? */
@@ -203,6 +204,7 @@ usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e
expr]...\n\
               -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
    or: strace -c[df] [-I n] [-e expr]... [-O overhead] [-S sortby]\n\
               -p pid... / [-D] [-E var=val]... [-u username] PROG [ARGS]\n\
+-A -- print absolute paths instead of relative paths everywhere\n\
 -c -- count time, calls, and errors for each syscall and report summary\n\
 -C -- like -c but also print regular output\n\
 -w -- summarise syscall latency (default is system time)\n\
@@ -1678,9 +1680,13 @@ init(int argc, char *argv[])
 #ifdef USE_LIBUNWIND
  "k"
 #endif
+ "A"
  "D"
  "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
  switch (c) {
+ case 'A':
+ show_abs_path = 1;
+ break;
  case 'b':
  if (strcmp(optarg, "execve") != 0)
  error_msg_and_die("Syscall '%s' for -b isn't supported",
diff --git a/util.c b/util.c
index 4e62a8a..c3224a9 100644
--- a/util.c
+++ b/util.c
@@ -422,6 +422,11 @@ void
 printfd(struct tcb *tcp, int fd)
 {
  char path[PATH_MAX + 1];
+
+ if (show_fd_path &&
+    getfdpath(tcp, fd, path, sizeof(path)) >= 0)
+ tprintf("%d<%s>", fd, path);
+ else
  if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
  static const char socket_prefix[] = "socket:[";
  const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
@@ -592,11 +597,64 @@ string_quote(const char *instr, char *outstr, long
len, int size)
 }

 /*
- * Print path string specified by address `addr' and length `n'.
- * If path length exceeds `n', append `...' to the output.
+ * Encode a path(either cwd or fd path) in a manner fit for printing
+ * before a relative path.
  */
+static void
+encode_path(char *path, int n)
+{
+ char *outstr;
+
+ path[n++] = '/';
+ path[n++] = '\0';
+
+ /* path has n-1 characters followed by a null */
+ outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
+ string_quote(path, outstr, -1, n);
+ outstr[strlen(outstr)-1] = '\0'; /* Don't print the closing quotes */
+ tprints(outstr);
+}
+
+/*
+ * Print the current working directory of the tracee process
+ */
+static bool
+print_tracee_cwd(struct tcb *tcp)
+{
+ int link_size = sizeof("/proc//cwd") + sizeof(int) * 3;
+ char linkpath[link_size];
+ char cwd[MAXPATHLEN + 2];
+ ssize_t n;
+
+ snprintf(linkpath, link_size, "/proc/%u/cwd", tcp->pid);
+ n = readlink(linkpath, cwd, MAXPATHLEN);
+
+ if (n > 0) {
+ encode_path(cwd, n);
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Print absolute path string corresponding to an `fd`.
+ */
+static bool
+print_tracee_fdpath(struct tcb *tcp, int fd)
+{
+ char path[PATH_MAX + 1];
+ int n;
+
+ n = getfdpath(tcp, fd, path, sizeof(path));
+ if (n > 0) {
+ encode_path(path, n);
+ return true;
+ }
+ return false;
+}
+
 void
-printpathn(struct tcb *tcp, long addr, unsigned int n)
+printpath_common(struct tcb *tcp, int fd, long addr, unsigned int n)
 {
  char path[MAXPATHLEN + 1];
  int nul_seen;
@@ -616,11 +674,30 @@ printpathn(struct tcb *tcp, long addr, unsigned int n)
  tprintf("%#lx", addr);
  else {
  char *outstr;
+ bool prefix_printed = false;

  path[n] = '\0';
+
+ /* If the path prefix of a relative path does not depend
+ * on an fd */
+ if (fd == -1 && show_abs_path && *path && *path != '/')
+ prefix_printed = print_tracee_cwd(tcp);
+
+ /* If path prefix of a relative path depends on the fd */
+ else if (show_abs_path && *path && *path != '/') {
+ if (fd == AT_FDCWD)
+ prefix_printed = print_tracee_cwd(tcp);
+ else
+ prefix_printed = print_tracee_fdpath(tcp, fd);
+ }
+
  n++;
  outstr = alloca(4 * n); /* 4*(n-1) + 3 for quotes and NUL */
  string_quote(path, outstr, -1, n);
+
+ /* Dont print opening quotes if cwd/decoded dirfd is printed */
+ if (prefix_printed)
+ outstr += 1;
  tprints(outstr);
  if (!nul_seen)
  tprints("...");
@@ -628,6 +705,18 @@ printpathn(struct tcb *tcp, long addr, unsigned int n)
 }

 void
+printpathat(struct tcb *tcp, int fd, long addr)
+{
+ printpath_common(tcp, fd, addr, MAXPATHLEN);
+}
+
+void
+printpathn(struct tcb *tcp, long addr, unsigned int n)
+{
+ printpath_common(tcp, -1, addr, n);
+}
+
+void
 printpath(struct tcb *tcp, long addr)
 {
  /* Size must correspond to char path[] size in printpathn */
@@ -864,7 +953,7 @@ static bool process_vm_readv_not_supported = 1;
  * at address `addr' to our space at `laddr'
  */
 int
-umoven(struct tcb *tcp, long addr, int len, char *laddr)
+umoven(struct tcb *tcp, long addr, unsigned int len, char *laddr)
 {
  int pid = tcp->pid;
  int n, m, nread;
@@ -886,7 +975,7 @@ umoven(struct tcb *tcp, long addr, int len, char *laddr)
  remote[0].iov_base = (void*)addr;
  local[0].iov_len = remote[0].iov_len = len;
  r = process_vm_readv(pid, local, 1, remote, 1, 0);
- if (r == len)
+ if ((unsigned int)r == len)
  return 0;
  if (r >= 0) {
  error_msg("umoven: short read (%d < %d) @0x%lx",
@@ -985,7 +1074,7 @@ umoven(struct tcb *tcp, long addr, int len, char
*laddr)
  * we never write past laddr[len-1]).
  */
 int
-umovestr(struct tcb *tcp, long addr, int len, char *laddr)
+umovestr(struct tcb *tcp, long addr, unsigned int len, char *laddr)
 {
 #if SIZEOF_LONG == 4
  const unsigned long x01010101 = 0x01010101ul;


Thanks!
Zubin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20140924/213df28c/attachment.html>


More information about the Strace-devel mailing list