162306a36Sopenharmony_ci#!/bin/sh
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0-only
362306a36Sopenharmony_ci# ----------------------------------------------------------------------
462306a36Sopenharmony_ci# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
562306a36Sopenharmony_ci#
662306a36Sopenharmony_ci# Inspired from extract-ikconfig
762306a36Sopenharmony_ci# (c) 2009,2010 Dick Streefland <dick@streefland.net>
862306a36Sopenharmony_ci#
962306a36Sopenharmony_ci# (c) 2011      Corentin Chary <corentin.chary@gmail.com>
1062306a36Sopenharmony_ci#
1162306a36Sopenharmony_ci# ----------------------------------------------------------------------
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cicheck_vmlinux()
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	# Use readelf to check if it's a valid ELF
1662306a36Sopenharmony_ci	# TODO: find a better to way to check that it's really vmlinux
1762306a36Sopenharmony_ci	#       and not just an elf
1862306a36Sopenharmony_ci	readelf -h $1 > /dev/null 2>&1 || return 1
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	cat $1
2162306a36Sopenharmony_ci	exit 0
2262306a36Sopenharmony_ci}
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_citry_decompress()
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	# The obscure use of the "tr" filter is to work around older versions of
2762306a36Sopenharmony_ci	# "grep" that report the byte offset of the line instead of the pattern.
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	# Try to find the header ($1) and decompress from here
3062306a36Sopenharmony_ci	for	pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
3162306a36Sopenharmony_ci	do
3262306a36Sopenharmony_ci		pos=${pos%%:*}
3362306a36Sopenharmony_ci		tail -c+$pos "$img" | $3 > $tmp 2> /dev/null
3462306a36Sopenharmony_ci		check_vmlinux $tmp
3562306a36Sopenharmony_ci	done
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci# Check invocation:
3962306a36Sopenharmony_cime=${0##*/}
4062306a36Sopenharmony_ciimg=$1
4162306a36Sopenharmony_ciif	[ $# -ne 1 -o ! -s "$img" ]
4262306a36Sopenharmony_cithen
4362306a36Sopenharmony_ci	echo "Usage: $me <kernel-image>" >&2
4462306a36Sopenharmony_ci	exit 2
4562306a36Sopenharmony_cifi
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci# Prepare temp files:
4862306a36Sopenharmony_citmp=$(mktemp /tmp/vmlinux-XXX)
4962306a36Sopenharmony_citrap "rm -f $tmp" 0
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci# That didn't work, so retry after decompression.
5262306a36Sopenharmony_citry_decompress '\037\213\010' xy    gunzip
5362306a36Sopenharmony_citry_decompress '\3757zXZ\000' abcde unxz
5462306a36Sopenharmony_citry_decompress 'BZh'          xy    bunzip2
5562306a36Sopenharmony_citry_decompress '\135\0\0\0'   xxx   unlzma
5662306a36Sopenharmony_citry_decompress '\211\114\132' xy    'lzop -d'
5762306a36Sopenharmony_citry_decompress '\002!L\030'   xxx   'lz4 -d'
5862306a36Sopenharmony_citry_decompress '(\265/\375'   xxx   unzstd
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci# Finally check for uncompressed images or objects:
6162306a36Sopenharmony_cicheck_vmlinux $img
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci# Bail out:
6462306a36Sopenharmony_ciecho "$me: Cannot find vmlinux." >&2
65