#!/bin/bash

# Copyright (c) 2018-2023 Red Hat.
#
# This is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 3, or (at your
# option) any later version.
#
# It is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# Test building an assembler source file without creating a gap in the notes.

TEST_NAME=assembler-gap
. $srcdir/common.sh

PLUGIN_OPTS="-fplugin-arg-annobin-no-attach"

start_test

# Assemble the file, and include debug information which will
# identify the producer as being AS.

$GAS --gdwarf-2 $srcdir/gap.S -o gap1.o

# Compile a C source file as well, so that we end up with a binary
# that was partially built by GCC, and partially not.  Note - we
# are not using all of the hardening options as we want to be sure
# that annocheck will notice.

pwd
echo "compilation comnmand: $GCC -fplugin=$PLUGIN $PLUGIN_OPTS -c -O2 -fPIC" 

$GCC -fplugin=$PLUGIN $PLUGIN_OPTS -c -O2 -fPIC $srcdir/hello.c 
$GCC -fplugin=$PLUGIN $PLUGIN_OPTS -c -O2 -fPIC $srcdir/hello2.c 
$GCC -fplugin=$PLUGIN $PLUGIN_OPTS -c -O2 -fPIC $srcdir/hello3.c 

# Put our assembled file between C files, so that the gap will be noticed.
$GCC -nostartfiles -e 0 hello.o hello2.o gap1.o hello3.o -o assembler-gap-test1.exe \
     -Wl,--defsym,extern_func3=0 \
     -Wl,-z,now -pie

$ANNOCHECK --skip-all --test-gaps -v -v --suppress-version-warnings assembler-gap-test1.exe > assembler-gap-test1.out

# FAIL if a gap is NOT reported
# The "skip: gaps test" match is for the ARM where annobin notes are not expected.
grep --silent -e "gaps were detected" -e "not all of the .text section is covered by notes" -e "skip: gaps test" assembler-gap-test1.out
if [ $? != 0 ];
then
    echo "  $TEST_NAME: FAIL: GAP *not* found in notes:"
    echo "  Annocheck output:"
    cat assembler-gap-test1.out
    echo "  Notes:"
    $ANNOCHECK --disable-hardened --enable-notes assembler-gap-test1.exe
    exit 1
fi

# Repeat the test, but this time, have the assembler generate a generic note.

$GAS --generate-missing-build-notes=yes $srcdir/gap.S -o gap2.o
if [ $? != 0 ];
then
    echo "  $TEST_NAME: Assembler does not support generating build notes.  Skipping test."
    exit 0
fi

$GCC -nostartfiles -e 0 hello.o hello2.o gap2.o hello3.o -o assembler-gap-test2.exe \
     -Wl,--defsym,extern_func3=0 \
     -Wl,-z,now -pie -Wl,-Map,assembler-gap-test2.map

$ANNOCHECK -v -v assembler-gap-test2.exe --skip-all --test-notes --test-gaps --suppress-version-warnings > assembler-gap-test2.out

# FAIL if a gap IS reported
grep --silent -e "no gaps found" -e "skip: gaps test" assembler-gap-test2.out
if [ $? != 0 ];
then
    echo "  $TEST_NAME: FAIL: GAP reported (with assembler covered by a note):"
    echo "  Annocheck output:"
    cat assembler-gap-test2.out
    echo "  Notes:"
    $ANNOCHECK --disable-hardened --enable-notes assembler-gap-test2.exe
    echo "  Disassembly:"
    objdump -d assembler-gap-test2.exe
    echo "  Linker Map:"
    cat assembler-gap-test2.map
    echo "  Readelf hello2.o"
    readelf -SWg hello2.o assembler-gap-test2.exe

    exit 1
fi

end_test
