mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			184 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
	
		
			6.6 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/bin/bash -ex
 | 
						|
 | 
						|
function usage() {
 | 
						|
    echo "Usage: $0 [--project <js|browser>] <workspace-dir> flags..."
 | 
						|
    echo "flags are treated the same way as a commit message would be"
 | 
						|
    echo "(as in, they are scanned for directives just like a try: ... line)"
 | 
						|
}
 | 
						|
 | 
						|
PROJECT=js
 | 
						|
WORKSPACE=
 | 
						|
while [[ $# -gt 0 ]]; do
 | 
						|
    if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then
 | 
						|
        usage
 | 
						|
        exit 0
 | 
						|
    elif [[ "$1" == "--project" ]]; then
 | 
						|
        shift
 | 
						|
        PROJECT="$1"
 | 
						|
        shift
 | 
						|
    elif [[ "$1" == "--no-tooltool" ]]; then
 | 
						|
        shift
 | 
						|
    elif [[ -z "$WORKSPACE" ]]; then
 | 
						|
        WORKSPACE=$( cd "$1" && pwd )
 | 
						|
        shift
 | 
						|
        break
 | 
						|
    fi
 | 
						|
done
 | 
						|
 | 
						|
function check_commit_msg () {
 | 
						|
    ( set +e;
 | 
						|
    if [[ -n "$AUTOMATION" ]]; then
 | 
						|
        hg --cwd "$GECKO_PATH" log -r. --template '{desc}\n' | grep -F -q -- "$1"
 | 
						|
    else
 | 
						|
        echo -- "$SCRIPT_FLAGS" | grep -F -q -- "$1"
 | 
						|
    fi
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
if check_commit_msg "--dep"; then
 | 
						|
    HAZ_DEP=1
 | 
						|
fi
 | 
						|
 | 
						|
SCRIPT_FLAGS=$*
 | 
						|
 | 
						|
ANALYSIS_DIR="$WORKSPACE/haz-$PROJECT"
 | 
						|
 | 
						|
# Ensure all the scripts in this dir are on the path....
 | 
						|
DIRNAME=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
 | 
						|
PATH=$DIRNAME:$PATH
 | 
						|
 | 
						|
# Use GECKO_BASE_REPOSITORY as a signal for whether we are running in automation.
 | 
						|
export AUTOMATION=${GECKO_BASE_REPOSITORY:+1}
 | 
						|
 | 
						|
: "${GECKO_PATH:="$DIRNAME"/../../..}"
 | 
						|
 | 
						|
if ! [ -d "$GECKO_PATH" ]; then
 | 
						|
    echo "GECKO_PATH must be set to a directory containing a gecko source checkout" >&2
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# Directory to hold the compiled JS shell that will run the analysis.
 | 
						|
HAZARD_SHELL_OBJDIR=$WORKSPACE/obj-haz-shell
 | 
						|
 | 
						|
export NO_MERCURIAL_SETUP_CHECK=1
 | 
						|
 | 
						|
if [[ "$PROJECT" = "browser" ]]; then (
 | 
						|
    cd "$WORKSPACE"
 | 
						|
    set "$WORKSPACE"
 | 
						|
    # Mozbuild config:
 | 
						|
    export MOZBUILD_STATE_PATH=$WORKSPACE/mozbuild/
 | 
						|
    # Create .mozbuild so mach doesn't complain about this
 | 
						|
    mkdir -p "$MOZBUILD_STATE_PATH"
 | 
						|
) fi
 | 
						|
 | 
						|
# Build the shell
 | 
						|
export HAZARD_SHELL_OBJDIR # This will be picked up by mozconfig.haz_shell.
 | 
						|
$GECKO_PATH/mach hazards build-shell
 | 
						|
 | 
						|
# Run a self-test
 | 
						|
$GECKO_PATH/mach hazards self-test --shell-objdir="$HAZARD_SHELL_OBJDIR"
 | 
						|
 | 
						|
# Artifacts folder is outside of the cache.
 | 
						|
mkdir -p "$HOME"/artifacts/ || true
 | 
						|
 | 
						|
function grab_artifacts () {
 | 
						|
    local artifacts
 | 
						|
    artifacts="$HOME/artifacts"
 | 
						|
 | 
						|
    [ -d "$ANALYSIS_DIR" ] && (
 | 
						|
        cd "$ANALYSIS_DIR"
 | 
						|
        ls -lah
 | 
						|
 | 
						|
        # Do not error out if no files found
 | 
						|
        shopt -s nullglob
 | 
						|
        set +e
 | 
						|
        local important
 | 
						|
        important=(refs.txt unnecessary.txt hazards.txt gcFunctions.txt allFunctions.txt heapWriteHazards.txt rootingHazards.json hazards.html)
 | 
						|
 | 
						|
        # Bundle up the less important but still useful intermediate outputs,
 | 
						|
        # just to cut down on the clutter in treeherder's Job Details pane.
 | 
						|
        tar -acvf "${artifacts}/hazardIntermediates.tar.xz" --exclude-from <(IFS=$'\n'; echo "${important[*]}") *.txt *.lst build_xgill.log
 | 
						|
 | 
						|
        # Upload the important outputs individually, so that they will be
 | 
						|
        # visible in Job Details and accessible to automated jobs.
 | 
						|
        for f in "${important[@]}"; do
 | 
						|
            gzip -9 -c "$f" > "${artifacts}/$f.gz"
 | 
						|
        done
 | 
						|
 | 
						|
        # Check whether the user requested .xdb file upload in the top commit comment
 | 
						|
        if check_commit_msg "--upload-xdbs"; then
 | 
						|
            HAZ_UPLOAD_XDBS=1
 | 
						|
        fi
 | 
						|
 | 
						|
        if [ -n "$HAZ_UPLOAD_XDBS" ]; then
 | 
						|
            for f in *.xdb; do
 | 
						|
                xz -c "$f" > "${artifacts}/$f.bz2"
 | 
						|
            done
 | 
						|
        fi
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
function check_hazards () {
 | 
						|
    (
 | 
						|
    set +e
 | 
						|
    NUM_HAZARDS=$(grep -c 'Function.*has unrooted.*live across GC call' "$1"/hazards.txt)
 | 
						|
    NUM_UNSAFE=$(grep -c '^Function.*takes unsafe address of unrooted' "$1"/refs.txt)
 | 
						|
    NUM_UNNECESSARY=$(grep -c '^Function.* has unnecessary root' "$1"/unnecessary.txt)
 | 
						|
    NUM_DROPPED=$(grep -c '^Dropped CFG' "$1"/build_xgill.log)
 | 
						|
    NUM_WRITE_HAZARDS=$(perl -lne 'print $1 if m!found (\d+)/\d+ allowed errors!' "$1"/heapWriteHazards.txt)
 | 
						|
    NUM_MISSING=$(grep -c '^Function.*expected hazard.*but none were found' "$1"/hazards.txt)
 | 
						|
 | 
						|
    set +x
 | 
						|
    echo "TinderboxPrint: rooting hazards<br/>$NUM_HAZARDS"
 | 
						|
    echo "TinderboxPrint: (unsafe references to unrooted GC pointers)<br/>$NUM_UNSAFE"
 | 
						|
    echo "TinderboxPrint: (unnecessary roots)<br/>$NUM_UNNECESSARY"
 | 
						|
    echo "TinderboxPrint: missing expected hazards<br/>$NUM_MISSING"
 | 
						|
    echo "TinderboxPrint: heap write hazards<br/>$NUM_WRITE_HAZARDS"
 | 
						|
 | 
						|
    # Display errors in a way that will get picked up by the taskcluster scraper.
 | 
						|
    perl -lne 'print "TEST-UNEXPECTED-FAIL | hazards | $1 $2" if /^Function.* has (unrooted .*live across GC call).* (at .*)$/' "$1"/hazards.txt
 | 
						|
 | 
						|
    exit_status=0
 | 
						|
 | 
						|
    if [ $NUM_HAZARDS -gt 0 ]; then
 | 
						|
        echo "TEST-UNEXPECTED-FAIL | hazards | $NUM_HAZARDS rooting hazards detected" >&2
 | 
						|
        echo "TinderboxPrint: documentation<br/><a href='https://firefox-source-docs.mozilla.org/js/HazardAnalysis/#diagnosing-a-rooting-hazards-failure'>static rooting hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"
 | 
						|
        exit_status=1
 | 
						|
    fi
 | 
						|
 | 
						|
    if [ $NUM_MISSING -gt 0 ]; then
 | 
						|
        echo "TEST-UNEXPECTED-FAIL | hazards | $NUM_MISSING expected hazards went undetected" >&2
 | 
						|
        echo "TinderboxPrint: documentation<br/><a href='https://firefox-source-docs.mozilla.org/js/HazardAnalysis/#diagnosing-a-rooting-hazards-failure'>static rooting hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"
 | 
						|
        exit_status=1
 | 
						|
    fi
 | 
						|
 | 
						|
    NUM_ALLOWED_WRITE_HAZARDS=0
 | 
						|
    if [ $NUM_WRITE_HAZARDS -gt $NUM_ALLOWED_WRITE_HAZARDS ]; then
 | 
						|
        echo "TEST-UNEXPECTED-FAIL | heap-write-hazards | $NUM_WRITE_HAZARDS heap write hazards detected out of $NUM_ALLOWED_WRITE_HAZARDS allowed" >&2
 | 
						|
        echo "TinderboxPrint: documentation<br/><a href='https://firefox-source-docs.mozilla.org/js/HazardAnalysis/#diagnosing-a-heap-write-hazard-failure'>heap write hazard analysis failures</a>, visit \"Inspect Task\" link for hazard details"
 | 
						|
        exit_status = 1
 | 
						|
    fi
 | 
						|
 | 
						|
    if [ $NUM_DROPPED -gt 0 ]; then
 | 
						|
        echo "TEST-UNEXPECTED-FAIL | hazards | $NUM_DROPPED CFGs dropped" >&2
 | 
						|
        echo "TinderboxPrint: sixgill unable to handle constructs<br/>$NUM_DROPPED"
 | 
						|
        exit_status=1
 | 
						|
    fi
 | 
						|
 | 
						|
    if [ $exit_status -ne 0 ]; then
 | 
						|
        exit $exit_status
 | 
						|
    fi
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
trap grab_artifacts EXIT
 | 
						|
 | 
						|
# Gather the information from the source tree by compiling it.
 | 
						|
$GECKO_PATH/mach hazards gather --project=$PROJECT --work-dir="$ANALYSIS_DIR"
 | 
						|
 | 
						|
# Analyze the collected information.
 | 
						|
$GECKO_PATH/mach hazards analyze --project=$PROJECT --shell-objdir="$HAZARD_SHELL_OBJDIR" --work-dir="$ANALYSIS_DIR"
 | 
						|
 | 
						|
check_hazards "$ANALYSIS_DIR"
 | 
						|
 | 
						|
################################### script end ###################################
 |