blob: a63d91601b537279c1ef24ccfcd9076b5cfe0e8b [file] [log] [blame]
Jim Cownie5e8470a2013-09-27 10:38:44 +00001#!/usr/bin/perl
2
3#
4#//===----------------------------------------------------------------------===//
5#//
6#// The LLVM Compiler Infrastructure
7#//
8#// This file is dual licensed under the MIT and the University of Illinois Open
9#// Source Licenses. See LICENSE.txt for details.
10#//
11#//===----------------------------------------------------------------------===//
12#
13
14use strict;
15use warnings;
16
17use FindBin;
18use lib "$FindBin::Bin/lib";
19
20use Platform ":vars";
21use tools;
22
23our $VERSION = "0.004";
24
25my $hex = qr{[0-9a-f]}i; # hex digit.
26
Andrey Churbanovd315cea2015-01-16 12:54:51 +000027# mic-specific details.
Jim Cownie5e8470a2013-09-27 10:38:44 +000028
Andrey Churbanovd315cea2015-01-16 12:54:51 +000029sub bad_mic_fmt($) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000030 # Before we allowed both elf64-x86-64-freebsd and elf-l1om-freebsd.
31 # Now the first one is obsolete, only elf64-l1om-freebsd is allowed.
32 my ( $fmt ) = @_;
33 if ( 0 ) {
Andrey Churbanovd315cea2015-01-16 12:54:51 +000034 } elsif ( "$target_mic_arch" eq "knf" ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000035 return $fmt !~ m{\Aelf64-l1om?\z};
Andrey Churbanovd315cea2015-01-16 12:54:51 +000036 } elsif ( "$target_mic_arch" eq "knc" ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000037 return $fmt !~ m{\Aelf64-k1om?\z};
38 } else {
39 return 1;
40 };
Andrey Churbanovd315cea2015-01-16 12:54:51 +000041}; # sub bad_mic_fmt
Jim Cownie5e8470a2013-09-27 10:38:44 +000042
Andrey Churbanovd315cea2015-01-16 12:54:51 +000043# Undesired instructions for mic: all x87 and some other.
Jim Cownie5e8470a2013-09-27 10:38:44 +000044# AC: Since compiler 2010-06-30 x87 instructions are supported, removed the check of x87.
Andrey Churbanovd315cea2015-01-16 12:54:51 +000045my $mic_bad_re;
46sub bad_mic_instr($$) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000047 my ( $instr, $args ) = @_;
Andrey Churbanovd315cea2015-01-16 12:54:51 +000048 if ( "$target_mic_arch" eq "knc" ) {
Jim Cownie5e8470a2013-09-27 10:38:44 +000049 # workaround of bad code generation on KNF Linux* OS:
Andrey Churbanovd315cea2015-01-16 12:54:51 +000050 return ( defined( $instr ) and $instr =~ $mic_bad_re );
Jim Cownie5e8470a2013-09-27 10:38:44 +000051 } else {
Andrey Churbanovd315cea2015-01-16 12:54:51 +000052 return ( defined( $instr ) and $instr =~ $mic_bad_re or defined( $args ) and $args =~ m{xmm}i );
Jim Cownie5e8470a2013-09-27 10:38:44 +000053 }
Andrey Churbanovd315cea2015-01-16 12:54:51 +000054}; # sub bad_mic_instr
Jim Cownie5e8470a2013-09-27 10:38:44 +000055
56# lin_32-specific details.
57
58sub bad_ia32_fmt($) {
59 my ( $fmt ) = @_;
60 return $fmt !~ m{\Aelf32-i386\z};
61}; # sub bad_ia32_fmt
62
63my @sse2 =
64 qw{
65 movapd movupd movhpd movlpd movmskpd movsd
66 addpd addsd subpd subsd mulpd mulsd divpd divsd sqrtpd sqrtsd maxpd maxsd minpd minsd
67 andpd andnpd orpd xorpd
68 cmppd cmpsd comisd ucomisd
69 shufpd unpckhpd unpcklpd
70 cvtpd2pi cvttpd2pi cvtpi2pd cvtpd2dq cvttpd2dq cvtdq2pd cvtps2pd cvtpd2ps cvtss2sd cvtsd2ss
71 cvtsd2si cvttsd2si cvtsi2sd cvtdq2ps cvtps2dq cvttps2dq movdqa movdqu movq2dq movdq2q
72 pmuludq paddq psubq pshuflw pshufhw pshufd pslldq psrldq punpckhqdq punpcklqdq clflush
73 lfence mfence maskmovdqu movntpd movntdq movnti
74 };
75my @sse3 =
76 qw{
77 fisttp lddqu addsubps addsubpd haddps hsubps haddpd hsubpd movshdup movsldup movddup monitor
78 mwait
79 };
80my @ssse3 =
81 qw{
82 phaddw phaddsw phaddd phsubw phsubsw phsubd pabsb pabsw pabsd pmaddubsw pmulhrsw pshufb
83 psignb psignw psignd palignr
84 };
85my @sse4 =
86 (
87 # SSE4.1
88 qw{
89 pmulld pmuldq dppd dpps movntdqa blendpd blendps blendvpd blendvps pblendvb pblendw pminuw
90 pminud pminsb pminsd pmaxuw pmaxud pmaxsb pmaxsd roundps roundpd roundss roundsd extractps
91 insertps pinsrb pinsrd pinsrq pextrb pextrw pextrd pextrq pmovsxbw pmovzxbw pmovsxbd
92 pmovzxbd pmovsxwd pmovzxwd pmovsxbq pmovzxbq pmovsxwq pmovzxwq pmovsxdq pmovzxdq mpsadbw
93 phminposuw ptest pcmpeqq packusdw
94 },
95 # SSE4.2
96 qw{
97 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq crc32 popcnt
98 }
99 );
100
101# Undesired instructions for IA-32 architecture: Pentium 4 (SSE2) and newer.
102# TODO: It would be much more reliable to list *allowed* instructions rather than list undesired
103# instructions. In such a case the list will be stable and not require update when SSE5 is released.
104my @ia32_bad_list = ( @sse2, @sse3, @ssse3, @sse4 );
105
106my $ia32_bad_re = qr{@{[ "^(?:" . join( "|", @ia32_bad_list ) . ")" ]}}i;
107
108sub bad_ia32_instr($$) {
109 my ( $instr, $args ) = @_;
110 return ( defined( $instr ) and $instr =~ $ia32_bad_re );
111}; # sub bad_ia32_instr
112
113sub check_file($;$$) {
114
115 my ( $file, $show_instructions, $max_instructions ) = @_;
116 my @bulk;
117
118 if ( not defined( $max_instructions ) ) {
119 $max_instructions = 100;
120 }; # if
121
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000122 execute( [ "x86_64-k1om-linux-objdump", "-d", $file ], -stdout => \@bulk );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000123
124 my $n = 0;
125 my $errors = 0;
126 my $current_func = ""; # Name of current fuction.
127 my $reported_func = ""; # name of last reported function.
128 foreach my $line ( @bulk ) {
129 ++ $n;
130 if ( 0 ) {
131 } elsif ( $line =~ m{^\s*$} ) {
132 # Empty line.
133 # Ignore.
134 } elsif ( $line =~ m{^In archive (.*?):\s*$} ) {
135 # In archive libiomp5.a:
136 } elsif ( $line =~ m{^(?:.*?):\s*file format (.*?)\s*$} ) {
137 # libiomp5.so: file format elf64-x86-64-freebsd
138 # kmp_ftn_cdecl.o: file format elf64-x86-64
139 my $fmt = $1;
140 if ( bad_fmt( $fmt ) ) {
141 runtime_error( "Invalid file format: $fmt." );
142 }; # if
143 } elsif ( $line =~ m{^Disassembly of section (.*?):\s*$} ) {
144 # Disassembly of section .plt:
145 } elsif ( $line =~ m{^$hex+ <([^>]+)>:\s*$} ) {
146 # 0000000000017e98 <__kmp_str_format@plt-0x10>:
147 $current_func = $1;
148 } elsif ( $line =~ m{^\s*\.{3}\s*$} ) {
149 } elsif ( $line =~ m{^\s*($hex+):\s+($hex$hex(?: $hex$hex)*)\s+(?:lock\s+|rex[.a-z]*\s+)?([^ ]+)(?:\s+([^#]+?))?\s*(?:#|$)} ) {
150 # 17e98: ff 35 fa 7d 26 00 pushq 0x267dfa(%rip) # 27fc98 <_GLOBAL_OFFSET_TABLE>
151 my ( $addr, $dump, $instr, $args ) = ( $1, $2, $3, $4 );
152 # Check this is not a bad instruction and xmm registers are not used.
153 if ( bad_instr( $instr, $args ) ) {
154 if ( $errors == 0 ) {
155 warning( "Invalid instructions found in `$file':" );
156 }; # if
157 if ( $current_func ne $reported_func ) {
158 warning( " $current_func" );
159 $reported_func = $current_func;
160 }; # if
161 ++ $errors;
162 if ( $show_instructions ) {
163 warning( " $line" );
164 }; # if
165 if ( $errors >= $max_instructions ) {
166 info( "$errors invalid instructions found; scanning stopped." );
167 last;
168 }; # if
169 }; # if
170 } else {
171 runtime_error( "Error parsing objdump output line $n:\n>>>> $line\n" );
172 }; # if
173 }; # foreach $line
174
175 return $errors;
176
177}; # sub check_file
178
179# --------------------------------------------------------------------------------------------------
180
181# Parse command line.
182my $max_instructions;
183my $show_instructions;
184get_options(
185 "max-instructions=i" => \$max_instructions,
186 "show-instructions!" => \$show_instructions,
Jim Cownie5e8470a2013-09-27 10:38:44 +0000187 Platform::target_options(),
188);
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000189if ( "$target_os" eq "lin" and "$target_mic_arch" eq "knf" ) {
190 $mic_bad_re = qr{^(?:pause|[slm]fence|scatter|gather|cmpxchg16b|clevict[12])}i;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000191} else {
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000192 $mic_bad_re = qr{^(?:pause|[slm]fence|scatter|gather|cmov|cmpxchg16b|clevict[12])}i;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000193};
194if ( 0 ) {
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000195} elsif ( $target_os eq "lin" and $target_arch eq "mic" ) {
196 *bad_instr = \*bad_mic_instr;
197 *bad_fmt = \*bad_mic_fmt;
Jim Cownie5e8470a2013-09-27 10:38:44 +0000198} elsif ( $target_platform eq "lin_32" ) {
199 *bad_instr = \*bad_ia32_instr;
200 *bad_fmt = \*bad_ia32_fmt;
201} else {
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000202 runtime_error( "Only works on lin_32 and lin_mic platforms." );
Jim Cownie5e8470a2013-09-27 10:38:44 +0000203}; # if
204
205# Do the work.
206my $rc = 0;
207if ( not @ARGV ) {
208 info( "No arguments specified -- nothing to do." );
209} else {
210 foreach my $arg ( @ARGV ) {
211 my $errs = check_file( $arg, $show_instructions, $max_instructions );
212 if ( $errs > 0 ) {
213 $rc = 3;
214 }; # if
215 }; # foreach $arg
216}; # if
217
218exit( $rc );
219
220__END__
221
222=pod
223
224=head1 NAME
225
226B<check-instruction-set.pl> -- Make sure binary file does not contain undesired instructions.
227
228=head1 SYNOPSIS
229
230B<check-instructions.pl> I<option>... I<file>...
231
232=head1 OPTIONS
233
234=over
235
236=item B<--architecture=>I<arch>
237
238Specify target architecture.
239
240=item B<--max-instructions=>I<number>
241
242Stop scanning if I<number> invalid instructions found. 100 by default.
243
244=item B<--os=>I<os>
245
246Specify target OS.
247
248=item B<-->[B<no->]B<show-instructions>
249
250Show invalid instructions found in the file. Bu default, instructions are not shown.
251
252=item Standard Options
253
254=over
255
256=item B<--doc>
257
258=item B<--manual>
259
260Print full help message and exit.
261
262=item B<--help>
263
264Print short help message and exit.
265
266=item B<--usage>
267
268Print very short usage message and exit.
269
270=item B<--verbose>
271
272Do print informational messages.
273
274=item B<--version>
275
276Print program version and exit.
277
278=item B<--quiet>
279
280Work quiet, do not print informational messages.
281
282=back
283
284=back
285
286=head1 ARGUMENTS
287
288=over
289
290=item I<file>
291
292File (object file or library, either static or dynamic) to check.
293
294=back
295
296=head1 DESCRIPTION
297
298The script runs F<objdump> utility to get disassembler listing and checks the file does not contain
299unwanted instructions.
300
301Currently the script works only for:
302
303=over
304
Andrey Churbanovd315cea2015-01-16 12:54:51 +0000305=item C<lin_mic>
Jim Cownie5e8470a2013-09-27 10:38:44 +0000306
307Intel(R) Many Integrated Core Architecture target OS. Undesired unstructions are: all x87 instructions and some others.
308
309=item C<lin_32>
310
311Undesired instructions are instructions not valid for Pentium 3 processor (SSE2 and newer).
312
313=back
314
315=cut
316