| #!/usr/bin/python |
| # Copyright 2012 Google Inc. All Rights Reserved. |
| """A script that symbolizes perf.data files.""" |
| import optparse |
| import os |
| import shutil |
| from subprocess import call |
| from subprocess import PIPE |
| from subprocess import Popen |
| from utils import misc |
| |
| |
| GSUTIL_CMD = "gsutil cp gs://chromeos-image-archive/%s-release/%s/debug.tgz %s" |
| TAR_CMD = "tar -zxvf %s -C %s" |
| PERF_BINARY = "/google/data/ro/projects/perf/perf" |
| VMLINUX_FLAG = " --vmlinux=/usr/lib/debug/boot/vmlinux" |
| PERF_CMD = PERF_BINARY +" report -i %s -n --symfs=%s" + VMLINUX_FLAG |
| |
| |
| def main(): |
| parser = optparse.OptionParser() |
| parser.add_option("--in", dest="in_dir") |
| parser.add_option("--out", dest="out_dir") |
| parser.add_option("--cache", dest="cache") |
| (opts, _) = parser.parse_args() |
| if not _ValidateOpts(opts): |
| return 1 |
| else: |
| for filename in os.listdir(opts.in_dir): |
| try: |
| _DownloadSymbols(filename, opts.cache) |
| _PerfReport(filename, opts.in_dir, opts.out_dir, opts.cache) |
| except: |
| print "Exception caught. Continuing..." |
| return 0 |
| |
| |
| def _ValidateOpts(opts): |
| """Ensures all directories exist, before attempting to populate.""" |
| if not os.path.exists(opts.in_dir): |
| print "Input directory doesn't exist." |
| return False |
| if not os.path.exists(opts.out_dir): |
| print "Output directory doesn't exist. Creating it..." |
| os.makedirs(opts.out_dir) |
| if not os.path.exists(opts.cache): |
| print "Cache directory doesn't exist." |
| return False |
| return True |
| |
| |
| def _ParseFilename(filename, canonical=False): |
| """Returns a tuple (key, time, board, lsb_version). |
| If canonical is True, instead returns (database_key, board, canonical_vers) |
| canonical_vers includes the revision string. |
| """ |
| key, time, board, vers = filename.split("~") |
| if canonical: |
| vers = misc.GetChromeOSVersionFromLSBVersion(vers) |
| return (key, time, board, vers) |
| |
| |
| def _FormReleaseDir(board, version): |
| return "%s-release~%s" % (board, version) |
| |
| |
| def _DownloadSymbols(filename, cache): |
| """ Incrementally downloads appropriate symbols. |
| We store the downloads in cache, with each set of symbols in a TLD |
| named like cache/$board-release~$canonical_vers/usr/lib/debug |
| """ |
| _, _, board, vers = _ParseFilename(filename, canonical=True) |
| tmp_suffix = ".tmp" |
| |
| tarball_subdir = _FormReleaseDir(board, vers) |
| tarball_dir = os.path.join(cache, tarball_subdir) |
| tarball_path = os.path.join(tarball_dir, "debug.tgz") |
| |
| symbol_subdir = os.path.join("usr", "lib") |
| symbol_dir = os.path.join(tarball_dir, symbol_subdir) |
| |
| if os.path.isdir(symbol_dir): |
| print "Symbol directory %s exists, skipping download." % symbol_dir |
| return |
| else: |
| # First download using gsutil. |
| if not os.path.isfile(tarball_path): |
| download_cmd = GSUTIL_CMD % (board, vers, tarball_path + tmp_suffix) |
| print "Downloading symbols for %s" % filename |
| print download_cmd |
| ret = call(download_cmd.split()) |
| if ret != 0: |
| print "gsutil returned non-zero error code: %s." % ret |
| # Clean up the empty directory structures. |
| os.remove(tarball_path + tmp_suffix) |
| raise IOError |
| |
| shutil.move(tarball_path + tmp_suffix, tarball_path) |
| |
| # Next, untar the tarball. |
| os.makedirs(symbol_dir + tmp_suffix) |
| extract_cmd = TAR_CMD % (tarball_path, symbol_dir + tmp_suffix) |
| print "Extracting symbols for %s" % filename |
| print extract_cmd |
| ret = call(extract_cmd.split()) |
| if ret != 0: |
| print "tar returned non-zero code: %s." % ret |
| raise IOError |
| shutil.move(symbol_dir + tmp_suffix, symbol_dir) |
| os.remove(tarball_path) |
| |
| |
| def _PerfReport(filename, in_dir, out_dir, cache): |
| """ Call perf report on the file, storing output to the output dir. |
| The output is currently stored as $out_dir/$filename |
| """ |
| _, _, board, vers = _ParseFilename(filename, canonical=True) |
| symbol_cache_tld = _FormReleaseDir(board, vers) |
| input_file = os.path.join(in_dir, filename) |
| symfs = os.path.join(cache, symbol_cache_tld) |
| report_cmd = PERF_CMD % (input_file, symfs) |
| print "Reporting." |
| print report_cmd |
| report_proc = Popen(report_cmd.split(), stdout=PIPE) |
| outfile = open(os.path.join(out_dir, filename), "w") |
| outfile.write(report_proc.stdout.read()) |
| outfile.close() |
| |
| |
| if __name__ == "__main__": |
| exit(main()) |