js/src/devtools/rootAnalysis/run_complete

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rwxr-xr-x

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 #!/usr/bin/perl
michael@0 2
michael@0 3 # Sixgill: Static assertion checker for C/C++ programs.
michael@0 4 # Copyright (C) 2009-2010 Stanford University
michael@0 5 # Author: Brian Hackett
michael@0 6 #
michael@0 7 # This program is free software: you can redistribute it and/or modify
michael@0 8 # it under the terms of the GNU General Public License as published by
michael@0 9 # the Free Software Foundation, either version 3 of the License, or
michael@0 10 # (at your option) any later version.
michael@0 11 #
michael@0 12 # This program is distributed in the hope that it will be useful,
michael@0 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
michael@0 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
michael@0 15 # GNU General Public License for more details.
michael@0 16 #
michael@0 17 # You should have received a copy of the GNU General Public License
michael@0 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
michael@0 19
michael@0 20 # do a complete run of the system from raw source to reports. this requires
michael@0 21 # various run_monitor processes to be running in the background (maybe on other
michael@0 22 # machines) and watching a shared poll_file for jobs. if the output directory
michael@0 23 # for this script already exists then an incremental analysis will be performed
michael@0 24 # and the reports will only reflect the changes since the earlier run.
michael@0 25
michael@0 26 use strict;
michael@0 27 use warnings;
michael@0 28 use IO::Handle;
michael@0 29 use File::Basename qw(dirname);
michael@0 30 use Getopt::Long;
michael@0 31 use Cwd;
michael@0 32
michael@0 33 #################################
michael@0 34 # environment specific settings #
michael@0 35 #################################
michael@0 36
michael@0 37 my $WORKDIR;
michael@0 38 my $SIXGILL_BIN;
michael@0 39
michael@0 40 # poll file shared with the run_monitor script.
michael@0 41 my $poll_file;
michael@0 42
michael@0 43 # root directory of the project.
michael@0 44 my $build_dir;
michael@0 45
michael@0 46 # directory containing gcc wrapper scripts.
michael@0 47 my $wrap_dir;
michael@0 48
michael@0 49 # optional file with annotations from the web interface.
michael@0 50 my $ann_file = "";
michael@0 51
michael@0 52 # optional output directory to do a diff against.
michael@0 53 my $old_dir = "";
michael@0 54
michael@0 55 # run in the foreground
michael@0 56 my $foreground;
michael@0 57
michael@0 58 my $builder = "make -j4";
michael@0 59
michael@0 60 my $suppress_logs;
michael@0 61 GetOptions("build-root|b=s" => \$build_dir,
michael@0 62 "poll-file=s" => \$poll_file,
michael@0 63 "no-logs!" => \$suppress_logs,
michael@0 64 "work-dir=s" => \$WORKDIR,
michael@0 65 "sixgill-binaries|binaries|b=s" => \$SIXGILL_BIN,
michael@0 66 "wrap-dir=s" => \$wrap_dir,
michael@0 67 "annotations-file|annotations|a=s" => \$ann_file,
michael@0 68 "old-dir|old=s" => \$old_dir,
michael@0 69 "foreground!" => \$foreground,
michael@0 70 "buildcommand=s" => \$builder,
michael@0 71 )
michael@0 72 or die;
michael@0 73
michael@0 74 if (not -d $build_dir) {
michael@0 75 mkdir($build_dir);
michael@0 76 }
michael@0 77 if ($old_dir ne "" && not -d $old_dir) {
michael@0 78 die "Old directory '$old_dir' does not exist\n";
michael@0 79 }
michael@0 80
michael@0 81 $WORKDIR ||= "sixgill-work";
michael@0 82 mkdir($WORKDIR, 0755) if ! -d $WORKDIR;
michael@0 83 $poll_file ||= "$WORKDIR/poll.file";
michael@0 84 $build_dir ||= "$WORKDIR/js-inbound-xgill";
michael@0 85
michael@0 86 if (!defined $SIXGILL_BIN) {
michael@0 87 chomp(my $path = `which xmanager`);
michael@0 88 if ($path) {
michael@0 89 use File::Basename qw(dirname);
michael@0 90 $SIXGILL_BIN = dirname($path);
michael@0 91 } else {
michael@0 92 die "Cannot find sixgill binaries. Use the -b option.";
michael@0 93 }
michael@0 94 }
michael@0 95
michael@0 96 $wrap_dir ||= "$WORKDIR/xgill-inbound/wrap_gcc";
michael@0 97 $wrap_dir = "$SIXGILL_BIN/../scripts/wrap_gcc" if not (-e "$wrap_dir/basecc");
michael@0 98 die "Bad wrapper directory: $wrap_dir" if not (-e "$wrap_dir/basecc");
michael@0 99
michael@0 100 # code to clean the project from $build_dir.
michael@0 101 sub clean_project {
michael@0 102 system("make clean");
michael@0 103 }
michael@0 104
michael@0 105 # code to build the project from $build_dir.
michael@0 106 sub build_project {
michael@0 107 return system($builder) >> 8;
michael@0 108 }
michael@0 109
michael@0 110 our %kill_on_exit;
michael@0 111 END {
michael@0 112 for my $pid (keys %kill_on_exit) {
michael@0 113 kill($pid);
michael@0 114 }
michael@0 115 }
michael@0 116
michael@0 117 # commands to start the various xgill binaries. timeouts can be specified
michael@0 118 # for the backend analyses here, and a memory limit can be specified for
michael@0 119 # xmanager if desired (and USE_COUNT_ALLOCATOR is defined in util/alloc.h).
michael@0 120 my $xmanager = "$SIXGILL_BIN/xmanager";
michael@0 121 my $xsource = "$SIXGILL_BIN/xsource";
michael@0 122 my $xmemlocal = "$SIXGILL_BIN/xmemlocal -timeout=20";
michael@0 123 my $xinfer = "$SIXGILL_BIN/xinfer -timeout=60";
michael@0 124 my $xcheck = "$SIXGILL_BIN/xcheck -timeout=30";
michael@0 125
michael@0 126 # prefix directory to strip off source files.
michael@0 127 my $prefix_dir = $build_dir;
michael@0 128
michael@0 129 ##########################
michael@0 130 # general purpose script #
michael@0 131 ##########################
michael@0 132
michael@0 133 # Prevent ccache from being used. I don't think this does any good. The problem
michael@0 134 # I'm struggling with is that if autoconf.mk still has 'ccache gcc' in it, the
michael@0 135 # builds fail in a mysterious way.
michael@0 136 $ENV{CCACHE_COMPILERCHECK} = 'date +%s.%N';
michael@0 137 delete $ENV{CCACHE_PREFIX};
michael@0 138
michael@0 139 my $usage = "USAGE: run_complete result-dir\n";
michael@0 140 my $result_dir = shift or die $usage;
michael@0 141
michael@0 142 if (not $foreground) {
michael@0 143 my $pid = fork();
michael@0 144 if ($pid != 0) {
michael@0 145 print "Forked, exiting...\n";
michael@0 146 exit(0);
michael@0 147 }
michael@0 148 }
michael@0 149
michael@0 150 # if the result directory does not already exist, mark for a clean build.
michael@0 151 my $do_clean = 0;
michael@0 152 if (not (-d $result_dir)) {
michael@0 153 $do_clean = 1;
michael@0 154 mkdir $result_dir;
michael@0 155 }
michael@0 156
michael@0 157 if (!$suppress_logs) {
michael@0 158 my $log_file = "$result_dir/complete.log";
michael@0 159 open(OUT, ">>", $log_file) or die "append to $log_file: $!";
michael@0 160 OUT->autoflush(1); # don't buffer writes to the main log.
michael@0 161
michael@0 162 # redirect stdout and stderr to the log.
michael@0 163 STDOUT->fdopen(\*OUT, "w");
michael@0 164 STDERR->fdopen(\*OUT, "w");
michael@0 165 }
michael@0 166
michael@0 167 # pids to wait on before exiting. these are collating worker output.
michael@0 168 my @waitpids;
michael@0 169
michael@0 170 chdir $result_dir;
michael@0 171
michael@0 172 # to do a partial run, comment out the commands here you don't want to do.
michael@0 173
michael@0 174 my $status = run_build();
michael@0 175
michael@0 176 # end of run commands.
michael@0 177
michael@0 178 for my $pid (@waitpids) {
michael@0 179 waitpid($pid, 0);
michael@0 180 $status ||= $? >> 8;
michael@0 181 }
michael@0 182
michael@0 183 print "Exiting run_complete with status $status\n";
michael@0 184 exit $status;
michael@0 185
michael@0 186 # get the IP address which a freshly created manager is listening on.
michael@0 187 sub get_manager_address
michael@0 188 {
michael@0 189 my $log_file = shift or die;
michael@0 190
michael@0 191 # give the manager one second to start, any longer and something's broken.
michael@0 192 sleep(1);
michael@0 193
michael@0 194 my $log_data = `cat $log_file`;
michael@0 195 my ($port) = $log_data =~ /Listening on ([\.\:0-9]*)/
michael@0 196 or die "no manager found";
michael@0 197 print OUT "Connecting to manager on port $port\n" unless $suppress_logs;
michael@0 198 print "Connecting to manager on port $port.\n";
michael@0 199 return $1;
michael@0 200 }
michael@0 201
michael@0 202 sub run_build
michael@0 203 {
michael@0 204 print "build started: ";
michael@0 205 print scalar(localtime());
michael@0 206 print "\n";
michael@0 207
michael@0 208 # fork off a process to run the build.
michael@0 209 defined(my $pid = fork) or die;
michael@0 210
michael@0 211 # log file for the manager.
michael@0 212 my $manager_log_file = "$result_dir/build_manager.log";
michael@0 213
michael@0 214 if (!$pid) {
michael@0 215 # this is the child process, fork another process to run a manager.
michael@0 216 defined(my $pid = fork) or die;
michael@0 217 exec("$xmanager -terminate-on-assert > $manager_log_file 2>&1") if (!$pid);
michael@0 218 $kill_on_exit{$pid} = 1;
michael@0 219
michael@0 220 if (!$suppress_logs) {
michael@0 221 # open new streams to redirect stdout and stderr.
michael@0 222 open(LOGOUT, "> $result_dir/build.log");
michael@0 223 open(LOGERR, "> $result_dir/build_err.log");
michael@0 224 STDOUT->fdopen(\*LOGOUT, "w");
michael@0 225 STDERR->fdopen(\*LOGERR, "w");
michael@0 226 }
michael@0 227
michael@0 228 my $address = get_manager_address($manager_log_file);
michael@0 229
michael@0 230 # write the configuration file for the wrapper script.
michael@0 231 my $config_file = "$WORKDIR/xgill.config";
michael@0 232 open(CONFIG, ">", $config_file) or die "create $config_file: $!";
michael@0 233 print CONFIG "$prefix_dir\n";
michael@0 234 print CONFIG Cwd::abs_path("$result_dir/build_xgill.log")."\n";
michael@0 235 print CONFIG "$address\n";
michael@0 236 my @extra = ("-fplugin-arg-xgill-mangle=1");
michael@0 237 push(@extra, "-fplugin-arg-xgill-annfile=$ann_file")
michael@0 238 if ($ann_file ne "" && -e $ann_file);
michael@0 239 print CONFIG join(" ", @extra) . "\n";
michael@0 240 close(CONFIG);
michael@0 241
michael@0 242 # Tell the wrapper where to find the config
michael@0 243 $ENV{"XGILL_CONFIG"} = Cwd::abs_path($config_file);
michael@0 244
michael@0 245 # update the PATH so that the build will see the wrappers.
michael@0 246 $ENV{"PATH"} = "$wrap_dir:" . $ENV{"PATH"};
michael@0 247
michael@0 248 # do the build, cleaning if necessary.
michael@0 249 chdir $build_dir;
michael@0 250 clean_project() if ($do_clean);
michael@0 251 my $exit_status = build_project();
michael@0 252
michael@0 253 # signal the manager that it's over.
michael@0 254 system("$xsource -remote=$address -end-manager");
michael@0 255
michael@0 256 # wait for the manager to clean up and terminate.
michael@0 257 print "Waiting for manager to finish (build status $exit_status)...\n";
michael@0 258 waitpid($pid, 0);
michael@0 259 my $manager_status = $?;
michael@0 260 delete $kill_on_exit{$pid};
michael@0 261
michael@0 262 # build is finished, the complete run can resume.
michael@0 263 # return value only useful if --foreground
michael@0 264 print "Exiting with status " . ($manager_status || $exit_status) . "\n";
michael@0 265 exit($manager_status || $exit_status);
michael@0 266 }
michael@0 267
michael@0 268 # this is the complete process, wait for the build to finish.
michael@0 269 waitpid($pid, 0);
michael@0 270 my $status = $? >> 8;
michael@0 271 print "build finished (status $status): ";
michael@0 272 print scalar(localtime());
michael@0 273 print "\n";
michael@0 274
michael@0 275 return $status;
michael@0 276 }
michael@0 277
michael@0 278 sub run_pass
michael@0 279 {
michael@0 280 my ($name, $command) = @_;
michael@0 281 my $log_file = "$result_dir/manager.$name.log";
michael@0 282
michael@0 283 # extra commands to pass to the manager.
michael@0 284 my $manager_extra = "";
michael@0 285 $manager_extra .= "-modset-wait=10" if ($name eq "xmemlocal");
michael@0 286
michael@0 287 # fork off a manager process for the analysis.
michael@0 288 defined(my $pid = fork) or die;
michael@0 289 exec("$xmanager $manager_extra > $log_file 2>&1") if (!$pid);
michael@0 290
michael@0 291 my $address = get_manager_address($log_file);
michael@0 292
michael@0 293 # write the poll file for this pass.
michael@0 294 if (! -d dirname($poll_file)) {
michael@0 295 system("mkdir", "-p", dirname($poll_file));
michael@0 296 }
michael@0 297 open(POLL, "> $poll_file");
michael@0 298 print POLL "$command\n";
michael@0 299 print POLL "$result_dir/$name\n";
michael@0 300 print POLL "$address\n";
michael@0 301 close(POLL);
michael@0 302
michael@0 303 print "$name started: ";
michael@0 304 print scalar(localtime());
michael@0 305 print "\n";
michael@0 306
michael@0 307 waitpid($pid, 0);
michael@0 308 unlink($poll_file);
michael@0 309
michael@0 310 print "$name finished: ";
michael@0 311 print scalar(localtime());
michael@0 312 print "\n";
michael@0 313
michael@0 314 # collate the worker's output into a single file. make this asynchronous
michael@0 315 # so we can wait a bit and make sure we get all worker output.
michael@0 316 defined($pid = fork) or die;
michael@0 317
michael@0 318 if (!$pid) {
michael@0 319 sleep(20);
michael@0 320 exec("cat $name.*.log > $name.log");
michael@0 321 }
michael@0 322
michael@0 323 push(@waitpids, $pid);
michael@0 324 }
michael@0 325
michael@0 326 # the names of all directories containing reports to archive.
michael@0 327 my $indexes;
michael@0 328
michael@0 329 sub run_index
michael@0 330 {
michael@0 331 my ($name, $kind) = @_;
michael@0 332
michael@0 333 return if (not (-e "report_$kind.xdb"));
michael@0 334
michael@0 335 print "$name started: ";
michael@0 336 print scalar(localtime());
michael@0 337 print "\n";
michael@0 338
michael@0 339 # make an index for the report diff if applicable.
michael@0 340 if ($old_dir ne "") {
michael@0 341 system("make_index $kind $old_dir > $name.diff.log");
michael@0 342 system("mv $kind diff_$kind");
michael@0 343 $indexes .= " diff_$kind";
michael@0 344 }
michael@0 345
michael@0 346 # make an index for the full set of reports.
michael@0 347 system("make_index $kind > $name.log");
michael@0 348 $indexes .= " $kind";
michael@0 349
michael@0 350 print "$name finished: ";
michael@0 351 print scalar(localtime());
michael@0 352 print "\n";
michael@0 353 }
michael@0 354
michael@0 355 sub archive_indexes
michael@0 356 {
michael@0 357 print "archive started: ";
michael@0 358 print scalar(localtime());
michael@0 359 print "\n";
michael@0 360
michael@0 361 system("tar -czf reports.tgz $indexes");
michael@0 362 system("rm -rf $indexes");
michael@0 363
michael@0 364 print "archive finished: ";
michael@0 365 print scalar(localtime());
michael@0 366 print "\n";
michael@0 367 }

mercurial