#!/bin/sh -eu
#
# Copyright © 2017 Samuel Holland <samuel@sholland.org>
# See LICENSE in the project directory for license terms.
#
# Requires GNU sort or compatible for hexadecimal sorting.
#

# Adjust these as needed
ARCH=${ARCH:-or1k}
CROSS_COMPILE=${CROSS_COMPILE:-${ARCH}-linux-musl-}

# Generated, but might need adjustment
case "$ARCH" in
  arm)
    CALL_INSN='(bl|blx)'
    TAIL_INSN=
    ;;
  or1k)
    CALL_INSN='l\.jal'
    TAIL_INSN='l\.j'
    ;;
esac

# Command-line parameters
dir=$1

# Internal variables
assembly=${dir}/blob.s
sections=${dir}/sections
symbols=${dir}/symbols

# Usage: warn <message>
warn() {
  printf 'warning: %s\n' "$*" >&2
}

# Ensure the disassembled file exists
make "$assembly"

# Add ARM interleaved instruction/immediate data marker
if test "$ARCH" = "arm"; then
  grep -m1 'text$' "$sections" | sed 's/text/$a/' >> "$symbols"
fi

# Merge the symbols
sort -go "$symbols" -u "$symbols"

# Add all normally-called functions
grep -E "${CALL_INSN}\s(0x)?[[:xdigit:]]{2,}" "$assembly" |
sed -E "s/^.*${CALL_INSN}\s//" |
sort -gu |
while read -r addr dummy; do
  { printf "$addr" | grep -q "^0x"; } || addr=0x${addr}
  grep -q "$(printf '^0x%08x' "$addr")" "$symbols" && continue
  printf '0x%08x func_%08x\n' "$addr" "$addr"
done >> "$symbols"

# Merge the symbols
sort -go "$symbols" -u "$symbols"

# Update the disassembly
make "$assembly"

# Add all tail-called functions (from the last instruction of another function)
if test -n "$TAIL_INSN"; then
  grep -B2 '^[[:xdigit:]]\{8\} <[[:alnum:]_]\+>:$' "$assembly" |
  grep "${TAIL_INSN}\s[[:xdigit:]]" |
  sed "s/^.*${TAIL_INSN}\s\([[:xdigit:]]\+\)\s.*$/0x\1/" |
  sort -gu |
  while read -r addr dummy; do
    { printf "$addr" | grep -q "^0x"; } || addr=0x${addr}
    grep -q "$(printf '^0x%08x' "$addr")" "$symbols" && continue
    printf '0x%08x func_%08x\n' "$addr" "$addr"
  done >> "$symbols"
fi

# Merge the symbols
sort -go "$symbols" -u "$symbols"

# Build everything with the new symbols
make BLOB="$dir"
