cros_sdk: add --strace for ease of debugging

Trying to run cros_sdk through strace is difficult -- it requires being
root, otherwise the sudo call fails in confusing ways.  Add an --strace
option for devs to easily run things themselves.  This aids in debugging
some of the lower level calls we make in chromite.

BUG=None
TEST=`cros_sdk --strace -- true` works

Change-Id: I879d35d49f45594b9da2cef538ff60ae623a6d47
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/3779418
Reviewed-by: Ram Chandrasekar <rchandrasekar@google.com>
Auto-Submit: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
Commit-Queue: Ram Chandrasekar <rchandrasekar@google.com>
diff --git a/scripts/cros_sdk.py b/scripts/cros_sdk.py
index 7a4c9fa..16e1081 100644
--- a/scripts/cros_sdk.py
+++ b/scripts/cros_sdk.py
@@ -21,8 +21,10 @@
 import random
 import re
 import resource
+import shlex
 import subprocess
 import sys
+from typing import List
 import urllib.parse
 
 from chromite.cbuildbot import cbuildbot_alerts
@@ -666,16 +668,24 @@
   process_util.ExitAsStatus(os.waitpid(pid, 0)[1])
 
 
-def _ReExecuteIfNeeded(argv):
+def _BuildReExecCommand(argv, opts) -> List[str]:
+  """Generate new command for self-reexec."""
+  # Make sure to preserve the active Python executable in case the version
+  # we're running as is not the default one found via the (new) $PATH.
+  cmd = _SudoCommand() + ['--']
+  if opts.strace:
+    cmd += ['strace'] + shlex.split(opts.strace_arguments) + ['--']
+  return cmd + [sys.executable] + argv
+
+
+def _ReExecuteIfNeeded(argv, opts):
   """Re-execute cros_sdk as root.
 
   Also unshare the mount namespace so as to ensure that processes outside
   the chroot can't mess with our mounts.
   """
   if osutils.IsNonRootUser():
-    # Make sure to preserve the active Python executable in case the version
-    # we're running as is not the default one found via the (new) $PATH.
-    cmd = _SudoCommand() + ['--'] + [sys.executable] + argv
+    cmd = _BuildReExecCommand(argv, opts)
     logging.debug('Reexecing self via sudo:\n%s', cros_build_lib.CmdToStr(cmd))
     os.execvp(cmd[0], cmd)
 
@@ -871,6 +881,17 @@
         action='store_false',
         help=f'Do not create a new {ns} namespace.')
 
+  # Debug options.
+  group = parser.debug_group
+  group.add_argument(
+      '--strace',
+      action='store_true',
+      help='Run cros_sdk through strace after re-exec via sudo')
+  group.add_argument(
+      '--strace-arguments',
+      default='',
+      help='Extra strace options (shell quoting permitted)')
+
   # Internal options.
   group = parser.add_argument_group(
       'Internal Chromium OS Build Team Options',
@@ -939,7 +960,7 @@
     parser.error('Cannot --snapshot_delete the same snapshot you are '
                  'restoring with --snapshot_restore.')
 
-  _ReExecuteIfNeeded([sys.argv[0]] + argv)
+  _ReExecuteIfNeeded([sys.argv[0]] + argv, options)
 
   lock_path = os.path.dirname(options.chroot)
   lock_path = os.path.join(