#!/bin/bash
#
# The Go linker does not seem to know what to do with relative
# addressing of rodata.* offset from %rip. GCC likes to use this
# addressing mode on this architecture, so we quickly run into
# mis-computation when the relative addressing used in a .syso file of
# symbol located data is resolved to completely the wrong place by the
# Go (internal) linker.
#
# As a workaround for this, we can modify the assembly source code
# generated by GCC to not point at problematic '.rodata.*' sections,
# and place this data in the good old '.text' section where Go's
# linker can make sense of it.
#
# This script exists to generate a '.syso' file from some '*.c' files.
# It works by recognizing the '*.c' command line arguments and
# converting them into fixed-up '*.s' files. It then performs the
# compilation for the collection of the '*.s' files. Upon success, it
# purges the intermediate '*.s' files.
#
# The fragile aspect of this present script is which compiler
# arguments should be used for the compilation from '.c' -> '.s'
# files. What we do is accumulate arguments until we encounter our
# first '*.c' file and use those to perform the '.c' -> '.s'
# compilation. We build up a complete command line for gcc
# substituting '.s' files for '.c' files in the original command
# line. Then with the new command line assembled we invoke gcc with
# those. If that works, we remove all of the intermediate '.s' files.

GCC="${GCC:=gcc}"
setup=0
args=()
final=()
ses=()

for arg in "$@"; do
    if [[ "${arg##*.}" = "c" ]]; then
	setup=1
	s="${arg%.*}.s"
	"${GCC}" "${args[@]}" -S -o "${s}" "${arg}"
	sed -i -e 's/.*\.rodata\..*/\t.text/' "${s}"
	final+=("${s}")
	ses+=("${s}")
    else
	if [[ $setup -eq 0 ]]; then
	    args+=("${arg}")
	fi
	final+=("${arg}")
    fi
done

#echo final: "${final[@]}"
#echo args: "${args[@]}"
#echo ses: "${ses[@]}"

"${GCC}" "${final[@]}"
if [[ $? -ne 0 ]]; then
    echo "failed to compile"
    exit 1
fi
rm -f "${ses[@]}"
