xref: /linux/scripts/markup_oops.pl (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1cb77f0d6SKamil Rytarowski#!/usr/bin/env perl
2*76e692f5SThomas Gleixner# SPDX-License-Identifier: GPL-2.0-only
35aea50b5SArjan van de Ven
4d32ad102SArjan van de Venuse File::Basename;
551fbb4baSMatthew Wilcoxuse Math::BigInt;
652e13e21SHui Zhuuse Getopt::Long;
7d32ad102SArjan van de Ven
85aea50b5SArjan van de Ven# Copyright 2008, Intel Corporation
95aea50b5SArjan van de Ven#
105aea50b5SArjan van de Ven# This file is part of the Linux kernel
115aea50b5SArjan van de Ven#
125aea50b5SArjan van de Ven# Authors:
135aea50b5SArjan van de Ven# 	Arjan van de Ven <arjan@linux.intel.com>
145aea50b5SArjan van de Ven
155aea50b5SArjan van de Ven
1652e13e21SHui Zhumy $cross_compile = "";
1752e13e21SHui Zhumy $vmlinux_name = "";
1852e13e21SHui Zhumy $modulefile = "";
1952e13e21SHui Zhu
2052e13e21SHui Zhu# Get options
2152e13e21SHui ZhuGetopt::Long::GetOptions(
2252e13e21SHui Zhu	'cross-compile|c=s'	=> \$cross_compile,
2352e13e21SHui Zhu	'module|m=s'		=> \$modulefile,
2452e13e21SHui Zhu	'help|h'		=> \&usage,
2559dde385SHui Zhu) || usage ();
265aea50b5SArjan van de Venmy $vmlinux_name = $ARGV[0];
27d32ad102SArjan van de Venif (!defined($vmlinux_name)) {
28d32ad102SArjan van de Ven	my $kerver = `uname -r`;
29d32ad102SArjan van de Ven	chomp($kerver);
30d32ad102SArjan van de Ven	$vmlinux_name = "/lib/modules/$kerver/build/vmlinux";
31d32ad102SArjan van de Ven	print "No vmlinux specified, assuming $vmlinux_name\n";
32d32ad102SArjan van de Ven}
33d32ad102SArjan van de Venmy $filename = $vmlinux_name;
3452e13e21SHui Zhu
3552e13e21SHui Zhu# Parse the oops to find the EIP value
365aea50b5SArjan van de Ven
375aea50b5SArjan van de Venmy $target = "0";
38d32ad102SArjan van de Venmy $function;
39d32ad102SArjan van de Venmy $module = "";
4011df65c3SArjan van de Venmy $func_offset = 0;
41d32ad102SArjan van de Venmy $vmaoffset = 0;
42d32ad102SArjan van de Ven
43c19ef7fdSArjan van de Venmy %regs;
44c19ef7fdSArjan van de Ven
45c19ef7fdSArjan van de Ven
46c19ef7fdSArjan van de Vensub parse_x86_regs
47c19ef7fdSArjan van de Ven{
48c19ef7fdSArjan van de Ven	my ($line) = @_;
49c19ef7fdSArjan van de Ven	if ($line =~ /EAX: ([0-9a-f]+) EBX: ([0-9a-f]+) ECX: ([0-9a-f]+) EDX: ([0-9a-f]+)/) {
50c19ef7fdSArjan van de Ven		$regs{"%eax"} = $1;
51c19ef7fdSArjan van de Ven		$regs{"%ebx"} = $2;
52c19ef7fdSArjan van de Ven		$regs{"%ecx"} = $3;
53c19ef7fdSArjan van de Ven		$regs{"%edx"} = $4;
54c19ef7fdSArjan van de Ven	}
55c19ef7fdSArjan van de Ven	if ($line =~ /ESI: ([0-9a-f]+) EDI: ([0-9a-f]+) EBP: ([0-9a-f]+) ESP: ([0-9a-f]+)/) {
56c19ef7fdSArjan van de Ven		$regs{"%esi"} = $1;
57c19ef7fdSArjan van de Ven		$regs{"%edi"} = $2;
58c19ef7fdSArjan van de Ven		$regs{"%esp"} = $4;
59c19ef7fdSArjan van de Ven	}
6011df65c3SArjan van de Ven	if ($line =~ /RAX: ([0-9a-f]+) RBX: ([0-9a-f]+) RCX: ([0-9a-f]+)/) {
6111df65c3SArjan van de Ven		$regs{"%eax"} = $1;
6211df65c3SArjan van de Ven		$regs{"%ebx"} = $2;
6311df65c3SArjan van de Ven		$regs{"%ecx"} = $3;
6411df65c3SArjan van de Ven	}
6511df65c3SArjan van de Ven	if ($line =~ /RDX: ([0-9a-f]+) RSI: ([0-9a-f]+) RDI: ([0-9a-f]+)/) {
6611df65c3SArjan van de Ven		$regs{"%edx"} = $1;
6711df65c3SArjan van de Ven		$regs{"%esi"} = $2;
6811df65c3SArjan van de Ven		$regs{"%edi"} = $3;
6911df65c3SArjan van de Ven	}
7011df65c3SArjan van de Ven	if ($line =~ /RBP: ([0-9a-f]+) R08: ([0-9a-f]+) R09: ([0-9a-f]+)/) {
7111df65c3SArjan van de Ven		$regs{"%r08"} = $2;
7211df65c3SArjan van de Ven		$regs{"%r09"} = $3;
7311df65c3SArjan van de Ven	}
7411df65c3SArjan van de Ven	if ($line =~ /R10: ([0-9a-f]+) R11: ([0-9a-f]+) R12: ([0-9a-f]+)/) {
7511df65c3SArjan van de Ven		$regs{"%r10"} = $1;
7611df65c3SArjan van de Ven		$regs{"%r11"} = $2;
7711df65c3SArjan van de Ven		$regs{"%r12"} = $3;
7811df65c3SArjan van de Ven	}
7911df65c3SArjan van de Ven	if ($line =~ /R13: ([0-9a-f]+) R14: ([0-9a-f]+) R15: ([0-9a-f]+)/) {
8011df65c3SArjan van de Ven		$regs{"%r13"} = $1;
8111df65c3SArjan van de Ven		$regs{"%r14"} = $2;
8211df65c3SArjan van de Ven		$regs{"%r15"} = $3;
8311df65c3SArjan van de Ven	}
8411df65c3SArjan van de Ven}
8511df65c3SArjan van de Ven
8611df65c3SArjan van de Vensub reg_name
8711df65c3SArjan van de Ven{
8811df65c3SArjan van de Ven	my ($reg) = @_;
8911df65c3SArjan van de Ven	$reg =~ s/r(.)x/e\1x/;
9011df65c3SArjan van de Ven	$reg =~ s/r(.)i/e\1i/;
9111df65c3SArjan van de Ven	$reg =~ s/r(.)p/e\1p/;
9211df65c3SArjan van de Ven	return $reg;
93c19ef7fdSArjan van de Ven}
94c19ef7fdSArjan van de Ven
95c19ef7fdSArjan van de Vensub process_x86_regs
96c19ef7fdSArjan van de Ven{
97c19ef7fdSArjan van de Ven	my ($line, $cntr) = @_;
98c19ef7fdSArjan van de Ven	my $str = "";
99c19ef7fdSArjan van de Ven	if (length($line) < 40) {
100c19ef7fdSArjan van de Ven		return ""; # not an asm istruction
101c19ef7fdSArjan van de Ven	}
102c19ef7fdSArjan van de Ven
103c19ef7fdSArjan van de Ven	# find the arguments to the instruction
104c19ef7fdSArjan van de Ven	if ($line =~ /([0-9a-zA-Z\,\%\(\)\-\+]+)$/) {
105c19ef7fdSArjan van de Ven		$lastword = $1;
106c19ef7fdSArjan van de Ven	} else {
107c19ef7fdSArjan van de Ven		return "";
108c19ef7fdSArjan van de Ven	}
109c19ef7fdSArjan van de Ven
110c19ef7fdSArjan van de Ven	# we need to find the registers that get clobbered,
111c19ef7fdSArjan van de Ven	# since their value is no longer relevant for previous
112c19ef7fdSArjan van de Ven	# instructions in the stream.
113c19ef7fdSArjan van de Ven
114c19ef7fdSArjan van de Ven	$clobber = $lastword;
115c19ef7fdSArjan van de Ven	# first, remove all memory operands, they're read only
116c19ef7fdSArjan van de Ven	$clobber =~ s/\([a-z0-9\%\,]+\)//g;
117c19ef7fdSArjan van de Ven	# then, remove everything before the comma, thats the read part
118c19ef7fdSArjan van de Ven	$clobber =~ s/.*\,//g;
119c19ef7fdSArjan van de Ven
120c19ef7fdSArjan van de Ven	# if this is the instruction that faulted, we haven't actually done
121c19ef7fdSArjan van de Ven	# the write yet... nothing is clobbered.
122c19ef7fdSArjan van de Ven	if ($cntr == 0) {
123c19ef7fdSArjan van de Ven		$clobber = "";
124c19ef7fdSArjan van de Ven	}
125c19ef7fdSArjan van de Ven
126c19ef7fdSArjan van de Ven	foreach $reg (keys(%regs)) {
12711df65c3SArjan van de Ven		my $clobberprime = reg_name($clobber);
12811df65c3SArjan van de Ven		my $lastwordprime = reg_name($lastword);
129c19ef7fdSArjan van de Ven		my $val = $regs{$reg};
13011df65c3SArjan van de Ven		if ($val =~ /^[0]+$/) {
13111df65c3SArjan van de Ven			$val = "0";
13211df65c3SArjan van de Ven		} else {
13311df65c3SArjan van de Ven			$val =~ s/^0*//;
13411df65c3SArjan van de Ven		}
13511df65c3SArjan van de Ven
136c19ef7fdSArjan van de Ven		# first check if we're clobbering this register; if we do
137c19ef7fdSArjan van de Ven		# we print it with a =>, and then delete its value
13811df65c3SArjan van de Ven		if ($clobber =~ /$reg/ || $clobberprime =~ /$reg/) {
139c19ef7fdSArjan van de Ven			if (length($val) > 0) {
140c19ef7fdSArjan van de Ven				$str = $str . " $reg => $val ";
141c19ef7fdSArjan van de Ven			}
142c19ef7fdSArjan van de Ven			$regs{$reg} = "";
143c19ef7fdSArjan van de Ven			$val = "";
144c19ef7fdSArjan van de Ven		}
145c19ef7fdSArjan van de Ven		# now check if we're reading this register
14611df65c3SArjan van de Ven		if ($lastword =~ /$reg/ || $lastwordprime =~ /$reg/) {
147c19ef7fdSArjan van de Ven			if (length($val) > 0) {
148c19ef7fdSArjan van de Ven				$str = $str . " $reg = $val ";
149c19ef7fdSArjan van de Ven			}
150c19ef7fdSArjan van de Ven		}
151c19ef7fdSArjan van de Ven	}
152c19ef7fdSArjan van de Ven	return $str;
153c19ef7fdSArjan van de Ven}
154c19ef7fdSArjan van de Ven
155c19ef7fdSArjan van de Ven# parse the oops
1565aea50b5SArjan van de Venwhile (<STDIN>) {
157d32ad102SArjan van de Ven	my $line = $_;
158d32ad102SArjan van de Ven	if ($line =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) {
1595aea50b5SArjan van de Ven		$target = $1;
1605aea50b5SArjan van de Ven	}
16111df65c3SArjan van de Ven	if ($line =~ /RIP: 0010:\[\<([a-z0-9]+)\>\]/) {
16211df65c3SArjan van de Ven		$target = $1;
16311df65c3SArjan van de Ven	}
1641f8cdae4SHui Zhu	if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
165d32ad102SArjan van de Ven		$function = $1;
166d32ad102SArjan van de Ven		$func_offset = $2;
1675aea50b5SArjan van de Ven	}
168ef2b9b05SHui Zhu	if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\]  \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
16911df65c3SArjan van de Ven		$function = $1;
17011df65c3SArjan van de Ven		$func_offset = $2;
17111df65c3SArjan van de Ven	}
1725aea50b5SArjan van de Ven
173d32ad102SArjan van de Ven	# check if it's a module
174d32ad102SArjan van de Ven	if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
175d32ad102SArjan van de Ven		$module = $3;
176d32ad102SArjan van de Ven	}
17711df65c3SArjan van de Ven	if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\]  \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
17811df65c3SArjan van de Ven		$module = $3;
17911df65c3SArjan van de Ven	}
180c19ef7fdSArjan van de Ven	parse_x86_regs($line);
1815aea50b5SArjan van de Ven}
1825aea50b5SArjan van de Ven
18351fbb4baSMatthew Wilcoxmy $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$func_offset");
18451fbb4baSMatthew Wilcoxmy $decodestop = Math::BigInt->from_hex("0x$target") + 8192;
1855aea50b5SArjan van de Venif ($target eq "0") {
1865aea50b5SArjan van de Ven	print "No oops found!\n";
18752e13e21SHui Zhu	usage();
1885aea50b5SArjan van de Ven}
1895aea50b5SArjan van de Ven
190d32ad102SArjan van de Ven# if it's a module, we need to find the .ko file and calculate a load offset
191d32ad102SArjan van de Venif ($module ne "") {
19252e13e21SHui Zhu	if ($modulefile eq "") {
19359dde385SHui Zhu		$modulefile = `modinfo -F filename $module`;
194d32ad102SArjan van de Ven		chomp($modulefile);
19552e13e21SHui Zhu	}
196d32ad102SArjan van de Ven	$filename = $modulefile;
197d32ad102SArjan van de Ven	if ($filename eq "") {
198d32ad102SArjan van de Ven		print "Module .ko file for $module not found. Aborting\n";
199d32ad102SArjan van de Ven		exit;
200d32ad102SArjan van de Ven	}
201d32ad102SArjan van de Ven	# ok so we found the module, now we need to calculate the vma offset
20252e13e21SHui Zhu	open(FILE, $cross_compile."objdump -dS $filename |") || die "Cannot start objdump";
203d32ad102SArjan van de Ven	while (<FILE>) {
204d32ad102SArjan van de Ven		if ($_ =~ /^([0-9a-f]+) \<$function\>\:/) {
205d32ad102SArjan van de Ven			my $fu = $1;
20652e13e21SHui Zhu			$vmaoffset = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$fu") - Math::BigInt->from_hex("0x$func_offset");
207d32ad102SArjan van de Ven		}
208d32ad102SArjan van de Ven	}
209d32ad102SArjan van de Ven	close(FILE);
210d32ad102SArjan van de Ven}
211d32ad102SArjan van de Ven
2125aea50b5SArjan van de Venmy $counter = 0;
2135aea50b5SArjan van de Venmy $state   = 0;
2140139f1d9SHui Zhumy $center  = -1;
2155aea50b5SArjan van de Venmy @lines;
216c19ef7fdSArjan van de Venmy @reglines;
2175aea50b5SArjan van de Ven
2185aea50b5SArjan van de Vensub InRange {
2195aea50b5SArjan van de Ven	my ($address, $target) = @_;
2205aea50b5SArjan van de Ven	my $ad = "0x".$address;
2215aea50b5SArjan van de Ven	my $ta = "0x".$target;
22252e13e21SHui Zhu	my $delta = Math::BigInt->from_hex($ad) - Math::BigInt->from_hex($ta);
2235aea50b5SArjan van de Ven
2245aea50b5SArjan van de Ven	if (($delta > -4096) && ($delta < 4096)) {
2255aea50b5SArjan van de Ven		return 1;
2265aea50b5SArjan van de Ven	}
2275aea50b5SArjan van de Ven	return 0;
2285aea50b5SArjan van de Ven}
2295aea50b5SArjan van de Ven
2305aea50b5SArjan van de Ven
2315aea50b5SArjan van de Ven
2325aea50b5SArjan van de Ven# first, parse the input into the lines array, but to keep size down,
2335aea50b5SArjan van de Ven# we only do this for 4Kb around the sweet spot
2345aea50b5SArjan van de Ven
23552e13e21SHui Zhuopen(FILE, $cross_compile."objdump -dS --adjust-vma=$vmaoffset --start-address=$decodestart --stop-address=$decodestop $filename |") || die "Cannot start objdump";
2365aea50b5SArjan van de Ven
2375aea50b5SArjan van de Venwhile (<FILE>) {
2385aea50b5SArjan van de Ven	my $line = $_;
2395aea50b5SArjan van de Ven	chomp($line);
2405aea50b5SArjan van de Ven	if ($state == 0) {
2415aea50b5SArjan van de Ven		if ($line =~ /^([a-f0-9]+)\:/) {
2425aea50b5SArjan van de Ven			if (InRange($1, $target)) {
2435aea50b5SArjan van de Ven				$state = 1;
2445aea50b5SArjan van de Ven			}
2455aea50b5SArjan van de Ven		}
2460139f1d9SHui Zhu	}
2470139f1d9SHui Zhu	if ($state == 1) {
2485aea50b5SArjan van de Ven		if ($line =~ /^([a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]+)\:/) {
2495aea50b5SArjan van de Ven			my $val = $1;
2505aea50b5SArjan van de Ven			if (!InRange($val, $target)) {
2515aea50b5SArjan van de Ven				last;
2525aea50b5SArjan van de Ven			}
2535aea50b5SArjan van de Ven			if ($val eq $target) {
2545aea50b5SArjan van de Ven				$center = $counter;
2555aea50b5SArjan van de Ven			}
2565aea50b5SArjan van de Ven		}
2575aea50b5SArjan van de Ven		$lines[$counter] = $line;
2585aea50b5SArjan van de Ven
2595aea50b5SArjan van de Ven		$counter = $counter + 1;
2605aea50b5SArjan van de Ven	}
2615aea50b5SArjan van de Ven}
2625aea50b5SArjan van de Ven
2635aea50b5SArjan van de Venclose(FILE);
2645aea50b5SArjan van de Ven
2655aea50b5SArjan van de Venif ($counter == 0) {
2665aea50b5SArjan van de Ven	print "No matching code found \n";
2675aea50b5SArjan van de Ven	exit;
2685aea50b5SArjan van de Ven}
2695aea50b5SArjan van de Ven
2700139f1d9SHui Zhuif ($center == -1) {
2715aea50b5SArjan van de Ven	print "No matching code found \n";
2725aea50b5SArjan van de Ven	exit;
2735aea50b5SArjan van de Ven}
2745aea50b5SArjan van de Ven
2755aea50b5SArjan van de Venmy $start;
2765aea50b5SArjan van de Venmy $finish;
2775aea50b5SArjan van de Venmy $codelines = 0;
2785aea50b5SArjan van de Venmy $binarylines = 0;
2795aea50b5SArjan van de Ven# now we go up and down in the array to find how much we want to print
2805aea50b5SArjan van de Ven
2815aea50b5SArjan van de Ven$start = $center;
2825aea50b5SArjan van de Ven
2835aea50b5SArjan van de Venwhile ($start > 1) {
2845aea50b5SArjan van de Ven	$start = $start - 1;
2855aea50b5SArjan van de Ven	my $line = $lines[$start];
2865aea50b5SArjan van de Ven	if ($line =~ /^([a-f0-9]+)\:/) {
2875aea50b5SArjan van de Ven		$binarylines = $binarylines + 1;
2885aea50b5SArjan van de Ven	} else {
2895aea50b5SArjan van de Ven		$codelines = $codelines + 1;
2905aea50b5SArjan van de Ven	}
2915aea50b5SArjan van de Ven	if ($codelines > 10) {
2925aea50b5SArjan van de Ven		last;
2935aea50b5SArjan van de Ven	}
2945aea50b5SArjan van de Ven	if ($binarylines > 20) {
2955aea50b5SArjan van de Ven		last;
2965aea50b5SArjan van de Ven	}
2975aea50b5SArjan van de Ven}
2985aea50b5SArjan van de Ven
2995aea50b5SArjan van de Ven
3005aea50b5SArjan van de Ven$finish = $center;
3015aea50b5SArjan van de Ven$codelines = 0;
3025aea50b5SArjan van de Ven$binarylines = 0;
3035aea50b5SArjan van de Venwhile ($finish < $counter) {
3045aea50b5SArjan van de Ven	$finish = $finish + 1;
3055aea50b5SArjan van de Ven	my $line = $lines[$finish];
3065aea50b5SArjan van de Ven	if ($line =~ /^([a-f0-9]+)\:/) {
3075aea50b5SArjan van de Ven		$binarylines = $binarylines + 1;
3085aea50b5SArjan van de Ven	} else {
3095aea50b5SArjan van de Ven		$codelines = $codelines + 1;
3105aea50b5SArjan van de Ven	}
3115aea50b5SArjan van de Ven	if ($codelines > 10) {
3125aea50b5SArjan van de Ven		last;
3135aea50b5SArjan van de Ven	}
3145aea50b5SArjan van de Ven	if ($binarylines > 20) {
3155aea50b5SArjan van de Ven		last;
3165aea50b5SArjan van de Ven	}
3175aea50b5SArjan van de Ven}
3185aea50b5SArjan van de Ven
3195aea50b5SArjan van de Ven
3205aea50b5SArjan van de Venmy $i;
3215aea50b5SArjan van de Ven
322c19ef7fdSArjan van de Ven
323c19ef7fdSArjan van de Ven# start annotating the registers in the asm.
324c19ef7fdSArjan van de Ven# this goes from the oopsing point back, so that the annotator
325c19ef7fdSArjan van de Ven# can track (opportunistically) which registers got written and
326c19ef7fdSArjan van de Ven# whos value no longer is relevant.
327c19ef7fdSArjan van de Ven
328c19ef7fdSArjan van de Ven$i = $center;
329c19ef7fdSArjan van de Venwhile ($i >= $start) {
330c19ef7fdSArjan van de Ven	$reglines[$i] = process_x86_regs($lines[$i], $center - $i);
331c19ef7fdSArjan van de Ven	$i = $i - 1;
3325aea50b5SArjan van de Ven}
3335aea50b5SArjan van de Ven
334c19ef7fdSArjan van de Ven$i = $start;
335c19ef7fdSArjan van de Venwhile ($i < $finish) {
336c19ef7fdSArjan van de Ven	my $line;
337c19ef7fdSArjan van de Ven	if ($i == $center) {
338c19ef7fdSArjan van de Ven		$line =  "*$lines[$i] ";
339c19ef7fdSArjan van de Ven	} else {
340c19ef7fdSArjan van de Ven		$line =  " $lines[$i] ";
341c19ef7fdSArjan van de Ven	}
342c19ef7fdSArjan van de Ven	print $line;
343c19ef7fdSArjan van de Ven	if (defined($reglines[$i]) && length($reglines[$i]) > 0) {
344c19ef7fdSArjan van de Ven		my $c = 60 - length($line);
345c19ef7fdSArjan van de Ven		while ($c > 0) { print " "; $c = $c - 1; };
346c19ef7fdSArjan van de Ven		print "| $reglines[$i]";
347c19ef7fdSArjan van de Ven	}
348c19ef7fdSArjan van de Ven	if ($i == $center) {
349c19ef7fdSArjan van de Ven		print "<--- faulting instruction";
350c19ef7fdSArjan van de Ven	}
351c19ef7fdSArjan van de Ven	print "\n";
352c19ef7fdSArjan van de Ven	$i = $i +1;
353c19ef7fdSArjan van de Ven}
3545aea50b5SArjan van de Ven
35552e13e21SHui Zhusub usage {
35652e13e21SHui Zhu	print <<EOT;
35752e13e21SHui ZhuUsage:
35852e13e21SHui Zhu  dmesg | perl $0 [OPTION] [VMLINUX]
35952e13e21SHui Zhu
36052e13e21SHui ZhuOPTION:
36152e13e21SHui Zhu  -c, --cross-compile CROSS_COMPILE	Specify the prefix used for toolchain.
36259dde385SHui Zhu  -m, --module MODULE_DIRNAME		Specify the module filename.
36352e13e21SHui Zhu  -h, --help				Help.
36452e13e21SHui ZhuEOT
36552e13e21SHui Zhu	exit;
36652e13e21SHui Zhu}
367