| #!/bin/bash | |
| # Copyright (C) 2022-2025 Free Software Foundation, Inc. | |
| # | |
| # This file is part of GDB. | |
| # | |
| # This program 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 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program 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. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # Used to generate .xml.in files, like so: | |
| # $ ./update-linux-from-src.sh ~/linux-stable.git | |
| pwd=$(pwd -P) | |
| parse_args () | |
| { | |
| if [ $# -lt 1 ]; then | |
| echo "dir argument needed" | |
| exit 1 | |
| fi | |
| d="$1" | |
| shift | |
| if [ ! -d "$d" ]; then | |
| echo "cannot find $d" | |
| exit 1 | |
| fi | |
| } | |
| gen_from_kernel_headers () | |
| { | |
| local f | |
| f="$1" | |
| local arch | |
| arch="$2" | |
| echo "Generating $f" | |
| local tmpdir | |
| tmpdir=$(mktemp -d) | |
| trap 'rm -Rf $tmpdir/*' EXIT | |
| local build | |
| build="$tmpdir"/build | |
| local install | |
| install="$tmpdir"/install | |
| local usr | |
| usr="$install"/usr | |
| local include | |
| include="$usr"/include | |
| mkdir -p "$build" "$usr" | |
| ( | |
| cd "$build" || exit 1 | |
| make \ | |
| -f "$d"/Makefile \ | |
| ARCH="$arch" \ | |
| INSTALL_HDR_PATH="$usr" \ | |
| headers_install \ | |
| > "$build"/header_install.log \ | |
| 2>&1 | |
| "$pwd"/update-linux.sh \ | |
| "$pwd"/"$f" \ | |
| -nostdinc \ | |
| -isystem "$include" | |
| ) | |
| trap '' EXIT | |
| rm -Rf "$tmpdir" | |
| } | |
| pre () | |
| { | |
| local f | |
| f="$1" | |
| local start_date | |
| start_date="$2" | |
| local h | |
| h="$3" | |
| local prefix | |
| prefix=" " | |
| if [ "$h" != "" ]; then | |
| file_files="files" | |
| belong_belongs="belong" | |
| files=$(echo -e "$prefix$f\n$prefix$h") | |
| else | |
| file_files="file" | |
| belong_belongs="belongs" | |
| files="$prefix$f" | |
| fi | |
| local year | |
| year=$(date +%Y) | |
| cat <<EOF | |
| <?xml version="1.0"?> | |
| <!-- Copyright (C) $start_date-$year Free Software Foundation, Inc. | |
| Copying and distribution of this file, with or without modification, | |
| are permitted in any medium without royalty provided the copyright | |
| notice and this notice are preserved. --> | |
| <!DOCTYPE feature SYSTEM "gdb-syscalls.dtd"> | |
| <!-- This file was generated using the following $file_files: | |
| $files | |
| The $file_files mentioned above $belong_belongs to the Linux Kernel. --> | |
| EOF | |
| echo '<syscalls_info>' | |
| } | |
| post () | |
| { | |
| echo '</syscalls_info>' | |
| } | |
| one () | |
| { | |
| local f | |
| f="$1" | |
| local select_abis | |
| select_abis="$2" | |
| local start_date | |
| start_date="$3" | |
| local offset | |
| offset="$4" | |
| local h | |
| h="$5" | |
| tmp=$(mktemp) | |
| trap 'rm -f $tmp' EXIT | |
| pre "$f" "$start_date" "$h" | |
| # Print out num, abi, name. | |
| grep -v "^#" "$d/$f" \ | |
| | awk '{print $1, $2, $3}' \ | |
| > "$tmp" | |
| local decimal | |
| decimal="[0-9][0-9]*" | |
| # Print out num, "removed", name. | |
| grep -E "^# $decimal was sys_*" "$d/$f" \ | |
| | awk '{print $2, "removed", gensub("^sys_", "", 1, $4)}' \ | |
| >> "$tmp" | |
| case $h in | |
| arch/arm/include/uapi/asm/unistd.h) | |
| grep '#define __ARM_NR_[a-z].*__ARM_NR_BASE\+' "$d/$h" \ | |
| | sed 's/#define //;s/__ARM_NR_BASE+//;s/[()]//g;s/__ARM_NR_/ARM_/' \ | |
| | awk '{print $2 + 0x0f0000, "private", $1}' \ | |
| >> "$tmp" | |
| ;; | |
| esac | |
| local nums | |
| declare -a nums | |
| local abis | |
| declare -a abis | |
| local names | |
| declare -a names | |
| local name_exists | |
| declare -A name_exists | |
| local i | |
| i=0 | |
| local _num | |
| local _abi | |
| local _name | |
| while read -r -a line; do | |
| _num="${line[0]}" | |
| _abi="${line[1]}" | |
| _name="${line[2]}" | |
| local found | |
| found=false | |
| for a in $select_abis; do | |
| if [ "$a" = "$_abi" ]; then | |
| found=true | |
| break | |
| fi | |
| done | |
| if ! $found; then | |
| continue | |
| fi | |
| if [ "${_name/reserved+([0-9])/}" = "" ]; then | |
| continue | |
| fi | |
| if [ "${_name/unused+([0-9])/}" = "" ]; then | |
| continue | |
| fi | |
| nums[i]="$_num" | |
| abis[i]="$_abi" | |
| names[i]="$_name" | |
| if [ "$_abi" != "removed" ]; then | |
| name_exists[$_name]=1 | |
| fi | |
| i=$((i + 1)) | |
| done < <(sort -V "$tmp") | |
| local n | |
| n=$i | |
| for ((i = 0 ; i < n ; i++)); do | |
| _name=${names[$i]} | |
| _abi=${abis[$i]} | |
| _num=$((${nums[$i]} + offset)) | |
| if [ "$_abi" = "removed" ] && [ "${name_exists[$_name]}" = 1 ]; then | |
| _name=old$_name | |
| fi | |
| echo -n " <syscall name=\"$_name\" number=\"$_num\"/>" | |
| if [ "$_abi" = "removed" ]; then | |
| echo " <!-- removed -->" | |
| else | |
| echo | |
| fi | |
| done | |
| post | |
| } | |
| regen () | |
| { | |
| local f | |
| f="$1" | |
| local start_date | |
| start_date=2009 | |
| local offset | |
| offset=0 | |
| local h | |
| h= | |
| local t | |
| local abi | |
| case $f in | |
| amd64-linux.xml.in) | |
| t="arch/x86/entry/syscalls/syscall_64.tbl" | |
| abi="common 64" | |
| ;; | |
| i386-linux.xml.in) | |
| t="arch/x86/entry/syscalls/syscall_32.tbl" | |
| abi=i386 | |
| ;; | |
| ppc64-linux.xml.in) | |
| t="arch/powerpc/kernel/syscalls/syscall.tbl" | |
| abi="common 64 nospu" | |
| ;; | |
| ppc-linux.xml.in) | |
| t="arch/powerpc/kernel/syscalls/syscall.tbl" | |
| abi="common 32 nospu" | |
| ;; | |
| s390-linux.xml.in) | |
| t="arch/s390/kernel/syscalls/syscall.tbl" | |
| abi="common 32" | |
| ;; | |
| s390x-linux.xml.in) | |
| t="arch/s390/kernel/syscalls/syscall.tbl" | |
| abi="common 64" | |
| ;; | |
| sparc64-linux.xml.in) | |
| t="arch/sparc/kernel/syscalls/syscall.tbl" | |
| abi="common 64" | |
| start_date="2010" | |
| ;; | |
| sparc-linux.xml.in) | |
| t="arch/sparc/kernel/syscalls/syscall.tbl" | |
| abi="common 32" | |
| start_date="2010" | |
| ;; | |
| mips-n32-linux.xml.in) | |
| t="arch/mips/kernel/syscalls/syscall_n32.tbl" | |
| abi="n32" | |
| start_date="2011" | |
| offset=6000 | |
| ;; | |
| mips-n64-linux.xml.in) | |
| t="arch/mips/kernel/syscalls/syscall_n64.tbl" | |
| abi="n64" | |
| start_date="2011" | |
| offset=5000 | |
| ;; | |
| mips-o32-linux.xml.in) | |
| t="arch/mips/kernel/syscalls/syscall_o32.tbl" | |
| abi="o32" | |
| start_date="2011" | |
| offset=4000 | |
| ;; | |
| bfin-linux.xml.in) | |
| echo "Skipping $f, no longer supported" | |
| return | |
| ;; | |
| aarch64-linux.xml.in) | |
| # No syscall.tbl. | |
| gen_from_kernel_headers "$f" arm64 | |
| return | |
| ;; | |
| riscv-linux.xml.in) | |
| # No syscall.tbl. | |
| gen_from_kernel_headers "$f" riscv | |
| return | |
| ;; | |
| arm-linux.xml.in) | |
| t="arch/arm/tools/syscall.tbl" | |
| h="arch/arm/include/uapi/asm/unistd.h" | |
| abi="common eabi oabi removed private" | |
| ;; | |
| loongarch-linux.xml.in) | |
| echo "Skipping $f, no syscall.tbl" | |
| return | |
| ;; | |
| linux-defaults.xml.in) | |
| return | |
| ;; | |
| *) | |
| echo "Don't know how to generate $f" | |
| return | |
| ;; | |
| esac | |
| echo "Generating $f" | |
| one "$t" "$abi" "$start_date" "$offset" "$h" > "$f" | |
| } | |
| main () | |
| { | |
| shopt -s extglob | |
| # Set global d. | |
| parse_args "$@" | |
| local f | |
| for f in *.xml.in; do | |
| regen "$f" | |
| done | |
| } | |
| main "$@" |