#!/bin/bash
set -e

linux_ver=6.9.12
linux_url="https://cdn.kernel.org/pub/linux/kernel/v${linux_ver%.*.*}.x/linux-$linux_ver.tar.xz"

gen_vmlinux_h() {
  local arch=($1)
  local linux_arch=$2
  local bitness=$3
  local endianness=$4
  local build_path="$(realpath out/build-$arch)"

  (
    cd out/linux-$linux_ver
    rm -rf $build_path
    mkdir $build_path
    make O=$build_path LLVM=1 ARCH=$linux_arch tinyconfig
    cat >>"$build_path/.config" <<EOF
CONFIG_${bitness}BIT=y
CONFIG_${endianness}_ENDIAN=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_DEBUG_INFO_BTF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_NET=y
CONFIG_INET=y
EOF
    make O=$build_path LLVM=1 ARCH=$linux_arch olddefconfig
    make O=$build_path LLVM=1 ARCH=$linux_arch all -j$(nproc)
  )

  mkdir -p bpf/vmlinux
  cat >"bpf/vmlinux/$arch.h" <<EOF
// Generated using tools/vendor-vmlinux-h from Linux $linux_ver
// Do not edit!

EOF
  /usr/sbin/bpftool btf dump file $build_path/vmlinux format c >bpf/vmlinux/$arch.h
  echo -n "#elif defined(MIMIC_BPF_TARGET_ARCH_${arch[0]})" >>bpf/vmlinux.h
  for _arch in ${arch[@]:1}; do
    echo -n " || defined(MIMIC_BPF_TARGET_ARCH_$_arch)" >>bpf/vmlinux.h
  done
  echo >>bpf/vmlinux.h
  echo "#include \"vmlinux/$arch.h\"  // IWYU pragma: export" >>bpf/vmlinux.h
}

[ -d out ] || mkdir out
[ -f out/linux-$linux_ver.tar.xz ] || wget -O out/linux-$linux_ver.tar.xz $linux_url
[ -d out/linux-$linux_ver ] || tar xf out/linux-$linux_ver.tar.xz -C out

cat >bpf/vmlinux.h <<EOF
// Generated using tools/vendor-vmlinux-h, do not edit!

#ifndef _BPF_VMLINUX_H
#define _BPF_VMLINUX_H

#if defined(MIMIC_BPF_USE_SYSTEM_VMLINUX)
#include "vmlinux/system.h"  // IWYU pragma: export
EOF

gen_vmlinux_h 'i386 i486 i586 i686' x86 32 LITTLE
gen_vmlinux_h 'x86_64' x86 64 LITTLE
gen_vmlinux_h 'arm' arm 32 LITTLE
gen_vmlinux_h 'aarch64' arm64 64 LITTLE
gen_vmlinux_h 'riscv64' riscv 64 LITTLE
gen_vmlinux_h 'loongarch64 loong64' loongarch 64 LITTLE
gen_vmlinux_h 'ppc powerpc' powerpc 32 BIG
gen_vmlinux_h 'ppc64 powerpc64' powerpc 64 BIG
gen_vmlinux_h 'ppc64le powerpc64le' powerpc 64 LITTLE
gen_vmlinux_h 'mips' mips 32 BIG
gen_vmlinux_h 'mipsel' mips 32 LITTLE
gen_vmlinux_h 'mips64' mips 64 BIG
gen_vmlinux_h 'mips64el' mips 64 LITTLE
gen_vmlinux_h 's390x' s390 64 BIG

cat >>bpf/vmlinux.h <<EOF
#else
#include <asm/types.h>       // IWYU pragma: export
#include <linux/bpf.h>       // IWYU pragma: export
#include <linux/if_ether.h>  // IWYU pragma: export
#include <linux/in.h>        // IWYU pragma: export
#include <linux/ip.h>        // IWYU pragma: export
#include <linux/ipv6.h>      // IWYU pragma: export
#include <linux/stddef.h>    // IWYU pragma: export
#include <linux/tcp.h>       // IWYU pragma: export
#include <linux/types.h>     // IWYU pragma: export
#include <linux/udp.h>       // IWYU pragma: export
#include <stdbool.h>         // IWYU pragma: export
#endif

#endif  // _BPF_VMLINUX_H
EOF
